我们在手写Servlet时,会继承HttpServlet类。在HttpServlet类中,有几个重要的方法:doPost()方法、doGet()方法、service()方法。当我们调用自己写的Servlet时,系统会默认调用doGet()方法;或者说,当我们指定一种传输方式,系统会自动调用我们重写的方法。这是采用设计模式中模板模式实现的。

Servlet与模板模式_父类

Servlet是由Tomcat之类的servlet容器来调用处理浏览器请求的,并需要集成基类HttpServlet。反编译出HttpServlet的class文件,我们可以看出,该类中存在两个service()方法:

Servlet与模板模式_父类_02

HttpServlet自定义的service方法,protected修饰的service方法,Tomcat容器实际调用的是这个service()方法。service()方法的实现就是根据http求情的类型(get、post),将处理委派给doGet、doPost等方法,由这些子类的方法来最终处理浏览器的求情。

protected void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException
{
    String method = req.getMethod();

    if (method.equals(METHOD_GET)) {
long lastModified = getLastModified(req);
        if (lastModified == -1) {
// servlet doesn't support if-modified-since, no reason
            // to go through further expensive logic
            doGet(req, resp);
        } else {
long ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE);
            if (ifModifiedSince < lastModified) {
// If the servlet mod time is later, call doGet()
                // Round down to the nearest second for a proper compare
                // A ifModifiedSince of -1 will always be less
                maybeSetLastModified(resp, lastModified);
                doGet(req, resp);
            } else {
                resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
            }
        }

    } 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 {
//
        // Note that this means NO servlet supports whatever
        // method was requested, anywhere on this server.
        //

        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);
    }
}

另外一个service方法是继承于GenericServlet的

public abstract void service(ServletRequest req, ServletResponse res)
throws ServletException, IOException;
@Override
    public void service(ServletRequest req, ServletResponse res)
throws ServletException, IOException
    {
        HttpServletRequest  request;
        HttpServletResponse response;
        
        if (!(req instanceof HttpServletRequest &&
                res instanceof HttpServletResponse)) {
throw new ServletException("non-HTTP request or response");
        }

        request = (HttpServletRequest) req;
        response = (HttpServletResponse) res;

        service(request, response);
    }
}

主要完成的功能是接收客户端请求,并将resquest和response传递给service()方法。父类GenericServlet中,则是service()方法的最高级抽象,给出的是service()抽象方法。


由此可知:

HttpServlet定义了一个处理的框架,或者说是模板,实现Servlet只需要继承HttpServlet并重写doPost()和doGet()方法就可以了。


servlet调用流程图

Servlet与模板模式_设计模式_03

咱们只要实现doGet和doPost方法,service方法中已经定义了模板。


下面来实现一个自定义的servlet

Servlet与模板模式_父类_04

总结:

模板方法在父类HttpServlet的service中,用户只要自己实现doGet/doPost方法即可。

关注并回复福利  有惊喜哟


                         老铁们帮忙点个赞

Servlet与模板模式_设计模式_05