springcloud feign 子线程内携带token消费服务

子线程内通过feignClient调用服务并携带token

所需解决问题:
1、前端发过来请求,后台requestAttributes仅在当前线程可见;
2、请求结束后,数据销毁!
3、requestAttributes未共享到子线程
介绍:
InheritableThreadLocal数据可在父线程及子线程中共享!

方案一:

private static final ThreadLocal<RequestAttributes> requestAttributesHolder =
			new NamedThreadLocal<>("Request attributes");

private static final ThreadLocal<RequestAttributes> inheritableRequestAttributesHolder =
			new NamedInheritableThreadLocal<>("Request context");

InheritableThreadLocal 中数据在子线程中可见
所有可以将参数 boolean inheritable 赋为true!
注意: 如果使用全局线程池,将任务丢到线程池中,那么此方法将失效。
因为任务丢到线程池后,当前请求的线程不会等待任务执行完毕。请求会退出结束(通过RequestListener可以看到,请求destroy掉了),所以你获取不到header了!

 /**
 * Bind the given RequestAttributes to the current thread.
 * @param attributes the RequestAttributes to expose,
 * or {@code null} to reset the thread-bound context
 * @param inheritable whether to expose the RequestAttributes as inheritable
 * for child threads (using an {@link InheritableThreadLocal})
 */
public static void setRequestAttributes(@Nullable RequestAttributes attributes, boolean inheritable) {
	if (attributes == null) {
		resetRequestAttributes();
	}
	else {
		if (inheritable) {
			inheritableRequestAttributesHolder.set(attributes);
			requestAttributesHolder.remove();
		}
		else {
			requestAttributesHolder.set(attributes);
			inheritableRequestAttributesHolder.remove();
		}
	}
}

方案二:

使用threadLocal,将token存在threadLocal中。

封装token获取,释放操作,方便使用者,仅编写业务逻辑!

public abstract class FeignConsumerWithTokenRunnable implements Runnable {
	private final static Logger LOGGER = Logger.getLogger(FeignConsumerWithTokenRunnable.class.getName());
	
    private static final ThreadLocal<String> tokenThreadLocal = new ThreadLocal<>();

    public abstract void feignConsumerWithToeknTask();

    public abstract String getToken();

    @Override
    public void run(){
        try {
            tokenThreadLocal.set(getToken());
            feignConsumerWithToeknTask();
        }catch(Exception e) {
           	//Todo 打印日志
        }finally {
            tokenThreadLocal.remove();
        }
    }

}
 public void getDataAsync(@RequestHeader("Authorization") String authToken, Long id) {
        taskExecutor.execute(new FeignConsumerWithTokenRunnable() {
            @Override
            public void feignConsumerWithToeknTask() {
            	//业务逻辑
                downloadService.downloadAsyn(id);
            }

            @Override
            public String getToken() {
                return token;
            }
        });
    }

添加配置类,继承RequestInterceptor接口,实现apply方法,从threadLocal中获取token。

@Configuration
public class FeignClientConfig implements RequestInterceptor {

	private final static Logger LOGGER = Logger.getLogger(FeignClientConfig.class.getName());

    @Override
    public void apply(RequestTemplate requestTemplate) {
        String token = "";
        try {
            RequestAttributes requestAttributes = RequestContextHolder.currentRequestAttributes();
            if (requestAttributes != null) {
                HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest();
                token = request.getHeader("Authorization");
            }
        }catch (Exception e) {
            token = ReportResource.threadLocal.get();
            LOGGER.warning("Get token from requestAttributes failed , successed from threadLocal");
        }
        if(!StringUtils.isBlank(token))
            requestTemplate.header("Authorization", token);
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值