AOP 获取 RequestContextHolder

转载 2017年09月14日 13:53:44

转载: http://blog.csdn.net/lexang1/article/details/52619215

在使用spring时,经常需要在普通类中获取session,request等对像.
比如一些AOP拦截器类,在有使用struts2时,因为struts2有一个接口使用org.apache.struts2.ServletActionContext即可很方便的取到session对像.
用法:

[java] view plain copy
  1. //获取请求对像  
  2.     public static HttpServletRequest getRequest() {  
  3.         return  ServletActionContext.getRequest();  
  4.     }  
  5.     //获取输出对象  
  6.     public static HttpServletResponse getResponse(){  
  7.         return ServletActionContext.getResponse();  
  8.   
  9.     }  



但在单独使用spring时如何在普通类中获取session,reuqest呢?
首先要在web.xml增加如下代码:


[html] view plain copy
  1. <listener>  
  2.         <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>  
  3.  </listener>  

使用方法:

  在普通bean中

[java] view plain copy
  1. @Autowired    
  2. private HttpSession session;    
  3.     
  4. @Autowired    
  5. private HttpServletRequest request;    

在普通类中


[java] view plain copy
  1.     public static HttpServletRequest getRequest(){  
  2.         HttpServletRequest req = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();  
  3.         return req;  
  4.     }  
  5.   
  6.     public static HttpServletResponse getResponse(){  
  7.         HttpServletResponse resp = ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getResponse();  
  8.         return resp;  
  9.     }  

你必须要有一个request的引用,否则是取不到的。request可以通过控制器传入,有了request自然就可以取到session了,或者可以通过spring的WebUtils取Session数据,如下:
拦截器举例:
[java] view plain copy
  1. public boolean preHandle(HttpServletRequest request,  
  2. HttpServletResponse response, Object handler) throws  
  3. Exception {  
  4. String context = (String) WebUtils.getSessionAttribute(request,  
  5. "context_key");  
  6. return context != null ;  
  7. }  

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

[java] view plain copy
  1. protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {  
  2.         HttpServletRequest processedRequest = request;  
  3.         ......  
  4.                 processedRequest = checkMultipart(request);  
  5.                 multipartRequestParsed = processedRequest != request;  
  6.         ......  
  7.                 // Actually invoke the handler.  
  8.                 mv = ha.handle(processedRequest, response, mappedHandler.getHandler());  
  9.         ......  
  10.     }  
  11.   
  12.     protected HttpServletRequest checkMultipart(HttpServletRequest request) throws MultipartException {  
  13.         if (this.multipartResolver != null && this.multipartResolver.isMultipart(request)) {  
  14.             if (request instanceof MultipartHttpServletRequest) {  
  15.                 logger.debug("Request is already a MultipartHttpServletRequest - if not in a forward, " +  
  16.                         "this typically results from an additional MultipartFilter in web.xml");  
  17.             }  
  18.             else {  
  19.                 return this.multipartResolver.resolveMultipart(request);  
  20.             }  
  21.         }  
  22.         // If not returned before: return original request.  
  23.         return request;  
  24.     }  

那么,RequestContextHolder中的request又是从哪来的呢? 
继续翻看DispatcherServlet的源码,从其父类FrameworkServlet中找到的processRequest()以相关方法源码:

