Java登陆第二十九天——Servlet继承关系,service和doGet的区别

发布时间 2023-12-23 18:02:10作者: ocraft

Servlet继承关系树:
image

Servlet接口

查看Servlet源码

public interface Servlet {
    void init(ServletConfig var1) throws ServletException;

    ServletConfig getServletConfig();

    void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException;

    String getServletInfo();

    void destroy();
}

方法解释

方法名 描述
void init(ServletConfig var1) Servlet构造完毕后,Tomcat自动调用该方法(var1也是Tomcat自动生成)
ServletConfig getServletConfig() 获取ServletConfig对象(下一篇介绍ServletConfig)
void service(ServletRequest var1, ServletResponse var2) 处理请求并作出响应
String getServletInfo() 获取一个描述Servlet信息的String
void destroy() Servlet在被删除前会调用的方法

抽象类GenericServlet

查看部分GenericServlet源码

public abstract class GenericServlet implements Servlet, ServletConfig, Serializable {
    private transient ServletConfig config;

    public void init(ServletConfig config) throws ServletException {
        this.config = config;
        this.init();
    }

    public void init() throws ServletException {}

    public abstract void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException;

    public void destroy() {}
}

方法解释

方法名 描述
void destroy() 这种写法叫平庸实现,把抽象方法重写为普通方法却不实现
void init(ServletConfig config) ServletConfig依旧由Tomcat生成,把传参赋值给成员变量,然后在方法体内调用重载方法init()
void init() 真正需要用户实现的方法(HttpServlet继承了GenericServlet)
abstract void service(ServletRequest var1, ServletResponse var2) 再次抽象声明(代表GenericServlet不负责实现该方法)

上述init(ServletConfig config)写法大大提高了扩展性,使得有时无需关注ServletConfig对象也能实现init方法。

抽象类HttpServlet

查看HttpServlet中实现的service源码,解析在下

public abstract class HttpServlet extends GenericServlet {

    public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
        HttpServletRequest request;
        HttpServletResponse response;
        try {
            request = (HttpServletRequest)req;
            response = (HttpServletResponse)res;
        } catch (ClassCastException var6) {
            throw new ServletException(lStrings.getString("http.non_http"));
        }
        this.service(request, response);
    }
}

    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String method = req.getMethod();
        long lastModified;
        if (method.equals("GET")) {
            lastModified = this.getLastModified(req);
            if (lastModified == -1L) {
                this.doGet(req, resp);
            } else {
                long ifModifiedSince;
                try {
                    ifModifiedSince = req.getDateHeader("If-Modified-Since");
                } catch (IllegalArgumentException var9) {
                    ifModifiedSince = -1L;
                }

                if (ifModifiedSince < lastModified / 1000L * 1000L) {
                    this.maybeSetLastModified(resp, lastModified);
                    this.doGet(req, resp);
                } else {
                    resp.setStatus(304);
                }
            }
        } else if (method.equals("HEAD")) {
            lastModified = this.getLastModified(req);
            this.maybeSetLastModified(resp, lastModified);
            this.doHead(req, resp);
        } else if (method.equals("POST")) {
            this.doPost(req, resp);
        } else if (method.equals("PUT")) {
            this.doPut(req, resp);
        } else if (method.equals("DELETE")) {
            this.doDelete(req, resp);
        } else if (method.equals("OPTIONS")) {
            this.doOptions(req, resp);
        } else if (method.equals("TRACE")) {
            this.doTrace(req, resp);
        } else {
            String errMsg = lStrings.getString("http.method_not_implemented");
            Object[] errArgs = new Object[]{method};
            errMsg = MessageFormat.format(errMsg, errArgs);
            resp.sendError(501, errMsg);
        }

    }

图片解析,删除了部分代码

image

  • 如果HttpServlet的实现类没有重写service()方法,不论什么请求方法都会直接报错

    • 也有不重写service()的方法,那就是重写doGet或do...

    • 也有部分人选择重写do...而不是service()

    • Tomcat也会自动调用service(),重写了do...也会成功被执行

    • 根据上述情况分析,重写service()和重写do...效果是一致的