求助!Feign调用报错:No qualifying bean of type 'org.

2020-08-19 09:57发布

问题:

在GateWay通过FeignClient调用Auth模块的方法出错。
先上错误,然后是源码,最后是结论:

feign.codec.EncodeException: 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:384) ~[feign-core-10.7.4.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 POST "/usercenter/login/test" [ExceptionHandlingWebHandler]
Stack trace:
		at feign.ReflectiveFeign$BuildEncodedTemplateFromArgs.resolve(ReflectiveFeign.java:384) ~[feign-core-10.7.4.jar:na]
		at feign.ReflectiveFeign$BuildTemplateByResolvingArgs.create(ReflectiveFeign.java:232) ~[feign-core-10.7.4.jar:na]
		at feign.SynchronousMethodHandler.invoke(SynchronousMethodHandler.java:75) ~[feign-core-10.7.4.jar:na]
  • JsonResule返回类与User类
public class JsonResult implements Serializable {
    private final long SERIALIZABLE_ID = 1<<31L;

    private int status;
    private boolean success;
    private String message;
    private Object result;

    private JsonResult(){
        status=200;
        success=true;
        message=null;
        result=null;
    }
     /*------------一些方法------------*/
    /*------------Getter&Setter实现------------*/
}
public class User implements Serializable {
    private final static long SERIALIZABLE_ID=1<<31L;
    private String id;
    private String pwd;
    private String token;
    private String path;
    private String ip;
    /*------Getter&Setter实现-----*/
}
  • AuthApi模块:
@RestController
@RequestMapping("token")
@CrossOrigin("*")
public class AuthApi {
    @Autowired
    AuthController authController;
    /**
     * @decription 验证用户token及资源权限
     * @param user
     * @return JsonResult
     */
    @RequestMapping("/check")
    public JsonResult checkToken(@RequestBody User user){
        return authController.checkToken(user);
    }
}
  • GateWay的AuthFeignApi及配置类:
@Service
@FeignClient(value = "auth",configuration = FeignConfig.class)
public interface AuthFeignApi {
    @RequestMapping(value = "/token/check",method = {RequestMethod.POST})
    JsonResult checkToken(@RequestBody User user);
}
@Configuration
public class FeignConfig {
    @Autowired
    private ObjectFactory<HttpMessageConverters> messageConverters;

    @Bean
    Logger.Level feignLoggerLevel() {
        return Logger.Level.FULL;
    }

    //feign拦截器,设置header信息
    @Bean
    FeignInterceptor feignInterceptor() {
        return new FeignInterceptor();
    }

    @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"));
            mediaTypes.add(MediaType.valueOf(MediaType.APPLICATION_JSON_VALUE + ";charset=UTF-8"));
            setSupportedMediaTypes(mediaTypes);
        }
    }
}
public class FeignInterceptor {

    public void apply(RequestTemplate requestTemplate) {
        requestTemplate.header("Access-Control-Allow-Origin", "*")
                        .header("Content-Type","application/json");
    }
}
  • GateWay的拦截器中调用AuthFeignApi:
@Controller
public class AuthenticationFitler implements GlobalFilter, Ordered {

    @Autowired(required = true)
    AuthFeignApi authFeignApi;
    /**
     * 拦截器,校验
     * @param exchange
     * @param chain
     * @return
     */
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
     //   exchange.getRequest().getHeaders().set("Access-Control-Allow-Origin","*");
        String token = exchange.getRequest().getHeaders().getFirst("token");
         String id = exchange.getRequest().getHeaders().getFirst("id");
        String pwd = exchange.getRequest().getHeaders().getFirst("pwd");
        String path = exchange.getRequest().getPath().toString();

        //是否为白名单
        if(WhiteListFilter.isWhiteUser(id)||WhiteListFilter.isWhiteResources(path))
            return chain.filter(exchange);

        //token校验
        User user = new User();
        user.setToken(token);
        user.setId(id);
        user.setPwd(pwd);
        JsonResult result = authFeignApi.checkToken(user);     //此处
        if(!result.isSuccess()){
            exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
            return exchange.getResponse().setComplete();
        }
        //用户-资源权限校验
        return chain.filter(exchange);
    }

}
  • 结论
    试过去掉checkToken()方法的参数User,也就是无参调用AuthApi,这样可以调用,然后返回JsonResult的时候报错,所以猜想是接口间传递数据出了问题。但是从早上试到现在,网上找到的方法基本都试过了,还是没能解决。
    求大佬解答,感激不尽!

回答1:

手动注入就可以了

@Bean
@ConditionalOnMissingBean
public HttpMessageConverters messageConverters(ObjectProvider<HttpMessageConverter<?>> converters) {
    return new HttpMessageConverters(converters.orderedStream().collect(Collectors.toList()));
}


回答2:


楼主的错误看着像是spring没法找到接口实现导致的,我看你的feign接口上加了@Service,可以去掉试试,@FeignClient一个注解就够了,在入口类上别忘启动@EnableFeignClients