Servlet继承关系树:
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);
}
}
图片解析,删除了部分代码
-
如果HttpServlet的实现类没有重写service()方法,不论什么请求方法都会直接报错
-
也有不重写service()的方法,那就是重写doGet或do...
-
也有部分人选择重写do...而不是service()
-
Tomcat也会自动调用service(),重写了do...也会成功被执行
-
根据上述情况分析,重写service()和重写do...效果是一致的
-