0%

RequestContextHolder类:持有上下文的Request容器

如果想在service层通过request获取请求报文中的信息,可以通过RequestContextHolder得到request对象。

用法:

1
2
3
4
5
6
7
8
//  获取请求对象
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
// 转化为ServletRequestAttributes
ServletRequestAttributes sra = (ServletRequestAttributes) requestAttributes;
// 获取到HttpServletRequest 对象
HttpServletRequest request = sra.getRequest();
// 获取到HttpServletResponse 对象
HttpServletResponse response = sra.getResponse();

request 和 response 如何与RequestContextHolder进行挂钩的?看底层源码

首先分析RequestContextHolder这个类,里面有两个ThreadLocal保存当前线程下的request

1
2
3
4
5
public abstract class RequestContextHolder {
// 得到存储进去的request
private static final ThreadLocal<RequestAttributes> requestAttributesHolder = new NamedThreadLocal("Request attributes");
//可被子线程继承的reques
private static final ThreadLocal<RequestAttributes> inheritableRequestAttributesHolder = new NamedInheritableThreadLocal("Request context");

再看getRequestAttributes() 方法,相当于直接获取ThreadLocal里面的值,这样就保证了每一次获取到的Request是该请求的request.

1
2
3
4
5
6
7
8
@Nullable
public static RequestAttributes getRequestAttributes() {
RequestAttributes attributes = (RequestAttributes)requestAttributesHolder.get();
if (attributes == null) {
attributes = (RequestAttributes)inheritableRequestAttributesHolder.get();
}
return attributes;
}

request和response等是什么时候设置进去的?

springMVC 核心类DispatcherServlet 继承关系:DispatcherServlet -> FrameworkServlet -> HttpServletBean -> HttpServlet

  1. HttpServletBean 进行初始化工作
  2. FrameworkServlet 初始化 WebApplicationContext,并提供service方法预处理请
  3. DispatcherServlet 具体分发处理.

那么就可以在FrameworkServlet查看到该类重写了service(),doGet(),doPost()…等方法,这些实现里面都有一个预处理方法processRequest(request, response);,所以定位到了我们要找的位置

查看processRequest(request, response);的实现,具体可以分为以下几步:

  1. 获取上一个请求的参数
  2. 重新建立新的参数
  3. 设置到XXContextHolder
  4. 父类的service()处理请求
  5. 恢复request(恢复原来的LocaleContext和ServiceRequestAttributes到LocaleContextHolder和RequestContextHolder,避免影响Servlet以外的处理,如Filter
  6. 发布事件(发布ServletRequestHandlerEvent消息,这个请求是否执行成功都会发布消息)
-------------本文结束感谢您的阅读-------------

欢迎关注我的其它发布渠道