首先还是把demo跑起来:

  • 添加依赖
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
  • 添加注解
@SpringBootApplication
@EnableFeignClients//添加这个注解
public class FeignBootApplication {public static void main(String[] args) {SpringApplication.run(FeignBootApplication.class, args);}
}
  • 在接口上添加@FeignClient注解
//这是feign接口
@FeignClient(name="ServerDemoFeignClient", url="http://localhost:8080")
public interface ServerDemoFeignClient {@GetMapping("/server/demo/hello/{username}")public String hello(@PathVariable("username")String username,@RequestParam("msg") String msg);
}
//这是服务端接口
@RestController
@RequestMapping("/server/demo")
public class ServerDemoController {@GetMapping("/hello/{username}")public String hello(@PathVariable("username")String username, @RequestParam("msg")String msg){return "hello:" + username+",say:"+ msg;}
}

需要注意的是:

1.在feign接口里面用的注解已经全都替换成了Web的注解,而不再是feign原生的注解,@SpringQueryMap用来代替@QueryMap完成url传参。

2.@FeignClient必须得有个名字,可以用name、value来指定。这个名字是用来创建负载均衡的时候用的。

3.url和name都可以用占位符的方式来使用,比如:@FeignClient(name = “f e i g n . n a m e " , u r l = " {feign.name}", url = "feign.name",url="{feign.url}”)

4.feign接口对应的bean在spring容器中的名字是这个类的全路径名,也可以设置qualifier来设置bean的别名。

feign接口的继承性

因为feign接口使用的注解和web使用的是同样的注解,这样更方便抽出父接口,让服务端controller和feign接口同时继承父接口即可,比如:
先抽一个父接口出来:

@RequestMapping("/server/demo2")
public interface DemoApi {@GetMapping("/hello/{username}")public String hello(@PathVariable("username") String username, @RequestParam("msg") String msg);
}

父接口中定义了完整的请求路径和请求参数。
feign客户端:

@FeignClient(name="ServerDemoFeignClient2",url="http://localhost:8080")
public interface ServerDemoFeignClient2 extends DemoApi {
}

客户端需要继承这个接口,但是里面的代码却很干净,而且不再需要去指定url信息。

服务提供者server端:

@RestController
public class ServerDemoController2 implements DemoApi {public String hello(String username, String msg){return "hello:" + username+",say:"+ msg;}
}

server端也不再需要指定url路径信息和web相关的注解。

自定义feign的配置

@EnableFeignClients(defaultConfiguration=FooConfiguration.class)或者@FeignClient(configuration = FooConfiguration.class)都可以使用configuration覆盖默认的一些配置,比如自定义encoder、decoder、contract等等,defaultConfiguration是对所有的feign客户端都起作用,而configuration只对当前的feign客户端起作用,可以参考:FeignClientsConfiguration。
spring-cloud-starter-openfeign默认已经配置了:

Decoder: ResponseEntityDecoder
Encoder: SpringEncoder
Logger: Slf4jLogger
Contract: SpringMvcContract
Feign.Builder: HystrixFeign.Builder
Client feignClient: 如果有Ribbon那么就是LoadBalancerFeignClient,否则如果有FeignBlockingLoadBalancerClient那么就是用这个,否则使用默认的feign client。

这也是为什么我们可以直接在接口参数和返回值上使用对象而不用手动去定义encoder和decoder,并且为啥可以直接使用web里面的注解而不是使用feign原生的注解,都是这些默认的配置起了作用。

spring-cloud-starter-openfeign默认没有配置哪些bean呢:

Logger.Level
Retryer
ErrorDecoder
Request.Options
Collection<RequestInterceptor>
SetterFactory
QueryMapEncoder

但是,如果你配置了,框架也会帮你加载使用。
比如,我们要自定义一个拦截器:

@Configuration
public class FooConfiguration {@Beanpublic BasicAuthRequestInterceptor basicAuthRequestInterceptor() {return new BasicAuthRequestInterceptor("user", "password");}
}

当然也可以在配置文件配置:


feign:client:config:feignName:connectTimeout: 5000readTimeout: 5000loggerLevel: fullerrorDecoder: com.example.SimpleErrorDecoderretryer: com.example.SimpleRetryerrequestInterceptors:- com.example.FooRequestInterceptor- com.example.BarRequestInterceptordecode404: falseencoder: com.example.SimpleEncoderdecoder: com.example.SimpleDecodercontract: com.example.SimpleContract

