In the Spring Cloud cluster, communication between roles is based on REST services. When invoking services, you need to use a REST client, which is commonly used. In addition to using the RestTemplate that Spring comes with, you can also use another REST client: Feign.
When using Feign, you can decorate the interface with your own or third-party annotations to give it access to Web Service s.
Feign also supports plug-in encoders and decoders that encapsulate and parse requests and responses differently.
Spring Cloud integrates Feign into Netflix projects, and when integrated with Eureka and Ribbon, Feign has load balancing capabilities.
Examples of Feign's use in the Spring Boot Web project are as follows: Spring Boot 2 Publish and Call REST Services>
The following example is the use of Spring Cloud.
Development Tools: IntelliJ IDEA 2019.2.3
1. Server-side
1. Create Project
Create a new SpringBoot project in IDEA named "spring-feign-server", SpringBoot version selection 2.1.10, check Spring Cloud Discovert ->on the interface of selecting Dependencies
Eureka Server, the pom.xml configuration file created automatically adds the latest stable version dependency of SpringCloud, currently Greenwich.SR3.
The complete content of pom.xml is as follows:
<?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.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.10.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.example</groupId> <artifactId>spring-feign-server</artifactId> <version>0.0.1-SNAPSHOT</version> <name>spring-feign-server</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> <spring-cloud.version>Greenwich.SR3</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>
2. Modify configuration application.yml
Modify the port number to 8761; unregister your own information to the Eureka server and do not grab the registration information from the Eureka server.
server: port: 8761 eureka: client: register-with-eureka: false fetch-registry: false
3. Modify the startup class code SpringFeignServerApplication.java
Add comment @EnableEurekaServer
package com.example.springfeignserver; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; @SpringBootApplication @EnableEurekaServer public class SpringFeignServerApplication { public static void main(String[] args) { SpringApplication.run(SpringFeignServerApplication.class, args); } }
2. Service Providers
1. Create Project
Create a new SpringBoot project in IDEA, with the exception of the name "spring-feign-provider", as you did above to create the server side.
2. Modify configuration application.yml
spring: application: name: spring-feign-provider eureka: instance: hostname: localhost client: serviceUrl: defaultZone: http://localhost:8761/eureka/
3. Add an entity class User.java
package com.example.springfeignprovider; public class User { String name; Integer age; public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } }
4. Modify the startup class code SpringFeignProviderApplication.java
Add the comment @EnableEurekaClient and @RestController;
Let the class read console input at startup to decide which port to use to start the server;
Add 2 controller methods for testing.
package com.example.springfeignprovider; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; import org.springframework.http.MediaType; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import javax.servlet.http.HttpServletRequest; import java.util.Scanner; @SpringBootApplication @EnableEurekaClient @RestController public class SpringFeignProviderApplication { public static void main(String[] args) { //SpringApplication.run(SpringFeignProviderApplication.class, args); Scanner scan = new Scanner(System.in); String port = scan.nextLine(); new SpringApplicationBuilder(SpringFeignProviderApplication.class).properties("server.port=" + port).run(args); } @RequestMapping("/hello") public String hello(HttpServletRequest request) { return "hello world." + request.getServerPort(); } @RequestMapping(value="/user/{name}", produces = MediaType.APPLICATION_JSON_VALUE) public User user(@PathVariable String name) { User u = new User(); u.setName(name); u.setAge(30); return u; } }
3. Service Callers
1. Create Project
Create a new SpringBoot project in IDEA named "spring-feign-invoker", SpringBoot version selection 2.1.10, check Spring Cloud Discovert -> Eureka Server, Spring Cloud Routing -> OpenFeign on the interface of selecting Dependencies.
The complete content of pom.xml is as follows:
<?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.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.10.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.example</groupId> <artifactId>spring-feign-invoker</artifactId> <version>0.0.1-SNAPSHOT</version> <name>spring-feign-invoker</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> <spring-cloud.version>Greenwich.SR3</spring-cloud.version> </properties> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</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> </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>
2. Modify configuration application.yml
server: port: 9000 spring: application: name: spring-feign-invoker eureka: instance: hostname: localhost client: serviceUrl: defaultZone: http://localhost:8761/eureka/
3. Add an entity class User.java
package com.example.springfeigninvoker; public class User { String name; Integer age; public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } }
4. Add a client interface UserClient.java
package com.example.springfeigninvoker; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; //Declare the name of the service invoked @FeignClient("spring-feign-provider") public interface UserClient { @RequestMapping(method = RequestMethod.GET, value = "/hello") String hello(); @RequestMapping(method = RequestMethod.GET, value = "/user/{name}") User getUser(@PathVariable("name") String name); }
5. Modify the startup class code CloudInvokerApplication.java
Add the comment @EnableEurekaClient and @EnableFeignClients.
package com.example.springfeigninvoker; 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 public class SpringFeignInvokerApplication { public static void main(String[] args) { SpringApplication.run(SpringFeignInvokerApplication.class, args); } }
6. Add Controller InvokerController.java
package com.example.springfeigninvoker; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.http.MediaType; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; @RestController @Configuration public class InvokerController { @Autowired private UserClient userClient; @RequestMapping(value = "/invokeHello", method = RequestMethod.GET) public String invokeHello(){ return userClient.hello(); } @RequestMapping(value = "/invokeUser", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) public String invokeUser(){ return userClient.getUser("Xiao Ming").getAge().toString(); } }
IV. Testing
1. Start the server side.
Browser access http://localhost:8761/, normal
2. Start two service providers by typing 8080 and 8081 in the console, respectively.
(1) Browser access http://localhost:8080/user/Xiaoming
Output: {"name": "Xiaoming", "age":30}
(2) Browser access http://localhost:8081/user/Xiaoqiang
Output: {"name": "Xiaoqiang", "age":30}
3. Start the service caller.
(1) Browsers access http://localhost:9000/invokeHello, and pages display toggling between ports 8080 and 8081 below:
hello world.8080
hello world.8081
(2) Browser access http://localhost:9000/invokeUser, output:
30