AOP 获取 RequestContextHolder
转载: http://blog.csdn.net/lexang1/article/details/52619215
在使用spring时,经常需要在普通类中获取session,request等对像.
比如一些AOP拦截器类,在有使用struts2时,因为struts2有一个接口使用org.apache.struts2.ServletActionContext即可很方便的取到session对像.
用法:
- //获取请求对像
- public static HttpServletRequest getRequest() {
- return ServletActionContext.getRequest();
- }
- //获取输出对象
- public static HttpServletResponse getResponse(){
- return ServletActionContext.getResponse();
- }
但在单独使用spring时如何在普通类中获取session,reuqest呢?
首先要在web.xml增加如下代码:
- <listener>
- <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
- </listener>
使用方法:
在普通bean中
- @Autowired
- private HttpSession session;
- @Autowired
- private HttpServletRequest request;
在普通类中
- public static HttpServletRequest getRequest(){
- HttpServletRequest req = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
- return req;
- }
- public static HttpServletResponse getResponse(){
- HttpServletResponse resp = ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getResponse();
- return resp;
- }
你必须要有一个request的引用,否则是取不到的。request可以通过控制器传入,有了request自然就可以取到session了,或者可以通过spring的WebUtils取Session数据,如下:
拦截器举例:
- public boolean preHandle(HttpServletRequest request,
- HttpServletResponse response, Object handler) throws
- Exception {
- String context = (String) WebUtils.getSessionAttribute(request,
- "context_key");
- return context != null ;
- }
RequestContextHolder使用误区
在spring mvc中,为了随时都能取到当前请求的request对象,可以通过RequestContextHolder的静态方法getRequestAttributes()获取Request相关的变量,如request, response等。
在大部分的情况下,它都能很好地工作,但在商品管理编辑中,新增商品时,却出现了意外的问题:通过RequestHolder.getRequest().getParameter()得不到参数值,通过debug发现,通过spring mvc的method注入的request对象实际为MultipartHttpServletRequest,而通过RequestHolder.getRequest()获取到的request对象却是RequestFacfade的实例。
原来在商品新增时,由于使用了文件上传,form表单的enctype类型为”multipart/form-data”,spring mvc对文件上传的处理类实际却为spring-mvc.xml文件中配置的CommonsMultipartResolver, 该类先判断当前请求是否为multipart类型,如果是的话,将request对象转为MultipartHttpServletRequet,相关的源码见DisptcherServlet
- protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
- HttpServletRequest processedRequest = request;
- ......
- processedRequest = checkMultipart(request);
- multipartRequestParsed = processedRequest != request;
- ......
- // Actually invoke the handler.
- mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
- ......
- }
- protected HttpServletRequest checkMultipart(HttpServletRequest request) throws MultipartException {
- if (this.multipartResolver != null && this.multipartResolver.isMultipart(request)) {
- if (request instanceof MultipartHttpServletRequest) {
- logger.debug("Request is already a MultipartHttpServletRequest - if not in a forward, " +
- "this typically results from an additional MultipartFilter in web.xml");
- }
- else {
- return this.multipartResolver.resolveMultipart(request);
- }
- }
- // If not returned before: return original request.
- return request;
- }
那么,RequestContextHolder中的request又是从哪来的呢?
继续翻看DispatcherServlet的源码,从其父类FrameworkServlet中找到的processRequest()以相关方法源码:
- protected final void processRequest(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException {
- ......
- RequestAttributes previousAttributes = RequestContextHolder.getRequestAttributes();
- ServletRequestAttributes requestAttributes = buildRequestAttributes(request, response, previousAttributes);
- WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
- asyncManager.registerCallableInterceptor(FrameworkServlet.class.getName(), new RequestBindingInterceptor());
- initContextHolders(request, localeContext, requestAttributes);
- try {
- doService(request, response);
- }
- ......
- }
- protected ServletRequestAttributes buildRequestAttributes(
- HttpServletRequest request, HttpServletResponse response, RequestAttributes previousAttributes) {
- if (previousAttributes == null || previousAttributes instanceof ServletRequestAttributes) {
- return new ServletRequestAttributes(request);
- }
- else {
- return null; // preserve the pre-bound RequestAttributes instance
- }
- }
- private void initContextHolders(
- HttpServletRequest request, LocaleContext localeContext, RequestAttributes requestAttributes) {
- if (localeContext != null) {
- LocaleContextHolder.setLocaleContext(localeContext, this.threadContextInheritable);
- }
- if (requestAttributes != null) {
- RequestContextHolder.setRequestAttributes(requestAttributes, this.threadContextInheritable);
- }
- if (logger.isTraceEnabled()) {
- logger.trace("Bound request context to thread: " + request);
- }
- }
从这里可以看到,initContextHolder()方法中完成了RequestContextHolder的requestAttributes设置,而doService()在这之后调用,DispatcherServlet中的processRequest()方法即在doService()之中,所以从RequestContextHolder中获取到的就是原来的RequestFacade对象,而不是经过spring mvc处理之后的MultipartHttpServletRequest对象,其后果就是,从RequestContextHolder获取request后,无法直接通过getParameter()获取参数值。
最便捷的解决办法:
直接将HttpServletRequest作为spring mvc的方法入参,即可以正确获取参数值。
AOP 获取 RequestContextHolder的更多相关文章
- AOP获取方法注解实现动态切换数据源
AOP获取方法注解实现动态切换数据源(以下方式尚未经过测试,仅提供思路) ------ 自定义一个用于切换数据源的注解: package com.xxx.annotation; import org. ...
- Spring AOP获取不了增强类(额外方法)或无法通过getBean()获取对象
Spring AOP获取不了增强类(额外方法)和无法通过getBean()获取对象 今天在学习AOP发现一个小问题 Spring AOP获取不了额外方法,左思右想发现是接口上出了问题 先上代码 获取不 ...
- spring aop 获取request、response对象
在网上看到有不少人说如下方式获取: 1.在web.xml中添加监听 <listener> <listener-class> org. ...
- Spring-boot 配置Aop获取controller里的request中的参数以及其返回值
首先在你的Maven的pom文件里加入aop的依赖: <dependency> <groupId>org.springframework.boot</groupId> ...
- spring aop获取目标对象的方法对象(包括方法上的注解)
这两天在学习权限控制模块.以前看过传智播客黎活明老师的巴巴运动网视频教程,里面就讲到权限控制的解决方案,当时也只是看看视频,没有动手实践,虽说看过几遍,可是对于系统中的权限控制还是很迷茫,所以借着这次 ...
- Spring AOP获取方法的参数名称和参数值
aop配置: <aop:aspectj-autoproxy expose-proxy="true" /> @Before(value = "execution ...
- Spring AOP获取拦截方法的参数名称跟参数值
注意:这种方式需要JDK1.8版本支持 开始:http://www.cnblogs.com/wing7319/p/9592184.html 1.aop配置: <aop:aspectj-autop ...
- 2018-02-11 发布 spring 自定义注解(annotation)与 aop获取注解
知识点: Java自定义注解.spring aop @aspect的使用 首先我们先介绍Java自定义注解. 在开发过程中,我们实现接口的时候,会出现@Override,有时还会提示写@Suppres ...
- 【转】spring 自定义注解(annotation)与 aop获取注解
首先我们先介绍Java自定义注解. 在开发过程中,我们实现接口的时候,会出现@Override,有时还会提示写@SuppressWarnings.其实这个就是Java特有的特性,注解. 注解就是某种注 ...
随机推荐
- Hive 实现 wordcount
创建表: create table hive_wordcount(context string); load data local inpath '/home/hadoop/files/hellowo ...
- CF908D New Year and Arbitrary Arrangement 期望、DP
题目传送门 题意:给出正整数$pa,pb,k$,最开始你有一个空串,每一次你有$\frac{pa}{pa + pb}$的概率向串最后放一个$a$,有$\frac{pb}{pa + pb}$的概率向串最 ...
- 在属性property做一些简单的验证
开发C#的程序,写到属性property时,我们可以在Set方法中做一些简单的规则验证: 如下面,Insus.NET写一个Age属性,只允许用户输入10以内的数字: class AA { privat ...
- ( 转)Ubuntu下创建、重命名、删除文件及文件夹,强制清空回收站方法
Ubuntu下创建.重命名.删除文件及文件夹,强制清空回收站方法 mkdir 目录名 ——创建一个目录 rmdir 空目录名 ——删除一个空目录 rm 文件名 文件名 ——删除一个文件或多个文件 rm ...
- ORA-00020:maximum number of processes (150) exceeded
异常的含义 超过最大的进程数 我们使用下面的语句可以查看与进程(process)的相关参数: 如上所示,这里的最大进程数是150. 问题可能存在的原因 1.应用程序在使用数据库连接池时,使用完成后没有 ...
- C# SignalR 即时通信
MSDN教程:https://docs.microsoft.com/en-us/aspnet/signalr/ 个人博客:http://www.cnblogs.com/zhili/p/SignalRQ ...
- Nginx 反向代理 上传大文件报 413
Nginx 中上传文件限制是 2m,上传太大就报错,配置一下 client_max_body_size 1024m; 就可以上传 1G 大小文件 添加在 location 中,如果是反向代理就添加在反 ...
- ASP.NET MVC5+EF6+EasyUI 后台管理系统(63)-WebApi与Unity注入
系列目录 前言: 有时候我们系统需要开放数据给手机App端或其他移动设备,不得不说Asp.net WebApi是目前首选 本节记录Asp.net MVC WebApi怎么利用Unity注入.系列开头已 ...
- Centos下堡垒机Jumpserver V3.0环境部署完整记录(1)-安装篇
由于来源身份不明.越权操作.密码泄露.数据被窃.违规操作等因素都可能会使运营的业务系统面临严重威胁,一旦发生事故,如果不能快速定位事故原因,运维人员往往就会背黑锅.几种常见的运维人员背黑锅场景:1)由 ...
- 如何新增一个ssh-key文件
前言 由于在公司有一个sshkey 在用,用于绑定公司的git code 仓库.那么在家要连上git hub 仓库,就也需要一个 ssh key .为了避免公司信息外露,所以还是新增一个ssh key ...