springcloud-Feign 的使用
Feign 的使用
Feign 是对服务端和客户端通用接口的封装,让代码可以复用做到统一管理。简化了调用方的代码
Feign相当于ribbon + Hystrix的封装集成,但是是由额外的性能开销的;
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency>
开启注解
@EnableFeignClients @EnableDiscoveryClient //或者 //开启feign支持,clients指定哪个类开启feign @EnableFeignClients(clients = { StudentService.class,TeacherServiceFeign.class})
客户端接口注解申明
@FeignClient(name = "MICRO-ORDER",path = "/feign" /*fallback = StudentServiceFallback.class,*/ ,fallbackFactory = StudentServiceFallbackFactory.class) public interface StudentService { @GetMapping("/student/getAllStudent") String getAllStudent(); @PostMapping("/student/saveStudent") String saveStudent(@RequestBody Student student); @GetMapping("/student/getStudentById") String getStudentById(@RequestParam("id") Integer id); //验证异常的接口 @GetMapping("/student/errorMessage") String errorMessage(@RequestParam("id") Integer id); }
服务端提供出对应url的Controller即可
FeignClient注解的一些属性
Feign 的服务降级
从上面注解信息可以看到,服务降级方式由两种 fallback 和 fallbackFactory
fallback
如上示例的接口中,fallback 配置可以这么写
@Service public class StudentServiceFallback implements StudentService{ @Override public String getAllStudent() { return "获取所有学生信息失败"; } @Override public String saveStudent(Student student) { return "保存学生信息失败"; } @Override public String getStudentById(Integer id) { return "根据Id获取学生信息失败"; } /* * 这种方式拿不到provider的具体异常信息 * */ @Override public String errorMessage(Integer id) { return "根据Id获取学生信息失败"; } }
这个用法的缺点是无法获取到Exception 信息
fallbackFactory
而fallbackFactory的使用例子如下
@Slf4j @Component public class StudentServiceFallbackFactory implements FallbackFactory<StudentService> { @Override public StudentService create(Throwable throwable) { if(throwable == null) { return null; } final String msg = throwable.getMessage(); log.info("exception:" + msg); return new StudentService() { @Override public String getAllStudent() { log.info("exception=====getAllStudent==========" + msg); return msg; } @Override public String saveStudent(Student student) { log.info("exception=====saveStudent==========" + msg); return msg; } @Override public String getStudentById(Integer id) { log.info("exception=====getStudentById==========" + msg); return msg; } @Override public String errorMessage(Integer id) { log.info("exception=====errorMessage==========" + msg); return msg; } }; } }
其中的参数throwable中的message内容是被组件封装过的,并不是java原生的异常信息
Feign 的异常处理器ErrorDecoder
配合前面服务降级,Feign也有类似springMvc异常处理器,如果定义了,会在fallbackFactory处理之前处理过throwable参数
@Slf4j class FeignErrorDecoder implements ErrorDecoder { @Override public Exception decode(String s, Response response) { RuntimeException runtimeException = null; try { //重新包装 String retMsg = Util.toString(response.body().asReader()); log.info(retMsg); runtimeException = new RuntimeException(retMsg); } catch (IOException e) { e.printStackTrace(); } return runtimeException; } }