Directory navigation
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:
- Microservice topic 01-Spring Application
- Microservice topic 02-Spring Web MVC view technology
- Microservice topic 03-REST
- Microservice topic 04-Spring WebFlux principle
- Microservice topic 05-Spring WebFlux application
- Microservices topic 06-Cloud Native Applications
- Microservice topic 07-Spring Cloud configuration management
- Microservice topic 08-Spring Cloud service discovery
- Microservice topic 09-Spring Cloud load balancing
- Microservice topic 10-Spring Cloud service circuit breaker
- Microservice topic 11-Spring Cloud service call
- Microservice topic 12-Spring Cloud Gateway
- Microservice topic 13-Spring Cloud Stream (on)
- Microservice topic 14-Spring Cloud Bus
- Microservice topic 15-Spring Cloud Stream implementation
- Microservice topic 16-Spring Cloud overall review
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:
- 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.
- Spring WebMVC
For example, using a combined annotation:, @RestController
the effect is equivalent to using @Controller
+ @ResponseBody
+ @RequestBody
these three annotations at the same time .
- Spring Cloud
On RestTemplate
the basis of the support load balancing, only you need to add @LoadBalanced
annotations 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 @ResponseBody
can 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;
...
}
- 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 {
...
}
- 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
)
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
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
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 @GetMapping
kind of notes, etc. In fact, their meta-annotation is @RequestMapping
that the @RequestMapping
yuan marked @GetMapping
, but @GetMapping
specifies 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 @AliasFor
only 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 @GetMapping
customized a @OptionsMapping
comment. It is worth noting: If you do not increase the yuan notes @RequestMapping
, it would be an error, the other by the need @AliasFor
to redefine the property, so property alias by annotating and cover to complete a custom annotation.
Then look at SpringBootApplication Notes:
This is why we can use directly in the project start SpringBoot @EnableAutoConfiguration
reason, just as classes start this section of the same cache validation Demo. It is noteworthy that @EnableAutoConfiguration
from SpringFramework, which @SpringBootApplication
comes from SpringBoot jar package, put it plainly, is SpringBoot further package for Spring, so why learn SpringBoot to learn Spring, the reason why!
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
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 WebMvcConfigurer
achieve 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
, , @ResponseBody
I mentioned earlier, by default JSON protocol MappingJackson2HttpMessageConverter
processing, and TEXT protocol StringHttpMessageConverter
processing. Please refer to the source code for return value processing RequestResponseBodyMethodProcessor
.
Interface programming
ResponseEntity
And RequestEntity
then 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
@EnableWebMvc
It 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
@RequestBody
And@ResponseBody
implementation class: theRequestResponseBodyMethodProcessor
andHttpEntityMethodProcessor
.
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