说明:该文章只是简单描述了如何进行通信,并没有关于feign的详细注解和高级使用。(大佬看看我写的有没有问题也是可以的)。
流程简述:一个程序作为eureka服务端供其余两个应用注册,另外两个应用注册后使用feign进行应用间通信。
使用环境:JDK 8、SpringBoot: 2.1.3、SpringCloud:Greenwich.SR1
版本不一致可能会导致莫名奇妙的错误。
1、eureka服务端的创建(eureka-server):
(1)打开idea创建springboot项目,在选模块的时候记得选上下图所示模块:
(2)给出pom.xml和application.yml的配置文件(只要你按照(1)选了Eureka Server模块,pom.xml应该是和我一样的)
pom.xml:
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.3.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>eureka-server</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>eureka-server</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>Greenwich.SR1</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
application.yml配置:
server:
#服务端口
port: 8761
spring:
application:
name: eureka-server
eureka:
client:
# 禁止自己注册自己
register-with-eureka: false
# 服务开启的url
service-url:
defaultZone: http://localhost:8761/eureka/
(3)在启动类上加上注解:@EnableEurekaServer
2、两个eureka客户端的创建(feign-client、feign-server):
首先创建feign-client应用
(1)创建springboot应用,在选择模块的时候选择下图所示的两个模块:
(2)给出pom.xml和application.yml的配置(只要你(1)中选的模块是和我一样的,那么pom.xml应该也是和我一样的)
pom.xml(feign-client)
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.3.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>feign-client</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>feign-client</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>Greenwich.SR1</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
application.yml(feign-client):
server:
port: 8080
spring:
application:
name: feign-client
eureka:
client:
service-url:
# 注册到服务于该url的eurekaServer
defaultZone: http://localhost:8761/eureka/
(3)在启动类上加上注解:@EnableDiscoveryClient
然后我们以相同的方式创建feign-server应用:
给出feign-server的application.yml配置文件(pom.xml就不给了,因为暂时不需要加东西)
server:
port: 8081
spring:
application:
name: feign-server
eureka:
client:
service-url:
# 注册到服务于该url的eurekaServer
defaultZone: http://localhost:8761/eureka/
另外一定要给feign-server启动类加上注解:@EnableDiscoveryClient
至此,一个简单eureka服务端和两个客户端就创建好了,我们将这三个应用启动,然后在浏览器上输入:localhost:8761
看到如下画面就代表初步准备就已经弄好了:
接下来,我们配置并使用feign进行应用间的远程通信:
首先我们先理清思路,是feign-server要调用feign-client的服务,所以我们需要在feign-server应用里配置feign
在feign-server应用里配置feign:
(1)添加jar依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
(2)在启动类上加上注解:@EnableFeignClients,可以配置basePackage属性,指定feign客户端的包。(本应用没有指定)
接下来我们来编写业务类:
1、先写feign-client的接口:
目录结构:
ClientController类:
@Controller
@RequestMapping("/client")
public class ClientController {
//返回字符串
@GetMapping("/msg")
@ResponseBody
public String msg(){
return "你调用了Client端的服务!";
}
//返回list,在list末尾添加“client”
//必须使用Post方法,参数要加上@RequestBody
@PostMapping("/list")
@ResponseBody
public List<String> list(@RequestBody List<String> list){
list.add("client");
return list;
}
//返回对象(为dog的name赋值)
//必须使用Post方法,参数要加上@RequestBody
@PostMapping("/dog")
@ResponseBody
public Dog setDogName(@RequestBody Dog dog){
dog.setName("clientDog");
return dog;
}
}
Dog类:
public class Dog {
private String name;
//feign返回对象时,一定要添加无参构造方法,不然会报错:反序列化失败
public Dog(){}
public Dog(String name){
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
2、编写feign-server的业务类:
目录结构
AFeignClient接口(核心,通过该接口实现向客户端访问):
//@FeignClient里的name填写需要请求的客户端的name(注册在eureka上的name)
//即在application.yml里配置的spring.application.name
@FeignClient(name = "feign-client")
public interface AFeignClient {
//url必须一样,方法名可以不同
@GetMapping("/client/msg")
String getMsgFromClient();
@PostMapping("/client/list")
List<String> getListFromClient(@RequestBody List<String> stringList);
@PostMapping("/client/dog")
Dog setDogName(@RequestBody Dog dog);
}
ServerController类:
@Controller
@RequestMapping("/server")
public class ServerController {
//@Autowired 编译器可能会报红,但是依然能运行(大佬告诉我为啥...)
//有人可能会说@EnableFeignClients注解可以配置basePackages属性指定feign-client
//我这样做了,但是依然会报红
//如果你的应用启动会报错,提示无法注入该bean,那么你可以配置下basePackages
//例如:@EnableFeignClients(basePackages = "com.example.feignserver.client")
@Autowired
private AFeignClient aFeignClient;
//从client端获取字符串
@RequestMapping("/msg")
public void msg(){
String msg = aFeignClient.getMsgFromClient();
System.out.println(msg);
}
//从client端获取处理后的list
@RequestMapping("/list")
public void list(){
ArrayList<String> strList = new ArrayList<>();
strList.add("server");
List<String> listFromClient = aFeignClient.getListFromClient(strList);
System.out.println(listFromClient);
}
//从client端获取处理的对象
@RequestMapping("/dog")
public void setDogName(){
Dog dog = aFeignClient.setDogName(new Dog());
System.out.println(dog.getName());
}
}
Dog类和client端的是一样的,就不再给出了。
那么接下来该测试了:
(1)同时打开三个应用,在浏览器上访问localhost:8761,确认两个客户端都已经注册。
(2)测试server端的返回字符串接口,在浏览器上访问:localhost:8081/server/msg,feign-server的控制台打印出如下内容:
(2)测试list接口,访问:localhost:8081/server/list,feign-server的控制台打印出如下内容:
(3)测试对象接口,访问:localhost:8081/server/dog,feign-server的控制台打印出如下内容:
我们可以看见,feign-server应用通过feign向feign-client发送请求并接受了数据。