您的位置:首页 > 其它

循循渐进的GenericServlet

2015-09-26 09:45 309 查看
在做web开发时,创建自己的servlet时,通常需要实现javax.servlet.Servlet接口,并覆写Servlet所有的方法,例如:
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();
}
}

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: