java 实现的FeignClient接口地址 not found feign接口调用返回null |
您所在的位置:网站首页 › feign调用返回null › java 实现的FeignClient接口地址 not found feign接口调用返回null |
0. 前言 关于Feign的调用前面自己在学习微服务的时候没有过多留意,后面到了公司真正调用的时候,一堆问题,连都连不通,要么空指针异常,要么获取不到参数,花了大半个下午还没解决,回家后特地自己建了两个微服务进行实验,觉得要好好总结一下知识点,要不然太对不起我下午花的时间了。 1. Feign 的服务降级业务失败后,不能直接报错,而应该返回用户一个友好提示或者默认结果,这个就是失败降级逻辑。 实现方式①方式一:FallbackClass,无法对远程调用的异常做处理 ②方式二:FallbackFactory,可以对远程调用的异常做处理,我们选择这种 Feign 接口@FeignClient(value = "user-service",fallbackFactory = UserFeignServiceFallBackFactory.class) public interface UserFeignService { @GetMapping("all/{ids}") Result getAll(@PathVariable String ids); }实现 FallbackFactory 类public class UserFeignServiceFallBackFactory implements FallbackFactory { @Override public UserFeignService create(Throwable throwable) { return new UserFeignService() { @Override public Result getAll(String ids) { System.out.println(throwable); return null; } }; } }踩坑点:不管服务降不降级,在接口上面都不能加 @RequestMapping(),要不然可能会报错 Error creating bean with name 'requestMappingHandlerMapping' defined in class path resource内部好像是因为在初始化加载bean时,Spring会通过 @Controller 和 @RequesMapping 来判断是否为Controller对象,所以若加了 @RequestMapping 会被Spring误判,导致bean对象创建失败 2. 从Spring获取Feign对象在启动类配置好 @EnableFeignClients() 后,Spring在启动的时候就会自动生成 Feign接口的实例对象 ,正常情况在Spring管理的对象中进行注入调用一般没什么问题,但是我的一些骚操作,引出了一堆问题: 需求:在项目启动的时候就要调Feign进行一些数据的初始化,所以单独写一个类 InitGetData.class 用来初始化,在启动类中调用 @EnableFeignClients("cn.itcast.order") //开启Feign功能 @MapperScan("cn.itcast.order") //扫描包,配置接口实现类 @SpringBootApplication public class OrderApplication { public static void main(String[] args) { SpringApplication.run(OrderApplication.class, args); InitGetData initGetData = new InitGetData(); initGetData.init(); } }在 SpringApplication.run(OrderApplication.class, args) 后面再进行调用,确保Spring服务启动后能注册进 nacos 中来实现Feign连接 我之前 InitGetData.class 写法为: public class InitGetData { @Autowired private UserFeignService userFeignService; public void init() { String ids = "柳岩,文二狗,郑爽爽"; Result result = userFeignService.getAll(ids); List jsObjects = result.getData(); System.out.println(jsObjects); } }当时想的是,UserFeignService的实例对象在Spring初始化的时候就生成了,所以能自动注入进去 然而报错了 Exception in thread "main" java.lang.NullPointerException空指针,因为 InitGetData 实例对象不受Spring管理,而 @Autowired 是在Spring初始化的时候就把所有bean对象生成了并对管理的实例对象进行自动注入,后面不会再监听注入,所以后面调用对象报空指针,因为不受Spring管理,对象没有注入进去 方法1,让Spring来管理该对象,Spring初始化的时候进行注入@Component public class InitGetData { @Autowired private UserFeignService userFeignService; public void init() { String ids = "柳岩,文二狗,郑爽爽"; Result result = userFeignService.getAll(ids); List jsObjects = result.getData(); System.out.println(jsObjects); } }@EnableFeignClients("cn.itcast.order") //开启Feign功能 @MapperScan("cn.itcast.order") //扫描包,配置接口实现类 @SpringBootApplication public class OrderApplication { public static void main(String[] args) { SpringApplication.run(OrderApplication.class, args); // SpringUtils.getBean - 获取Spring容器中的实例对象 InitGetData initGetData = SpringUtils.getBean(InitGetData.class); initGetData.init(); } }拓展:若想声明为 static 类型来进行自动注入,则写法应为 private static UserFeignService userFeignService; @Autowired private void setUserFeignService(UserFeignService userFeignService) { this.userFeignService = userFeignService; }要不然可能会报错,大致原因应该是Spring构造实例对象的时候三级缓存,实例化和属性赋值要分开完成,如果都在实例化这一步进行,会造成bean对象创建失败,具体原因还不是很清楚,因为普通对象之间注入可以正常运行,但是static类型直接注入我报错了 方法2,从Spring容器中拿到实例手动注入public class InitGetData { private static UserFeignService userFeignService; public void init() { String ids = "柳岩,文二狗,郑爽爽"; Result result = getUserFeignService().getAll(ids); List jsObjects = result.getData(); System.out.println(jsObjects); } private static UserFeignService getUserFeignService() { if (userFeignService == null) { synchronized (InitGetData.class) { if (userFeignService == null) { userFeignService = SpringUtils.getBean(UserFeignService.class); } return userFeignService; } } return userFeignService; } }@EnableFeignClients("cn.itcast.order") //开启Feign功能 @MapperScan("cn.itcast.order") //扫描包,配置接口实现类 @SpringBootApplication public class OrderApplication { public static void main(String[] args) { SpringApplication.run(OrderApplication.class, args); InitGetData initGetData = new InitGetData(); initGetData.init(); } }拓展:手动去容器拿实例声明出对象,可以用单例模式-懒汉式(静态内部类) private static class LazyLoadUserFeignService { public final static UserFeignService userFeignService = SpringUtils.getBean(UserFeignService.class); } public static UserFeignService getUserFeignService() { return LazyLoadUserFeignService.userFeignService; }3. 小结想复盘下午遇到的问题,结果牺牲了一晚上下班的时间,写了这么久,但还是值得的,至少没白白浪费时间,又把相关知识梳理了一遍,犯错的根本原因还是把原理忘记了,这以后就是低级错误了
|
今日新闻 |
点击排行 |
|
推荐新闻 |
图片新闻 |
|
专题文章 |
CopyRight 2018-2019 实验室设备网 版权所有 win10的实时保护怎么永久关闭 |