由于容器对HttpServletRequest对象,做了过多的修改。当用户快速多次请求,并从HttpServletRequest对象中获取ServletContext时有可能会抛出一个NullPointerException异常。为了保存,永远可以获取到ServletContext对象,且即使快速多次请求也可以获取到ServletContext对象,特别是在Filter中获取ServletContext对象时,就必须要从FilterConfig中获取ServletContext对象:
以下代码,当用户访问网站的任何一下页面时,都给ServletContext中的一个key值加1,由于这新数据并不是最主要的数据,更不能影响到用户的操作,所以,应该放到一个独立的线程中去访问。同时为了防止同时增加造成数据丢掉的问题,应该给方法添加同步代码块。
如果你看过HttpServlet、GenericServlet的源代码,你也不难发现,它们都是从Config(配置)对象中获取ServletContext对象的。
示例代码:以下功能,用于记录网站的刷新或是访问量。
package cn.onner1.filter;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
/**
* 开始一个线程不影响用户的操作感受
* @author <a href="wangjian_me@126.com">王健</a>
*/
public class CountFilter implements Filter{
private Add add = new Add();
public void destroy() {
}
public void doFilter(ServletRequest arg0, ServletResponse arg1,
FilterChain arg2) throws IOException, ServletException {
new Thread(){//开始一个新的线程不影响用户的操作感受
public void run() {
//必须要从FilterConfig中获取Ctx对象,速度+稳定,尽量不要从request中获取ServletContext
add.add(conf.getServletContext());
};
}.start();
arg2.doFilter(arg0, arg1);
}
private FilterConfig conf;
public void init(FilterConfig arg0) throws ServletException {
this.conf=arg0;
}
}
class Add{
//同步代码块,通过一个线程来操作,不会影响用户的感受
public synchronized void add(ServletContext ctx){
Integer count = (Integer) ctx.getAttribute("count");
count++;
ctx.setAttribute("count",count);
}
}