在servlet项目中,我们新建TestServlet类继承Httpservlet,重写其doPost与doGet方法,就可以接收前台的get和post请求,那么这是为什么呢?
首先通过源码我们可以发现:
HttpServlet 继承自 GenericServlet 抽象类,
GenericServlet 实现了 Servlet 接口,ServletConfig 接口,Serializable 接口
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();
}
其中有三个生命周期函数:
1.init() servlet容器一旦创建就会调用init()函数进行初始化
2.service() 前台有请求,就会调用service()方法提供服务
3.destroy() servlet容器销毁会调用destroy()
两个获取servlet信息的方法:
getServletConfig() 用于获取servlet的配置信息
getServletInfo() 用于获取servlet的信息
ServletConfig接口,也是一个顶层接口,其中的方法都是关于servlet的配置信息获取
public interface ServletConfig {
String getServletName();
ServletContext getServletContext();
String getInitParameter(String var1);
Enumeration<String> getInitParameterNames();
}
Serializable接口,实现该接口表示该类可被序列化
public interface Serializable {
}
GenericServlet是一个抽象类,实现了servlet,servletconfig,serializable
实现了servlet接口, servlet容器调用servlet接口的方法就会交给下游GenericServlet实现
而GenericServlet又将方法交给下游HttpServlet方法
public abstract class GenericServlet implements Servlet, ServletConfig, Serializable {
private static final long serialVersionUID = 1L;
private transient ServletConfig config;
public GenericServlet() {
}
public void destroy() {
}
public String getInitParameter(String name) {
return this.getServletConfig().getInitParameter(name);
}
public Enumeration<String> getInitParameterNames() {
return this.getServletConfig().getInitParameterNames();
}
public ServletConfig getServletConfig() {
return this.config;
}
public ServletContext getServletContext() {
return this.getServletConfig().getServletContext();
}
public String getServletInfo() {
return "";
}
public void init(ServletConfig config) throws ServletException {
this.config = config;
this.init();
}
public void init() throws ServletException {
}
public void log(String message) {
this.getServletContext().log(this.getServletName() + ": " + message);
}
public void log(String message, Throwable t) {
this.getServletContext().log(this.getServletName() + ": " + message, t);
}
public abstract void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException;
public String getServletName() {
return this.config.getServletName();
}
}
那么在实际应用过程中,我们一般只关心如何收到请求与返回响应
在HttpServlet源码中的service()方法通过继承父类,父类实现父接口,实际上源自顶层接口Servlet的生命周期函数,就是Servlet对外提供服务的方法
在方法中可以看到HttpServlet对请求按照请求类型进行分类,因此我们只需要重写其方法,就可以接收不同类型的请求
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);
}
}
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String msg = lStrings.getString("http.method_get_not_supported");
this.sendMethodNotAllowed(req, resp, msg);
}
protected long getLastModified(HttpServletRequest req) {
return -1L;
}
protected void doHead(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
if (DispatcherType.INCLUDE.equals(req.getDispatcherType())) {
this.doGet(req, resp);
} else {
HttpServlet.NoBodyResponse response = new HttpServlet.NoBodyResponse(resp);
this.doGet(req, response);
if (req.isAsyncStarted()) {
req.getAsyncContext().addListener(new HttpServlet.NoBodyAsyncContextListener(response));
} else {
response.setContentLength();
}
}
}
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String msg = lStrings.getString("http.method_post_not_supported");
this.sendMethodNotAllowed(req, resp, msg);
}
protected void doPut(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String msg = lStrings.getString("http.method_put_not_supported");
this.sendMethodNotAllowed(req, resp, msg);
}
protected void doDelete(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String msg = lStrings.getString("http.method_delete_not_supported");
this.sendMethodNotAllowed(req, resp, msg);
}
也就是说,前端请求到Servlet容器,Servlet下发到GenericServlet,GenericServlet又将方法交给下游HttpServlet方法,那么我们写一个servlet继承HttpServlet,让其将请求下发,就可以接收request请求了
总结:
servlet 总体结构如下:
请求与响应的下发: