通过ThreadLocal和Filter实现请求上下文【更新】

相信大家可能都看了我的上一篇文章:通过ThreadLocal和Filter实现请求上下文【旧】

但是大家有没有发现上一篇文章的RequestContext.Java的实现有点混乱,不是很清晰,于是就重新修改了实现代码,有了该篇文章。

 

场景1:使用Spring的AOP面向切面编程,很多人都是为了给某个模块动态地添加功能。肯定会新增个做切面(Aspect)的类,这个类是个普通的Spring bean,这个Aspect怎么获取request、session对象呢?

 

场景2:在Service中,怎么获取当前登录用户信息?

           很多人都会想到,在用户登陆的时候,将用户信息存到session中。Action层将session中存的用户信息取出,再作为方法参数传到service层。但是这样做的话,代码的维护量会增加!!

 

场景3:在Service中要用到request或session对象,那么我们要怎么获取呢?

            相信很多人都会直接将request、session对象作为方法的参数,传递到Service中,但是这么做的话,先不说代码简洁问题,也加大了代码的复杂程度!

 

相信大家都知道ThreadLocal类,它是在当前线程(Thread.currentThread())的ThreadLocalMap对象中添加值,key为ThreadLocal对象,也就是说ThreadLocal类用来提供线程内部的局部变量。我们都知道Http请求就是一个线程,只要我们在这个线程中,添加了我们想要的request、session对象,那么响应服务器请求的Action、Service、Dao等这些层面的代码不就都可以通过当前线程(Thread.currentThread())取出request、session对象了!但是我们怎么在请求到Action等Control控制器之前,添加这些信息呢?很容易我们想到了Filter过滤器,因为Http请求会调用Filter的doFilter进行处理,是在同一个线程中,可以在Filter中用ThreadLocal来实现!

 

接下来,看demo:

 

获取当前请求上下文的工具类LocalRequestContextHolder.java:

package edu.threadlocal;

import java.util.HashMap;
import javax.servlet.ServletContext;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import edu.vo.UserVO;

/**
 * Title: LocalRequestContextHolder.java
 * Description: 初始化和获取LocalRequestContext(当前请求上下文)的工具类
 * @author yh.zeng
 * @date 2017-6-21
 */
public class LocalRequestContextHolder {

	private final static ThreadLocal contexts = new ThreadLocal();
	
	private LocalRequestContextHolder(){}
	
	/**
	 * 初始化当前请求的上下文
	 * @param ctx
	 * @param req
	 * @param res
	 */
	public static void setLocalRequestContext(ServletContext servletContext, HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) {
		LocalRequestContext rc = new LocalRequestContext();
		rc.servletContext = servletContext;
		rc.request = httpServletRequest;
		rc.response = httpServletResponse;
		rc.session = httpServletRequest.getSession();
		rc.cookies = new HashMap();
		Cookie[] cookies = httpServletRequest.getCookies();
		if(cookies != null){
			for(Cookie ck : cookies) {
				rc.cookies.put(ck.getName(), ck);
			}
		}
		//当前用户信息
		Object userObj = httpServletRequest.getSession().getAttribute("user");
		if(userObj != null){
			rc.currentUser = (UserVO)userObj;
		}
		contexts.set(rc);
	}
	
	/**
	 * 获取当前请求的上下文
	 * @return
	 */
	public static LocalRequestContext getLocalRequestContext(){
		return contexts.get();
	}
	
    /**
     * 清除当前线程对请求上下文对象的引用(即让GC回收当前请求上下文对象)
     */
	public static void destoryLocalRequestContext() {
		contexts.remove();
	}

	
	
}

 

当前请求上下文LocalRequestContext.java:

package edu.threadlocal;

import java.util.Map;
import javax.servlet.ServletContext;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import edu.vo.UserVO;

/**
 * Title: LocalRequestContext.java
 * Description: 当前请求上下文对象 (存放了HttpSession、HttpServletRequest等对象)
 * @author yh.zeng
 * @date 2017-6-25
 */
public class LocalRequestContext {
	
	public ServletContext servletContext;
	public HttpSession session;
	public HttpServletRequest request;
	public HttpServletResponse response;
	public Map cookies;
	public UserVO currentUser;  //当前登陆用户
	
	public ServletContext getServletContext() {
		return servletContext;
	}

