在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的时候报错,所以猜想是接口间传递数据出了问题。但是从早上试到现在,网上找到的方法基本都试过了,还是没能解决。求大佬解答,感激不尽!