3 声明式 REST 客户端 Feign

1 前言

  Java 项目中接口调用是怎么做的?

  • Httpclient:HttpClient 是 Apache Jakarta Common 下的子项目,用来提供高效的、最新的、功能丰富的支持 Http 协议的客户端编程工具包,并且它支持 Http 协议最新的版本和建议。HttpClient 相比传统的 JDK 自带的 URLConnection,增加了易用性和灵活性,是客户端发送 Http 请求变得容易,提高了开发效率。
  • Okhttp:一个处理网络请求的开源项目,是安卓端最火的轻量级框架,由 Square 公司贡献,用于替代 HttpUrlConnection 和 Apache HttpClient。OkHttp 有简介的 API、高效的性能,并支持多种协议(Http/2 和 SPDY)。
  • Httpurlconnection:Httpurlconnection 是 Java 的标准类,它继承自 URLConnection,可用于向指定网站发送 GET、POST 请求。HttpURLConnection 使用比较复杂,不像 HttpClient 那么容易使用。
  • RestTemplate:RestTemplate 是 Spring 提供的用于访问 Rest 服务的客户端,RestTemplate 提供了多种便捷访问远程 Http 服务的方法,能够大大提高客户端的编写效率。

  上面介绍的是最常见的集中调用接口的方法,我们下面是介绍的方法比上面的更简单方面,它是 Feign。

2 介绍

  Feign 是一个声明式的 REST 客户端,它能让 REST 调用更加简单。Feign 提供了 Http 请求的模板,通过编写简单的忌口和插入注解,就可以定义好 Http 请求的参数、格式、地址等信息。
  而 Feign 则会完全代理 Http 请求,我们只需要湘调用方法一样调用它就可以完成服务请求及相关处理。Spring Cloud 对 Feign 进行了封装,使其支持 Spring MVC 标准注解和 HttpMessaeConverters。Feign 可以与 Eureka 和 Ribbon 组合使用以支持负载均衡。

3 Spring Cloud 集成 Feign

  • 创建 spring-cloud-web-admin-feign 项目,pom.xml 文件和之前的差不多,只是添加了如下依赖:
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
  • 在启动类中添加 @EnableFeignClients 注解,如果你的 Feign 接口定义跟你的启动类不在一个包名下,还需要指定扫描的包名 @EnableFeignClients(basePackages = “com.pky.spring.cloud”),如下代码所示:
package com.pky.spring.cloud.web.admin.feign;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.openfeign.EnableFeignClients;

@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients(basePackages = "com.pky.spring.cloud")
public class WebAdminFeignApplication {
    public static void main(String[] args) {
        SpringApplication.run(WebAdminFeignApplication.class);
    }
}
  • 使用 Feign 调用接口
      定义一个 Feign 的客户端,以接口的形式存在,这里调用之前 admin-provider 服务提供者的接口,代码如下:
package com.pky.spring.cloud.web.admin.feign.service;

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;

@FeignClient(value = "admin-provider", path = "/admin")
public interface AdminService {

    @GetMapping(value = "")
    public String testFeign();

    @PostMapping(value = "user")
    public String testFeignPost();
}

  @FeignClient 注解表示当前是一个 Feign的客户端,value 属性是对应的服务名称,也就是需要调用哪个服务的接口,path 就是接口中 URI 统一的前缀。

  • AdminFeignController
package com.pky.spring.cloud.web.admin.feign.controller;

import com.pky.spring.cloud.web.admin.feign.service.AdminService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping(value = "feign")
public class AdminFeignController {

    @Autowired
    AdminService adminService;

    @GetMapping(value = "")
    public String testFeign(){
        return adminService.testFeign();
    }

    @GetMapping(value = "test_post")
    public String testFeignPost(){
        return adminService.testFeignPost();
    }
}

浏览器输入 http://localhost:9701/feign/ ,显示 “hello, I’m service admin from port :9601”,证明调用成功。

4 自定义 Feign 的配置

4.1 日志配置

  有时候我们遇到 bug,比如接口调用哪个失败、参数没收到等问题,或者想看看调用性能,就需要配置 Feign 的日志了,一次让 Feign 把请求信息输出出来。

  • 定义一个配置类,如下:
package com.pky.spring.cloud.web.admin.feign.config;

