Microservice topic 03-REST

Preface

In the previous chapter, we talked about Spring Web MVC . In this section, continue to share the content of the microservice topic, a total of 16 sections, namely:

The key points of this section are:

  • REST theoretical basis: basic concepts, architectural properties, architectural constraints, usage scenarios, implementation framework (server, client)
  • REST server practice: Spring Boot REST application, HATEOAS application, document generation, etc.
  • REST client practice: traditional browsers, Apache HttpClient, Spring RestTemplate and other related practices

REST theoretical basis

I introduced Spring's MVC combined with view to display data. In addition to using JavaScript to call these data in WebBrowser, you can also use the remote server's Java program and C# program to call. In other words, the current program can be called not only in BS, but also in CS, but you need to use the RestTemplate class to complete. RestTemplate is a bit similar to a template requested by a WebService client. It can call the WebService requested by http and convert the result into the corresponding object type.

RPC

Q: What is RPC?

A: RPC stands for Remote Procedure Call, which translates to remote service call.

Q: What is the connection between RPC and REST?

A: The previous section introduced that Spring MVC can render data to the front end through its view technology. In addition to calling these data through browsers such as JS, they can also be called using Java programs and C# programs on remote servers. In other words, the current program can be called not only in the B/S architecture, but also in the C/S architecture. There are usually two ways to implement it:

  • Service Oriented Architecture (SOA)

It is usually achieved with the help of Web Services. Such as SOAP (Transmission Medium Protocol) or HTTP, SMTP (Communication Protocol).

  • Microservices (MSA)

It is usually achieved with REST. We know that REST often uses media: HTML, JSON, XML, etc. The realization principle is based on HTTP (communication protocol).

There are usually two versions of HTTP: one is HTTP 1.1, which uses a short connection (Keep-Alive); the other is HTTP/2, which uses a long connection.

In terms of technical implementation, RPC has three implementation methods:

  1. Spring client: RestTemplate

RestTemplate is a bit similar to a template requested by a WebService client. It can call the WebService requested by http and convert the result into the corresponding object type.

  1. Spring WebMVC

For example, using a combined annotation:, @RestControllerthe effect is equivalent to using @Controller+ @ResponseBody+ @RequestBodythese three annotations at the same time .

  1. Spring Cloud

On RestTemplatethe basis of the support load balancing, only you need to add @LoadBalancedannotations to.

If you want to know more about REST theory, you can refer to this WIKI .

Cacheability

As on the World Wide Web, clients and intermediaries can cache responses. The response must implicitly or explicitly define itself as cacheable or non-cacheable to prevent the client from providing stale or inappropriate data in response to other requests. A well-managed cache partially or completely eliminates some client-server interactions, thereby further improving scalability and performance.

So how do we understand the cached response problem? In fact, the above mentioned annotation @ResponseBodycan be understood as a response body (Response Body). We know that the response is usually divided into two parts: response header and response body:

Refer to the HttpEntity source code, which contains the response header and response body:

  public class HttpEntity<T> {
    
    
  	...
  	
  	//响应头
  	private final HttpHeaders headers;
  
  	//响应体
  	private final T body;
  	
  	...
  }
  1. Response header (Headers)

The response header is used to store Meta-Data, such as setting up Connection to Keep-Alive to establish a long connection, setting Accept-Language to automatically identify Locale parsing language, and so on.

Q: So how does the response header store the functions corresponding to many fields?

A: According to the source code analysis, the request header is designed by a multi-value Map (multi-value Map is a structure provided by Spring) (that is, one Key corresponds to multiple Values).

Refer to the source code of HttpHeaders, which implements MultiValueMap:

public class HttpHeaders implements MultiValueMap<String, String>, Serializable {
    
    
    ...
}
  1. Response body (Body/Payload)

Usually in HTTP entity or REST scenarios, we call it Body; in messaging (JMS), event, SOAP, and other scenarios, we call it Payload.

The response body is used to store business information (Business Data). Usually HTTP entities, REST.

HTTP status code

You can refer to the source code: ( org.springframework.http.HttpStatus)

Insert picture description here
Regarding http status codes, the common ones are:

status code Enumerated field Remarks
200 OK Request succeeded
304 NOT_MODIFIED If the client sends a conditional GET request and the request has been allowed, but the content of the document has not changed, the server should return this status code.
400 BAD_REQUEST The semantics are wrong, or the request parameters are wrong.
404 NOT_FOUND The request failed, and the requested resource was not found on the server.
500 INTERNAL_SERVER_ERROR The server encountered an unexpected situation that caused it to fail to complete the processing of the request.

Cache verification Demo :
startup class:

@EnableAutoConfiguration
@ComponentScan(basePackages = "com.test.micro.services.mvc.controller")
public class MvcRestApplication {
    
    

