1、引入依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
2、1.在启动类添加注解开启Feign的功能、加上@EnableFeignClients注解即可:
3、编写客户端
@FeignClient("userService")
public interface UserClient {
@GetMapping("/user/{id}")
User findById(@PathVariable("id") Long id);
}
主要是基于SpringMVC的注解来声明远程调用的信息,比如:
•服务名称:userService
•请求方式:GET
•请求路径:/user/{id}
•请求参数:Long id
•返回值类型:List<User>
4、用Feign客户端代替RestTemplate
远程访问接口例子
主工程略
被调用的工程略
1、在主工程下新建feign-api模块,导入依赖如下:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.km.cloud</groupId>
<version>1.0-SNAPSHOT</version>
<artifactId>spring-cloud-alibaba-demo</artifactId>
</parent>
<groupId>org.km.cloud</groupId>
<artifactId>feign-api</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>feign-api</name>
<description>Demo project for Spring Boot</description>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<junit.version>4.12</junit.version>
<log4j.version>1.2.17</log4j.version>
<lombok.version>1.16.18</lombok.version>
<spring-cloud.version>2020.0.4</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!--Spring Cloud Alibaba Nacos discovery -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
<exclusions>
<exclusion>
<groupId>com.netflix.ribbon</groupId>
<artifactId>ribbon</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-loadbalancer</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
</dependencies>
</project>
2、新建包service,并新建接口UserClient
package org.km.cloud.service;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
/**
* 被调用工程的微服务名 详见目标工程配置文件的 spring.application.name 的值
*/
@FeignClient("spring-cloud-alibaba-provider")
public interface UserClient {
@GetMapping("/dept/nacos/{id}")
String getDeptInfo(@PathVariable("id") Long id);
}
3、新建cotroller包,并新建类UserController,内容如下
package org.km.cloud.controller;
import org.km.cloud.service.UserClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class UserController {
@Autowired
UserClient userClient;
@GetMapping("/")
public Object getInfo(){
return userClient.getDeptInfo(2l);
}
}
启动类加上注解@EnableFeignClients和 @EnableDiscoveryClient
package org.km.cloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
@SpringBootApplication
@EnableDiscoveryClient //服务发现
@EnableFeignClients //远程调用
public class FeignApiApplication {
public static void main(String[] args) {
SpringApplication.run(FeignApiApplication.class, args);
}
}
配置信息如下:
server:
port: 7777
spring:
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
application:
name: openfeign-api
启动后,测试地址http://localhost:7777/
自定义Feign的配置
类型 | 作用 | 说明 |
feign.Logger.Level | 修改日志级别 | 包含四种不同的级别:NONE、BASIC、HEADERS、FULL |
feign.codec.Decoder | 响应结果的解析器 | http远程调用的结果做解析,例如解析json字符串为java对象 |
feign.codec.Encoder | 请求参数编码 | 将请求参数编码,便于通过http请求发送 |
feign. Contract | 支持的注解格式 | 默认是SpringMVC的注解 |
feign. Retryer | 失败重试机制 | 请求失败的重试机制,默认是没有,不过会使用Ribbon的重试 |
配置Feign日志有两种方式:
方式一:配置文件方式
1、局部生效
2、全局失效
```yaml
feign:
client:
config:
userservice: # 针对某个微服务的配置
loggerLevel: FULL # 日志级别
```
也可以针对所有服务:
```yaml
feign:
client:
config:
default: # 这里用default就是全局配置,如果是写服务名称,则是针对某个微服务的配置
loggerLevel: FULL # 日志级别
配置Feign日志的方式二:java代码方式,需要先声明一个Bean:
也可以基于Java代码来修改日志级别,先声明一个类,然后声明一个Logger.Level的对象:
public class DefaultFeignConfiguration {
@Bean
public Logger.Level feignLogLevel(){
return Logger.Level.BASIC; // 日志级别为BASIC
}
}
如果要**全局生效**,将其放到启动类的@EnableFeignClients这个注解中:
```java
@EnableFeignClients(defaultConfiguration = DefaultFeignConfiguration .class)
如果是**局部生效**,则把它放到对应的@FeignClient这个注解中:
```java
@FeignClient(value = "userservice", configuration = DefaultFeignConfiguration .class)
Feign的性能优化
Feign底层发起http请求,依赖于其它的框架。其底层客户端实现包括:
•URLConnection:默认实现,不支持连接池
•Apache HttpClient :支持连接池
•OKHttp:支持连接池
Apache HttpClient 优化如下
#1)引入依赖
<!--httpClient的依赖 -->
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-httpclient</artifactId>
</dependency>
```
2)配置连接池
在 application.yml中添加配置:
feign:
client:
config:
default: # default全局的配置
loggerLevel: BASIC # 日志级别,BASIC就是基本的请求和响应信息
httpclient:
enabled: true # 开启feign对HttpClient的支持
max-connections: 200 # 最大的连接数
max-connections-per-route: 50 # 每个路径的最大连接数
fengn-api独立成子工程
引入feign-api的依赖:
```xml
<dependency>
<groupId>org.km.cloud</groupId>
<artifactId>feign-api</artifactId>
<version>1.0</version>
</dependency>
```
#### 4)解决扫描包问题
方式一:
指定Feign应该扫描的包:
```java
@EnableFeignClients(basePackages = "org.km.cloud.clients")
```
方式二:
指定需要加载的Client接口:
```java
@EnableFeignClients(clients = {UserClient.class})