java 实现的FeignClient接口地址 not found feign接口调用返回null

您所在的位置:网站首页 feign调用返回null java 实现的FeignClient接口地址 not found feign接口调用返回null

java 实现的FeignClient接口地址 not found feign接口调用返回null

2024-07-12 11:14:51| 来源: 网络整理| 查看: 265

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. 小结

想复盘下午遇到的问题,结果牺牲了一晚上下班的时间,写了这么久,但还是值得的,至少没白白浪费时间,又把相关知识梳理了一遍,犯错的根本原因还是把原理忘记了,这以后就是低级错误了



【本文地址】

公司简介

联系我们

今日新闻


点击排行

实验室常用的仪器、试剂和
说到实验室常用到的东西,主要就分为仪器、试剂和耗
不用再找了,全球10大实验
01、赛默飞世尔科技(热电)Thermo Fisher Scientif
三代水柜的量产巅峰T-72坦
作者:寞寒最近,西边闹腾挺大,本来小寞以为忙完这
通风柜跟实验室通风系统有
说到通风柜跟实验室通风,不少人都纠结二者到底是不
集消毒杀菌、烘干收纳为一
厨房是家里细菌较多的地方,潮湿的环境、没有完全密
实验室设备之全钢实验台如
全钢实验台是实验室家具中较为重要的家具之一,很多

推荐新闻


图片新闻

实验室药品柜的特性有哪些
实验室药品柜是实验室家具的重要组成部分之一,主要
小学科学实验中有哪些教学
计算机 计算器 一般 打孔器 打气筒 仪器车 显微镜
实验室各种仪器原理动图讲
1.紫外分光光谱UV分析原理:吸收紫外光能量,引起分
高中化学常见仪器及实验装
1、可加热仪器:2、计量仪器:(1)仪器A的名称:量
微生物操作主要设备和器具
今天盘点一下微生物操作主要设备和器具,别嫌我啰嗦
浅谈通风柜使用基本常识
 众所周知,通风柜功能中最主要的就是排气功能。在

专题文章

    CopyRight 2018-2019 实验室设备网 版权所有 win10的实时保护怎么永久关闭