最近项目中用到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】