前言 Feign is a Java to HTTP client binder inspired by Retrofit, JAXRS-2.0, and WebSocket. Feign’s first goal was reducing the complexity of binding Denominator uniformly to HTTP APIs regardless of ReSTfulness.(Github )
添加依赖 pom.xml
1 2 3 4 <dependency > <groupId > org.springframework.cloud</groupId > <artifactId > spring-cloud-starter-openfeign</artifactId > </dependency >
在主启动类添加注解
在主启动类上添加@EnableFeignClients
启动Feign自动装配
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 package com;import org.mybatis.spring.annotation.MapperScan;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.cloud.openfeign.EnableFeignClients;@EnableFeignClients @SpringBootApplication @MapperScan("com.dao") public class Application { public static void main (String[] args) { SpringApplication.run(Application.class, args); } }
手动指定客户端类 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 package com;import com.clients.UserClients;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.cloud.openfeign.EnableFeignClients;@EnableFeignClients(clients = UserClients.class) @SpringBootApplication public class FeignApiApplication { public static void main (String[] args) { SpringApplication.run(FeignApiApplication.class, args); } }
创建接口
创建用于发送请求的接口
Feign中的注解与SpringMVC中相同
@FeignClient("")
:指定请求的地址(或服务名)@GetMapping("")
:发送Get请求,并指定请求参数@PathVariable
:指定Rest风格的请求参数
src/main/java/com/clients/UserClients.java
1 2 3 4 5 6 7 8 9 10 11 12 13 package com.clients;import com.pojo.User;import org.springframework.cloud.openfeign.FeignClient;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.PathVariable;@FeignClient("eureka-service-user") public interface UserClients { @GetMapping("/users/{id}") User getUserById (@PathVariable int id) ; }
通过Feign发送请求
使用Feign代替RestTemplate发送请求
1 2 3 4 5 6 @Autowired private UserClients userClients; public void method () { User user = userClients.getUserById(order.getUserId()); }
修改日志级别 通过配置文件
feign.client.config.default.loggerLevel
:设置所有服务的日志级别
NONE
:缺省值。没有日志BASIC
:基本信息。包含请求发送时间、请求结束时间、请求耗时HEADERS
:详细信息。包含请求头和响应头FULL
:完整信息。包含请求体和响应体
feign.client.config.服务名.loggerLevel
:设置指定服务的日志级别
src/main/resources/application.yml
1 2 3 4 5 6 7 feign: client: config: default: loggerLevel: NONE 服务名: loggerLevel: FULL
通过配置类 创建配置类 1 2 3 4 5 6 7 8 9 10 11 12 13 package com.conf;import feign.Logger;import org.springframework.boot.SpringBootConfiguration;import org.springframework.context.annotation.Bean;public class FeignClientConfig { @Bean public Logger.Level feignLogLevel () { return Logger.Level.FULL; } }
在全局应用配置
1 @EnableFeignClients(defaultConfiguration = FeignClientConfig.class)
在指定服务应用配置
1 @FeignClient(value = "eureka-service-user", configuration = FeignClientConfig.class)
性能优化
将默认的不支持连接池底层实现URLConnection
换成支持连接池的底层实现Apache HttpClient
引入依赖 pom.xml
1 2 3 4 <dependency > <groupId > io.github.openfeign</groupId > <artifactId > feign-httpclient</artifactId > </dependency >
配置连接池
feign.httpclient.enabled
:启动Feign对HttpClient的支持feign.httpclient.max-connections
:最大连接数feign.httpclient.max-connections-per-route
:每个路径的最大连接数feign.httpclient.connection-timeout
:请求超时时间feign.httpclient.time-to-live
:存活时间
src/main/resource/application.yml
1 2 3 4 5 feign: httpclient: enabled: true max-connections: 200 max-connections-per-route: 50
最佳实践
把Feign抽取为一个服务,当其他服务需要使用Feign客户端时,继承Feign服务,就可以直接使用
抽取模块
创建一个名为FeignAPI
的模块
添加依赖
FeignAPI/pom.xml
1 2 3 4 <dependency > <groupId > org.springframework.cloud</groupId > <artifactId > spring-cloud-starter-openfeign</artifactId > </dependency >
在启动类添加注解
FeignAPI/src/main/java/com/FeignApiApplication.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 package com;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.cloud.openfeign.EnableFeignClients;@EnableFeignClients @SpringBootApplication public class FeignApiApplication { public static void main (String[] args) { SpringApplication.run(FeignApiApplication.class, args); } }
创建实体类
FeignAPI/src/main/java/com/pojo/User.java
1 2 3 4 5 6 7 8 9 10 11 package com.pojo;import lombok.Data;@Data public class User { private Integer id; private String name; }
创建Feign客户端接口
FeignAPI/src/main/java/com/clients/UserClients.java
1 2 3 4 5 6 7 8 9 10 11 12 13 package com.clients;import com.pojo.User;import org.springframework.cloud.openfeign.FeignClient;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.PathVariable;@FeignClient(value = "eureka-service-user") public interface UserClients { @GetMapping("/users/{id}") User getUserById (@PathVariable int id) ; }
使用抽取的模块
在需要利用Feign发送请求的模块中,引入FeignAPI
模块作为依赖
Other/pom.xml
1 2 3 4 5 <dependency > <groupId > com</groupId > <artifactId > FeignAPI</artifactId > <version > 0.0.1-SNAPSHOT</version > </dependency >
注入对象,通过对象调用方法,发起请求
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 package com.service;import com.clients.UserClients;import com.dao.OrderDao;import com.pojo.Order;import com.pojo.User;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;import org.springframework.web.client.RestTemplate;import java.util.List;@Service public class OrderService { @Autowired private OrderDao orderDao; @Autowired private UserClients userClients; public Order getOrderById (int id) { Order order = orderDao.selectById(id); User user = userClients.getUserById(order.getUserId()); order.setUser(user); return order; } }
完成 参考文献 哔哩哔哩——黑马程序员