Spring Boot 2.2 애플리케이션이 있습니다. 다음과 같은 서비스를 만들었습니다.
@Async
@PreAuthorize("hasAnyRole('ROLE_PBX')")
@PlanAuthorization(allowedPlans = {PlanType.BUSINESS, PlanType.ENTERPRISE})
public Future<AuditCdr> saveCDR(Cdr3CXDto cdrRecord) {
log.debug("Current tenant {}", TenantContext.getCurrentTenantId());
return new AsyncResult<AuditCdr>(auditCdrRepository.save(cdr3CXMapper.cdr3CXDtoToAuditCdr(cdrRecord)));
}
이것은 내 @Async 구성입니다.
@Configuration
@EnableAsync
public class AsyncConfiguration implements AsyncConfigurer {
@Override
public Executor getAsyncExecutor() {
SecurityContextHolder.setStrategyName(SecurityContextHolder.MODE_INHERITABLETHREADLOCAL);
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(2);
executor.setMaxPoolSize(10);
executor.setQueueCapacity(500);
executor.setThreadNamePrefix("threadAsync");
executor.setWaitForTasksToCompleteOnShutdown(true);
executor.initialize();
return executor;
}
}
사용 SecurityContextHolder.MODE_INHERITABLETHREADLOCAL
하면 Security 컨텍스트가 @Async 메서드로 전달되는 것을 볼 수 있습니다. 다중 테넌트 애플리케이션에서 ThreadLocal을 사용하여 테넌트의 ID를 설정합니다.
public class TenantContext {
public final static String TENANT_DEFAULT = "empty";
private static final ThreadLocal<String> code = new ThreadLocal<>();
public static void setCurrentTenantId(String code) {
if (code != null)
TenantContext.code.set(code);
}
public static String getCurrentTenantId() {
String tenantId = code.get();
if (StringUtils.isNotBlank(tenantId)) {
return tenantId;
}
return TENANT_DEFAULT;
}
public static void clear() {
code.remove();
}
}
ThreadLocal은 스레드와 관련이 있기 때문에 @Async 메서드에서는 사용할 수 없습니다. 또한 내 사용자 지정 @PlanAuthorization
aop는 테넌트 계획의 확인을 수행하기 위해 필요합니다. 내 애플리케이션의 @Async 메서드에서 TenantContext를 설정하는 깔끔한 방법이 있습니까?