spring,struts2在普通类中获取session和request,及RequestContextHolder使用误区
2016-09-22 10:12
399 查看
在使用spring时,经常需要在普通类中获取session,request等对像.
比如一些AOP拦截器类,在有使用struts2时,因为struts2有一个接口使用org.apache.struts2.ServletActionContext即可很方便的取到session对像.
用法:
但在单独使用spring时如何在普通类中获取session,reuqest呢?
首先要在web.xml增加如下代码:
使用方法:
在普通bean中
在普通类中
你必须要有一个request的引用,否则是取不到的。request可以通过控制器传入,有了request自然就可以取到session了,或者可以通过spring的WebUtils取Session数据,如下:
拦截器举例:
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
那么,RequestContextHolder中的request又是从哪来的呢?
继续翻看DispatcherServlet的源码,从其父类FrameworkServlet中找到的processRequest()以相关方法源码:
从这里可以看到,initContextHolder()方法中完成了RequestContextHolder的requestAttributes设置,而doService()在这之后调用,DispatcherServlet中的processRequest()方法即在doService()之中,所以从RequestContextHolder中获取到的就是原来的RequestFacade对象,而不是经过spring mvc处理之后的MultipartHttpServletRequest对象,其后果就是,从RequestContextHolder获取request后,无法直接通过getParameter()获取参数值。
最便捷的解决办法:
直接将HttpServletRequest作为spring mvc的方法入参,即可以正确获取参数值。
比如一些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的方法入参,即可以正确获取参数值。
相关文章推荐
- 关于ActionContext.getContext()取得的值是什么,和struts2如何获取request,session,appliaction作用域
- struts2 获取"作用域"对象:Request Session Application 与 Aware 接口的使用
- Spring MVC的RequestContextHolder使用误区
- spring中普通类如何获取session,request等对象
- [JShop]Spring MVC的RequestContextHolder使用误区
- spring提供的RequestContextHolder在非contrller层获取request和response对象
- Struts2 设置session及获取spring aplicationicontext
- Struts2中文件上传和多文件上传以及获取HttpServletRequest / HttpSession / ServletContext / HttpServletRespons
- Spring MVC的RequestContextHolder使用误区
- Struts2使用7 -- 如何获取request、session?
- spring 普通类获取四大作用域request、applicationContext、session、page
- Struts2中解耦合通过actionContext对象获取到aplication,session,request,paramter等对象
- <精华帖>在Struts2中使用ValueStack、ActionContext、ServletContext、request、session等 .
- spring的普通类中获取session和request对像
- Spring MVC的RequestContextHolder使用及误区
- Spring MVC的RequestContextHolder使用误区
- spring在普通类中获取session和request,springsession
- struts2系列十之4中获取使用request,session,application的方法和页面显示的三种方法【后期ognl算第四种】
- spring-mvc使用request的方法,获取session方法
- 使用SpringContextHolder获取bean实例