import feign.Logger;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class FeignConfiguration {

    /**
     * 日志级别
     * @return
     */
    @Bean
    Logger.Level feignLoggerLevel() {
        return Logger.Level.FULL;
    }
}
  • 日志级别源码
    public static enum Level {
        NONE,  // 不输出日志
        BASIC,   // 只输出请求方法的 URL 和响应的状态码以及接口执行的时间
        HEADERS,  // 将 BASIC 信息和请求头信息输出
        FULL;   // 输出完整的请求信息

        private Level() {
        }
    }
  • 配置类建好后,需要在 Feign Client 中的 @FeignClient 注解中指定使用的配置类,如下:
package com.pky.spring.cloud.web.admin.feign.service;

import com.pky.spring.cloud.web.admin.feign.config.FeignConfiguration;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;

@FeignClient(value = "admin-provider", path = "/admin", configuration = FeignConfiguration.class)
public interface AdminService {

    @GetMapping(value = "")
    public String testFeign();

    @PostMapping(value = "user")
    public String testFeignPost();
}
  • 还需要在配置文件中配置输出的信息,application.yml 增加如下配置:
# 日志
logging:
  level:
    com:
      pky:
        spring:
          cloud : DEBUG
  • 通过 Feign 调用接口,可以在控制台看到如下输出的调用信息
[AdminService#testFeign] ---> GET http://admin-provider/admin HTTP/1.1
[AdminService#testFeign] ---> END HTTP (0-byte body)
[AdminService#testFeign] <--- HTTP/1.1 200 (4ms)
[AdminService#testFeign] content-length: 40
[AdminService#testFeign] content-type: text/plain;charset=UTF-8
[AdminService#testFeign] date: Fri, 09 Aug 2019 06:18:45 GMT
[AdminService#testFeign] 
[AdminService#testFeign] hello, I'm service admin from port :9601
[AdminService#testFeign] <--- END HTTP (40-byte body)
4.2 Basic 认证配置

  通常我们调用的接口都是有权限控制的,很多时候可能认证的值是通过参数去传递的,还有就是通过请求头去传递认证信息,比如 Basic 认证方式。在 Feign 中我们可以直接配置 Basic 认证,如下代码所示:

package com.pky.spring.cloud.web.admin.feign.config;

import feign.Logger;
import feign.auth.BasicAuthRequestInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class FeignConfiguration {

    /**
     * 日志级别
     * @return
     */
    @Bean
    Logger.Level feignLoggerLevel() {
        return Logger.Level.FULL;
    }

    /**
     * Basic 认证配置
     * @return
     */
    @Bean
    public BasicAuthRequestInterceptor basicAuthRequestInterceptor() {
        return new BasicAuthRequestInterceptor("pky", "123");
    }
}

  或者你可以自定义属于自己的认证方式,其实就是定义一个请求拦截器。在请求之前做认证操作,然后往请求头中设置认证之后的信息。通过实现 RequestInterceptor 接口来自定义认证方式,代码如下:

package com.pky.spring.cloud.web.admin.feign.config;

import feign.RequestInterceptor;
import feign.RequestTemplate;
import org.springframework.context.annotation.Configuration;

@Configuration
public class FeignBasicAuthRequestInterceptor implements RequestInterceptor {
    
    public FeignBasicAuthRequestInterceptor() {
        
    }
   
    @Override
    public void apply(RequestTemplate requestTemplate) {
        // 业务逻辑
    }
}

  然后我们将配置改成我们自定义的就可以了,这样当 Feign 去请求接口的时候,每次请求之前都会进入 FeignBasicAuthRequestInterceptor 的 apply 方法中,在其里面就可以做属于自己的逻辑了,还需要在 FeignConfiguration 类中实例化 FeignBasicAuthRequestInterceptor ,如下

package config;

import com.pky.spring.cloud.web.admin.feign.config.FeignBasicAuthRequestInterceptor;
import feign.Logger;
import feign.auth.BasicAuthRequestInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class FeignConfiguration {

	@Bean
    public FeignBasicAuthRequestInterceptor basicAuthRequestInterceptor(){
        return new FeignBasicAuthRequestInterceptor();
    }
}
4.3 超时时间配置

  通过 Options 可以配置连接超时时间和读取超时时间,Options 的第一个参数是连接超时时间(ms),默认值是 10 * 1000;第第二个是读取超时时间(ms),默认值是 60 * 1000,如下代码所示

package com.pky.spring.cloud.web.admin.feign.config;

import feign.Logger;
import feign.Request;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class FeignConfiguration {

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值