在网站程序的任何地方获取到request对象.doc

 
在一个WEB程序中,你想不想在一个JAVABEAN中获取到httpservletrequest对象?
只需要使用一个filter就可以搞定了!!
这是通过 ThreadLocal实现的,下面引用一段定义:
ThreadLocal 是什么

  ThreadLocal是什么呢?其实ThreadLocal并非是一个线程的本地实现版本,它并不是一个Thread,而是thread local variable(线程局部变量)。也许把它命名为ThreadLocalVar更加合适。线程局部变量(ThreadLocal)其实的功用非常简单,就是为每一个使用该变量的线程都提供一个变量值的副本,是每一个线程都可以独立地改变自己的副本,而不会和其它线程的副本冲突。从线程的角度看,就好像每一个线程都完全拥有该变量。线程局部变量并不是Java的新发明,在其它的一些语言编译器实现(如IBM XL FORTRAN)中,它在语言的层次提供了直接的支持。因为Java中没有提供在语言层次的直接支持,而是提供了一个ThreadLocal的类来提供支持,所以,在Java中编写线程局部变量的代码相对比较笨拙,这也许是线程局部变量没有在Java中得到很好的普及的一个原因吧。
 
其实hibernate中获取session的代码正式利用了这种原理:
package com.dcsoft.sbgl.hibernate;
 
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.cfg.Configuration;
 
/**
 * Configures and provides access to Hibernate sessions, tied to the
 * current thread of execution. Follows the Thread Local Session
 * pattern, see {@link http://hibernate.org/42.html }.
 */
public class HibernateSessionFactory {
 
    /**
     * Location of hibernate.cfg.xml file.
     * Location should be on the classpath as Hibernate uses 
     * #resourceAsStream style lookup for its configuration file.
     * The default classpath location of the hibernate config file is
     * in the default package. Use #setConfigFile() to update
     * the location of the configuration file for the current session.  
     */
    private static String CONFIG_FILE_LOCATION = "/hibernate.cfg.xml";
    private static final ThreadLocal threadLocal = new ThreadLocal();
    private static Configuration configuration = new Configuration();
    private static org.hibernate.SessionFactory sessionFactory;
    private static String configFile = CONFIG_FILE_LOCATION;
 
    private HibernateSessionFactory() {
    }
   
    /**
     * Returns the ThreadLocal Session instance. Lazy initialize
     * the <code>SessionFactory</code> if needed.
     *
     * @return Session
     * @throws HibernateException
     */
    public static Session getSession() throws HibernateException {
        Session session = (Session) threadLocal.get();
 
        if (session == null || !session.isOpen()) {
            if (sessionFactory == null) {
                rebuildSessionFactory();
            }
            session = (sessionFactory != null) ? sessionFactory.openSession()
                    : null;
            threadLocal.set(session);
        }
 
        return session;
    }
 
    /**
     * Rebuild hibernate session factory
     *
     */
    public static void rebuildSessionFactory() {
        try {
            configuration.configure(configFile);
            sessionFactory = configuration.buildSessionFactory();
        } catch (Exception e) {
            System.err
                    .println("%%%% Error Creating SessionFactory %%%%");
            e.printStackTrace();
        }
    }
 
    /**
     * Close the single hibernate session instance.
     *
     * @throws HibernateException
     */
    public static void closeSession() throws HibernateException {
        Session session = (Session) threadLocal.get();
        threadLocal.set(null);
 
        if (session != null) {
            session.close();
        }
    }
 
    /**
     * return session factory
     *
     */
    public static org.hibernate.SessionFactory getSessionFactory() {
        return sessionFactory;
    }
 
    /**
     * return session factory
     *
     *   session factory will be rebuilded in the next call
     */
    public static void setConfigFile(String configFile) {
        HibernateSessionFactory.configFile = configFile;
        sessionFactory = null;
    }
 
    /**
     * return hibernate configuration
     *
     */
    public static Configuration getConfiguration() {
        return configuration;
    }
 
}
 
从而保证了在一个线程中的session是同一个,既然这种方式能够被hibernate使用,那么,我们自己为什么不能利用一下呢??
下面我们想在任何地方都可以获取到request对象,因为对现在大部分服务器来说,每一次访问均在一个线程中。这就为我们的构思提供了可能性;
原理:
在开始一次请求的开始增加一个filter,将当前的request存入当前线程的一个ThreadLocal变量中。这样,我们就可以在任何地方都能够获取到request了。
下面是部分代码:
Filter:
package com.hf.servlet.filter;
 
import java.io.IOException;
 
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
 
import org.apache.log4j.Logger;
/**
 * 将此过滤器配置在 web.xml中,就可以在任何地方获取到当前的request了。
 * @author Administrator
 *
 */
public class WebContextHolderFilter implements Filter {
    private static Logger logger = Logger.getLogger(WebContextHolderFilter.class);
    /**
     * 在这里可以进行字符集的设置
     */
    public void init(FilterConfig config) throws ServletException {
       logger.info(" 初始化WebContextHolderFilter…………开始");
       logger.info(" 初始化WebContextHolderFilter………… 结束");
    }
 
    public void doFilter(ServletRequest srequest, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        logger.info(" 进入一个WebContextHolderFilter的dofilter 方法");
        if(WebContextHolder.get()==null){
            logger.info("WebContextHolder 还没有相应的request,放入开始");
            WebContextHolder.set((HttpServletRequest)srequest);
            logger.info("WebContextHolder 还没有相应的request,放入结束");
           
        }else{
            logger.info("WebContextHolder 已经有相应的request,不进行重复放入");
        }
        logger.info(" 后面的filter链 开始");
        chain.doFilter(srequest, response);
        logger.info(" 后面的filter链 结束");
    }
 
    public void destroy() {
        // TODO Auto-generated method stub
       
    }
 
}
 
ThreadLocal 持有类:
package com.hf.servlet.filter;
 
 
import javax.servlet.http.HttpServletRequest;
 
import org.apache.log4j.Logger;
 
public class WebContextHolder {
    private static Logger logger = Logger.getLogger(WebContextHolder.class);
     private static ThreadLocal requestHolder = new ThreadLocal();
     public static void set(HttpServletRequest request){
     logger.info(" 在filter中将request加入当前的ThreadLocal");
     requestHolder.set(request);
 
      }
     public static HttpServletRequest get(){
     logger.info(" 从当前的ThreadLocal中获取当前的request");
     return (HttpServletRequest) requestHolder.get();
     }
    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub
 
    }
 
}
 
使用方式:
可以写在任一地方
HttpServletRequest myRequest=WebContextHolder.get();
        myRequest.setAttribute("test",myRequest.getRemoteAddr());
        myRequest.getRequestDispatcher("/testResult.jsp").forward(myRequest,response);
 
要源代码的可以发邮件给我。
演示代码使用:
点击连接的时候会在servlet中调用HttpServletRequest
HttpServletRequest myRequest=WebContextHolder.get();
myRequest=WebContextHolder.get();
        myRequest.setAttribute("test",myRequest.getRemoteAddr());
设置一个test 参数,请注意myRequest是从WebContextHolder中取到的^_^
然后转向到testResult.jsp,在页面上打印出存入的数据,这时是取的暗含对象request
 
 
Ps :一直测试着没什么问题,但刚刚出现了null异常,说myRequest为null;并不是经常报出,不知道为什么,
将doFilter中的代码改为:
logger.info(" 进入一个WebContextHolderFilter的dofilter 方法");
        if(WebContextHolder.get()==null){
            logger.info("WebContextHolder 还没有相应的request,放入开始");
            WebContextHolder.set((HttpServletRequest)srequest);
            logger.info("WebContextHolder 还没有相应的request,放入结束");
           
        }else{
            logger.info("WebContextHolder 已经有相应的request,不进行重复放入");
        }
        logger.info(" 后面的filter链 开始");
        chain.doFilter(srequest, response);
        logger.info(" 后面的filter链 结束");
        logger.info(" 清空filter中的request 开始");
        WebContextHolder.set(null);
        logger.info(" 清空filter中的request 结束");
到目前为止还没出现问题,不知道为什么,明白的指点一下。
现在只能说慎用了暂时……
 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值