HttpServlet概述
在大多數的Web應用程序中,客戶端都是通過Http協議去訪問服務器端的資源,而我們編寫的Servlet主要是用於Http協議的請求和響應處理。爲了快速開發應用於Http協議的Servlet類,Sun公司在javax.servlet.http包中提供了一個抽象類HttpServlet,它繼承於GenericServlet,用於創建適合基於Http協議的Web Servlet。
public abstract class HttpServlet extends GenericServlet {}
下列表中羅列了HttpServlet的所有方法:
Method Summary | |
---|---|
protected void | doDelete(HttpServletRequest req, HttpServletResponse resp) |
protected void | doGet(HttpServletRequest req, HttpServletResponse resp) |
protected void | doHead(HttpServletRequest req, HttpServletResponse resp) |
protected void | doOptions(HttpServletRequest req, HttpServletResponse resp) |
protected void | doPost(HttpServletRequest req, HttpServletResponse resp) |
protected void | doPut(HttpServletRequest req, HttpServletResponse resp) |
protected void | doTrace(HttpServletRequest req, HttpServletResponse resp) |
protected long | getLastModified(HttpServletRequest req) |
protected void | service(HttpServletRequest req, HttpServletResponse resp) |
void | service(ServletRequest req, ServletResponse res) |
下面我們就針對HttpServlet抽象類中提供的各個方法進行討論。
重寫的service()方法
在HttpServlet類中提供了兩種重載的service()方法:
public abstract class HttpServlet extends GenericServlet {
@Override
public void service(ServletRequest req, ServletResponse res)
throws ServletException, IOException {
HttpServletRequest request;
HttpServletResponse response;
try {
request = (HttpServletRequest) req;
response = (HttpServletResponse) res;
} catch (ClassCastException e) {
throw new ServletException("non-HTTP request or response");
}
service(request, response);
}
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String method = req.getMethod();
if (method.equals(METHOD_GET)) {
long lastModified = getLastModified(req);
maybeSetLastModified(resp, lastModified);
doGet(req, resp);
} else if (method.equals(METHOD_HEAD)) {
long lastModified = getLastModified(req);
maybeSetLastModified(resp, lastModified);
doHead(req, resp);
} else if (method.equals(METHOD_POST)) {
doPost(req, resp);
} else if (method.equals(METHOD_PUT)) {
doPut(req, resp);
} else if (method.equals(METHOD_DELETE)) {
doDelete(req, resp);
} else if (method.equals(METHOD_OPTIONS)) {
doOptions(req,resp);
} else if (method.equals(METHOD_TRACE)) {
doTrace(req,resp);
} else {
String errMsg = lStrings.getString("http.method_not_implemented");
Object[] errArgs = new Object[1];
errArgs[0] = method;
errMsg = MessageFormat.format(errMsg, errArgs);
resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED, errMsg);
}
}
通過查看HttpServlet的源代碼我們可以知道,第一個service()方法是GenericServlet類中的Service()方法的實現。在該service()方法中將ServletRequest和ServletResponse對象轉換成HttpServletRequest(繼承於ServletRequest接口)和HttpServletResponse(繼承於ServletResponse接口),然後調用了第二個service()方法,對客戶端的請求進行處理。
在第二個service()方法中,針對Http 1.1協議中定義的7種請求方式Get、Post、Head、Put、Delete、Trace和Options提供了7種處理方法。這7種方法的參數類型及異常拋出類型與HttpServlet類中的第二個service()方法是一致的。當Servlet容器接收到一個針對HttpServlet對象的請求時,調用該對象的方法順序如下:
- 調用公用service()方法,將參數類型轉換成HttpServletRequest和HttpServletResponse,然後調用受保護的service()方法。
- 在受保護的service()方法中,獲取Http請求方法的名字,然後根據請求方法的類型,調用響應的doXXX()方法。
因此,我們在自定義Servlet繼承於HttpServlet的時候,通常不需要重寫service()方法,只需重寫響應的doXXX()方法即可。
七種請求處理方法
在HttpServlet抽象類中提供了針對Http 1.1協議中定義的7種請求方式Get、Post、Head、Put、Delete、Trace和Options提供了7種處理方法:
- protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
- protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
- protected void doHead(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
- protected void doPut(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
- protected void doDelete(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
- protected void doTrace(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
- protected void doOptions(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
這7種處理請求的方法中,HttpServlet類對Trace和Options方法做了適當的實現,因此我們不需要重寫doTrace()和doOptions()方法。而對於其他的5種請求處理方法,HttpServlet類提供的實現都是返回Http錯誤。對於Http 1.0的客戶端請求,這些方法返回的狀態碼爲400,表示客戶端發送的請求在語法上是錯誤的。對於Http 1.1的客戶端請求,這些方法返回的狀態碼爲405,表示對於指定資源的請求方法不被允許。
而對於Http協議的實際應用來講,我們最常用的是Get和Post,所以在自定義Servlet時,常重寫doGet()和doPost()兩個請求處理方法。其中doGet()方法用來處理Get方式的請求,doPost()方法用來處理Post方式的請求,下面我們通過一個案例來看一看:
- 創建一個HTML頁面用於發送客戶端請求。
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>index.html</title>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
</head>
<body>
<h1>GET方式請求</h1>
<form id="userinfo" method="get" action="threeServlet">
用戶名:<input type="text" id="username" name="username">
<input type="submit" id="submit" value="提交">
</form>
<h1>POST方式請求</h1>
<form id="userinfo" method="post" action="threeServlet">
用戶名:<input type="text" id="username" name="username">
<input type="submit" id="submit" value="提交">
</form>
</body>
</html>
- 創建一個Servlet用於處理請求。
public class ThreeServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("這是GET方式發送的請求,Servlet使用doGet()方法來處理.");
}
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("這是POST方式發送的請求,Servlet使用doPost()方法來處理.");
}
}
- 配置web.xml文件。
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5"
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_2_5.xsd">
<servlet>
<servlet-name>ThreeServlet</servlet-name>
<servlet-class>app.java.servlet.ThreeServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ThreeServlet</servlet-name>
<url-pattern>/threeServlet</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
- 將Web工程發佈到Tomcat服務器,並啓動Tomcat服務器。
- 打開瀏覽器,在地址欄中輸入http://localhost:8080/08_servlet/index.html。
利用GET方式發送請求,控制檯會打印doGet()方法的內容。利用POST方式發送請求,控制檯會打印doPost()方法的內容。
轉載說明:請註明作者及原文鏈接,謝謝!