通过redis监听,进行feign调用时报异常代码:
org.springframework.beans.factory.support.ScopeNotActiveException: Error creating bean with name 'scopedTarget.oauth2ClientContext': Scope 'request' is not active for the current thread; consider defining a scoped proxy for this bean if you intend to refer to it from a singleton; nested exception is java.lang.IllegalStateException: 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.
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:383) ~[spring-beans-5.3.22.jar:5.3.22]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) ~[spring-beans-5.3.22.jar:5.3.22]
at org.springframework.aop.target.SimpleBeanTargetSource.getTarget(SimpleBeanTargetSource.java:35) ~[spring-aop-5.3.22.jar:5.3.22]
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:195) ~[spring-aop-5.3.22.jar:5.3.22]
at com.sun.proxy.$Proxy161.getAccessToken(Unknown Source) ~[na:na]
at org.springframework.cloud.commons.security.AccessTokenContextRelay.copyToken(AccessTokenContextRelay.java:52) ~[spring-cloud-commons-3.1.3.jar:3.1.3]
at com.workcell.workdata.common.security.interceptor.WorkdataFeignClientInterceptor.apply(WorkdataFeignClientInterceptor.java:68) ~[workdata-common-security-4.5.0.jar:na]
at feign.SynchronousMethodHandler.targetRequest(SynchronousMethodHandler.java:161) ~[feign-core-11.8.jar:na]
at feign.SynchronousMethodHandler.executeAndDecode(SynchronousMethodHandler.java:110) ~[feign-core-11.8.jar:na]
at feign.SynchronousMethodHandler.invoke(SynchronousMethodHandler.java:89) ~[feign-core-11.8.jar:na]
at com.workcell.workdata.common.sentinel.feign.WorkdataSentinelInvocationHandler.invoke(WorkdataSentinelInvocationHandler.java:99) ~[workdata-common-sentinel-4.5.0.jar:na]
at org.springframework.cloud.openfeign.FeignCachingInvocationHandlerFactory$1.proceed(FeignCachingInvocationHandlerFactory.java:66) ~[spring-cloud-openfeign-core-3.1.3.jar:3.1.3]
at org.springframework.cache.interceptor.CacheInterceptor.lambda$invoke$0(CacheInterceptor.java:54) ~[spring-context-5.3.22.jar:5.3.22]
at org.springframework.cache.interceptor.CacheAspectSupport.execute(CacheAspectSupport.java:351) ~[spring-context-5.3.22.jar:5.3.22]
at org.springframework.cache.interceptor.CacheInterceptor.invoke(CacheInterceptor.java:64) ~[spring-context-5.3.22.jar:5.3.22]
at org.springframework.cloud.openfeign.FeignCachingInvocationHandlerFactory.lambda$create$1(FeignCachingInvocationHandlerFactory.java:53) ~[spring-cloud-openfeign-core-3.1.3.jar:3.1.3]
at com.sun.proxy.$Proxy197.queryInventoryInfo(Unknown Source) ~[na:na]
at com.workcell.workdata.fe.config.RedisKeyExpirationListener.onMessage(RedisKeyExpirationListener.java:97) ~[classes/:na]
at org.springframework.data.redis.listener.RedisMessageListenerContainer.processMessage(RedisMessageListenerContainer.java:845) [spring-data-redis-2.7.2.jar:2.7.2]
at org.springframework.data.redis.listener.RedisMessageListenerContainer.lambda$dispatchMessage$7(RedisMessageListenerContainer.java:993) [spring-data-redis-2.7.2.jar:2.7.2]
at java.lang.Thread.run(Thread.java:748) ~[na:1.8.0_162]
Caused by: java.lang.IllegalStateException: 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.
at org.springframework.web.context.request.RequestContextHolder.currentRequestAttributes(RequestContextHolder.java:131) ~[spring-web-5.3.22.jar:5.3.22]
at org.springframework.web.context.request.AbstractRequestAttributesScope.get(AbstractRequestAttributesScope.java:42) ~[spring-web-5.3.22.jar:5.3.22]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:371) ~[spring-beans-5.3.22.jar:5.3.22]
... 20 common frames omitted
原因:
通过以上报错信息,分析出该错误是因为非web请求方式调用feign失败,因为我们在调用微服务接口时,一般情况下,我们都是在web接口里的具体实现方法通过feign来调用,也就是说,无论怎么样我们的最外层都是有一个web请求来搭建桥梁的,但是本次业务逻辑使用监听的方式,所以导致我们的调用变成非web请求方式。
使用Redis监听时,当前线程中没有HttpServletRequest对象,需要手动创建一个HttpServletRequest对象,并将其设置为当前线程的HttpServletRequest对象。
解决:
调用feign之前添加以下代码
自己手动创建一个HttpServletRequest对象即可
import feign.Request;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
// 获取当前请求的信息
Request.HttpMethod method = Request.HttpMethod.POST;
// 创建HttpServletRequest对象,并设置相关属性
HttpServletRequest request = new HttpServletRequestWrapper(new MockHttpServletRequest(method.name(), ""));
// 将HttpServletRequest对象设置为当前线程的HttpServletRequest对象
RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(request));