1 Servlet 继承结构
1.1Servlet 接口
反编译工具打开看其源码解析:
代码:
package javax.servlet; import java.io.IOException; public abstract interface Servlet { public abstract void init(ServletConfig paramServletConfig) throws ServletException; public abstract ServletConfig getServletConfig(); public abstract void service(ServletRequest paramServletRequest, ServletResponse paramServletResponse) throws ServletException, IOException; public abstract String getServletInfo(); public abstract void destroy(); }
1.init(),创建 Servlet 对象后立即调用该方法完成其他初始化工作。
2.service(),处理客户端请求,执行业务操作,利用响应对象响应客户端请求。
3.destroy(),在销毁 Servlet 对象之前调用该方法,释放资源。
4.getServletConfig(),ServletConfig 是容器向 servlet 传递参数的载体。
5.getServletInfo(),获取 servlet 相关信息。
1.2 ServletConfig 接口
代码:
package javax.servlet; import java.util.Enumeration; public abstract interface ServletConfig { public abstract String getServletName(); public abstract ServletContext getServletContext(); public abstract String getInitParameter(String paramString); public abstract Enumeration<String> getInitParameterNames(); }
Servlet 运行期间,需要一些辅助信息,这些信息可以在 web.xml 文件中,使用一个或多 个元素,进行配置。当 Tomcat 初始化一个 Servlet 时,会将该 Servlet 的配置信息,封装到一个 ServletConfig 对象中,通过调用 init(ServletConfig config)方法,将 ServletConfig 对称传递给 Servlet
1.3 GenericServlet 是个抽象类
代码:
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 void destroy() { } public String getInitParameter(String name) { return getServletConfig().getInitParameter(name); } public Enumeration<String> getInitParameterNames() { return getServletConfig().getInitParameterNames(); } public ServletConfig getServletConfig() { return this.config; } public ServletContext getServletContext() { return getServletConfig().getServletContext(); } public String getServletInfo() { return ""; } public void init(ServletConfig config) throws ServletException { this.config = config; init(); } public void init() throws ServletException { } public void log(String msg) { getServletContext().log(getServletName() + ": " + msg); } public void log(String message, Throwable t) { getServletContext().log(getServletName() + ": " + message, t); } public abstract void service(ServletRequest paramServletRequest, ServletResponse paramServletResponse) throws ServletException, IOException; public String getServletName() { return this.config.getServletName(); } }
GenericServlet 是实现了 Servlet 接口的抽象类。在 GenericServlet 中进一步的定义了Servlet 接口的具体实现,其设计的目的是为了和应用层协议解耦,在 GenericServlet 中包含一个 Service 抽象方法。我们也可以通过继承 GenericServlet 并实现 Service 方法实现请求的处 理 , 但是需要将 ServletReuqest 和 ServletResponse 转为 HttpServletRequest 和HttpServletResponse。
有的人会问有什么用呢?
我HttpServlet直接实现上面三个接口不香吗?现在Http协议较为优秀但是我以后再来一个XXX协议,再来跟多XXX协议,你的代码就会非常的冗余而且很多无用代码,而采用中间接口以后不管什么协议直接继承就可以了。
1.4 HttpServlet类
可以看到一个service父类和子类的方法同名:
也就是我们在写的时候会自动的转为子接口类型HttpServletRequest和Response因为他重写了GenericServlet,这个调用不是递归调用你看参数是不同的。
继承自 GenericServlet. 针对于处理 HTTP 协议的请求所定制。在 HttpServlet 的 service() 方法中已经把 ServletReuqest 和 ServletResponse 转 为 HttpServletRequest 和 HttpServletResponse。 直接使用 HttpServletRequest 和 HttpServletResponse, 不再需要强转。实际开发中, 直接继承 HttpServlet, 并根据请求方式复写 doXxx() 方法即可。