The ninth chapter Spring Cloud Feign declarative call service

In the Spring Cloud Netflix stack, each microservice exposes its own services in the form of HTTP interface, so HTTP client must be used when calling remote services. We can use the native URLConnection of JDK, HttpClient of Apache and asynchronous HTTP of Netty Client, Spring's RestTemplate. But the most convenient and elegant thing to use is feign. In real projects, services are invoked declaratively. Instead of storing two copies of the same model and api definitions in the customer service end and the service end. Feign encapsulates RestTemplate to help us define and implement the definition of dependent service interface. Spring Cloud Feign based on Netflix Feign Implemented, organize Spring Cloud Ribbon And Spring CloudHystrix, and the implementation of declarative Web Services client definition.

The project structure is shown in the figure:


OrderController class

package com.example.demo.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

import com.example.demo.entity.User;
import com.example.demo.feign.UserFeignClient;

//Declarative service
@RestController
public class OrderController {
		
	  @Autowired
	  private UserFeignClient userFeignClient;

	  @GetMapping("/order/{id}")
	  public User findById(@PathVariable Long id) {
	    return this.userFeignClient.findById(id);
	  }

	  @GetMapping("/testPost")
	  public User testPost(User user) {
	    return this.userFeignClient.postUser(user);
	  }

	  @GetMapping("/testGet")
	  public User testGet(User user) {
	    return this.userFeignClient.getUser(user);
	  }
}

User class

package com.example.demo.entity;

import java.math.BigDecimal;

public class User {
  private Long id;

  private String username;

  private String name;

  private Short age;

  private BigDecimal balance;

  public Long getId() {
    return this.id;
  }

  public void setId(Long id) {
    this.id = id;
  }

  public String getUsername() {
    return this.username;
  }

  public void setUsername(String username) {
    this.username = username;
  }

  public String getName() {
    return this.name;
  }

  public void setName(String name) {
    this.name = name;
  }

  public Short getAge() {
    return this.age;
  }

  public void setAge(Short age) {
    this.age = age;
  }

  public BigDecimal getBalance() {
    return this.balance;
  }

  public void setBalance(BigDecimal balance) {
    this.balance = balance;
  }

}

UserFeignClient class

package com.example.demo.feign;

import org.springframework.cloud.netflix.feign.FeignClient;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import com.example.demo.entity.User;

////Declarative service
@FeignClient("spring-cloud-user") // The name of which service to call
public interface UserFeignClient {

	@RequestMapping(value = "/user/{id}", method = RequestMethod.GET)
	public User findById(@PathVariable("id") Long id); // 1. @GetMapping does not support 2
														// @Setting value of PathVariable

	@RequestMapping(value = "/testPost", method = RequestMethod.POST)
	public User postUser(@RequestBody User user);

	// The request will not succeed. As long as the parameter is a complex object and even if the GET method is specified, feign will still send the request in the POST method
	@RequestMapping(value = "/getUser", method = RequestMethod.GET)
	public User getUser(User user);
}

SpringCloudOrderApplication class

package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.feign.EnableFeignClients;

/**
 * Declarative service
 *
 */

@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients//Represent as a Fegin client
public class SpringCloudOrderApplication {
	
	public static void main(String[] args) {
		SpringApplication.run(SpringCloudOrderApplication.class, args);
	}
}

application.yml configuration

spring:
  application:
    name: spring-cloud-order-feign    #Name of the microservice
server:
  port: 7906  #Microservice port number
eureka:
  client:
    healthcheck: 
      enabled: true   # Open health check
    serviceUrl:
      defaultZone: http://user:123456@localhost:8761/eureka ා URL of eureka service
  instance:
    prefer-ip-address: true
# Solution to the timeout exception of the first request:
hystrix: 
  command: 
    default: 
      execution: 
        isolation: 
          thread: 
            timeoutInMilliseconds: 5000
# Or:
# hystrix.command.default.execution.timeout.enabled: false
# Or:

# Timeout issue: https://github.com/spring-cloud/spring-cloud-netflix/issues/768
# Timeout solution: http://stackoverflow.com/questions/27375557/hystrix-command-failures-with-timed-out-and-no-fallback-available
# hystrix to configure: https://github.com/Netflix/Hystrix/wiki/Configuration#execution.isolation.thread.timeoutInMilliseconds


pom.xml configuration

<?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.example.demo</groupId>
	<artifactId>spring-cloud-order_feign</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>war</packaging>

	<name>spring-cloud-order_feign</name>
	<description>spring-cloud-order_feign</description>

	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>1.4.1.RELEASE</version>
	</parent>

	<properties>
		<!-- Encoding when copying files -->  
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
		  <!-- Compile time encoding -->  
        <maven.compiler.encoding>UTF-8</maven.compiler.encoding>  
        <!-- jdk Edition -->  
		<java.version>1.8</java.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<!-- Registration Center -->
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-eureka</artifactId>
		</dependency>
		<!-- This library allows us to access a lot of information about the application,Include:/env,/info,/metrics,/health etc. -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-actuator</artifactId>
		</dependency>
		<!-- Add declarative feign rely on -->
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-feign</artifactId>
		</dependency>
		
		<!-- For hot deployment -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-devtools</artifactId>
		</dependency>		
	</dependencies>
	<dependencyManagement>
		<dependencies>
		<!-- Version dependency management, so you do not need to specify to add a dependency later version -->
			<dependency>
				<groupId>org.springframework.cloud</groupId>
				<artifactId>spring-cloud-dependencies</artifactId>
				<version>Camden.SR2</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
		</dependencies>
	</dependencyManagement>

	<build>
		<plugins>
		<!-- To think integration-test Provide support. -->
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>
</project>







Tags: Spring Maven encoding Apache

Posted on Thu, 30 Apr 2020 22:26:04 -0700 by adksga