1.前言
本文将介绍如何使用spring cloud feign组件完成微服务间的通信,并且feign组件自动集成ribbon的负载均衡方便我们的开发。
2.准备
首先我们需要一个eureka服务为我们做微服务的发现。
3.开始!
新建一个feignserver项目,使用idea的新建选择Spring Initializr的话可以直接勾选组件,当然也可以后面自己编写pom文件内容,eclipse同理。(可以勾选Web/Eureka Discovery/Feign)。
新建完成之后在idea中右击项目接着new > model > maven groupId的名字和主项目名相同,创建名为client/server/common的三个model,其中client为对外暴露的接口,server表示具体处理内容,common为在调用中使用的通用dto。
主pom:主pom文件用来管理子model中依赖的版本包括之后server和client都要依赖common,所以版本内容都在主pom中控制(注意:在新建项目中主pom中包含一个<build></build>标签的springboot maven打包插件,记得要去掉,这个标签会在server中使用,如果在主pom中不去掉之后打包会出问题)。
<?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>
<modules>
<module>client</module>
<module>server</module>
<module>common</module>
</modules>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.5.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.yq.feignserver</groupId>
<artifactId>feignserver</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>feignserver</name>
<packaging>pom</packaging>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>Greenwich.SR1</spring-cloud.version>
<feign-common.version>0.0.1-SNAPSHOT</feign-common.version>
</properties>
<dependencies>
</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>
<dependency>
<groupId>com.yq.feign</groupId>
<artifactId>common</artifactId>
<version>${feign-common.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
</project>
client pom:
<?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">
<parent>
<artifactId>feignserver</artifactId>
<groupId>com.yq.feignserver</groupId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>com.yq.feignserver</groupId>
<artifactId>client</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
</dependency>
<dependency>
<groupId>com.yq.feign</groupId>
<artifactId>common</artifactId>
</dependency>
</dependencies>
</project>
common pom:
<?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">
<parent>
<artifactId>feignserver</artifactId>
<groupId>com.yq.feignserver</groupId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>com.yq.feignserver</groupId>
<artifactId>common</artifactId>
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.6</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>
server pom:
<?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">
<parent>
<artifactId>feignserver</artifactId>
<groupId>com.yq.feignserver</groupId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>com.yq.feignserver</groupId>
<artifactId>server</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>com.yq.feign</groupId>
<artifactId>common</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
在server中创建springboot的启动类(代码省略记得在启动类中加上eureka的@EnableDiscoveryClient
注解),并且在resource目录下添加application.yml文件。
application.yml:(其中的配置可以根据自身情况进行修改)。
spring:
application:
name: feignserver
server:
port: 8079
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/
instance:
prefer-ip-address: true
在common的dto包中创建实体类。
实体类:
@Data
public class ProductInfo {
private String id;
private String name;
private BigDecimal price;
private String icon;
private String type;
}
在server的controller包中创建提供数据的controller。
controller:这里简化了实体对象的生成,只是new出来填充数据,想要做复杂的可以自己引入mybatis,数据库等。
@RestController
public class ServerController {
@GetMapping("/product/{productId}")
public ProductInfo getProduct(@PathVariable String productId){
ProductInfo productInfo = new ProductInfo();
productInfo.setIcon("icon");
productInfo.setId(productId);
productInfo.setName("name");
productInfo.setPrice(BigDecimal.valueOf(1.2));
productInfo.setType("type");
return productInfo;
}
}
接着在client中添加一个使用feign对外暴露的接口:方法名可以随意,注意两边的mapping中的值一定要对应
其中FeignClinet中的值为本服务的服务名。
@FeignClient(name="feignserver")//服务名,和spring.application.name对应
public interface FeignInterface {
@GetMapping("/product/{productId}")
ProductInfo getProduct(@PathVariable String productId);
}
这样一个提供方就编写完成了,先启动一次测试controller接口编写无误没有报错之后,继续编写调用方端。
创建调用方:
调用方的创建方式一样名称为feignclient,创建client/common/server 模块,只是调用方我只用到server模块,此时我们还需要在feignclient项目中引用feignserver,那么我们把feignserver注册到本地的maven仓库中。在feignserver项目中使用maven命令 mvn -Dmaven.test.skip=true -U clean install
完成之后,我们就可以在feignclient中引用feignserver项目。
由于我们feignclient只用到server模块,我就只修改server的pom文件。
<?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">
<parent>
<artifactId>feignclient</artifactId>
<groupId>com.yq.feign</groupId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>com.yq.feign</groupId>
<artifactId>server</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.yq.feignserver</groupId>
<artifactId>common</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.yq.feignserver</groupId>
<artifactId>client</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
此处简化了对feignserver中的包版本管理,可以优化把版本管理放在主pom中,在server中我们依赖了feignserver的client模块和common模块。
在feignclient的server模块中添加springboot启动类,并且添加开启feign注解并且添加包含feign的类路径@EnableFeignClients("com.yq.feignserver.client")
。
编写feignclient中的controller,调用feignserver的接口:
@RestController
public class ClientController {
@Autowired
private FeignInterface feignInterface;
@GetMapping("/buy/{productId}")
public ProductInfo callProduct(@PathVariable String productId){
ProductInfo productInfo = feignInterface.getProduct(productId);
return productInfo;
}
}
然后启动项目调用/buy/1接口测试,会发现feignclient调用feignserver服务,完成。