通过ThreadLocal和Filter实现请求上下文【更新】
来源:互联网 发布:linux抓包命令 编辑:程序博客网 时间:2024/06/15 00:26
相信大家可能都看了我的上一篇文章:通过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<LocalRequestContext> contexts = new ThreadLocal<LocalRequestContext>();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<String, Cookie>();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<String, Cookie> 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<String, Cookie> getCookies() {return cookies;}public void setCookies(Map<String, Cookie> 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;// Fieldsprivate Integer id;private String username;private String password;// Property accessorspublic 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<UserVO> v = null; private UserList(){ v = new Vector<UserVO>(); } 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<UserVO> 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;@Overridepublic void destroy() {}@Overridepublic void doFilter(ServletRequest req, ServletResponse res,FilterChain chain) throws IOException, ServletException {LocalRequestContextHolder.setLocalRequestContext(servletContext, (HttpServletRequest)req, (HttpServletResponse)res);chain.doFilter(req, res);}@Overridepublic void init(FilterConfig config) throws ServletException {servletContext = config.getServletContext();}}
在web.xml中添加Filter配置,内容如下:
<!-- 初始化LocalRequestContext当前请求上下文,要放到Struts2的Filter前,否则无法过滤action --><filter> <filter-name>LocalRequestContextFilter</filter-name> <filter-class>edu.filter.LocalRequestContextFilter</filter-class></filter><filter-mapping> <filter-name>LocalRequestContextFilter</filter-name> <url-pattern>/*</url-pattern></filter-mapping>
还有就是,在用户登陆的Action中,在登陆成功之后,添加以下代码:
session.setAttribute("user", uservo);
项目demo: https://github.com/zengyh/SSHWebProject.git
- 通过ThreadLocal和Filter实现请求上下文【更新】
- 通过ThreadLocal和Filter实现请求上下文【旧】
- Filter和ThreadLocal实现事务管理
- 利用ThreadLocal & Filter 实现事务处理
- 利用ThreadLocal实现全局上下文工具类
- 通过Filter和HttpServletResponseWrapper,实现Gzip压缩
- 通过Filter实现二级域名和URLRewrite
- Flask: 程序和请求上下文
- 运用Filter,ThreadLocal和Reflection,实现form到bean的填充
- 分页的一些实现的思想和方法(ThreadLocal+Filter+pager-taglib)
- 通过filter实现servlet和jsp的中文编码问题:
- Flask-应用(程序)上下文和请求上下文
- 应用上下文&请求上下文
- 请求上下文
- 通过Fragment实现简单的上下文菜单
- 配置、error日志和请求上下文
- ThreadLocal应用之一-----利用拦截器或过滤器设置请求上下文
- 通过ThreadLocal和HandlerInterceptor实现java后台业务埋点日志功能
- Tablayout+Viewpager的简单使用
- hive UDAF函数
- Pyhon中遇到的问题1
- spring-boot&mvn&terminal
- jvm工作原理
- 通过ThreadLocal和Filter实现请求上下文【更新】
- 敌兵布阵 HDU
- Git的一些基本的命令行
- wangluofugai
- hvie UDF函数
- 【PB】寻找隐藏控件
- 理解HTML语义化
- c# 自定义配置文件
- Docker的“下一跳”在哪里?