问题描述:
通过网关拦截器统一认证人员信息,如:获取可以访问的url进行校验,需要使用feign调用资源服务获取资源。但是网关使用feign报错:HttpMessageConverters注入失败
环境:
springCloud(Hoxton.RELEASE),jdk(1.8),springBoot(2.2.1)
场景:
在网关拦截器中使用feign调用其他服务:
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
/*****/
Object obj= XXXFeign.getXXX(XXXDTO).getData();
}
错误信息:
No qualifying bean of type 'org.springframework.boot.autoconfigure.http.HttpMessageConverters' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
at feign.ReflectiveFeign$BuildEncodedTemplateFromArgs.resolve(ReflectiveFeign.java:376) ~[feign-core-10.4.0.jar!/:na]
Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException:
Error has been observed at the following site(s):
|_ checkpoint ⇢ org.springframework.cloud.gateway.filter.WeightCalculatorWebFilter [DefaultWebFilterChain]
|_ checkpoint ⇢ HTTP GET "/api/admin/baseUsers/info" [ExceptionHandlingWebHandler]
Stack trace:.
at feign.ReflectiveFeign$BuildEncodedTemplateFromArgs.resolve(ReflectiveFeign.java:376) ~[feign-core-10.4.0.jar!/:na]
at feign.ReflectiveFeign$BuildTemplateByResolvingArgs.create(ReflectiveFeign.java:224) ~[feign-core-10.4.0.jar!/:na]
at feign.SynchronousMethodHandler.invoke(SynchronousMethodHandler.java:75) ~[feign-core-10.4.0.jar!/:na]
at feign.ReflectiveFeign$FeignInvocationHandler.invoke(ReflectiveFeign.java:103) ~[feign-core-10.4.0.jar!/:na]
at com.sun.proxy.$Proxy90.getUserButtons(Unknown Source) ~[na:na]
at com.xzb.springcloud.gateway.filter.RoleAuthFilter.filter(RoleAuthFilter.java:105) ~[classes!/:0.0.1-SNAPSHOT]
at org.springframework.cloud.gateway.handler.FilteringWebHandler$GatewayFilterAdapter.filter(FilteringWebHandler.java:138) ~[spring-cloud-gateway-core-2.2.0.RELEASE.jar!/:2.2.0.RELEASE]
at org.springframework.cloud.gateway.filter.OrderedGatewayFilter.filter(OrderedGatewayFilter.java:44) ~[spring-cloud-gateway-core-2.2.0.RELEASE.jar!/:2.2.0.RELEASE]
at org.springframework.cloud.gateway.handler.FilteringWebHandler$DefaultGatewayFilterChain.lambda$filter$0(FilteringWebHandler.java:118) ~[spring-cloud-gateway-core-2.2.0.RELEASE.jar!/:2.2.0.RELEASE]
at org.springframework.cloud.gateway.handler.FilteringWebHandler$DefaultGatewayFilterChain$$Lambda$788/242982330.get(Unknown Source) ~[na:na]
at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:44) [reactor-core-3.3.0.RELEASE.jar!/:3.3.0.RELEASE]
at reactor.core.publisher.Mono.subscribe(Mono.java:4087) [reactor-core-3.3.0.RELEASE.jar!/:3.3.0.RELEASE]
分析:
通过日志可见HttpMessageConverters注入失败。
查看源码:
在HTTP协议不是很规范的情况下,需要配置Decoder
解决:
**1.**添加配置类(此代码,百度一搜一大堆,直接去粘贴就可以了):
@SpringBootConfiguration
public class FeignConfig {
@Bean
public Decoder feignDecoder() {
return new ResponseEntityDecoder(new SpringDecoder(feignHttpMessageConverter()));
}
public ObjectFactory<HttpMessageConverters> feignHttpMessageConverter() {
final HttpMessageConverters httpMessageConverters = new HttpMessageConverters(new GateWayMappingJackson2HttpMessageConverter());
return new ObjectFactory<HttpMessageConverters>() {
@Override
public HttpMessageConverters getObject() throws BeansException {
return httpMessageConverters;
}
};
}
public class GateWayMappingJackson2HttpMessageConverter extends MappingJackson2HttpMessageConverter {
GateWayMappingJackson2HttpMessageConverter() {
List<MediaType> mediaTypes = new ArrayList<>();
mediaTypes.add(MediaType.valueOf(MediaType.TEXT_HTML_VALUE + ";charset=UTF-8"));
setSupportedMediaTypes(mediaTypes);
}
}
}
可能是因为cloud版本的问题问题并没有解决,网上有说Greenwich.SR3下运行正常。
扩展:知道了原因后分析:HttpMessageConvertersAutoConfiguration这个类有个自动注入的条件的:@Conditional(NotReactiveWebApplicationCondition.class)
意思是非响应式服务的web才可以注入。
响应式服务相关知识自行百度
参考:https://blog.csdn.net/varyall/article/details/104243016(转发)
**2.**继续解决问题,既然没有初始化注入,那就手动初始化注入一下子,代码如下(添加配置):
@Configuration
public class HttpMsgConverConfig {
@Bean
KeyResolver userKeyResolver() {
return exchange -> Mono.just(Objects.requireNonNull(exchange.getRequest().getRemoteAddress()).getAddress().getHostAddress());
}
@Bean
@ConditionalOnMissingBean
public HttpMessageConverters messageConverters(ObjectProvider<HttpMessageConverter<?>> converters) {
return new HttpMessageConverters(converters.orderedStream().collect(Collectors.toList()));
}
}
问题解决。