美文网首页
springboot 整合feign

springboot 整合feign

作者: 万事俱备就差一个程序员了 | 来源:发表于2021-08-24 19:40 被阅读0次

    <meta charset="utf-8">

    Spring Cloud为Feign添加了Spring MVC的注解支持,并整合了Ribbon和Eureka来为使用Feign时提供负载均衡。

    使用Feign

    1. 添加依赖
        <dependencies>
    
            <!--openfein的依赖-->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-openfeign</artifactId>
                <version>2.1.3.RELEASE</version>
            </dependency>
        </dependencies>
    
    
    2. 启用Feign

    启用类上添加注解@EnableFeignClients客户端允许开启使用Feign调用,扫描@FeignClient标注的FeignClient接口

    @SpringBootApplication
    @EnableFeignClients
    @EnableWeb 
    public class FeignApplication {
        public static void main(String[] args) {
            SpringApplication.run(FeignApplication.class,args);
        }
    }
    
    
    3. 编写FeignClient接口
    @FeignClient(
            name = "demo-service",
            url = "http://localhost:8080/feign/server/",
            configuration = FeignInterceptor.class,
            fallback = TestService.DefaultFallback.class
    )
    public interface TestService {
    
        @RequestMapping(value = "/getError/{id}", method = RequestMethod.GET)
        public String getError(@RequestParam("id") Integer id);
    
        @RequestMapping(value = "/get1", method = RequestMethod.GET)
        public String get1();
    
        @RequestMapping(value = "/get2/{param}", method = RequestMethod.GET)
        public String get2(@RequestParam("param") String param);
    
        @RequestMapping(value = "/post1", method = RequestMethod.POST)
        public FeignDemo post1(@RequestBody FeignDemo demo);
    
    
    4. 对应的服务端
    @RestController
    @RequestMapping("/feign/server")
    public class FeignServerController {
    
        @GetMapping("/get1")
        public String get1() {
            return "get1";
        }
        @GetMapping("/get2/{para}")
        public String get2(@PathVariable("para") String para){
            return para;
        }
        @PostMapping("/post1")
        public FeignDemo  post1(@RequestBody FeignDemo demo) {
            return demo;
        }
    
        @Component
        public class DefaultFallback implements TestService {
    
            @Override
            public String getError(@RequestParam("id") Integer id){
                return "";
            }
    
            @Override
            public String get1() {
                return null;
            }
    
            @Override
            public String get2(String param) {
                return null;
            }
    
            @Override
            public FeignDemo post1(FeignDemo demo) {
                return null;
            }
    
        }
    }
    
    
    public class FeignDemo {
        private String name;
        private Integer age;
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public Integer getAge() {
            return age;
        }
    
        public void setAge(Integer age) {
            this.age = age;
        }
    
        @Override
        public String toString() {
            return "FeignDemo{" +
                    "name='" + name + '\'' +
                    ", age=" + age +
                    '}';
        }
    }
    
    
    5. 调用FeignClient
    @RunWith(SpringJUnit4ClassRunner.class)
    @SpringBootTest(classes = {FeignApplication.class},webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
    @ActiveProfiles("dev,feign")
    public class FeignClientTest {
    
        @Autowired
        private TestService testService;
    
        @Test
        public void testFallback(){
            testService.getError(1);
        }
        @Test
        public void testGet1(){
            System.out.println(testService.get1());
            System.out.println(testService.get2("abc"));
            System.out.printf("..");
            FeignDemo feignDemo = new FeignDemo();
            feignDemo.setName("name");
            feignDemo.setAge(1);
            System.out.println(testService.post1(feignDemo));
        }
    }
    
    

    使用Apache的HTTP Client

    使用Apache的HTTP Client替换Feign原生httpclient

    1. 添加依赖
    <!--httpclient的依赖,因为选择了使用httpclient-->
            <dependency>
                <groupId>org.apache.httpcomponents</groupId>
                <artifactId>httpclient</artifactId>
            </dependency>
            <dependency>
                <groupId>io.github.openfeign</groupId>
                <artifactId>feign-httpclient</artifactId>
                <version>10.4.0</version>
            </dependency>
    
    
    2. 启用

    配置中添加如下信息,表示启用httpclient。

    feign:
      httpclient:
        enabled: true
    
    

    Feign中使用OkHttp

    1. 添加依赖

    在Feign中使用OkHttp作为网络请求框架,则只需要在pom文件中加上feign-okhttp的依赖,代码如下:

    <dependency>
        <groupId>io.github.openfeign</groupId>
        <artifactId>feign-okhttp</artifactId>
        <version>10.2.0</version>
    </dependency
    
    
    启用配置
    feign:
      okhttp:
        enabled: true
    
    

    Feign-使用HttpClient和OkHttp

    修改日志级别

    在发送和接收请求的时候,将日志的输出定义了四个等级:

    级别 说明
    NONE 不做任何记录
    BASIC 仅记录请求方法和URL以及响应状态代码和执行时间
    HEADERS 记录基本信息以及请求和响应标头
    FULL 记录请求和响应的标题,正文和元数据
    1. 通过配置

    接口的全路径名

    logging:
      level:
        com.zto.titans.test.feign.service.TestService : DEBUG
    
    
    2. 通过配置类
    @Configuration
    public class FooConfiguration {
        @Bean
        Logger.Level feignLoggerLevel() {
            return Logger.Level.FULL;
        }
    }
    
    

    数据压缩

    feign:
      compression:
        request:
           enabled: true
        response:
           enabled: true
    
    

    配置以及配置覆盖

    1. 自定义配置类,指定配置
    public class TestConfiguration {
        @Bean
        Logger.Level feignLoggerLevel() {
            return Logger.Level.FULL;
        }
    }
    
    

    TestConfiguration指定到configuration中。

    @FeignClient(
            name = "test-service",
            configuration = {FeignInterceptor2.class,TestConfiguration.class}
    )
    
    
    2. 配置文件中 default全局配置

    feign.client.config.default.xxx ,通过这个default创建全局的配置属性。

    feign:
      client:
        config:
          default:
            connectTimeout: 5000
            readTimeout: 5000
            loggerLevel: basic
    
    
    3. 配置文件中专属配置

    feign.client.config.feignName.xxx , 按名字指定FeignClient的配置。

    feign:
      client:
        config:
          feignName:
            connectTimeout: 5000
            readTimeout: 5000
            loggerLevel: full
            errorDecoder: com.example.SimpleErrorDecoder
            retryer: com.example.SimpleRetryer
            requestInterceptors:
              - com.example.FooRequestInterceptor
              - com.example.BarRequestInterceptor
            decode404: false
            encoder: com.example.SimpleEncoder
            decoder: com.example.SimpleDecoder
    
    
    3. 配置的覆盖与追加

    org.springframework.cloud.openfeign.FeignClientFactoryBean#configureFeign中可以确认几个配置的优先级:

    1. 自定义配置类,指定配置
    2. 配置文件中 default全局配置
    3. 配置文件中专属配置
    configureUsingConfiguration(context, builder); // 1
    configureUsingProperties(properties.getConfig().get(properties.getDefaultConfig()),builder); //2
    configureUsingProperties(properties.getConfig().get(this.contextId),builder);//3 
    
    
    1. 覆盖的原则

    3 -覆盖-> 2 -覆盖-> 1

    2. 追加的原则

    requestInterceptors不是覆盖的模式,而是追加,从requestInterceptors的执行顺序的优先级看是:
    1 > 2 > 3
    注意:RequestInterceptor 的实现类,如果使用@Component注解,那么都会被识别到,并在1中添加,若 还在配置中指定了,在2,和3中会继续在requestInterceptors列表中追加,产生重复。

    拦截器

    RequestInterceptor 就是拦截器 可以在发送前做一些处理,比如统一添加header信息。
    其添加的一些规则,上配置追加里有提及

    1. 自定义三个RequestInterceptor
    class FeignInterceptor implements RequestInterceptor {
        @Override
        public void apply(RequestTemplate requestTemplate) {
            requestTemplate.header("user", "myuser1");
            requestTemplate.header("password", "mypassword");
        }
    }
    
    
    class FeignInterceptor1 implements RequestInterceptor {
        @Override
        public void apply(RequestTemplate requestTemplate) {
            requestTemplate.header("user1", "myuser1");
            requestTemplate.header("password1", "mypassword1");
        }
    }
    
    
    class FeignInterceptor2 implements RequestInterceptor {
        @Override
        public void apply(RequestTemplate requestTemplate) {
            requestTemplate.header("user2", "myuser2");
            requestTemplate.header("password2", "mypassword2");
        }
    }
    
    
    2. @FeignClient中指定一个
    @FeignClient(
            name = "test-service",
            url = "http://localhost:8080/feign/server/",
            configuration = {FeignInterceptor.class,TestConfiguration.class},
            fallback = TestService.DefaultFallback.class
    )
    
    
    3. 配置中指定2个

    default 指定了一个,test-service里指定一个

    feign:
      httpclient:
        enabled: true
      okhttp:
        enabled: true
      client:
        config:
          default:
            connectTimeout: 5000
            readTimeout: 5000
            #loggerLevel: none
            requestInterceptors:
              - com.zto.titans.test.feign.service.FeignInterceptor1
          test-service:
            #loggerLevel: basic
            requestInterceptors:
              - com.zto.titans.test.feign.service.FeignInterceptor2
    logging:
      level:
        com.zto.titans.test.feign.service.TestService : DEBUG
    
    

    根据配置的的追加逻辑,最终执行的顺序是:

    1:FeignInterceptor
    2:FeignInterceptor1
    3:FeignInterceptor2

    cat 埋点:

    断路器

    Feign使用Hystrix

    作者:rock_fish
    链接:https://www.jianshu.com/p/49accf2167b2
    来源:简书
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

    相关文章

      网友评论

          本文标题:springboot 整合feign

          本文链接:https://www.haomeiwen.com/subject/uvqjiltx.html