An overview of the

In microservices architecture, the most common scenario is that microservices call each other. Microservices are mainly called by RestTemplate, Feign, and OpenFeign.

RestTemplate

  • RestTemplate is a tool for making remote Http calls. It encapsulates Java’s underlying Http and allows users to ignore the underlying connection establishment.
  • RestTemplate is a client provided by Spring for accessing Rest services. RestTemplate provides multiple convenient methods for accessing remote Http services, which greatly improves client writing efficiency
  • RestTemplata not only supports RESTful specifications, but also defines return value object types.
  • RestTemplate supports local client load balancing and encapsulates the Ribbon.

I sorted out some information, and friends in need can click to get it directly.

Java Basics

One hundred Core Java architect books

Standard Ali P8 Java learning route and information

The latest collection of Java interview questions for 2021

Feign

  • Feign is a declarative lightweight RESTful HTTP service client in the Spring Cloud component.
  • Feign has a built-in Ribbon for client load balancing to invoke services in the service registry.
  • Feign is used by defining an interface with Feign’s annotations, and then calling the interface to invoke the service registry’s services as if they were local methods, with no sense of the remote method being invoked.
  • Feign itself does not support SpringMVC annotations, it has its own annotations;

OpenFeign

  • OpenFeign is a Spring Cloud annotation that supports SpringMVC on top of Feign, such as @requesMapping, etc.
  • OpenFeign’s @FeignClient can parse the interface under SpringMVC’s @RequestMapping annotation and generate implementation classes through dynamic proxy, which can perform load balancing and call other services.

Create a microservice consumer submodule

Create a micro-service consumer sub-module springboot project under Alibaba-server sub-project, and the final file directory is as follows:

Add dependency to poM file of microservice consumer submodule Alibaba-server-Consumer:

<dependencies> <! -- Web application --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId> Spring-boot-starter -web</artifactId> </dependency> <! - Must contain the spring-boot-starter-actuator package; otherwise, an error occurs when operating. --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <! - integration nacos configuration required jars - > < the dependency > < groupId > org. Springframework. Cloud < / groupId > < artifactId > spring - the cloud - starter - alibaba - nacos - config < / artifactId > < version > 2.2.1. RELEASE < / version > < / dependency > <! Nacos - integration service registry - > < the dependency > < groupId > org. Springframework. Cloud < / groupId > < artifactId > spring - the cloud - starter - alibaba - nacos - discovery < / artifactId > < version > 2.2.1. RELEASE < / version > < / dependency > <! -- sentinel --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId> </dependency> <! -- lombok --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> < version > 1.18.2 < / version > < optional > true < / optional > < / dependency > < / dependencies >Copy the code

Register consumer microservices alibaba- Server-consumer on nacOS

The configuration is as follows:

Invoke the provider microservice

Use RestTemplate

The controller of the provider alibaba-server-HelloWorld microservice is as follows:

@RestController
@RequestMapping("/lhj")
public class HelloWorlsController {
    @RequestMapping("/hello")
    public String hello(){
        return "hello world!";
    }
}

Copy the code

The port number is 8006 and the context is Hello

Add a RestTemplate configuration class