	public void setServletContext(ServletContext servletContext) {
		this.servletContext = servletContext;
	}

	public HttpSession getSession() {
		return session;
	}

	public void setSession(HttpSession session) {
		this.session = session;
	}

	public HttpServletRequest getRequest() {
		return request;
	}

	public void setRequest(HttpServletRequest request) {
		this.request = request;
	}

	public HttpServletResponse getResponse() {
		return response;
	}

	public void setResponse(HttpServletResponse response) {
		this.response = response;
	}

	public Map getCookies() {
		return cookies;
	}

	public void setCookies(Map cookies) {
		this.cookies = cookies;
	}

	public UserVO getCurrentUser() {
		return currentUser;
	}

	public void setCurrentUser(UserVO currentUser) {
		this.currentUser = currentUser;
	} 

}

 


用户信息UserVO.java:

package edu.vo;

import javax.servlet.http.HttpSessionBindingEvent;
import javax.servlet.http.HttpSessionBindingListener;

import edu.action.user.UserList;

/**
 * 
 * @author yh.zeng
 * 文件描述: 1)往Session中存放Users对象,则自动往UserList用户列表中添加该用户
 *          2)Session中移除Users对象,则自动从UserList用户列表中移除该用户
 */
public class UserVO implements java.io.Serializable,  HttpSessionBindingListener  {
	
	private static final long serialVersionUID = 7132790140796457462L;
	
	// Fields
	private Integer id;
	private String username;
	private String password;

	// Property accessors

	public Integer getId() {
		return this.id;
	}

	public void setId(Integer id) {
		this.id = id;
	}

	public String getUsername() {
		return this.username;
	}

	public void setUsername(String username) {
		this.username = username;
	}

	public String getPassword() {
		return this.password;
	}

	public void setPassword(String password) {
		this.password = password;
	}
	
    @Override
    public void valueBound(HttpSessionBindingEvent httpSessionBindingEvent) {
         UserList.getInstance().addUser(this);
    }

    @Override
    public void valueUnbound(HttpSessionBindingEvent httpSessionBindingEvent) {
         UserList.getInstance().removeUser(this);
    }
    

}


 

在线用户列表UserList.java:

package edu.action.user;

import java.util.Enumeration;
import java.util.Vector;
import edu.vo.UserVO;

/**
 * 文件名称: UserList.java
 * 编写人: yh.zeng
 * 编写时间: 17-1-5 下午7:48
 * 文件描述: 已登录的用户列表(在线用户列表)
 */
public class UserList
{
    private static UserList userList = new UserList();

    private Vector  v = null;


    private UserList(){
        v = new Vector();
    }


    public static UserList getInstance(){
        return userList;
    }


    public void addUser(UserVO user){
        if(user != null && !v.contains(user)){
            v.add(user);
        }
    }

    public void removeUser(UserVO user){
        if(user != null){
            v.remove(user);
        }
    }

    public Enumeration  getUserList(){
        return v.elements();
    }

    public int getUserCount(){
        return v.size();
    }


}

 

 

初始化当前请求上下文的过滤器LocalRequestContextFilter.java:

package edu.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;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import edu.threadlocal.LocalRequestContextHolder;

/**
 * Title: LocalRequestContextFilter.java
 * Description: 初始化当前请求上下文的过滤器
 * @author yh.zeng
 * @date 2017-6-22
 */
public class LocalRequestContextFilter implements Filter{

	private ServletContext servletContext;
	
	@Override
	public void destroy() {
	}

	@Override
	public void doFilter(ServletRequest req, ServletResponse res,
			FilterChain chain) throws IOException, ServletException {
		LocalRequestContextHolder.setLocalRequestContext(servletContext, (HttpServletRequest)req, (HttpServletResponse)res);
		chain.doFilter(req, res);
	}

	@Override
	public void init(FilterConfig config) throws ServletException {
		servletContext = config.getServletContext();
	}

}



 

在web.xml中添加Filter配置,内容如下:

	
	
	    LocalRequestContextFilter
	    edu.filter.LocalRequestContextFilter
		
	
	    LocalRequestContextFilter
        /*
		


 


还有就是,在用户登陆的Action中,在登陆成功之后,添加以下代码:

session.setAttribute("user", uservo);  


 项目demo: https://github.com/zengyh/SSHWebProject.git

 

 

你可能感兴趣的:(Java,Java,Web)