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注解的一些属性
属性名 | 默认值 | 作用 | 备注 |
---|---|---|---|
value | 空字符串 | 调用服务名称,和name属性相同 | |
serviceId | 空字符串 | 服务id,作用和name属性相同 | 已过期 |
name | 空字符串 | 调用服务名称,和value属性相同 | |
url | 空字符串 | 全路径地址或hostname,http或https可选 | |
decode404 | false | 配置响应状态码为404时是否应该抛出FeignExceptions | |
configuration | {} | 自定义当前feign client的一些配置 | 参考FeignClientsConfiguration |
fallback | void.class | 熔断机制,调用失败时,走的一些回退方法,可以用来抛出异常或给出默认返回数据。 | 底层依赖hystrix,启动类要加上@EnableHystrix |
fallbackFactory | 工厂类,用于生成fallback类示例,通过这个属性我们可以实现每个接口通用的容错逻辑,减少重复的代码 | ||
path | 空字符串 | 自动给所有方法的requestMapping前加上前缀,类似与controller类上的requestMapping | |
primary | true |
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;
}
}