Servlet的结构图如下:
1.Servlet接口源代码如下:
//javax.servlet.Servlet
public interface Servlet {
void init(ServletConfig var1) throws ServletException; //在容器启动时被容器调用,只会调用一次
ServletConfig getServletConfig(); //用于获取ServletConfig
void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException; // 用于具体处理一些请求
String getServletInfo(); //用于获取一些Servlet相关信息,如作者,版权等
void destroy(); //用于在Servlet销毁时释放一些资源,一般指关闭服务器,也只会调用一次
}
1.1 init方法调用时,会接收到一个ServletConfig(就是Servlet的配置)参数进去,我们再web.xml中定义的Servlet通过init-param标签配置的参数就是通过ServletConfig来保存的。
2.ServletConfig接口源代码
// javax.servlet;
public interface ServletConfig {
String getServletName(); //用于获取Servlet的名字,就是在Web.xml中定义的Servlet-name
ServletContext getServletContext(); //返回的是这个应用本身
String getInitParameter(String var1); //用于获取init-param配置的参数
Enumeration<String> getInitParameterNames(); //用于获取配置的所有init-param名字的集合
}
结论:ServletConfig是Servlet级别的,ServletContext是应用级(Application)别的。
3.GenericServlet抽象类
主要做了三件事:
1》实现了ServletConfig接口,我们可以直接调ServletConfig里面的方法,
2》提供无参的init方法
3》提供log方法,一个记录日志,一个记录异常
源码:
package javax.servlet;
import java.io.IOException;
import java.io.Serializable;
import java.util.Enumeration;
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(); //这里可以直接调用ServletContext,
}
public String getServletInfo() {
return "";
}
public void init(ServletConfig config) throws ServletException {
this.config = config;
this.init();
}
public void init() throws ServletException { //新增的无参init方法
}
public void log(String msg) {
this.getServletContext().log(this.getServletName() + ": " + msg);
}
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();
}
}
4.HttpServlet类
HttpServlet类是用Http协议实现的Servlet的基类,SpringMVC中的DispatcherServlet就是继承了HttpServlet,我们主要关心HttpServlet怎么处理请求,所以主要讲解下service方法。
在Service中将ServletRequest和ServletResponse转换为了HttpServletRequest和HttpServletResponse,然后根据不同的请求路由到不同的页面。
源码
package javax.servlet.http;
public abstract class HttpServlet extends GenericServlet {
private static final long serialVersionUID = 1L;
private static final String METHOD_DELETE = "DELETE";
private static final String METHOD_HEAD = "HEAD";
private static final String METHOD_GET = "GET";
private static final String METHOD_OPTIONS = "OPTIONS";
private static final String METHOD_POST = "POST";
private static final String METHOD_PUT = "PUT";
private static final String METHOD_TRACE = "TRACE";
private static final String HEADER_IFMODSINCE = "If-Modified-Since";
private static final String HEADER_LASTMOD = "Last-Modified";
private static final String LSTRING_FILE = "javax.servlet.http.LocalStrings";
private static final ResourceBundle lStrings = ResourceBundle.getBundle("javax.servlet.http.LocalStrings");
public HttpServlet() {
}
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
.......
}
protected long getLastModified(HttpServletRequest req) {
return -1L;
}
protected void doHead(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
......
}
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String protocol = req.getProtocol();
String msg = lStrings.getString("http.method_post_not_supported");
if (protocol.endsWith("1.1")) {
resp.sendError(405, msg);
} else {
resp.sendError(400, msg);
}
}
protected void doPut(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
......
}
protected void doDelete(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
......
}
private static Method[] getAllDeclaredMethods(Class<?> c) {
if (c.equals(HttpServlet.class)) {
return null;
} else {
Method[] parentMethods = getAllDeclaredMethods(c.getSuperclass());
Method[] thisMethods = c.getDeclaredMethods();
if (parentMethods != null && parentMethods.length > 0) {
Method[] allMethods = new Method[parentMethods.length + thisMethods.length];
System.arraycopy(parentMethods, 0, allMethods, 0, parentMethods.length);
System.arraycopy(thisMethods, 0, allMethods, parentMethods.length, thisMethods.length);
thisMethods = allMethods;
}
return thisMethods;
}
}
protected void doOptions(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
........
}
protected void doTrace(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
.......
}
//主要是这个方法,根据不同的请求类型路由到不同的方法中
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);
}
}
private void maybeSetLastModified(HttpServletResponse resp, long lastModified) {
.....
}
//转换ServletRequest和ServletReponse
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("non-HTTP request or response");
}
this.service(request, response);
}
}