Spring Cloud - using declarative REST client Feign call as the remote HTTP service Spring Cloud Start Tutorial (VI): with a declarative REST client Feign call as the remote HTTP service

Spring Cloud Getting Started tutorial (VI): with a declarative REST client Feign call as the remote HTTP service

First briefly explain what is declarative achieve?

Do one thing, you need to know three elements, where, what, how. That is what (where) do (what) where what way (how). When to do it (when) we included in the scope of how.

1) programmatically implemented: each element (where, what, how) are required to achieve a specific code is represented. The traditional way is generally programmatic implementation, developers need to be concerned about every business logic

2) declarative realization: only need to declare what to do and where (where) (what), without concern for how (how). Spring AOP is a kind of declarative implementations, such as Web site to check whether the login page logic of development, you can just needs to be done to check whether the user logs on (what) a statement by AOP configuration page loads (where), without concern for how to check whether the user Login (how). How to check this logic to achieve the AOP mechanism, AOP login to check implementation mechanism is being developed with the logic of the page itself is irrelevant.

In Spring Cloud Netflix stack, each micro services are exposed to their service in the form of an HTTP interface, so when calling a remote service must use the HTTP client. Feign Spring is a declarative REST client Cloud provides. REST interface can be called micro distal services provided by Feign access. Now we will use Feign to call SERVICE-HELLOWORLD exposed REST interface to get to the "Hello World" message. When using Feign, Spring Cloud integrates Ribbon Eureka to provide load balancing and HTTP client.

Here we are using Feign way to call the Hello World service cluster.

1. Create a Maven project, add spring-cloud-starter-feign dependent

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-feign</artifactId>
        </dependency>

Complete pom file 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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.chry</groupId>
<artifactId>springcloud.helloworld.feign.client</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>springcloud.helloworld.feign.client</name>
<description>Demo Feigh client application</description>

<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.3.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>

<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-feign</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>

<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Dalston.RC1</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>

<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
</project>

2. Create a startup class, you need to use it together with @EnableFeignClients comment Feign , automatic service discovery using open @EnableDiscoveryClient

Copy the code
 1 package springcloud.helloworld.feign.service;
 2 
 3 import org.springframework.boot.SpringApplication;
 4 import org.springframework.boot.autoconfigure.SpringBootApplication;
 5 import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
 6 import org.springframework.cloud.netflix.feign.EnableFeignClients;
 7 
 8 @SpringBootApplication
 9 @EnableDiscoveryClient
10 @EnableFeignClients
11 public class ServiceFeignApplication {
12     public static void main(String[] args) {
13         SpringApplication.run(ServiceFeignApplication.class, args);
14     }
15 }
Copy the code

3. Add Profile application.yml, using port 8902, the name is defined as a service-feign, and registered with the eureka service center

Copy the code
1 eureka:
2    client:
3       serviceUrl:
4         defaultZone: http://localhost:8761/eureka/
5 server:
6    port: 8902
7 spring:
8    application:
9       name: service-feign
Copy the code

4. Define Feign: an interface class annotated with @FeignClient,

@FeignClientFeign components used to notify the agent interface (no need to write interface), the user can directly through the @Autowiredinjection; This interface defines SERVICE-HELLOWORLD service (auto-discovery mechanism will locate specific URL through service centers) need to call by value ; @RequestMapping defined URL sERVICE-HELLOWORLD Feign need to access the service (in this example, the root "/")

Copy the code
 1 package springcloud.helloworld.feign.service;
 2 
 3 import org.springframework.cloud.netflix.feign.FeignClient;
 4 import org.springframework.web.bind.annotation.RequestMapping;
 5 import org.springframework.web.bind.annotation.RequestMethod;
 6 
 7 @FeignClient(value = "SERVICE-HELLOWORLD")
 8 public interface HelloWorldService {
 9     @RequestMapping(value = "/",method = RequestMethod.GET)
10     String sayHello();
11 }
Copy the code

Spring Cloud application at startup, Feign scans the marked @FeignClientannotation interface, proxy generation, and registered to Spring container. Feign created for each interface, a method to produce a proxy RequetTemplateobject that encapsulates all the information required for the HTTP request, the request parameter name, the request method and other information is determined in this process, the template of the reflected here Feign

5. Define a WebController.

Before implantation defined by the @FeignClient generated bean, 

sayHello () is mapped to http: // localhost: 8902 / hello, here, I modified the mapping Hello World Service, the root "/" modified into "/ hello".

Copy the code
 1 package springcloud.helloworld.feign.service;
 2 
 3 import org.springframework.beans.factory.annotation.Autowired;
 4 import org.springframework.web.bind.annotation.RequestMapping;
 5 import org.springframework.web.bind.annotation.RequestMethod;
 6 import org.springframework.web.bind.annotation.RestController;
 7 
 8 @RestController
 9 public class WebController {
10     @Autowired HelloWorldService helloWorldFeignService;
11     @RequestMapping(value = "/hello",method = RequestMethod.GET)
12     public String sayHello(){
13         return helloWorldFeignService.sayHello();
14     }
15 }
Copy the code