    public static void main(String[] args) {
    
    
        new SpringApplicationBuilder(MvcRestApplication.class)
                .run(args);
    }

}

CachedRestController

@Controller
public class CachedRestController {
    
    

      //  Spring MVC 返回值处理
      @RequestMapping("/cache") 
      public ResponseEntity<String> cachedHelloWorld(
              @RequestParam(name = "cached", required = false, defaultValue = "false") String cached) {
    
    
          if (!"false".equals(cached)) {
    
    
              //缓存返回 304
              return new ResponseEntity(HttpStatus.NOT_MODIFIED);
          } else {
    
    
              //不缓存返回 200
              return ResponseEntity.ok("Hello,World");
          }
      }
}

Code test:

First visit address:
http://localhost:8080/cache?chched=false

Insert picture description here
Do not join the cache, the http response code is 200

Control the cache in the url, the address of the second request http://localhost:8080/cache?cached=ture
Insert picture description here

After joining the cache, the http response code is 304

Analysis of results:

  • For the first complete request, get the response header (200) and get it directly.
  • For the second request, only the header information is read, the response header (304), the client (browser) fetches the last body result.

Uniform interface

URI & URL

The difference between URI and URL:

First look at the difference between URI and URL fields literally: U refers to Uniform, and R refers to Resource. The difference is that I focuses on identification, while L focuses on positioning.

In layman's terms, take an example: There is a person named Zhang San in Shandong and Henan. Zhang San is the so-called URI, and the specific Zhang San in Henan or Zhang San in Shandong is the so-called URL.

Expansion:

URI = scheme:[//authority]path[?query][#fragment] 。

The usual ways to implement scheme in URI are: HTTP, WeChat. The scheme generally refers to the protocol in the URL.

Resource operation

Here are some common methods of restful http:

HTTP verb Corresponding notes Remarks
GET @GetMapping Used to obtain resources.
PUT @PutMapping Used to create and update resources.
POST @PostMapping Used to create sub-resources.
PATCH @PatchMapping Used to create and update resources, similar to PUT, except that PATCH stands for partial update.
DELETE @DeleteMapping Delete resources.

Special note about PATCH verb:

Limitations of PATCH: Servlet API does not specify PATCH, but Spring Web has extended it:

 public abstract class FrameworkServlet extends HttpServletBean implements ApplicationContextAware {
    
    
    
        ...
    @Override    
    protected void service(HttpServletRequest request, HttpServletResponse response)
    			throws ServletException, IOException {
    
    
    
    		HttpMethod httpMethod = HttpMethod.resolve(request.getMethod());
    		if (httpMethod == HttpMethod.PATCH || httpMethod == null) {
    
    
    			processRequest(request, response);
    		}
    		else {
    
    
    			super.service(request, response);
    		}
    	}
        ...
    }

Previously, in the first section, we discussed the problem of pattern annotation (annotation derivation) of the Spring annotation programming model. Here are some issues related to the alias and coverage of annotation attributes of the Spring annotation programming model .

In the above-mentioned @GetMappingkind of notes, etc. In fact, their meta-annotation is @RequestMappingthat the @RequestMappingyuan marked @GetMapping, but @GetMappingspecifies the way the current request is Get. We can find out by looking at the source code:

    // 注解“派生性”
    @RequestMapping(method = RequestMethod.GET) 
    public @interface GetMapping {
    
    
        ...
        // 注解别名
        @AliasFor(annotation = RequestMapping.class) 
    	String name() default "";
        ...
    }

Tips: Regarding the features of annotated attribute alias and coverage, it was introduced in Spring Framework 4.2. It can only be used after Spring Boot 1.3, but it is Spring Boot that develops it.

Here's @AliasForonly goal mark in annotation properties, the annotation()notes must be meta-annotation, the annotation attribute()must be meta-annotation attributes.

for example:

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@RequestMapping(method = RequestMethod.OPTIONS)
public @interface OptionsMapping {
    
    
    
    // 指定 RequestMethod 的属性
    @AliasFor(annotation = RequestMapping.class) 
    // 不加的话,只是代表自己
    String name() default ""; 

}

Here I simulate @GetMappingcustomized a @OptionsMappingcomment. It is worth noting: If you do not increase the yuan notes @RequestMapping, it would be an error, the other by the need @AliasForto redefine the property, so property alias by annotating and cover to complete a custom annotation.

Then look at SpringBootApplication Notes:
Insert picture description here
This is why we can use directly in the project start SpringBoot @EnableAutoConfigurationreason, just as classes start this section of the same cache validation Demo. It is noteworthy that @EnableAutoConfigurationfrom SpringFramework, which @SpringBootApplicationcomes from SpringBoot jar package, put it plainly, is SpringBoot further package for Spring, so why learn SpringBoot to learn Spring, the reason why!
Insert picture description here

Custom annotation

Based on the above knowledge points, let's imitate springboot to define a custom annotation: for
example, implement the annotation that not only injects the bean but also implements the transaction:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Service // 它是 @Service 组件
@Transactional // 它是事务注解
public @interface TransactionalService {
    
     //  @Service + @Transactional

    @AliasFor(annotation = Service.class)
    String value(); // 服务名称

    @AliasFor(annotation = Transactional.class,attribute = "value")
    String txName();
}

Called at the service layer:

@TransactionalService(value = "echoService-2020", txName = "myTxName") // @Service Bean + @Transactional
// 定义它的 Bean 名称
public class EchoService {
    
    

    public void echo(String message) {
    
    
        System.out.println(message);
    }
}

Test category:

@ComponentScan(basePackages = "com.test.micro.services.mvc.service")
@EnableTransactionManagement
public class SpringApplication {
    
    

    @Component("myTxName")
    public static class MyPlatformTransactionManager implements PlatformTransactionManager {
    
    

        @Override
        public TransactionStatus getTransaction(@Nullable TransactionDefinition definition) throws TransactionException {
    
    
            return new DefaultTransactionStatus(
                    null, true, true,
                    definition.isReadOnly(), true, null
            );
        }

        @Override
        public void commit(TransactionStatus status) throws TransactionException {
    
    
            System.out.println("Commit()....");
        }

        @Override
        public void rollback(TransactionStatus status) throws TransactionException {
    
    
            System.out.println("rollback()....");
        }
    }

    public static void main(String[] args) {
    
    
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
        // 注册 SpringApplication 扫描  com.test.micro.services.mvc.service
        context.register(SpringApplication.class);

        context.refresh(); // 启动

        context.getBeansOfType(EchoService.class).forEach((beanName, bean) -> {
    
    
            System.err.println("Bean Name : " + beanName + " , Bean : " + bean);

            bean.echo("Hello,World");
        });

        context.close(); // 关闭
    }
}

Test result: It
Insert picture description here
shows that this annotation is effective, and the service is injected and the transaction is realized!

Self-describing message

The so-called self-describing information means that each message contains enough information to describe how to process the message, so that the code can process and parse the content.

The Jackson2 serialization method is used by default in SpringBoot, where the media type is application/json, and its processing class MappingJackson2HttpMessageConverter, so the browser access displays json. You also can go rewrite WebMvcConfigurerachieve different serialization rules, coding rules, media types and other configurations.

Next, let's take a look at the ways in which SpringBoot supports REST?

Annotation driven

Common example @RequestBody, , @ResponseBodyI mentioned earlier, by default JSON protocol MappingJackson2HttpMessageConverterprocessing, and TEXT protocol StringHttpMessageConverterprocessing. Please refer to the source code for return value processing RequestResponseBodyMethodProcessor.

Interface programming

ResponseEntityAnd RequestEntitythen inherit from HttpEntity. HttpEntity is the original HTTP information we mentioned earlier, including the request header and the request body. To put it bluntly, both Request and Response actually care most about the request header and request body. Please refer to the source code for return value processing HttpEntityMethodProcessor.

Media type ( MediaType)

The common application / json; charset = UTF- 8, where the source directory: org.springframework.http.MediaType#APPLICATION_JSON_UTF8_VALUE.

The HTTP message converter ( HttpMessageConverter) mentioned many times earlier also contains this attribute: application/json, where the source code path is located MappingJackson2HttpMessageConverter. text/html, where the source code path is located StringHttpMessageConverter.

@EnableWebMvc Source code guide

@EnableWebMvcIt is an annotation to quickly configure Spring WebMVC using Java annotations. After using this annotation, configure a configuration class inherited from WebMvcConfigurerAdapter to configure Spring WebMVC.

First, you need to import DelegatingWebMvcConfiguration(configure Class), and then register WebMvcConfigurer. In the process, you need to assemble various Beans and annotation-driven extension points required by Spring MVC:

  • HandlerMethodArgumentResolver
  • HandlerMethodReturnValueHandler
  • @RequestBodyAnd @ResponseBodyimplementation class: the RequestResponseBodyMethodProcessorand HttpEntityMethodProcessor.

postscript

Q: The difference between front-end separation and server-side rendering

A: Server rendering, data calculation + HTML rendering are all done on the server.

Front-end and back-end: data calculation is provided by the server, JSON Web endpoint (REST Web interface), HTML is completed by the main front-end JS, with React, Vue.js (front-end template engine)

Sample code in this section: https://github.com/harrypottry/microservices-project/spring-mvc-rest

For more architectural knowledge, please pay attention to this series of articles on Java : The Road to Growth of Java Architects

Guess you like

Origin blog.csdn.net/qq_34361283/article/details/106296164