当前位置: 代码迷 >> 综合 >> spring中ThreadLocal?的使用
  详细解决方案

spring中ThreadLocal?的使用

热度:52   发布时间:2023-09-05 17:40:55.0

 

解决问题:

在service层,使用RequestContextHolder获取controller层请求(HttpServletRequest)响应信息(HttpServletResponse)

RequestContextHolder使用:

RequestContextHolder含义持有上下文的Request容器

HttpServletRequest request= ((ServletRequestAttributes) (RequestContextHolder.getRequestAttributes())).getRequest();
HttpServletResponse response= ((ServletRequestAttributes) (RequestContextHolder.getRequestAttributes())).getResponse();

疑问:

request和response怎么和当前请求挂钩?查看RequestContextHolder类,ThreadLocal保存当前线程Request

private static final ThreadLocal<RequestAttributes> requestAttributesHolder =new NamedThreadLocal<>("Request attributes");private static final ThreadLocal<RequestAttributes> inheritableRequestAttributesHolder =new NamedInheritableThreadLocal<>("Request context");

所有对象是一个servlet,servlet的实现是DispatcherServlet,DispatcherServlet父类也就是它的爸爸FrameworkServlet

查看FrameworkServlet

运行servlet,一般是运行service方法,在FrameworkServlet查看service方法,可以看到service方法会执行processRequest请求

@Override
protected void service(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {HttpMethod httpMethod = HttpMethod.resolve(request.getMethod());if (httpMethod == HttpMethod.PATCH || httpMethod == null) {processRequest(request, response);}else {super.service(request, response);}
}

而对象赋值,就是processRequest请求,

protected final void processRequest(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {long startTime = System.currentTimeMillis();Throwable failureCause = null;LocaleContext previousLocaleContext = LocaleContextHolder.getLocaleContext();LocaleContext localeContext = buildLocaleContext(request);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);}catch (ServletException | IOException ex) {failureCause = ex;throw ex;}catch (Throwable ex) {failureCause = ex;throw new NestedServletException("Request processing failed", ex);}finally {resetContextHolders(request, previousLocaleContext, previousAttributes);if (requestAttributes != null) {requestAttributes.requestCompleted();}logResult(request, response, failureCause, asyncManager);publishRequestHandledEvent(request, response, startTime, failureCause);}
}

initContextHolders方法初始化

private void initContextHolders(HttpServletRequest request,@Nullable LocaleContext localeContext, @Nullable RequestAttributes requestAttributes) {if (localeContext != null) {LocaleContextHolder.setLocaleContext(localeContext, this.threadContextInheritable);}if (requestAttributes != null) {RequestContextHolder.setRequestAttributes(requestAttributes, this.threadContextInheritable);}
}

可以看出ThreadLocal 的Request 请求在setLocaleContext进行赋值

  相关解决方案