6. Start Feign application, visit http: // localhost: 8902 / hello, repeatedly refresh, and you can see the previous chapter Ribbon inside the application, the output of two alternating Hello World service. DESCRIPTION Feign access services, Spring Cloud has been used by default Ribbon load balancing.

                

6. In the Apache HTTP Client Feign

Feign using default JDK is native URLConnectionHTTP request, the pool is not connected, but are connected to each address a long gwai remains, namely the use of HTTP persistence connection . We may be replaced with the Apache HTTP Client Feign original http client, in order to gain control and performance is closely related to the connection pool timeout time. Spring Cloud from Brixtion.SR5version began to support this alternative, the first statement in Apache HTTP Client and project feign-httpclient-dependent:

Copy the code
 1 <!-- 使用Apache HttpClient替换Feign原生httpclient -->
 2         <dependency>
 3             <groupId>org.apache.httpcomponents</groupId>
 4             <artifactId>httpclient</artifactId>
 5         </dependency>
 6         <dependency>
 7             <groupId>com.netflix.feign</groupId>
 8             <artifactId>feign-httpclient</artifactId>
 9             <version>${feign-httpclient}</version>
10         </dependency>
Copy the code
Then add:application.properties
feign.httpclient.enabled=true

 7. Feign the Encoder, Decoder and ErrorDecoder

The method signature Feign method parameters into request parameters into the target sequence during the HTTP request, by an encoder (Encoder) completed. Similarly, the HTTP response data is deserialized into Java objects by a decoder (Decoder) completed. By default, will be marked with Feign @RequestParamconversion parameter annotated to add a string to the URL, the parameter will not be converted by the annotation to Jackson json into the request body. Note that if you @RequetMappingare methoddesignated as the request mode POST, then all solutions of unlabeled parameters will be ignored, for example:

@RequestMapping(value = "/group/{groupId}", method = RequestMethod.GET)
void update(@PathVariable("groupId") Integer groupId, @RequestParam("groupName") String groupName, DataObject obj);

At this time, because the declaration is no request body GET request, the objparameter is ignored.

In Spring Cloud environment, Feign the Encoder will not add parameters used to encode annotation. If you customize the Encoder, then only the coding objparameter will call your Encoder. For Decoder, the default will be entrusted to the SpringMVC MappingJackson2HttpMessageConverterdecode class. Only when the state code absence ErrorDecoder between 200 and 300 will be called. ErrorDecoder action is to return a response message exception that can be captured at the local call Feign interface according to HTTP. We have come to the Feign by ErrorDecoder interface to throw a business exception for the caller process.

First briefly explain what is declarative achieve?

Do one thing, you need to know three elements, where, what, how. That is what (where) do (what) where what way (how). When to do it (when) we included in the scope of how.

1) programmatically implemented: each element (where, what, how) are required to achieve a specific code is represented. The traditional way is generally programmatic implementation, developers need to be concerned about every business logic

2) declarative realization: only need to declare what to do and where (where) (what), without concern for how (how). Spring AOP is a kind of declarative implementations, such as Web site to check whether the login page logic of development, you can just needs to be done to check whether the user logs on (what) a statement by AOP configuration page loads (where), without concern for how to check whether the user Login (how). How to check this logic to achieve the AOP mechanism, AOP login to check implementation mechanism is being developed with the logic of the page itself is irrelevant.

In Spring Cloud Netflix stack, each micro services are exposed to their service in the form of an HTTP interface, so when calling a remote service must use the HTTP client. Feign Spring is a declarative REST client Cloud provides. REST interface can be called micro distal services provided by Feign access. Now we will use Feign to call SERVICE-HELLOWORLD exposed REST interface to get to the "Hello World" message. When using Feign, Spring Cloud integrates Ribbon Eureka to provide load balancing and HTTP client.

Here we are using Feign way to call the Hello World service cluster.

1. Create a Maven project, add spring-cloud-starter-feign dependent

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-feign</artifactId>
        </dependency>

Complete pom file 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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.chry</groupId>
<artifactId>springcloud.helloworld.feign.client</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>springcloud.helloworld.feign.client</name>
<description>Demo Feigh client application</description>

<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.3.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>

<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-feign</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>

<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Dalston.RC1</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>

<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
</project>

2. Create a startup class, you need to use it together with @EnableFeignClients comment Feign , automatic service discovery using open @EnableDiscoveryClient

Copy the code
 1 package springcloud.helloworld.feign.service;
 2 
 3 import org.springframework.boot.SpringApplication;
 4 import org.springframework.boot.autoconfigure.SpringBootApplication;
 5 import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
 6 import org.springframework.cloud.netflix.feign.EnableFeignClients;
 7 
 8 @SpringBootApplication
 9 @EnableDiscoveryClient
10 @EnableFeignClients
11 public class ServiceFeignApplication {
12     public static void main(String[] args) {
13         SpringApplication.run(ServiceFeignApplication.class, args);
14     }
15 }
Copy the code

