解决方法来自于 在非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;
}
这样就完美解决了。