Jakarta EE 程式設計/Servlet
Servlet 是在伺服器端執行的 Java 類,它接收 HTTP 資料,並在遵循 HTTP 協議的約束條件下進行處理或執行其他操作。
package servlet;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Servlet implementation class Hello
*/
@WebServlet("/Hello")
public class Hello extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public Hello() {
super();
// TODO Auto-generated constructor stub
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// TODO Auto-generated method stub
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
try {
out.println("Hello World");
} finally {
out.close();
}
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request,response);
}
}
我們注意到這個類中有兩個方法:doGet() 和 doPost()。第一個方法透過 HTTP 響應對 GET 請求的接收,第二個方法響應對 POST 請求的接收。由於我們希望在兩種情況下 Servlet 都能處理請求,因此 doPost() 會轉發到 doGet()。
- 將編譯後的類及其包放入工作 Web 目錄的
WEB-INF中的classes目錄中(這裡:webTest) - 透過新增以下內容來編輯
WEB-INF中的web.xml
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0"
metadata-complete="true">
<!-- Beginning here -->
<servlet>
<servlet-name>Hello</servlet-name><!-- Class name -->
<servlet-class>servlet.Hello</servlet-class><!-- Class tree: with the package -->
</servlet>
<servlet-mapping>
<servlet-name>Hello</servlet-name><!-- Class name -->
<url-pattern>/Hello</url-pattern><!-- Class pattern in the URL-->
</servlet-mapping>
<!-- End here -->
<web-app>
因此 WEB-INF 包含
WEB-INF
web.xml
classes
servlet
Hello.class
瀏覽器中的結果
Hello World
[協議://][DNS]:[埠]/[根目錄]/[Servlet 名稱]
// Returns the server name
request.getServerName();
// Returns the server port
request.getServerPort();
// Returns the name of the application hosting the servlet
request.getContextPath();
// Returns the servlet path
request.getServletPath();
// Returns the type of the HTTP request used
request.getMethod();
// Returns the parameters sent in the URL
request.getQueryString();
// Returns the URL used to contact the servlet
request.getRequestURL();
// Returns the local address
request.getLocalAddr();
// Returns the local name
request.getLocalName();
// Returns the local port
request.getLocalPort();
// Returns the remote address
request.getRemoteAddr();
// Returns the remote host
request.getRemoteHost();
Servlet 中的示例
package servlet;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Servlet implementation class Hello
*/
@WebServlet("/Hello")
public class Hello extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public Hello() {
super();
// TODO Auto-generated constructor stub
}
protected void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
try {
out.println(request.getServerName());
out.println("<br/>");
out.println(request.getServerPort());
out.println("<br/>");
out.println(request.getContextPath());
out.println("<br/>");
out.println(request.getServletPath());
out.println("<br/>");
out.println(request.getMethod());
out.println("<br/>");
out.println(request.getQueryString());
out.println("<br/>");
out.println(request.getRequestURL());
out.println("<br/>");
out.println(request.getLocalAddr());
out.println("<br/>");
out.println(request.getLocalName());
out.println("<br/>");
out.println(request.getLocalPort());
out.println("<br/>");
out.println(request.getRemoteAddr());
out.println("<br/>");
out.println(request.getRemoteHost());
} finally {
out.close();
}
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
processRequest(request, response);
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// TODO Auto-generated method stub
processRequest(request, response);
}
}
相關呼叫:https://:999/webTest/Hello
localhost 999 /webTest /Hello GET null https://:999/webTest/Hello 127.0.0.1 localhost 999 127.0.0.1 127.0.0.1
// Parameter retrieving by the "parameterName"
request.getParameter(parameterName);
// Returns an enumeration of all the parameters of a request
request.getParameterNames();
// Returns all the parameter values of "parameterName"
request.getParameterValues(parameterName);
// Returns an iteration of the parameter names
request.getParameterMap();
// Returns the header names
request.getHeaderNames();
// Returns the headers
request.getHeaders();
// Returns the number of bytes of the request
request.getContentLength();
// Returns the content type of the request
request.getContentType();
// Returns the default language
request.getLocale();
// Returns the list of languages
request.getLocales();
// Returns the header date
request.getDateHeader(String name);
// Returns the header specified by the "name"
request.getHeader(String name);
// Returns the headers specified by the "name"
request.getHeaders(String name);
// Store an object in the HttpServletRequest object
request.setAttribute(String name, Object o);
// Returns the stored object "name"
request.getAttribute(String name);
// Returns an enumeration of the attribute names
request.getAttributeNames();
// Remove the attribute "name" the attributes of the request
request.removeAttribute(String name);
HTTP 頭資訊為響應新增補充資訊。
// Indicates the nature of the information put into the response
response.setContentType(String type);
// Indicates the local language
response.setLocale(Locale loc);
// Adds the header "name" with the value "value"
response.addHeader(String name, String value);
(PrintWriter)getWriter()允許將文字傳輸到 HTTP 響應主體。(ServletOutputStream)getOutputStream()允許將二進位制資料傳輸到 HTTP 響應主體。
切勿同時使用這兩種方法,否則會導致 IllegalStateException 異常。
以下是一個二進位制傳送的示例
package servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Servlet implementation class ReponseHttp2
*/
@WebServlet("/HttpResponse2")
public class HttpResponse2 extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public HttpResponse2() {
super();
// TODO Auto-generated constructor stub
}
protected void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.sendRedirect("images/toto.jpg");
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
processRequest(request, response);
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
processRequest(request, response);
}
}
在這個示例中,我們使用 processRequest(request, response) 來始終在 GET 或 POST 中獲得相同的處理過程。
狀態碼分為 5 類
- 1XX:資訊
- 2XX:成功
- 3XX:重定向
- 4XX:客戶端錯誤
- 5XX:伺服器錯誤
有關這些程式碼的詳細資訊,請訪問 http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
setStatus(int rc)sendError(int sc, String message)
... 允許設定頁面的錯誤狀態。例如,我們將生成一個伺服器錯誤。
package servlet;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Servlet implementation class ReponseHTTP
*/
@WebServlet("/ReponseHTTP")
public class ReponseHTTP extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public ReponseHTTP() {
super();
// TODO Auto-generated constructor stub
}
protected void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
try {
response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE, "the server is overloaded. Please try later.");
} finally {
out.close();
}
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
processRequest(request, response);
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
processRequest(request, response);
}
}
包含外部資源。
RequestDispatcher rd = null;
rd = getServletContext().getRequestDispatcher("/header.html");
rd.include(request, response);
Servlet 結果傳輸到另一個資源。
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.HttpServlet;
import javax.servlet.HttpServletRequest;
import javax.servlet.HttpServletResponse;
public class Result extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
try {
int result = 10;
RequestDispatcher rd = null;
rd = getServletContext().getRequestDispatcher("/result.jsp");
request.setAttribute("theResult", result);
rd.forward(request, response);
} finally {
out.close();
}
}
}
目標資源:result.jsp
<%@page contentType="text/html" pageEncoding="UTF-8">
<%@page import="java.text.*" %>
<html>
<body>
<%
theResult = (double) request.getAttribute("theResult");
%>
Result: <%= theResult %>
</body>
</html>
伺服器通知瀏覽器向給定的 URL 傳送 HTTP 請求。
response.setStatus(HttpServletResponse.SC_MOVED_PERMANENTLY); // For a 301 HTTP response
response.setHeader("location", "http://www.google.be"); // For a 302 HTTP response
response.sendRedirect("http://www.google.be");
過濾器在 HTTP 請求被 Servlet 接收之前或在 HTTP 響應被返回之前新增一個處理過程。
其作用包括:
- 訪問控制
- 訪問日誌
- 資料解壓縮
- 解密
- 資料轉換
可以依次執行多個響應。過濾器類必須實現 javax.servlet.Filter 介面。
事件通知應用程式操作,例如物件的例項化和銷燬。
- 應用程式相關事件:由 Servlet 上下文觸發的事件。
- 會話相關事件:這些類必須實現
HttpSessionListener和HttpSessionAttributeListener介面。
這種同步避免了伺服器同時使用兩個執行緒,例如當同一個類的兩個例項使用兩個不同的客戶端呼叫同一個方法時。synchronized(this){} 必須應用於關鍵程序,例如計數器。
public class ... {
public void method() {
out = response.getWriter();
synchronized(this) {
counter++;
}
out.println("The counter value is " + counter);
}
}