feignName的规则是conetxtId>value>name>serviceId。

如果是配置全局默认的配置,只需要指定名字是default就可以,比如:

feign:client:config:default:connectTimeout: 5000readTimeout: 5000loggerLevel: basic

注意:

(1)如果同时在配置文件 和 @Bean都配置了,那么配置文件的优先级更高,当然可以设置这个feign.client.default-to-properties属性为false,那么@Bean的优先级会更高。

(2)configuration 的类上不需要添加@Configuration注解,否则这里面的配置的encoder、decoder等bean就变成默认配置的bean了。

feign客户端的ApplicationContext

每一个feign接口客户端在Spring容器里面都对应了一个单独的ApplicationContext,这些配置都是配置在这个context里面。因此如果想给同样的feign客户端设置不同的配置,可以给他们设置不同的context id,这样,这些配置就在不同的ApplicationContext中,不会造成冲突,比如:

@FeignClient(contextId = "fooClient", name = "stores", configuration = FooConfiguration.class)
public interface FooClient {
}
@FeignClient(contextId = "barClient", name = "stores", configuration = BarConfiguration.class)
public interface BarClient {
}

name一样,因此可以访问同样的服务器,但是contextId不一样,因此里面的配置可以不一样,因为是不同的ApplicationContext。Spring里面的ApplicationContext是存在父子结构的继承关系的,如果不想继承父Context,可以:

@Configuration
public class CustomConfiguration{@Beanpublic FeignClientConfigurer feignClientConfigurer() {return new FeignClientConfigurer() {@Overridepublic boolean inheritParentConfiguration() {return false;}};}
}

手动创建feign客户端

如果自定义配置还是无法满足你的需求,那就只能手动创建feign的客户端了,比如:

@Import(FeignClientsConfiguration.class)
class FooController {private FooClient fooClient;private FooClient adminClient;@Autowiredpublic FooController(Decoder decoder, Encoder encoder, Client client, Contract contract) {this.fooClient = Feign.builder().client(client).encoder(encoder).decoder(decoder).contract(contract).requestInterceptor(new BasicAuthRequestInterceptor("user", "user")).target(FooClient.class, "https://PROD-SVC");this.adminClient = Feign.builder().client(client).encoder(encoder).decoder(decoder).contract(contract).requestInterceptor(new BasicAuthRequestInterceptor("admin", "admin")).target(FooClient.class, "https://PROD-SVC");}
}

注意:@Import(FeignClientsConfiguration.class)是导入默认的配置,然后再做各种自定义的操作。

feign与hystrix

feign默认依赖了hystrix,但是默认并没有开启hystrix,除非设置feign.hystrix.enabled=true手动开启,然后hystrix就会把每个方法都包装到断路器里面,此时feign的客户端方法是可以返回HystrixCommand的,这样就可以做异步或者响应式编程。

fallback降级

@FeignClient()里面可以设置fallback或者fallbackFactory,fallbackFactory可以捕获异常,但是并不是原始的异常,而是feign经过包装以后的异常,可以定义ErrorDecoder完成自定义异常的处理。

看一个fallback的demo:

@FeignClient(name="ServerHystrixFeignClient",url="http://localhost:8080",path = "/server/hystrix",// 这里可以配置fallback或者fallbackFactory// fallback的优先级更高fallback = ServerHystrixFeignClientFallback.class,fallbackFactory = ServerHystrixFeignClientFallbackFactory.class)
public interface ServerHystrixFeignClient {@GetMapping("/hello")public String hello();
}
//必须要注入到spring容器,
//此时容器中会有两个类型是ServerHystrixFeignClient的bean
//一个feign客户端,一个是fallabck的bean
@Service
public class ServerHystrixFeignClientFallback implements ServerHystrixFeignClient{@Overridepublic String hello() {return "ServerHystrixFeignClientFallback fallback";}
}
//必须要注入到spring容器
@Service
public class ServerHystrixFeignClientFallbackFactory implements FallbackFactory<ServerHystrixFeignClient> {@Overridepublic ServerHystrixFeignClient create(Throwable cause) {//注意这里的异常类型:feign.FeignException$InternalServerErrorSystem.out.println(cause.getClass());return new ServerHystrixFeignClient(){@Overridepublic String hello() {return "ServerHystrixFeignClientFallbackFactory fallback";}};}
}

注意:这里的ServerHystrixFeignClient不能再去继承接口,因为接口上有@RequestMapping,而fallback最终也需要继承接口,因此,会把fallback的方法当成feign客户端的方法,这样就冲突了。但是,此时在spring容器里面仍然有两个相同类型的feign客户端,一个是feign客户端本身,另一个是fallback的bean,所以框架默认给feign客户端上添加了@Primary注解,因此feign客户端才可以正常注入,因为它的优先级比fallabck的优先级要高。如果想关闭primary,可以设置primary = false:

@FeignClient(name = "hello", primary = false)
public interface HelloClient {}

单独关闭某个客户端的断路器

如果开启了hystrix,默认是所有的feign客户端都开启了断路器,但是如果某个客户端不想开启,可以单独给它配置一个Feign.Builder(开启了hystrix后默认的Builder是HystrixFeign.Builder),并且设置scope为prototype,,举个例子:

@FeignClient(name="ServerHystrixPrototypeClient",url="http://localhost:8080",path = "/server/hystrix",// 自定义配置configuration = PrototypeConfiguration.class,fallback = ServerHystrixPrototypeClientFallback.class)
public interface ServerHystrixPrototypeClient {@GetMapping("/prototype")public String prototype();
}
//在这个配置里面设置Feign.Builder的scope
public class PrototypeConfiguration {@Bean@Scope("prototype")//注意这里的类型public Feign.Builder feignBuilder() {return Feign.builder();}
}

单独关闭某个client方法上的断路器

只要让feign抛出HystrixBadRequestException,那么本次请求就不会触发fallback和断路器,我们可以自定义feign的ErrorDecoder,在里面根据要访问的路径决定是否抛出HystrixBadRequestException:

public static class MyErrorDecoder implements ErrorDecoder {@Overridepublic Exception decode(String methodKey, Response response) {try{String res = Util.toString(response.body().asReader(Util.UTF_8));JsonElement je = new JsonParser().parse(res);JsonObject jo = je.getAsJsonObject();String path = jo.get("path").getAsString();System.out.println("path="+path);if(path.equals("/server/hystrix/error/hello")){return new HystrixBadRequestException(res);}else{return FeignException.errorStatus(methodKey, response);}}catch(Exception e){e.printStackTrace();return e ;}}
}

并发策略:

如果开启了hystrix(默认是关闭的feign.hystrix.enabled=false),同时还想在拦截器里面使用ThreadLocal,要么就禁用hystrix,要么把并发策略设置为SEMAPHORE,要么需要自定义并发策略才可以。


# 禁用hystrix
feign:hystrix:enabled: false
# 并发策略设置为SEMAPHORE
hystrix:command:default:execution:isolation:strategy: SEMAPHORE

关于如何自定义并发策略,可以查看前面文章,本文后面的参考代码中也有。

请求响应压缩

只需要设置以下配置项即可:

feign.compression.request.enabled=true
feign.compression.request.mime-types=text/xml,application/xml,application/json
feign.compression.request.min-request-size=2048
feign.compression.response.enabled=true
feign.compression.response.useGzipDecoder=true

参考代码下载:https://github.com/xjs1919/enumdemo下面的openfeign/feign-boot。

spring-cloud-starter-openfeign使用详解相关推荐

  1. 【夯实Spring Cloud】Spring Cloud分布式配置中心详解

    本文属于[夯实Spring Cloud]系列文章,该系列旨在用通俗易懂的语言,带大家了解和学习Spring Cloud技术,希望能给读者带来一些干货.系列目录如下: [夯实Spring Cloud]D ...

  2. Spring Cloud Eureka 配置原理详解

    导语:   首先对于Eureka注册中心默认大家都有所了解,这篇博客主要就是来通过Eureka的配置源码来了解一下关于Eureka配置中心都有那些详细的配置内容.对于Eureka 客户端的配置主要分为 ...

  3. Spring Cloud Ribbon的使用详解

    目录 一.概述 1.Ribbon是什么 2.Ribbon能干什么 3.Ribbon现状 4.未来替代方案 5.架构说明 二.RestTemplate 用法详解 三.Ribbon核心组件IRule 四. ...

  4. java B2B2C 仿淘宝电子商城系统-Spring Cloud Eureka参数配置项详解

    Eureka涉及到的参数配置项数量众多,它的很多功能都是通过参数配置来实现的,了解这些参数的含义有助于我们更好的应用Eureka的各种功能,下面对Eureka的配置项做具体介绍,供大家参考. 需要JA ...

  5. Spring Cloud Zuul之ZuulFilter详解

    简介 Spring Cloud Zuul网关在整个微服务体系中肩负对外开放接口.请求拦截.路由转发等作用,其核心处理则是ZuulFilter ZuulFilter部分源码 Zuul Filter全部继 ...

  6. Spring 3.0 注解注入详解

    Spring 3.0 注解注入详解 2011-04-15 09:44 17ZOUGUO ITEYE博客 我要评论(1) 字号:T | T AD: 一.各种注解方式 1.@Autowired注解(不推荐 ...

  7. spring cloud整合OpenFeign

    spring cloud整合OpenFeign pom.xml配置 <!-- https://mvnrepository.com/artifact/org.springframework.clo ...

  8. 超轻量级DI容器框架Google Guice与Spring框架的区别教程详解及其demo代码片段分享...

    超轻量级DI容器框架Google Guice与Spring框架的区别教程详解及其demo代码片段分享 DI框架 Google-Guice入门介绍 转载于:https://www.cnblogs.com ...

  9. spring(7)---深入理解Spring核心技术——Spring中的各模块详解

    深入理解Spring核心技术--Spring中的各模块详解 Spring框架的两个基本概念IOC容器和AOP,相信大家现在对Spring中的这两个部分的基本概念有了一定的认识,好了,那么今天我们就来正 ...

  10. 跟着小马哥学系列之 Spring AOP(Pointcut 组件详解)

    学好路更宽,钱多少加班. --小马哥 版本修订 2021.5.19:去除目录 2021.5.21:引用 Spring 官方 Pointcut 概念,修改 Pointcut 功能表述 简介 大家好,我是 ...

最新文章

  1. thinkphp 调用php文件上传,ThinkPHP实现带验证码的文件上传功能实例
  2. 图片跟着鼠标_刷完几百张网易云Banner,我发现了2个PPT图片处理的大招!
  3. 小余学调度:学习记录(2021.9.13-2021.9.19)母线操作和线路操作
  4. 3种团队分组适应项目_团队类型
  5. UIKeyboard键盘相关知识点
  6. android广播代码汇总一__无序广播
  7. 第二课--C语言基础(1,2部分--共三部分)
  8. k8s部署zabbix_Kubernetes 中部署 Zabbix
  9. 基于IdentityServer4的单点登录——IdentityServer
  10. 算术编码数据压缩Matlab报告,用matlab实现算术编码
  11. AppFabric 版本区分
  12. Tallest buildings/skyscrapers in the world
  13. 视觉问答06day[综述]:一文带你了解视觉问答VQA
  14. react项目—单击按钮返回上一页
  15. 清华大学胡事民是计算机视觉,ResNet也能用在3D模型上了,清华「计图」团队新研究已开源...
  16. Bash编程016——用户与组(二)
  17. Android 下获取 ICCID、电话号码 的两种方式
  18. 系统集成项目管理工程师:供应商项目立项
  19. 选择低功耗蓝牙芯片时应注意什么
  20. 惠普HP彩色激光打印机颜色校准方法大全

热门文章

  1. c++中queue用法
  2. 花书+吴恩达深度学习(十八)迁移学习和多任务学习
  3. 微信小程序如何零成本获客
  4. 861. Score After Flipping Matrix
  5. 性能测试:基础(2)
  6. python接口自动化(十七)--Json 数据处理---一次爬坑记(详解)
  7. 华景机器人怎么控制_【扫地机器人选购】支持华为hilink智能家居联动/支持华为小艺语音控制的扫地机器人...
  8. Eclipse .class文件中文乱码
  9. error: cannot read: aaa.java_Java期末考试习题库[选择题填空题改错题学生].doc
  10. 华为服务器装系统一直在读盘,系统重装一直在启动服务器