Servlet继承图:
HttpServlet是用Http协议实现的Servlet基类,写Servlet时可以直接继承它;接下来首先看看ServletConfig接口。
public interface ServletConfig {
public String getServletName();
public ServletContext getServletContext();
public String getInitParameter(String name);
public Enumeration getInitParameterNames();
ServletConfig 中封装了我们在web.xml中定义的Servlet的一些配置信息;例如:
<servlet>
<servlet-name>demo</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>demo.servlet</param-value>
</init-param>
</servlet>
在ServletConfig 中:
public String getServletName(); 获得Servlet的名字即:<servlet-name>demo</servlet-name>;
public ServletContext getServletContext(); 获得ServletContext代表这个应用本身;
public String getInitParameter(String name);获得init-param配置的参数;
public Enumeration getInitParameterNames();获取init-param中的名字集合,<param-name>contextConfigLocation</param-name>;
接下来看看Servlet的接口:
public interface Servlet {
public void init(ServletConfig config) throws ServletException;
public ServletConfig getServletConfig();
public void service(ServletRequest req, ServletResponse res)throws ServletException, IOException;
public String getServletInfo();
public void destroy();
}
init方法会在容器启动时调用一次;这时这个init方法会接受一个来自容器的ServletConfig 类型的参数,这是由容器实现ServletConfig 接口的类;
而这个参数GenericServlet 中有很大的作用。
getServletConfig()方法返回ServletConfig ,也就是init中传入的ServletConfig 类型的参数;
service用于集体处理一个请求;有容器的Wrapper管道调用;
getServletInfo获取Servlet的一些相关信息;
destroy销毁Servlet;
接下来看看Servlet的默认实现类GenericServlet:
public abstract class GenericServlet implements Servlet, ServletConfig, java.io.Serializable {
private transient ServletConfig config;
public GenericServlet() { }
public void init(ServletConfig config) throws ServletException {
this.config = config;
this.init();
}
public void init() throws ServletException {
}
public abstract void service(ServletRequest req, ServletResponse res) throws ServletException, IOException;
public String getServletInfo() {
return "";
}
public void destroy() {
}
// GenericServlet 实现了ServletConfig接口, 实际上是在底层调用了init方法传进来的ServletConfig;
public String getServletName() {
ServletConfig sc = getServletConfig();
if (sc == null) {
throw new IllegalStateException(
lStrings.getString("err.servlet_config_not_initialized"));
}
return sc.getServletName(); //调用init传来的ServletConfig 的getServletName(); 方法;
}
//调用init传来的ServletConfig 的getServletContext(); 方法;
public ServletContext getServletContext() {
ServletConfig sc = getServletConfig();
if (sc == null) {
throw new IllegalStateException(
lStrings.getString("err.servlet_config_not_initialized"));
}
return sc.getServletContext();
}
//调用init传来的ServletConfig 的getInitParameterNames(); 方法;
public Enumeration getInitParameterNames() {
ServletConfig sc = getServletConfig();
if (sc == null) {
throw new IllegalStateException(
lStrings.getString("err.servlet_config_not_initialized"));
}
return sc.getInitParameterNames();
}
//调用init传来的ServletConfig 的getInitParameter(name); 方法;
public String getInitParameter(String name) {
ServletConfig sc = getServletConfig();
if (sc == null) {
throw new IllegalStateException(
lStrings.getString("err.servlet_config_not_initialized"));
}
return sc.getInitParameter(name);
}
}
接下来看看HttpServlet,它是用来处理请求的主要重写了service方法,它是用来将不同的请求路由到不同的处理方法,
所以其子类只需要实现doGet,doPost等就行了:
public void service(ServletRequest req, ServletResponse res)
throws ServletException, IOException
{
HttpServletRequestrequest;
HttpServletResponseresponse;
try {
request = (HttpServletRequest) req;
response = (HttpServletResponse) res;
} catch (ClassCastException e) {
throw new ServletException("non-HTTP request or response");
}
service(request, response);
}
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) {
doGet(req, resp);
} else {
long ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE);
if (ifModifiedSince < (lastModified / 1000 * 1000)) {
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 {
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);
}
}