5.1、写一个 Feign 害户端
新建项目:
依赖:
org.springframework.boot spring-boot-starter-web org.springframework.cloud spring-cloud-starter-netflix-eureka-client org.springframework.cloud spring-cloud-starter-netflix-ribbon org.springframework.cloud spring-cloud-starter-openfeign org.springframework.boot spring-boot-starter-test test
关于服务中心使用的是8762(之前的案列写过)
地址:https://www.cnblogs.com/Mrchengs/p/10645911.html
配置文件:
spring.application.name=feignserver.port=8088eureka.client.service-url.defaultZone=http://localhost:8762/eureka/
主配置类:
@EnableFeignClients:开启Feign Client功能
@EnableFeignClients(basePackages = "com.cr.eurekafeignclient.feign")@EnableDiscoveryClient@SpringBootApplicationpublic class EurekaFeignClientApplication { public static void main(String[] args) { SpringApplication.run(EurekaFeignClientApplication.class, args); }}
上述的三个步骤已经开启了Feign的功能
实现之前eureka client的/port服务的调用
EurekaClientFeign.java
@FeignClient(value = "CLINET",configuration = feignconfig.class)public interface EurekaClientFeign { @GetMapping("/port") String port();}
@FeignClient:
value:远程调用其他服务的服务名
feignconfig.class为Feign Client的配置类
port():通过Feign来调用CLIENT服务的“/port”的API接口
feignconfig.java
@Configurationpublic class feignconfig { @Bean public Retryer feignRetryer(){ return new Retryer.Default(100, TimeUnit.SECONDS.toMillis(1L),5); }}
配置类:注入一个feignRetryer的Retryer的Bean
注入Bean之后,Feign在远程调用失败之后会进行重试
FeignService.java
@Servicepublic class FeignService { @Autowired EurekaClientFeign eurekaClientFeign; public String port(){ return eurekaClientFeign.port(); }}
在Service层FeignService注入EurekaClientFeign去调用port()方法
FeignController.java
@RestControllerpublic class FeignController { @Autowired FeignService feignService; @GetMapping("/feign") public String sayPort(){ return feignService.port(); }}
自动注入 FeignService 去调用其port()方法
FeignService 通过 EurekaClientFeign远程调用CLIENT服务的API接口“/port”
此时的两个提供者:
分别是8089和8090端口
启动服务:
Feign Client 程调用了 eureka-client 务(8089、8090)两个端口的实例“/port”API接口
Feign Client 有负载均衡的能力。
spring-cloud-starter-openfeign 的porn 文件
org.springframework.cloud spring-cloud-starter org.springframework.cloud spring-cloud-openfeign-core org.springframework spring-web org.springframework.cloud spring-cloud-commons io.github.openfeign feign-core io.github.openfeign feign-slf4j io.github.openfeign feign-hystrix io.github.openfeign feign-java8 org.springframework.cloud spring-cloud-starter-netflix-ribbon true org.springframework.cloud spring-cloud-starter-netflix-archaius true
5.2、FeignClient详解
@FeignClient注解源码
//// Source code recreated from a .class file by IntelliJ IDEA// (powered by Fernflower decompiler)//package org.springframework.cloud.openfeign;import java.lang.annotation.Documented;import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;import org.springframework.core.annotation.AliasFor;@Target({ElementType.TYPE})@Retention(RetentionPolicy.RUNTIME)@Documentedpublic @interface FeignClient { @AliasFor("name") String value() default ""; /** @deprecated */ @Deprecated String serviceId() default ""; String contextId() default ""; @AliasFor("value") String name() default ""; String qualifier() default ""; String url() default ""; boolean decode404() default false; Class [] configuration() default {}; Class fallback() default void.class; Class fallbackFactory() default void.class; String path() default ""; boolean primary() default true;}
FeignClient 注解被@Target(ElementType TYPE)修饰:
表示 FeignClient 注解的作用目标在接口上
@Retention(RetentionPolicy.RUNTll\伍)注解表明该注解会在 lass 字节码文件中存在,
在运行时可以通过反射获取到
@Documented 表示该注解将被包含在 Javadoc 中。
@Feign Client 注解用于创建声明式 API 接口,该接口是RESTful 风格的。
Feign 被设计成插拔式的,可以注入其他组件和 Feign一起使用
最典型的是如果 Ribbon 可用, Feign 会和Ribbon 结合进行负载均衡。
注解中的属性:
---value()和 name() 样,是被调用的服务的 Serviceld
---url ()直接填写硬编码的Uri 地址
---decode404()即 404 是被解码,还是抛异常。
---configuration ()指明 FeignClient 配置类,
默认的配置类为 FeignClientsConfiguration类,在缺省的情况下 这个类注入
了默认的 DecoderEncoder、 Contract 等配置的 Bean
---fall back()为配置熔断器的处理类。
5.3、FeignClient的配置
Feign Client 默认的配置类为 FeignClientsConfiguration,这个类在在 pring-cloud-netflix-core的jar下
现这个类注入了很多 Feign 相关的配置 Bean(默认不配置的时候使用默认的)
Decoder、Encoder 、Contract个类在没有Bean被注入的情况下,会自动注入默认配置的 Bean
@Configurationpublic class FeignClientsConfiguration { @Autowired private ObjectFactorymessageConverters; @Autowired( required = false ) private List parameterProcessors = new ArrayList(); @Autowired( required = false ) private List feignFormatterRegistrars = new ArrayList(); @Autowired( required = false ) private Logger logger; public FeignClientsConfiguration() { } @Bean @ConditionalOnMissingBean public Decoder feignDecoder() { return new OptionalDecoder(new ResponseEntityDecoder(new SpringDecoder(this.messageConverters))); } @Bean @ConditionalOnMissingBean @ConditionalOnMissingClass({ "org.springframework.data.domain.Pageable"}) public Encoder feignEncoder() { return new SpringEncoder(this.messageConverters); } @Bean @ConditionalOnClass( name = { "org.springframework.data.domain.Pageable"} ) @ConditionalOnMissingBean public Encoder feignEncoderPageable() { return new PageableSpringEncoder(new SpringEncoder(this.messageConverters)); } @Bean @ConditionalOnMissingBean public Contract feignContract(ConversionService feignConversionService) { return new SpringMvcContract(this.parameterProcessors, feignConversionService); } @Bean public FormattingConversionService feignConversionService() { FormattingConversionService conversionService = new DefaultFormattingConversionService(); Iterator var2 = this.feignFormatterRegistrars.iterator(); while(var2.hasNext()) { FeignFormatterRegistrar feignFormatterRegistrar = (FeignFormatterRegistrar)var2.next(); feignFormatterRegistrar.registerFormatters(conversionService); } return conversionService; } @Bean @ConditionalOnMissingBean public Retryer feignRetryer() { return Retryer.NEVER_RETRY; } @Bean @Scope("prototype") @ConditionalOnMissingBean public Builder feignBuilder(Retryer retryer) { return Feign.builder().retryer(retryer); } @Bean @ConditionalOnMissingBean({FeignLoggerFactory.class}) public FeignLoggerFactory feignLoggerFactory() { return new DefaultFeignLoggerFactory(this.logger); } @Bean @ConditionalOnClass( name = { "org.springframework.data.domain.Page"} ) public Module pageJacksonModule() { return new PageJacksonModule(); } @Configuration @ConditionalOnClass({HystrixCommand.class, HystrixFeign.class}) protected static class HystrixFeignConfiguration { protected HystrixFeignConfiguration() { } @Bean @Scope("prototype") @ConditionalOnMissingBean @ConditionalOnProperty( name = { "feign.hystrix.enabled"} ) public Builder feignHystrixBuilder() { return HystrixFeign.builder(); } }}
重写 FeignClientsConfiguration 类中的 Bean
覆盖掉默认的配置 Bean
从而达到自定义配置的目的
Feign 默认的配置在请求失败后 重试次数为 ,即不重试Retryer.NEVER_RETRY
现在希望在请求失败后能够重试
这时需要写 个配置 FeignConfig 类
在该类中注入Retryer的Bean会覆盖掉默认的 Retryer的Bean
@Configurationpublic class feignconfig { @Bean public Retryer feignRetryer(){ return new Retryer.Default(100, TimeUnit.SECONDS.toMillis(1L),5); }}