java的aop获取request_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增加如下代码:

org.springframework.web.context.request.RequestContextListener

使用方法:

在普通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的方法入参,即可以正确获取参数值。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值