@component public class RestTemplateConfig {@bean @loadBalanced // load balancing, Public RestTemplate RestTemplate() {return new RestTemplate(); }}Copy the code

Start the class

@SpringBootApplication @EnableDiscoveryClient public class ConsumerApplication { public static void main(String[] args) { SpringApplication.run(ConsumerApplication.class, args); }}Copy the code

Calls remote services in controller

Note: Using @AutoWired to inject the restTemplate can only invoke the service in a third way, since the @Autowired injected restTemplate cannot access the address directly, only through the registered service application name.

@RestController public class ConsumerController { @Autowired private LoadBalancerClient loadBalancerClient; // Add loadBalancerClient@autoWired private RestTemplate RestTemplate; Public ResponseEntity<String> MSG (){//1; RestTemplate restTemplate = new restTemplate (); ResponseEntity<String> response = restTemplate.getForEntity("http://localhost:8006/hello/lhj/hello", String.class); //2. Use the loadBalancerClient to obtain the URL from the application name and then use the restTemplate directly. ServiceInstance ServiceInstance = loadBalancerClient.choose("alibaba-server-helloworld"); String url = String.format("http://%s:%s",serviceInstance.getHost(),serviceInstance.getPort())+"/hello/lhj/hello"; RestTemplate restTemplate = new RestTemplate(); String response = restTemplate.getForObject(url, String.class); // 2. RestTemplate = new restTemplate (); //3. String response = restTemplate.getForObject("http://PRODUCT/msg", String.class); log.info("response={}",response); return response; System.out.println(response.getStatusCode()); System.out.println(response.getBody()); System.out.println(response.getHeaders()); return response; }}Copy the code

There are three ways to call RestTemplate

The first option is to write the url directly to the service’s access address (a new restTemplate must be used, not an injected one).

RestTemplate restTemplate = new RestTemplate();  
String response = restTemplate.getForObject("http://localhost:8006/hello/lhj/hello",String.class)
return response;

Copy the code

2: loadBalancerClient obtains the URL from the application name and then uses the restTemplate (a new restTemplate must be used, not an injected one)

ServiceInstance serviceInstance = loadBalancerClient.choose("alibaba-server-helloworld"); 
String url = String.format("http://%s:%s",serviceInstance.getHost(),serviceInstance.getPort())+"/hello/lhj/hello";
RestTemplate restTemplate = new RestTemplate(); 
String response = restTemplate.getForObject(url, String.class); 
return response;

Copy the code

Third way: Use @loadBalanced in the configuration class to directly use the service application name in the restTemplate (you can use the injected restTemplate)

String response = restTemplate.getForObject("http://alibaba-server-helloworld/hello/lhj/hello", String.class); 
return response;

Copy the code

Note: The address injected into the restTemplate with @AutoWired is not directly accessible, only through the registered service application name

The return value type of restTemplate

There are two classes of return value types, getForEntity and getForObject, each of which has three overloaded methods.

If you want to get a response header, you need to use getForEntity to send an HTTP request. The object returned is an instance of ResponseEntity. This instance contains the response data and the response header. ② getForObject getForObject method parameters and getForEntity, getForObject return value is the data returned by the service provider, using getForObject can not get the response header.

Browser access

Use Feign

File structure for consumer Alibaba-server-consumer microservices

The controller of the provider alibaba-server-HelloCloud microservice is as follows:

@RestController @RequestMapping("zj") public class HelloCloudController { @RequestMapping("hello") public String hello(String name){ return "hello cloud,"+name; }}Copy the code

The port number is 8007 and the context is Hello

Feign principle

● At startup, the program does a package scan, scans all @FeignClient-annotated classes in all packages, and injects these classes into Spring’s IOC container. The RequestTemplate is generated through the JDK’s dynamic proxy when the interface in the defined Feign is called. ● RequestTemplate contains all information about the request, such as request parameters, request URL, etc. RequestTemplate Request, and then send the Request to the client. This client is either HTTPUrlConnection of the JDK by default, or HTTPClient of Apache or OKhttp. ● finally, the client is packaged as a LoadBaLanceClient, and the ribbon load balances the calls.

(1) Add Feign dependency to POM file

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

Copy the code

(2) Add the @enableFeignClients annotation to the startup class

Add the @enableFeignClients annotation to the service’s startup class to enable Spring Cloud Feign support.

@SpringBootApplication @EnableDiscoveryClient @EnableFeignClients public class ConsumerApplication { public static void main(String[] args) { SpringApplication.run(ConsumerApplication.class, args); }}Copy the code

(3) Declare the service interface

@service @feignClient ("alibaba-server-hellocloud") // Spring.application. Name public interface FeignService { @requestMapping (value="/hello/zj/hello") @requestParam (value="name") String getService(@requestParam (value="name") String name); }Copy the code

① Methods in the interface can be arbitrarily named without adding public. ② In this interface, the @FeignClient annotation is used to specify the name of the service to be called to bind the service, and the Spring MVC annotation @requestMapping is used to bind the REST interface provided by the service. ③ The @requestParam annotation must include a value attribute.

(4) Call service interface in controller

@RestController public class ConsumerController { @Autowired private FeignService feignService; @GetMapping("/diaoyong") public String msg(){ return feignService.getService("lhj"); }}Copy the code

(5) Browser access

(6) Feign enables logging

If we want to track data sent by the Feign client, we need to enable Feign’s logging.

Feign creates an instance of Feign.logger for each client when it builds a service client decorated with the @FeignClient annotation, so that the DEBUG mode of the log object can be used to help analyze Feign’s request details.

Opening method:

① Configuration file open: In application. Yml, use the parameter configuration format of logging.level.{fully qualified name of the interface corresponding to Feign client} to enable logging on the specified client

Logging: level: {fully qualified name of the interface corresponding to the Feign client}: debugCopy the code

The @enableFeignClients annotation has a defaultConfiguration attribute that specifies the configuration of the default FeignClient.

@EnableFeignClients(defaultConfiguration =DefaultFeignConfiguration.class) @SpringBootApplication public class ProductApplication { public static void main(String[] args) { SpringApplication.run(ProductApplication.class, args); }}Copy the code
@Configuration public class DefaultFeignConfiguration { @Bean public Logger.Level feignLoggerLevel(){ return Logger.Level.FULL; }}Copy the code

Considerations for using Feign

The @requestBody annotation must be used when Feign’s service declaration interface uses an object as a parameter to receive it as JSON

	void insert(@RequestBody User user);  

Copy the code

The @requestParam attribute must be added to the Feign service declaration interface

	void delete(@RequestParam("accountCode") String accountCode); 
Copy the code

3. If you use @pathVariable in Feign’s service declaration interface, you must add the value attribute as above

	 ResultData<AccountDTO> getByCode(@PathVariable(value = "accountCode") String accountCode);  
Copy the code

(4) Specify the package path where the Feign interface resides by using @enableFeignClients annotation on the consumer module startup class

	 @EnableFeignClients(basePackages = "com.javadaily.feign.*")

Copy the code

The last