最近项目中用到JUC的Executor进行异步大数据量处理,场景是:分页执行数据查询以及下载。但是数据查询过程中需要通过SpringCloud Feign调用分页获取数据。获取数据的逻辑里包含了一块需要通过header里的自定义参数进行数据权限判断。因此需要进行自定义header在多线程场景下透传到服务提供方。
代码示例:
// 服务A代码块
@Autowired
private Executor taskExecutor;
taskExecutor.execute(() -> {
//Feign调用获取数据
PageInfo<ExportDTO> exportDTOList = ooFeign.getList();
});
// 服务B代码块
@ApiOperation("列表分页查询导出")
@RequestMapping(method = RequestMethod.POST, path = "/getList")
PageInfo<ExportDTO> getList(@RequestBody RequestDTO dto){
ServletRequestAttributes attrs = (ServletRequestAttributes) org.springframework.web.context.request.RequestContextHolder
.currentRequestAttributes();
HttpServletRequest request = attrs.getRequest();
String customCode = request.getHeader("custom-code");
// dao查询数据条件会使用到customCode
}
但是上述调用是由于在服务A内部启动一个异步线程发起的Feign远程调用服务B。服务B通过Spring MVC的RequestContextHolder 获取不到对应的header自定义参数。此时就要对Feign调用的header拦截处理。
代码示例:
// 异步线程增加设置ThreadLocal本地变量
RequestContextHolder.put(RequestContextHolder.CUSTOM_CODE,customCode);
// 拦截器配置类
public class RequestHeaderInterceptor extends BaseRequestInterceptor {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
public RequestHeaderInterceptor(FeignClientEncodingProperties properties) {
super(properties);
}
@Override
public void apply(RequestTemplate requestTemplate) {
// RequestContextHolder 是自定义的TheadLocal包装类,本地变量进行上线文传递
String customeCode = RequestContextHolder.getCustomCode();
requestTemplate.header(RequestContextHolder.CUSTOM_CODE, customeCode);
}
}
上面配置增加完后,自定义的header参数就可以通过异步线程发起Feign调用透传。
大致为 客户端请求->服务A->服务A获取请求header的自定义customCode->设置保存到服务A新启的异步线程中的本地变量->异步线程发起Feign调用服务B->服务A通过拦截器处理RestTemplate传递customCode ->服务B通过HttpServletRequest获取header里的参数。
-------------欢迎各位留言交流,如有不正确的地方,请予以指正。【Q:981233589】