Feign - 理解使用

20 篇文章 0 订阅
6 篇文章 0 订阅

最近在整合项目的RPC调用,对Feign有了更多对一些理解

Feign它是一个声明式WebService客户端.,它支持多种注解,Feign自带注解以及JAX-RS标准的注解.Feign也支持可拔插式的编码器和解码器.即我们可以自定义编码器、解码器、错误处理器;Spring Cloud是对Feign进行了封装,使其支持了Spring MVC标准注解和HttpMessageConverters.

使用

我们可以通过JAX-RS标准的注解直接使用Feign.

 

  • Feign配置
@Slf4j
public class CommonErrorDecoder implements ErrorDecoder {


    @Override
    public final Exception decode(String methodKey, Response response) {

        FeignException exception = errorStatus(methodKey, response);

        log.error("REST服务异常:URL ={}, CODE ={}, MSG ={}",
                response.request().url(),
                response.status(),
                exception.getMessage());

        return postDecode(methodKey, response, exception);
    }

    protected Exception postDecode(String methodKey, Response response, Exception exception) {
        return exception;
    }
}

     
@Configuration
public class FeignConfig {
    /**
     * 设置 OkHttpClient
     */
    @Bean
    public OkHttpClient okHttpClient() {
        return new OkHttpClient(new okhttp3.OkHttpClient().newBuilder()
                .addInterceptor(new HttpLoggingInterceptor()
                        .setLevel(HttpLoggingInterceptor.Level.BODY))
                .build());
    }

    @Bean
    public Gson gson() {
        return GsonFactory.create(Collections.emptyList());
    }

    @Bean
    public GsonEncoder gsonEncoder(Gson gson) {
        return new GsonEncoder(gson);
    }

    @Bean
    public GsonDecoder gsonDecoder() {
        return new GsonDecoder();
    }

    @Bean
    public JAXRSContract jaxrsContract() {
        return new JAXRSContract();
    }

    /**
     * 统一错误处理,RPC 调用失败发送报警信息
     */
    @Bean
    public CommonErrorDecoder commonErrorDecoder() {
        return new CommonErrorDecoder();
    }

    /**
     * 统一错误重试处理,RPC 调用失败客户端自动重试
     */
    @Bean
    public RetryErrorDecoder retryErrorDecoder() {
        return new RetryErrorDecoder();
    }

    /**
     * 设置重试策略 重试只对IOException起作用,其他情况重试需自定义errorDecoder
     */
    @Bean
    public Retryer retryer() {
        return new Retryer.Default(2000, SECONDS.toMillis(10), 5);
    }

    /**
     * 设置超时时间
     */
    @Bean
    public Request.Options options() {
        return new Request.Options(10000, 10000);
    }


@Bean("feignForTestApi")
    public Feign feignForOpenApi(OkHttpClient okHttpClient, GsonDecoder gsonDecoder, Gson gson,
            CommonErrorDecoder commonErrorDecoder, JAXRSContract jaxrsContract, Retryer retryer,
            Request.Options options) {
        return new Feign.Builder()
                .client(okHttpClient)
                .decoder(new OpenApiGsonDecoder(gsonDecoder, gson))
                .contract(jaxrsContract)
                .requestInterceptor(template -> {

                    // 把当前参数转存到map
                    final Map<String, String> params = new HashMap<>();
                    template.queries().forEach((key, values) -> {
 
                            params.put(key, values.iterator().next());
                  
                    });

                    // 清空参数
                    template.queries(Collections.emptyMap());

                    // 添加新的参数
                    params.put("param", key);
                    params.forEach(template::query);
                })
                .errorDecoder(commonErrorDecoder)
                .retryer(retryer)
                .options(options)
                .build();
    }
}

@Configuration
public class ApiConfig {
    @Value("${rest.testApi.url}")
    private String testApiHost;

  @Bean
    public TestApi initTestApi(@Qualifier("feignForTestApi") Feign feign) {
        return feign.newInstance(new Target.HardCodedTarget<>(TestApi.class, testApiHost));
    }
}
  • 配置好Feign后配置远程接口
public interface TestApi {

    @POST
    @Path("/v1/getInfo")
    List<Info> getInfo();

}

 

也可以使用Spring Cloud 封装好的Feign.

@FeignClient(name = "test-service", url = "${rest.testApi.url}")
public interface testApi {

    @RequestMapping(value = {"/v2/getInfo"}, method = {RequestMethod.GET}, consumes = {MediaType.APPLICATION_FORM_URLENCODED_VALUE})
    GetEntityIdResponse getId(@RequestParam("size") Integer size, @RequestParam("cityId") Integer cityId);
}

相关配置大同小异,完美封装了Fegin插拔式的好处,可通过yml文件配置自定义编码器、解码器、错误解码器、重试等

 

接下来理解Feign配合Ribbon、Hystrix实现负载均衡、熔断

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值