循循渐进的GenericServlet
2015-09-26 09:45
309 查看
在做web开发时,创建自己的servlet时,通常需要实现javax.servlet.Servlet接口,并覆写Servlet所有的方法,例如:
, ServletResponse)的逻辑不一样,所以就让GenericServlet为抽象类,把service(ServletRequest , ServletResponse)抽象出来。如下:
针对GenericServlet采取这样的方式:
下面附上javax.servlet.GenericServlet的源码,以便好好琢磨琢磨:
package javax.servlet;
import java.io.IOException;
import java.util.Enumeration;
public abstract class GenericServlet implements Servlet, ServletConfig, java.io.Serializable {
private transient ServletConfig config;
public GenericServlet() { }
public void destroy() {
}
public String getInitParameter(String name) {
return getServletConfig().getInitParameter(name);
}
public Enumeration getInitParameterNames() {
return getServletConfig().getInitParameterNames();
}
public ServletConfig getServletConfig() {
return config;
}
public ServletContext getServletContext() {
return 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 msg) {
getServletContext().log(getServletName() + ": "+ msg);
}
public void log(String message, Throwable t) {
getServletContext().log(getServletName() + ": " + message, t);
}
public abstract void service(ServletRequest req, ServletResponse res)
throws ServletException, IOException;
public String getServletName() {
return config.getServletName();
}
}
import java.io.IOException; import javax.servlet.Servlet; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; public class DemoServlet implements Servlet{ public void init(ServletConfig config) throws ServletException { // TODO Auto-generated method stub } public ServletConfig getServletConfig() { // TODO Auto-generated method stub return null; } public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException { // TODO Auto-generated method stub } public String getServletInfo() { // TODO Auto-generated method stub return null; } public void destroy() { // TODO Auto-generated method stub } }但是,如果需要自定义很多个servlet,而每个servlet都必须覆写javax.servlet.Servlet的五个方法,况且有些方法只是简单的覆盖了一下,根本没用实际用到,这样在开发servlet时就显得很繁琐,是不是可以简化开发呢?于是想到,定义一个GenericServlet类,这个类实现javax.servlet.Servlet接口,而自定义的servlet自需要继承抽象类即可。由于每个自定义的servlet需要处理service(ServletRequest
, ServletResponse)的逻辑不一样,所以就让GenericServlet为抽象类,把service(ServletRequest , ServletResponse)抽象出来。如下:
import java.io.IOException; import javax.servlet.Servlet; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; public abstract class GenericServlet implements Servlet { public void init(ServletConfig config) throws ServletException { // TODO Auto-generated method stub } public ServletConfig getServletConfig() { // TODO Auto-generated method stub return null; } public abstract void service(ServletRequest req, ServletResponse res) throws ServletException, IOException; public String getServletInfo() { // TODO Auto-generated method stub return null; } public void destroy() { // TODO Auto-generated method stub } }而对于刚才DemoServlet,便可以如下定义:
import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; public class DemoServlet extends GenericServlet { @Override public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException { // TODO Auto-generated method stub System.out.println("DemoServlet 的 service() 逻辑处理。"); } }但是可能自定的DemoServlet在实例化后需要额外做一些自己的init。于是需要这样做:
import java.io.IOException; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; public class DemoServlet extends GenericServlet { @Override public void init(ServletConfig config) throws ServletException { // TODO Auto-generated method stub System.out.println("DemoServlet 的 init() 逻辑处理。"); } @Override public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException { // TODO Auto-generated method stub System.out.println("DemoServlet 的 service() 逻辑处理。"); } }现在又有新的功能,需要DemoServlet能获取ServletConfig的参数信息,类似javax.servlet. ServletConfig接口的getServletName()、getServletContext()等方法,于是采用这样的方式:
import java.io.IOException; import java.util.Enumeration; import javax.servlet.ServletConfig; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; public class DemoServlet extends GenericServlet { private ServletConfig config; @Override public void init(ServletConfig config) throws ServletException { // TODO Auto-generated method stub this.config = config; System.out.println("DemoServlet 的 init() 逻辑处理。"); } @Override public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException { // TODO Auto-generated method stub System.out.println("DemoServlet 的 service() 逻辑处理。"); } public String getInitParameter(String name) { return config.getInitParameter(name); } public Enumeration getInitParameterNames() { return config.getInitParameterNames(); } public ServletContext getServletContext() { return config.getServletContext(); } public String getServletName() { return config.getServletName(); } }更显然一点:
public class DemoServlet extends GenericServlet implements ServletConfig{就是覆写了ServletConfig的方法,那么如果自定义很多servlet,开发又显得复杂起来了,于是想到让GenericServlet也实现ServletConfig接口,与是就有了如下的改进:
import java.io.IOException; import java.util.Enumeration; import javax.servlet.Servlet; import javax.servlet.ServletConfig; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; public abstract class GenericServlet implements Servlet, ServletConfig { private ServletConfig config; public void init(ServletConfig config) throws ServletException { // TODO Auto-generated method stub this.config = config; } public ServletConfig getServletConfig() { // TODO Auto-generated method stub return this.config; } public abstract void service(ServletRequest req, ServletResponse res) throws ServletException, IOException; public String getServletInfo() { // TODO Auto-generated method stub return null; } public void destroy() { // TODO Auto-generated method stub } public String getServletName() { // TODO Auto-generated method stub return getServletConfig().getServletName(); } public ServletContext getServletContext() { // TODO Auto-generated method stub return getServletConfig().getServletContext(); } public String getInitParameter(String name) { // TODO Auto-generated method stub return getServletConfig().getInitParameter(name); } public Enumeration getInitParameterNames() { // TODO Auto-generated method stub return getServletConfig().getInitParameterNames(); } }这样,就ok了。但是作为GenericServlet的子类DemoServlet,如果要覆写init(ServletConfig config),必须要这样做:
@Override public void init(ServletConfig config) throws ServletException { // TODO Auto-generated method stub super.init(config); System.out.println("DemoServlet 的 init() 逻辑处理。"); }不然,GenericServlet就无法缓存config,就会出NullPointerException。这样,又会让编程人员在编码时需要额外注意这一个坑,有木有好的解决方法呢?答案是肯定的。
针对GenericServlet采取这样的方式:
public void init(ServletConfig config) throws ServletException { // TODO Auto-generated method stub this.config = config; init(); } public void init(){ }如果子类需要做自己的init,只需要覆写init()就可以:
@Override public void init() { // TODO Auto-generated method stub System.out.println("DemoServlet 的 init() 逻辑处理。"); }只是一个值得学习的设计思路。
下面附上javax.servlet.GenericServlet的源码,以便好好琢磨琢磨:
package javax.servlet;
import java.io.IOException;
import java.util.Enumeration;
public abstract class GenericServlet implements Servlet, ServletConfig, java.io.Serializable {
private transient ServletConfig config;
public GenericServlet() { }
public void destroy() {
}
public String getInitParameter(String name) {
return getServletConfig().getInitParameter(name);
}
public Enumeration getInitParameterNames() {
return getServletConfig().getInitParameterNames();
}
public ServletConfig getServletConfig() {
return config;
}
public ServletContext getServletContext() {
return 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 msg) {
getServletContext().log(getServletName() + ": "+ msg);
}
public void log(String message, Throwable t) {
getServletContext().log(getServletName() + ": " + message, t);
}
public abstract void service(ServletRequest req, ServletResponse res)
throws ServletException, IOException;
public String getServletName() {
return config.getServletName();
}
}
相关文章推荐
- Android系统的常用权限整理
- Linux库函数int system(const char*command)简析http://www.2cto.com/os/201209/156638.html
- java界面项目----问题篇
- HDU 1950 Bridging signals (DP)
- Sqlite
- ThinkPHP+DWZ(xhEditor)上传图片
- 内存泄漏检查工具valgrind使用方法
- leetcode 270: Closest Binary Search Tree Value
- JVM/JDK/JRE/IDE—区别
- UVa 11729:Commando War(贪心)
- TYVJ P1577 泥泞的道路
- linux内核设计艺术---学习笔记(Ⅰ )
- SdCard操作
- Win7无法同时播放两个声音怎么办 Win7无法同时播放两个声音的应对措施
- poj_3628 动态规划
- MongoDB MapReduce 使用
- CMake 问题指南
- 永远不要拿别人跟自己攀比
- 解决Eclipse新建Android工程出错
- cmd删除文件