zoukankan      html  css  js  c++  java
  • OpenFeign使用笔记

    是什么

    Feign是一个声明式Web Service客户端。使用Feign能让编写Web Service客户端更加简单, 它的使用方法是定义一个接口,然后在上面添加注解,同时也支持JAX-RS标准的注解。Feign也支持可拔插式的编码器和解码器。Spring Cloud对Feign进行了封装,使其支持了Spring MVC标准注解和HttpMessageConverters。Feign可以与Eureka和Ribbon组合使用以支持负载均衡。

    怎么用

    官方github项目(readme里写得很详细,代码里还有示例)

    我遇到的一些特殊请求:

    (1)POST请求方式,但是请求参数放在查询字符串里:

    一般的查询字符串添加可以用@QueryMap Map<String, Object>(为什么要用这个,因为不是用的spring cloud分支下封装过的feign,不支持直接用spring的注解)

    @RequestLine("POST /example/foo/token")
    String getAccessToken(@QueryMap Map<String, Object> queryMap);

    (2)查询字符串里带特殊拼接符号如加号(实现形如GET /Groups?filter=displayName+Eq+{roleName}的查询): https://stackoverflow.com/questions/43868680/feign-client-does-not-resolve-query-parameter

    @RequestLine("GET /Groups?filter={roleName}")
    String isValidRole(@Param(value = "roleName", expander = PrefixExpander.class) String roleName);
    
    static final class PrefixExpander implements Param.Expander {
        @Override
        public String expand(Object value) {
            return "displayName+Eq+" + value;
        }
    }

    (3)feign添加自定义httpheader:

    @RequestLine("POST /add")
    @Headers("TOKEN: {userToken}")
    Response addRecord(RecordVO recordVO,
                                  @Param("TOKEN") String userToken);

    普通项目示例(<-这是一个原文链接,稍微修改了下)

    maven依赖

    <!-- open-feign -->
    <dependency>
    <groupId>io.github.openfeign</groupId>
    <artifactId>feign-core</artifactId>
    <version>10.0.1</version>
    </dependency>
    <dependency>
    <groupId>io.github.openfeign</groupId>
    <artifactId>feign-gson</artifactId>
    <version>10.0.1</version>
    </dependency>

    自定义接口

    import feign.Param;
    import feign.RequestLine;
    
    public interface RemoteService {
        
        @RequestLine("GET /users/list?name={name}")
        String getOwner(@Param(value = "name") String name);
    }

    通过@RequestLine指定HTTP协议及URL地址

    配置类

    RemoteService service = Feign.builder()
                .options(new Options(1000, 3500))
                .retryer(new Retryer.Default(5000, 5000, 3)).encoder(new GsonEncoder()).target(RemoteService.class, "http://127.0.0.1:8085");

    options方法指定连接超时时长及响应超时时长,retryer方法指定重试策略,target方法绑定接口与服务端地址。返回类型为绑定的接口类型。

    (ps.还可以指定其他的:比如

    .encoder(new GsonEncoder())
    .decoder(new GsonDecoder())
    .logger(new Logger.ErrorLogger())
    .logLevel(Logger.Level.BASIC))

    调用:

    String result = service.getOwner("scott");

    与调用本地方法相同的方式调用feign包装的接口,直接获取远程服务提供的返回值。

    spring cloud 项目示例(<-这是一个原文链接) 

    maven依赖 

    <dependency> 
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-feign</artifactId>
    </dependency>

    在启动类上加@EnableFeignClients

    注解,如果你的Feign接口定义跟你的启动类不在一个包名下,还需要制定扫描的包名@ EnableFeignClients(basePackages = "com.fangjia.api.client")

    配置类

    @Configuration
    public class FeignConfiguration {
        @Bean  
        Logger.Level feignLoggerLevel() {  
            return Logger.Level.FULL;  
        }  
    }

    自定义接口

    @FeignClient(value = "fangjia-fsh-house-service", path = "/house", configuration = FeignConfiguration.class, fallback = HouseRemoteClientHystrix.class)
    public interface HouseRemoteClient {
        
        /**
         * 获取企业下某用户的有效房产信息
         * @param eid    企业编号
         * @param uid    用户编号
         * @return
         */
        @GetMapping("/list/{eid}/{uid}")
        public HouseListDto hosueList(@PathVariable("eid")Long eid, @PathVariable("uid")String uid);    
        
        /**
         * 获取房产详细信息
         * @param houseId 房产编号
         * @return
         */
        @GetMapping("/{houseId}")
        public HouseInfoDto hosueInfo(@PathVariable("houseId")Long houseId);
        
    }

    熔断回调处理

    @Component
    public class HouseRemoteClientHystrix implements HouseRemoteClient {
    
        @Override
        public HouseListDto hosueList(Long eid, String uid) {
            return new HouseListDto();
        }
    
        @Override
        public HouseInfoDto hosueInfo(Long houseId) {
            return new HouseInfoDto();
        }
    }

    原理(<-这是一个原文链接)

    1. 首先通过@EnableFeignCleints注解开启FeignCleint
    2. 根据Feign的规则实现接口,并加@FeignCleint注解
    3. 程序启动后,会进行包扫描,扫描所有的@ FeignCleint的注解的类,并将这些信息注入到ioc容器中。
    4. 当接口的方法被调用,通过jdk的代理,来生成具体的RequesTemplate
    5. RequesTemplate在生成Request
    6. Request交给Client去处理,其中Client可以是HttpUrlConnection、HttpClient也可以是Okhttp
    7. 最后Client被封装到LoadBalanceClient类,这个类结合类Ribbon做到了负载均衡。
  • 相关阅读:
    Android App内存优化之图片优化
    APP中的存储路径
    为什么源码中很多方法就一行throw new RuntimeException("Stub!")
    Android运行时Crash自动恢复框架-Recovery
    Android图片压缩框架-Tiny 集成
    防止APP退到被安卓系统清理
    Android开发中,那些让你觉得相见恨晚的方法、类或接口
    安卓设置沉浸式状态栏
    Euler Sums系列(四)
    一个含有Fibonacci Number的级数
  • 原文地址:https://www.cnblogs.com/goingforward/p/9560069.html
Copyright © 2011-2022 走看看