SpringCloudAlibaba中定时任务和异步程序中调用Feign的问题

解决方法来自于  在非web请求中使用Feign完成微服务调用(定时任务,过期策略等)_牛哥哥的博客-CSDN博客

异常信息:

        No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request.

问题描述:

        写了一个批量导入发送模板的功能,因为导入的数据可能有点多,使用了@Async异步来进行处理,模板是在weixin项目中,导入是在mall项目中,就使用了Feign来进行调用,但是在实际处理过程中会出现上面的异常信息,就是说,当使用异步的时候,里面携带的Request参数不能传递给Feign中,所以会报这个异常信息。定时任务是因为是非Web请求,本来就不携带Request参数,也不能调用Feign。

解决方法:

        定义一个类来实现RequestAttributes

public class NonWebRequestAttributes implements RequestAttributes {

    public NonWebRequestAttributes(){

    }
    @Override
    public Object getAttribute(String name, int scope){return null;}

    @Override
    public void setAttribute(String name, Object value, int scope) {

    }
    @Override
    public void removeAttribute(String name, int scope){}
    @Override
    public String[] getAttributeNames(int scope){return new String[0];}

    @Override
    public void registerDestructionCallback(String name, Runnable callback, int scope) {

    }

    @Override
    public Object resolveReference(String key) {
        return null;
    }

    @Override
    public String getSessionId() {
        return null;
    }

    @Override
    public Object getSessionMutex() {
        return null;
    }
}

然后注入进RequestAttributes的拦截器中

@Component
@Slf4j
public class FeignConfig implements RequestInterceptor {
    public FeignConfig() {
    }
    @Bean
    public Retryer feignRetryer() {
        return  new Retryer.Default(100,1000,5);
    }
    @Bean
    public RequestContextListener requestContextListenerBean() {
        return new RequestContextListener();
    }
    @Override
    public void apply(RequestTemplate requestTemplate) {
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        if (Objects.nonNull(requestAttributes)){
            RequestContextHolder.setRequestAttributes(requestAttributes,true);
            try {
                ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();
                HttpServletRequest request = attributes.getRequest();
                requestTemplate.header(HttpHeaders.AUTHORIZATION, request.getHeader(HttpHeaders.AUTHORIZATION));
            }catch (Exception e){
                log.info("定时任务介入,授权异常");
            }

        }else {
            RequestContextHolder.setRequestAttributes(new NonWebRequestAttributes(), Boolean.TRUE);
            HttpServletRequest httpRequest = this.getHttpServletRequestSafely();
            if (null != httpRequest && null != httpRequest.getAttribute("X-Request-No")) {
                requestTemplate.header("X-Request-No", httpRequest.getAttribute("X-Request-No").toString());
            }
        }

    }

    public HttpServletRequest getHttpServletRequestSafely() {
        try {
            RequestAttributes requestAttributesSafely = this.getRequestAttributesSafely();
            return requestAttributesSafely instanceof NonWebRequestAttributes ? null : ((ServletRequestAttributes)requestAttributesSafely).getRequest();
        } catch (Exception var2) {
            return null;
        }
    }

    public RequestAttributes getRequestAttributesSafely() {
        RequestAttributes requestAttributes = null;
        try {
            requestAttributes = RequestContextHolder.currentRequestAttributes();
        } catch (IllegalStateException var3) {
            requestAttributes = new NonWebRequestAttributes();
        }

        return requestAttributes;
    }

这样就完美解决了。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值