[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>

[Servlet]深入研究HttpServlet_第1张图片

利用GET方式发送请求,控制台会打印doGet()方法的内容。利用POST方式发送请求,控制台会打印doPost()方法的内容。


转载说明:请注明作者及原文链接,谢谢!

你可能感兴趣的:(servlet)