ThreadLocal - 使用spring-boot作为REST API的上下文信息 [英] ThreadLocal - using as context information for REST API with spring-boot

查看:1189
本文介绍了ThreadLocal - 使用spring-boot作为REST API的上下文信息的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一些 spring-boot 应用程序(它公开了rest api)。提到的REST API
spring-security 保护。一切都很好,但是现在我需要为服务请求设置上下文
。设置上下文是关于选择数据源取决于用户上下文。关键是RoutingDataSource需要使用这个上下文。 (由于其他原因,必须在验证请求后直接设置此上下文,我还有其他使用RoutingDataSource的线程,但没有请求调用(没有用户上下文))。

I have some spring-boot application (it exposes rest api). The mentioned REST API is secured by spring-security. Everything is fine, however now I need to set context for servicing request. Setting context is about choosing datasource in depends on user context. The key is that RoutingDataSource need to use this context. (This context must be set directly after authenticating request due to other causes, I have also other thread which use RoutingDataSource, but no invoked by request (no user context)).

这些我可以做的事情,但是我的疑虑是关注上下文的线程安全性并清除它。我试图在文档中找到答案,但我没有成功。

These things I can do, however my doubts are concerned on thread-safety of context and clearing it. I tried to find answer in docs, but I didn't managed to.

public class CustomContextHolder {

   private static final ThreadLocal<DatabaseType> contextHolder = 
            new ThreadLocal<DatabaseType>();

   public static void setContext(DatabaseType databaseType) {
      contextHolder.set(databaseType);
   }

   public static CustomerType getContext() {
      return (CustomerType) contextHolder.get();
   }

   public static void clearContext() {
      contextHolder.remove();
   }
}

设置上下文:

@Component
class AuthorizedRequestFilter extends OncePerRequestFilter {
    @Override
    protected void doFilterInternal(HttpServletRequest request, 
                                    HttpServletResponse response, 
                                    FilterChain filterChain) throws ServletException, IOException {

        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        if (authentication != null && authentication.isAuthenticated()) {
            // here we set context
        }

        filterChain.doFilter(request, response);
    }
}

我可以做到。但是,因为 spring-boot 是多线程的,我使用 ThreadLocal 来保存上下文我害怕线程 - 这种配置的安全性。

I can do it. However, because spring-boot is multi-thread and I am using ThreadLocal for hold context I am afraid of thread-safety of this configuration.

当我设置这个上下文?
仅在成功授权请求后过滤。所以问题是:

When I set this context ? In filter, only after successful authorization of request. So the questions are:


  1. 它是否是线程安全的?这意味着:我可以假设执行过滤器的相同的线程(因此在其自己的本地上下文中也是这个线程集上下文)也执行整个请求(例如,从dao调用方法) ,发送响应,执行控制器的主体)?

  1. Is it thread-safe? It means: Can I assume that the same thread that executes filter (hence also this thread set context in its own local context) also executes entire request (e.g. calling methods from dao, sending response, executing body of controller) ?

如果是情况1.我可以假设一个线程从头到尾处理请求(开始包括过滤器)在安全请求之后)然后当我应该调用 clearContext()

If in case 1. I can assume that one thread works with request from begin to end (begin includes filter after secured request) then when I should call clearContext() ?


推荐答案

除非您故意启动子线程,否则它是单线程的。在这种情况下,
使用 InheritableThreadLocal 存储信息。

it's single threaded unless you purposely initiate child threads. in such case use InheritableThreadLocal to store information.

这篇关于ThreadLocal - 使用spring-boot作为REST API的上下文信息的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