适配器模式改造Servlet(GenericServlet)
Posted 一切随缘~~~
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了适配器模式改造Servlet(GenericServlet)相关的知识,希望对你有一定的参考价值。
适配器模式改造Servlet(GenericServlet)
GenericServlet
-
我们编写一个Servlet类直接实现Servlet接口有什么缺点?
- 我们只需要service方法,其他方法大部分情况下是不需要使用的。代码很丑陋。
-
适配器设计模式Adapter
- 手机直接插到220V的电压上,手机直接就报废了。怎么办?可以找一个充电器。这个充电器就是一个适配器。手机连接适配器。适配器连接220V的电压。这样问题就解决了。
-
之前的一篇博客写到抽象类的作用:降低接口实现类与接口之间的实现难度。
(实现类不一定需要用到接口中定义的所有方法,可以先创建一个抽象类先实现一部分方法,留下实现类需要的方法,实现类再继承抽象类,实现需要的方法。)
-
编写一个GenericServlet类,这个类是一个抽象类,其中有一个抽象方法service。
- GenericServlet实现Servlet接口。
- GenericServlet是一个适配器。
- 以后编写的所有Servlet类继承GenericServlet,重写service方法即可。
-
import javax.servlet.*; import java.io.IOException; public abstract class GenericServlet implements Servlet @Override public void init(ServletConfig servletConfig) throws ServletException @Override public ServletConfig getServletConfig() return null; // service设为抽象方法,留给子类去实现。 @Override public abstract void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException; @Override public String getServletInfo() return null; @Override public void destroy()
-
思考:GenericServlet类是否需要改造一下?怎么改造?更利于子类程序的编写?
-
思考第一个问题:我提供了一个GenericServlet之后,init方法还会执行吗?
- 还会执行。会执行GenericServlet类中的init方法。
-
思考第二个问题:init方法是谁调用的?
- Tomcat服务器调用的。
-
思考第三个问题:init方法中的ServletConfig对象是谁创建的?是谁传过来的?
- 都是Tomcat干的。
- Tomcat服务器先创建了ServletConfig对象,然后调用init方法,将ServletConfig对象传给了init方法。
-
思考一下Tomcat服务器伪代码:
-
public class Tomcat public static void main(String[] args) // ..... // Tomcat服务器伪代码 // 创建LoginServlet对象(通过反射机制,调用无参数构造方法来实例化LoginServlet对象) Class class = Class.forName("com.baidu.javaweb.servlet.LoginServlet"); Object obj = class.newInstance(); // 向下转型 Servlet servlet = (Servlet)obj; // 创建ServletConfig对象 // Tomcat服务器负责将ServletConfig对象实例化出来。 // 多态(Tomcat服务器完全实现了Servlet规范) ServletConfig servletConfig = new org.apache.catalina.core.StandardWrapperFacade(); // 调用Servlet的init方法 servlet.init(servletConfig); // 调用Servlet的service方法 // ....
-
-
-
再思考一下:
-
init方法中的ServletConfig对象是Tomcat小猫咪创建好的。
-
这个ServletConfig对象目前在inti方法的参数上,属于局部变量。
-
那么ServletConfig对象以后肯定要在service方法中使用,怎么才能保证ServletConfig对象在service方法中能够使用呢?
- 直接看代码:
import javax.servlet.*; import java.io.IOException; public abstract class GenericServlet implements Servlet // 成员变量 private ServletConfig config; @Override public void init(ServletConfig servletConfig) throws ServletException // 将servletConfig 赋值给 config this.config = servletConfig; @Override public ServletConfig getServletConfig() // 这里就可以返回config对象了。 return config; @Override public abstract void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException; @Override public String getServletInfo() return null; @Override public void destroy()
-
-
再思考一下:
-
如果继承GenericServlet的类,想要重写init方法呢?
- 给init方法加上final,这样子类就无法重写init方法了。
-
但是如果子类就是要重写init方法呢?
- 解决办法:再GenericServlet类中添加一个无参的init方法,供子类进行重写。
-
-
最终GenericServlet类的代码;
-
import javax.servlet.*; import java.io.IOException; public abstract class GenericServlet implements Servlet // 成员变量 private ServletConfig config; @Override public final void init(ServletConfig servletConfig) throws ServletException // 将servletConfig 赋值给 config this.config = servletConfig; this.init(); // 供子类重写 public void init() @Override public ServletConfig getServletConfig() // 这里就可以返回config对象了。 return config; @Override public abstract void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException; @Override public String getServletInfo() return null; @Override public void destroy()
-
-
值得庆幸的是:GenericServlet不需要我们程序员写,官方替我们写好了。
-
// // Source code recreated from a .class file by IntelliJ IDEA // (powered by FernFlower decompiler) // 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(); 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();
-
可以看到官方写的GenericServlet跟我们自己写的差不多,实现的思想是一样的。
-
以上是关于适配器模式改造Servlet(GenericServlet)的主要内容,如果未能解决你的问题,请参考以下文章