知名网站建设制作,阳江招聘网最新招聘2023,微信小程序管理平台入口,企业网站策划书1000字在线程池中#xff0c;子线程调用其他服务#xff0c;请求头丢失#xff0c;token为空的情况
看了很多篇文章的处理方法和在自己亲测的情况下做出说明#xff1a;
第一种#xff1a; 这种方式只支持在主线程情况下#xff0c;能够处理#xff0c;在多线程情况下#…在线程池中子线程调用其他服务请求头丢失token为空的情况
看了很多篇文章的处理方法和在自己亲测的情况下做出说明
第一种 这种方式只支持在主线程情况下能够处理在多线程情况下一旦主线程结束这里还是会为空
第二种
//请求属性可继承线程共享
RequestContextHolder.setRequestAttributes(RequestContextHolder.getRequestAttributes(),true);这种经测试后发现主线程直接启动子线程且执行完自己逻辑后便结束不需理会子线程结果的请求偶尔成功 偶尔失败
也就是当父线程比子线程执行完慢时请求属性还在子线程请求成功当快时请求属性随着父线程结束而销毁子线程的请求属性变为null请求失败。
第三种
采用的处理方式为ThreadLocal
新建一个ThreadLocal 工具类在多线程请求前获取到需要的属性值或者设置所有的属性值放入工具类MAP种进行存储在子线程调用服务时通过监听处将需要的值取出就可以解决了。实际如下
public class ThreadLocalUtil {//使用InheritableThreadLocal使得共享变量可被子线程继承private static final InheritableThreadLocalMapString,String headerMap new InheritableThreadLocalMapString, String(){Overrideprotected MapString, String initialValue() {return new HashMap();}};public static MapString,String get(){return headerMap.get();}public static String get(String key) {return headerMap.get().get(key);}public static void set(String key, String value){headerMap.get().put(key,value);}
}
在线程执行前加 1 EnumerationString headerNames servletRequest.getHeaderNames();while (headerNames.hasMoreElements()){String name headerNames.nextElement();if (Objects.equals(name,feignheader)){ThreadLocalUtil.set(name,servletRequest.getHeader(name));}}或者直接获取token在需要的地方再进行赋值。 2
RequestAttributes requestAttributes RequestContextHolder.getRequestAttributes();
ServletRequestAttributes srat (ServletRequestAttributes) requestAttributes;
HttpServletRequest request srat.getRequest();
ThreadLocalUtil.set(token, request.getHeader(authorization));修改监听处获取请求头信息赋值
1
Slf4j
Configuration
public class FeignConfig implements RequestInterceptor {Overridepublic void apply(RequestTemplate requestTemplate) {
// ServletRequestAttributes attributes (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
// //当主线程的请求执行完毕后Servlet会被销毁因此在这里需要做判空
// if (attributes ! null) {
// HttpServletRequest request attributes.getRequest();
//
// EnumerationString headerNames request.getHeaderNames();
//
// while (headerNames.hasMoreElements()) {
// String name headerNames.nextElement();
// //不能把所有消息头都传递下去否则会引起其他异常header的name都是小写
// if (name.equals(feignheader)) {
// requestTemplate.header(name,request.getHeader(name));
// }
// }
// }//读取设置的header信息传递到下一个服务MapString, String headerMap ThreadLocalUtil.get();for (String key : headerMap.keySet()) {log.info(--从ThreadLocal获取消息头传递到下一个服务key-[{}],value-[{}],key,headerMap.get(key));requestTemplate.header(key,headerMap.get(key));}}
}2
这里之所以直接拿token是因为后面传递获取token未获取到的问题如果有其它信息丢失可用上面1 的方法会更全面一点
Slf4j
Configuration
public class FeignConfig implements RequestInterceptor {Overridepublic void apply(RequestTemplate requestTemplate) {ServletRequestAttributes attributes (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();String token null;//当主线程的请求执行完毕后Servlet会被销毁因此在这里需要做判空if (attributes ! null) {ServletRequestAttributes srat (ServletRequestAttributes) requestAttributes;HttpServletRequest request srat.getRequest();token request.getHeader(authorization);}token StringUtils.isNotBlank(token) ? token : ThreadLocalUtil.get(token);//将token传递出去requestTemplate.header(authorization, token);}
}