[Servlet]深入研究HttpServlet

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>

這裏寫圖片描述

利用GET方式發送請求,控制檯會打印doGet()方法的內容。利用POST方式發送請求,控制檯會打印doPost()方法的內容。


轉載說明:請註明作者及原文鏈接,謝謝!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章