3. Add Profile application.yml, using port 8902, the name is defined as a service-feign, and registered with the eureka service center

Copy the code
1 eureka:
2    client:
3       serviceUrl:
4         defaultZone: http://localhost:8761/eureka/
5 server:
6    port: 8902
7 spring:
8    application:
9       name: service-feign
Copy the code

4. Define Feign: an interface class annotated with @FeignClient,

@FeignClientFeign components used to notify the agent interface (no need to write interface), the user can directly through the @Autowiredinjection; This interface defines SERVICE-HELLOWORLD service (auto-discovery mechanism will locate specific URL through service centers) need to call by value ; @RequestMapping defined URL sERVICE-HELLOWORLD Feign need to access the service (in this example, the root "/")

Copy the code
 1 package springcloud.helloworld.feign.service;
 2 
 3 import org.springframework.cloud.netflix.feign.FeignClient;
 4 import org.springframework.web.bind.annotation.RequestMapping;
 5 import org.springframework.web.bind.annotation.RequestMethod;
 6 
 7 @FeignClient(value = "SERVICE-HELLOWORLD")
 8 public interface HelloWorldService {
 9     @RequestMapping(value = "/",method = RequestMethod.GET)
10     String sayHello();
11 }
Copy the code

Spring Cloud application at startup, Feign scans the marked @FeignClientannotation interface, proxy generation, and registered to Spring container. Feign created for each interface, a method to produce a proxy RequetTemplateobject that encapsulates all the information required for the HTTP request, the request parameter name, the request method and other information is determined in this process, the template of the reflected here Feign

5. Define a WebController.

Before implantation defined by the @FeignClient generated bean, 

sayHello () is mapped to http: // localhost: 8902 / hello, here, I modified the mapping Hello World Service, the root "/" modified into "/ hello".

Copy the code
 1 package springcloud.helloworld.feign.service;
 2 
 3 import org.springframework.beans.factory.annotation.Autowired;
 4 import org.springframework.web.bind.annotation.RequestMapping;
 5 import org.springframework.web.bind.annotation.RequestMethod;
 6 import org.springframework.web.bind.annotation.RestController;
 7 
 8 @RestController
 9 public class WebController {
10     @Autowired HelloWorldService helloWorldFeignService;
11     @RequestMapping(value = "/hello",method = RequestMethod.GET)
12     public String sayHello(){
13         return helloWorldFeignService.sayHello();
14     }
15 }
Copy the code

6. Start Feign application, visit http: // localhost: 8902 / hello, repeatedly refresh, and you can see the previous chapter Ribbon inside the application, the output of two alternating Hello World service. DESCRIPTION Feign access services, Spring Cloud has been used by default Ribbon load balancing.

                

6. In the Apache HTTP Client Feign

Feign using default JDK is native URLConnectionHTTP request, the pool is not connected, but are connected to each address a long gwai remains, namely the use of HTTP persistence connection . We may be replaced with the Apache HTTP Client Feign original http client, in order to gain control and performance is closely related to the connection pool timeout time. Spring Cloud from Brixtion.SR5version began to support this alternative, the first statement in Apache HTTP Client and project feign-httpclient-dependent:

Copy the code
 1 <!-- 使用Apache HttpClient替换Feign原生httpclient -->
 2         <dependency>
 3             <groupId>org.apache.httpcomponents</groupId>
 4             <artifactId>httpclient</artifactId>
 5         </dependency>
 6         <dependency>
 7             <groupId>com.netflix.feign</groupId>
 8             <artifactId>feign-httpclient</artifactId>
 9             <version>${feign-httpclient}</version>
10         </dependency>
Copy the code
Then add:application.properties
feign.httpclient.enabled=true

 7. Feign the Encoder, Decoder and ErrorDecoder

The method signature Feign method parameters into request parameters into the target sequence during the HTTP request, by an encoder (Encoder) completed. Similarly, the HTTP response data is deserialized into Java objects by a decoder (Decoder) completed. By default, will be marked with Feign @RequestParamconversion parameter annotated to add a string to the URL, the parameter will not be converted by the annotation to Jackson json into the request body. Note that if you @RequetMappingare methoddesignated as the request mode POST, then all solutions of unlabeled parameters will be ignored, for example:

@RequestMapping(value = "/group/{groupId}", method = RequestMethod.GET)
void update(@PathVariable("groupId") Integer groupId, @RequestParam("groupName") String groupName, DataObject obj);

At this time, because the declaration is no request body GET request, the objparameter is ignored.

In Spring Cloud environment, Feign the Encoder will not add parameters used to encode annotation. If you customize the Encoder, then only the coding objparameter will call your Encoder. For Decoder, the default will be entrusted to the SpringMVC MappingJackson2HttpMessageConverterdecode class. Only when the state code absence ErrorDecoder between 200 and 300 will be called. ErrorDecoder action is to return a response message exception that can be captured at the local call Feign interface according to HTTP. We have come to the Feign by ErrorDecoder interface to throw a business exception for the caller process.

Guess you like

Origin www.cnblogs.com/wzb0228/p/10973131.html