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