[java] view plain copy
  1. protected final void processRequest(HttpServletRequest request, HttpServletResponse response)  
  2.             throws ServletException, IOException {  
  3.         ......  
  4.   
  5.         RequestAttributes previousAttributes = RequestContextHolder.getRequestAttributes();  
  6.         ServletRequestAttributes requestAttributes = buildRequestAttributes(request, response, previousAttributes);  
  7.   
  8.         WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);  
  9.         asyncManager.registerCallableInterceptor(FrameworkServlet.class.getName(), new RequestBindingInterceptor());  
  10.   
  11.         initContextHolders(request, localeContext, requestAttributes);  
  12.   
  13.         try {  
  14.             doService(request, response);  
  15.         }  
  16.         ......  
  17.     }  
  18.   
  19.   
  20.     protected ServletRequestAttributes buildRequestAttributes(  
  21.             HttpServletRequest request, HttpServletResponse response, RequestAttributes previousAttributes) {  
  22.   
  23.         if (previousAttributes == null || previousAttributes instanceof ServletRequestAttributes) {  
  24.             return new ServletRequestAttributes(request);  
  25.         }  
  26.         else {  
  27.             return null;  // preserve the pre-bound RequestAttributes instance  
  28.         }  
  29.     }  
  30.   
  31.   
  32.     private void initContextHolders(  
  33.             HttpServletRequest request, LocaleContext localeContext, RequestAttributes requestAttributes) {  
  34.   
  35.         if (localeContext != null) {  
  36.             LocaleContextHolder.setLocaleContext(localeContext, this.threadContextInheritable);  
  37.         }  
  38.         if (requestAttributes != null) {  
  39.             RequestContextHolder.setRequestAttributes(requestAttributes, this.threadContextInheritable);  
  40.         }  
  41.         if (logger.isTraceEnabled()) {  
  42.             logger.trace("Bound request context to thread: " + request);  
  43.         }  
  44.     }  

从这里可以看到,initContextHolder()方法中完成了RequestContextHolder的requestAttributes设置,而doService()在这之后调用,DispatcherServlet中的processRequest()方法即在doService()之中,所以从RequestContextHolder中获取到的就是原来的RequestFacade对象,而不是经过spring mvc处理之后的MultipartHttpServletRequest对象,其后果就是,从RequestContextHolder获取request后,无法直接通过getParameter()获取参数值。

        最便捷的解决办法: 
直接将HttpServletRequest作为spring mvc的方法入参,即可以正确获取参数值。


相关文章推荐

springmvc中aop对controller切面编程

概述: 最近在开发一个基础应用服务系统,利用加密的token标识来校验访问者的身份。几乎每一个接口都需要校验token。故采用aop面向切面编程,一次性对所有接口进行身份认证; 遇见的问题...

Spring MVC 注解下Controller 的AOP

spring mvc采用@Controller注解时,对Controller进行Aop拦截不起作用,原因是该注解的Controller已被spring容器内部代理了.需要对org.springfram...

反射..获取spring aop代理类 的目标类方法

背景: 在项目开发过程中(注:项目用的SpringMvc),有这么一种需求,系统所有的表格查询都有统一的查询接口,通过通用的Controller类组装查询条件以及调用查询接口返回查询数据。 ...

Spring AOP demo 和获取被CGLIB代理的对象

本文分为两部分:1)给出Spring AOP的一个例子(会使用CGLIB代理);2)给出获取被CGLIB代理的原始对象。 1、Spring AOP Demo 这部分参考了博文(http://www...

Spring中自定义注解与AOP中获取注解

原文地址:http://blog.csdn.net/qpfjalzm123/article/details/45061701 一、自定义注解(annotation) 自定义注解的作用:在反射中获...

AOP日志组件 多次获取post参数

AOP日志组件 多次获取post参数 需求:新增接口日志组件。通过拦截器对接口URL进行拦截处理,然后将接口post请求的参数与结果,写入日志表。 问题:POST方法的参数是存储在request.ge...

轻便的AOP编程框架-PostSharp (参数获取)

http://www.cnblogs.com/techmango/archive/2011/05/23/postsharp_light_weight_aop_framwork.html ...

Spring中的AOP——在Advice方法中获取目标方法的参数

Spring中的AOP(五)——在Advice方法中获取目标方法的参数             摘要 本文介绍使用Spring AOP编程中,在增强处理方法中获取目标方法的...

利用AOP获取自定义标签的参数以及方法的参数

在放假之前就一直在解决这个问题,当时采用的方法的是利用拦截器对自定义的标签进行拦截。采用的是下边的方法。 Method method = invocation.getMethod(); MetaCa...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)