Summary of Spring MVC request parameter reception
premise
In the daily use of Spring MVC for development, it is possible to encounter various types of front-end request parameters. Here is a relatively comprehensive summary. Handler Method ArgumentResolver is the interface to process controller parameters in Spring MVC. There are many subclasses of this interface, which deal with different parameters (annotation type). Here are just a few subclasses:
- RequestParamMethod ArgumentResolver: The parsing process uses @RequestParam annotation parameters, MultipartFile type parameters, and Simple type parameters (such as long, int).
- RequestResponseBody Method Processor: Parses the parameters that process the @RequestBody annotation.
- PathVariableMapMethodArgumentResolver: Parses the parameters that process the @PathVariable annotation.
In fact, in general, when parsing a controller's request parameters, you use the HandlerMethodArgumentResolver Composite, which loads all the enabled HandlerMethodArgumentResolver subclasses. The Handler Method ArgumentResolver subclass uses the HttpMessageConverter (actually a list, traversal matching parsing) subclass for matching parsing when parsing parameters, such as Mapping Jackson 2HttpMessageConverter. What HttpMessageConverter instance does the Handler Method ArgumentResolver subclass depend on is actually determined by ContentType in the request header (uniformly named MediaType in Spring MVC, see org. spring framework. http. MediaType). Therefore, we must specify the COO of the external request before processing the request parameters of the controller. What exactly is content type? The above logic can directly see the source code AbstractMessageConverter Method ArgumentResolver # readWithMessageConverters, the idea is relatively clear. In the @RequestMapping annotation, produces and consumes are related to the ContentType of the request or response:
- consumes: Specify the type of submitted content (ContentType) that handles the request, such as application/json, text/html, and accept the request only if it hits.
- produces: Specifies the content type returned, which is returned only if the type in the request request request header contains the specified type. If the JSON data is returned, application/json is generally used; charset = UTF-8.
In addition, the default use of Jackson as a JSON toolkit in Spring MVC is not recommended to modify the default Mapping Jackson 2HttpMessageConverter (for example, some people like to use FastJson to implement the introduction of HttpMessageConverter into FastJson as a converter) unless they fully understand the operation of the entire source code.
Reception of Spring MVC request parameters
In fact, the request of general form or JSON data is relatively simple. Some complex processing mainly includes URL path parameters, file upload, array or list type data. In addition, regarding the existence of date type attributes in parameter types (such as java.util.Date, java.sql.Date, java.time.LocalDate, java.time.LocalDateTime), it is generally necessary to customize the logic to implement String-> date type conversion when parsing. The truth is simple. Date-related types are different for each country, time zone and even for each user. In the demonstration, some examples are mainly used for the following model classes:
@Data
public class User {
private String name;
private Integer age;
private List<Contact> contacts;
}
@Data
public class Contact {
private String name;
private String phone;
}
Form parameter
Single parameter reception for non-object type:
This is the most commonly used form parameter submission. ContentType is specified as application/x-www-form-urlencoded, which is the URL encoding.
The corresponding controller is as follows:
@PostMapping(value = "/post")
public String post(@RequestParam(name = "name") String name,
@RequestParam(name = "age") Integer age) {
String content = String.format("name = %s,age = %d", name, age);
log.info(content);
return content;
}
To be honest, with perseverance, all complex parameter submissions can eventually be translated into multiple single parameter receivers, but doing so will result in a lot of redundant code and low maintainability. In this case, the parameter processor used is RequestParamMapMethodArgumentResolver.
Object type parameter reception:
We then write an interface for submitting user information, using the above mentioned model classes, mainly including user name, age and contact information list. At this time, our target controller is finally coded as follows:
@PostMapping(value = "/user")
public User saveUser(User user) {
log.info(user.toString());
return user;
}
We also specify ContentType as application/x-www-form-urlencoded, and then we need to construct the request parameters:
Because no annotations are used, the final parameter processor is ServletModelAttributeMethodProcessor, which encapsulates the form parameters in HttpServletRequest into Mutable Property Values instances, and then instantiates the parameter types (creating User instances by constructing reflections) to fill in the values by reflecting matching attributes. In addition, the list attribute request parameters in the request complex parameters look fantastic, and in fact they are written in the same way as the parameters that are finally mapped to the Map type are added to the. properties file. So, can you insert the whole request parameter into a field and submit it it?
It is not possible to do this directly, because the form form form actually submitted, key is user, value is actually a string, lacking a String - > User type converter. In fact, RequestParamMethod ArgumentResolver relies on the Converter list in WebConversion Service for parameter conversion:
The solution still exists, just add an implementation of org. spring framework. core. convert. converter. Converter:
@Component
public class StringUserConverter implements Converter<String, User> {
private static final ObjectMapper MAPPER = new ObjectMapper();
@Override
public User convert(String source) {
try {
return MAPPER.readValue(source, User.class);
} catch (IOException e) {
throw new IllegalArgumentException(e);
}
}
}
The above approach is a curve salvation approach and is not recommended in the production environment, but if some third-party interface docking can not avoid this parameter, you can choose this way of implementation.
JSON parameter
Generally speaking, POST a JSON string directly is a friendly way for Spring MVC. Just set ContentType to application/json and submit a raw JSON string:
The code of the back-end controller is also relatively simple:
@PostMapping(value = "/user-2")
public User saveUser2(@RequestBody User user) {
log.info(user.toString());
return user;
}
Because of the @RequestBody annotation, the final parameter processor used is RequestResponseBodyMethodProcessor. In fact, Mapping Jackson 2HttpMessageConverter is used to convert parameter types, and the underlying layer relies on Jackson-related packages.
URL parameter
The URL parameter, or request path parameter, is based on the parameters obtained from the URL template. For example, / user/{userId} is a URL template (the parameter placeholder in the URL template is {}), and the actual requested URL is / user/1. Then the userId can be extracted to 1 by matching the actual requested URL and URL template. In Spring MVC, the path parameter in the URL template is called PathVariable, corresponding to the annotation @PathVariable, and the corresponding parameter processor is PathVariable Method ArgumentResolver. Note that the @PathVariable parse matches the value(name) attribute irrespective of the order of the URL parameters. For a simple example:
The background controller is as follows:
@GetMapping(value = "/user/{name}/{age}")
public String findUser1(@PathVariable(value = "age") Integer age,
@PathVariable(value = "name") String name) {
String content = String.format("name = %s,age = %d", name, age);
log.info(content);
return content;
}
This usage is widely used in the Representational State Transfer(REST) software architecture style, which I personally feel is more flexible and clear (from the URL and request method can fully understand the meaning and function of the interface). Here are two relatively special ways to use them.
Conditional URL parameters
In fact, path parameters support regular expressions. For example, when we use the / sex/{sex} interface, we require sex to be either F(Female) or M(Male). Then our URL template can be defined as / sex/{sex:M|F}. The code is as follows:
@GetMapping(value = "/sex/{sex:M|F}")
public String findUser2(@PathVariable(value = "sex") String sex){
log.info(sex);
return sex;
}
Only requests from / sex/F or / sex/M enter the findUser2 controller method, and other requests for the path prefix are illegal and return a 404 status code. Here is just an introduction to the use of the simplest URL parameter regular expression. The more powerful use can be explored by itself.
@ Use of Matrix Variable
Matrix Variable is also a kind of URL parameter, corresponding to the annotation @Matrix Variable, but it is not a value in the URL (where the value is specified between two "/"), but a part of the value, which is separated by ";" and set by "=". For example, if we need to call a programmer whose name is Doge and the gender is male and the grouping is code animal, the URL of GET request can be expressed as: / call/doge;gender=male;group=programmer. The controller method we designed is as follows:
@GetMapping(value = "/call/{name}")
public String find(@PathVariable(value = "name") String name,
@MatrixVariable(value = "gender") String gender,
@MatrixVariable(value = "group") String group) {
String content = String.format("name = %s,gender = %s,group = %s", name, gender, group);
log.info(content);
return content;
}
Of course, if you write the code according to the example above, try to request that the interface discovery is false: 400 Bad Request - Missing matrix variable'gender'for method parameter of type String. This is because the @MatrixVariable annotation is not safe to use and is turned off by default in Spring MVC. To turn on support for @Matrix Variable, you need to set the RequestMapping Handler Mapping #setRemoveSemicolonContent method to false:
@Configuration
public class CustomMvcConfiguration implements InitializingBean {
@Autowired
private RequestMappingHandlerMapping requestMappingHandlerMapping;
@Override
public void afterPropertiesSet() throws Exception {
requestMappingHandlerMapping.setRemoveSemicolonContent(false);
}
}
It is not recommended to use @Matrix Variable unless there is a very special need.
File upload
File upload needs to select form-data when using POSTMAN to simulate requests, and submit in POST mode:
Suppose we have a picture file called doge.jpg on the D disk. Now we need to upload the file through the local service interface. The code of the controller is as follows:
@PostMapping(value = "/file1")
public String file1(@RequestPart(name = "file1") MultipartFile multipartFile) {
String content = String.format("name = %s,originName = %s,size = %d",
multipartFile.getName(), multipartFile.getOriginalFilename(), multipartFile.getSize());
log.info(content);
return content;
}
The console output is:
name = file1,originName = doge.jpg,size = 68727
Perhaps a little confused, how the parameters come from, we can use Fildder to grab a package to see:
It is known that the main attributes of the MultipartFile instance come from Content-Disposition, content-type and content-length respectively. In addition, InputStream is used to read the last part of the request body (byte sequence of the file). The parameter processor uses the RequestPart Method ArgumentResolver (remember that using @RequestPart and MultipartFile must be using this parameter processor). In other cases, uploaded file data can also be received using @RequestParam and MultipartFile or just MultipartFile (the name of the parameter must be the same as the name described by Content-Disposition in the POST form), mainly parsed through RequestParam Method ArgumentResolver, which is a functional comparison. Powerful, can see its support parameter method specifically, the controller method code of these two cases is as follows:
@PostMapping(value = "/file2")
public String file2(MultipartFile file1) {
String content = String.format("name = %s,originName = %s,size = %d",
file1.getName(), file1.getOriginalFilename(), file1.getSize());
log.info(content);
return content;
}
@PostMapping(value = "/file3")
public String file3(@RequestParam(name = "file1") MultipartFile multipartFile) {
String content = String.format("name = %s,originName = %s,size = %d",
multipartFile.getName(), multipartFile.getOriginalFilename(), multipartFile.getSize());
log.info(content);
return content;
}
Other parameters
Other parameters mainly include the request header, Cookie, Model, Map and other related parameters, and some are not very common or relatively native attribute value acquisition (such as HttpServletRequest, HttpServletResponse, etc.) is not discussed.
Request header
The value of the request header is obtained mainly through the parameters of the @RequestHeader annotation, and the parameter processor is RequestHeader Method ArgumentResolver, which requires the Key of the request header to be specified in the annotation. Simple and practical as follows:
Controller method code:
@PostMapping(value = "/header")
public String header(@RequestHeader(name = "Content-Type") String contentType) {
return contentType;
}
Cookie
The value of Cookie is obtained mainly through the parameter of @CookieValue annotation, the parameter processor is Servlet CookieValue Method ArgumentResolver, and the Key of Cookie needs to be specified in the annotation. The controller method code is as follows:
@PostMapping(value = "/cookie")
public String cookie(@CookieValue(name = "JSESSIONID") String sessionId) {
return sessionId;
}
Model type parameters
The processor for the Model type parameter is Model Method Processor, which is actually handled by returning the Model (Model Map type) directly to the Model in the Model AndViewContainer instance, because the functions of different interfaces and classes are bridged, the instance of the callback is the BindingAware Model Map type, which inherits from the Model Map and implements the Model at the same time. Interface. For instance:
@GetMapping(value = "/model")
public String model(Model model, ModelMap modelMap) {
log.info("{}", model == modelMap);
return "success";
}
Note that this interface is called, and the console outputs the Info log content as: true. Attribute items added in ModelMap or Model are appended to the HttpRequest Servlet and brought to the page for rendering.
@ ModelAttribute parameter
@ The parameter processor of the ModelAttribute annotation processing is ModelAttributeMethodProcessor, and the annotation of the functional source code of @ModelAttribute is as follows:
Annotation that binds a method parameter or method return value to a named model attribute, exposed to a web view.
Simply put, it binds method parameters or method return values to Model(Map) in the form of key-value, distinguishing the following three cases:
- 1. @ModelAttribute is used on the method (return value), the method has no return value (void type), and the Model(Map) parameter needs to be set by itself.
- 2. @ModelAttribute is used on the method (return value). The method has a return value (non-void type). The return value is added to the Model(Map) parameter. The key is specified by the value of @ModelAttribute. Otherwise, the return value type string (first letter changed to lowercase) is used.
- 3, @ ModelAttribute is used in the method parameter.
In a controller (using @Controller), if there are one or more methods that use @ModelAttribute, these methods are always executed before entering the controller method, and the order of execution is determined by the loading order (the specific order is priority without parameters, and sorted in ascending order according to the method initials). One example:
@Slf4j
@RestController
public class ModelAttributeController {
@ModelAttribute
public void before(Model model) {
log.info("before..........");
model.addAttribute("before", "beforeValue");
}
@ModelAttribute(value = "beforeArg")
public String beforeArg() {
log.info("beforeArg..........");
return "beforeArgValue";
}
@GetMapping(value = "/modelAttribute")
public String modelAttribute(Model model, @ModelAttribute(value = "beforeArg") String beforeArg) {
log.info("modelAttribute..........");
log.info("beforeArg..........{}", beforeArg);
log.info("{}", model);
return "success";
}
@ModelAttribute
public void after(Model model) {
log.info("after..........");
model.addAttribute("after", "afterValue");
}
@ModelAttribute(value = "afterArg")
public String afterArg() {
log.info("afterArg..........");
return "afterArgValue";
}
}
Calling this interface, the console outputs the log as follows:
after..........
before..........
afterArg..........
beforeArg..........
modelAttribute..........
beforeArg..........beforeArgValue
{after=afterValue, before=beforeValue, afterArg=afterArgValue, beforeArg=beforeArgValue}
The collation rules and parameter settings can be validated and retrieved.
Errors or BindingResult parameters
Errors is actually the parent interface of BindingResult. BindingResult is mainly used to call back the property items of the JSR parameter check exception. If the JSR check exception is exceptional, the MethodArgumentNotValidException exception will be thrown, and the Bad Request will be returned. See Defaultler Handler Exception Resolver, the global exception handler. The parameter processor of Errors type is ErrorsMethod ArgumentResolver. For instance:
@PostMapping(value = "/errors")
public String errors(@RequestBody @Validated ErrorsModel errors, BindingResult bindingResult) {
if (bindingResult.hasErrors()) {
for (ObjectError objectError : bindingResult.getAllErrors()) {
log.warn("name={},message={}", objectError.getObjectName(), objectError.getDefaultMessage());
}
}
return errors.toString();
}
//ErrorsModel
@Data
@NoArgsConstructor
public class ErrorsModel {
@NotNull(message = "id must not be null!")
private Integer id;
@NotEmpty(message = "errors name must not be empty!")
private String name;
}
The call interface console Warn log is as follows:
name=errors,message=errors name must not be empty!
Generally, it is not recommended to deal with the attribute items of JSR check exception in this way, because it involves a lot of repetitive hard coding work. It is recommended to inherit Response Entity Exception Handler directly and override the corresponding method.
@Value parameter
The parameters of the controller method can be @Value annotated parameters, which are assembled and converted from the Environment to the corresponding parameters (that is, the source of the parameters is not the requester), and the parameter processor is ExpressionValue Method ArgumentResolver. For instance:
@GetMapping(value = "/value")
public String value(@Value(value = "${spring.application.name}") String name) {
log.info("spring.application.name={}", name);
return name;
}
Map type parameter
Map type parameters have a relatively wide range. Corresponding to a series of parameter processors, we should pay attention to the difference between Map type parameters that use part of the annotations mentioned above and Map type parameters that do not use annotations at all. Here are some relatively typical examples of Map type parameter processing.
Map < String, Object > parameters without any annotations
In this case, the parameter actually calls back the ModelMap instance in the Model AndViewContainer directly. The parameter processor is MapMethodProcessor, and the attributes added to the Map parameter will be brought to the page.
Map < String, Object > parameter annotated with @RequestParam
In this case, the parameter processor is RequestParamMapMethodArgumentResolver, and the request method used needs to specify ContentType as x-www-form-urlencoded instead of application/json:
The controller code is:
@PostMapping(value = "/map")
public String mapArgs(@RequestParam Map<String, Object> map) {
log.info("{}", map);
return map.toString();
}
Map < String, Object > parameter annotated with @RequestHeader
In this case, the parameter processor is RequestHeaderMapMethodArgumentResolver, which is used to get the Key-Value of all request headers of the request.
Map < String, Object > parameter annotated with @PathVariable
In this case, the parameter processor is PathVariableMapMethodArgumentResolver, whose function is to obtain all path parameters and encapsulate them into a Key-Value structure.
MultipartFile Collection-Batch File Upload
When uploading batch files, we usually need to receive a set of MultipartFile s. There are two choices:
- 1. Using the MultipartHttpServletRequest parameter, call the getFiles method directly to get the list of MultipartFile s.
- 2. Modify the MultipartFile list with the @RequestParam annotation. The parameter processor is RequestParam Method ArgumentResolver, which is actually the first kind of encapsulation.
The controller method code is as follows:
@PostMapping(value = "/parts")
public String partArgs(@RequestParam(name = "file") List<MultipartFile> parts) {
log.info("{}", parts);
return parts.toString();
}
Date Type Parameter Processing
Date processing is considered by individuals to be the most complex in request parameter processing, because the general logic of date processing is not universal. Too much customization makes it difficult to have a unified standard processing logic to process and convert parameters of date type. However, here are some general methods to deal with the date formats of various exotic flowers. The following examples all use the date and time API introduced in Jdk8, which is similar around the date and time API with java.util.Date as its core.
I. Unified Receiving in String Form
This is the most primitive but effective way to receive it in the form of strings, and then process the type conversion by itself. Here is a small example:
@PostMapping(value = "/date1")
public String date1(@RequestBody UserDto userDto) {
UserEntity userEntity = new UserEntity();
userEntity.setUserId(userDto.getUserId());
userEntity.setBirthdayTime(LocalDateTime.parse(userDto.getBirthdayTime(), FORMATTER));
userEntity.setGraduationTime(LocalDateTime.parse(userDto.getGraduationTime(), FORMATTER));
log.info(userEntity.toString());
return "success";
}
@Data
public class UserDto {
private String userId;
private String birthdayTime;
private String graduationTime;
}
@Data
public class UserEntity {
private String userId;
private LocalDateTime birthdayTime;
private LocalDateTime graduationTime;
}
2. Use the annotation @DateTimeFormat or @JsonFormat
@ When the DateTimeFormat annotation is used in conjunction with the parameter @RequestBody, an InvalidFormatException exception is thrown, prompting the conversion to fail because only form submission (ContentType is x-www-form-urlencoded) is supported when processing this annotation. The examples are as follows:
@Data
public class UserDto2 {
private String userId;
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime birthdayTime;
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime graduationTime;
}
@PostMapping(value = "/date2")
public String date2(UserDto2 userDto2) {
log.info(userDto2.toString());
return "success";
}
//Or as follows
@PostMapping(value = "/date2")
public String date2(@RequestParam("name"="userId")String userId,
@RequestParam("name"="birthdayTime") @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime birthdayTime,
@RequestParam("name"="graduationTime") @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime graduationTime) {
return "success";
}
The @JsonFormat annotation can be used in the form or Json request parameter scenario, so the @JsonFormat annotation is preferred, but note the need to specify a time zone (for example, in China, the "GMT+8" of the Eastern Eighth District), otherwise it may lead to "time lag". For example:
@PostMapping(value = "/date2")
public String date2(@RequestBody UserDto2 userDto2) {
log.info(userDto2.toString());
return "success";
}
@Data
public class UserDto2 {
private String userId;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private LocalDateTime birthdayTime;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private LocalDateTime graduationTime;
}
3. Jackson serialization and deserialization customization
Because Spring MVC defaults to Jackson for @RequestBody parameter conversion, we can customize serializers and deserializers to achieve date type conversion, so we can submit request parameters in the form of application/json. The example here is to convert the string in the request Json parameter to the LocalDateTime type, which belongs to Json deserialization, so you need to customize the deserializer:
@PostMapping(value = "/date3")
public String date3(@RequestBody UserDto3 userDto3) {
log.info(userDto3.toString());
return "success";
}
@Data
public class UserDto3 {
private String userId;
@JsonDeserialize(using = CustomLocalDateTimeDeserializer.class)
private LocalDateTime birthdayTime;
@JsonDeserialize(using = CustomLocalDateTimeDeserializer.class)
private LocalDateTime graduationTime;
}
public class CustomLocalDateTimeDeserializer extends LocalDateTimeDeserializer {
public CustomLocalDateTimeDeserializer() {
super(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
}
}
IV. Best Practices
There are hard coding problems in the first three ways. In fact, the best practice is to modify the ObjectMapper in Mapping Jackson 2HttpMessageConverter directly to process the default serializer and deserializer for date types, so that it can take effect globally without using other annotations or customizing serialization schemes (of course, there are). Sometimes special processing customization is required, or other annotations or customized serialization schemes are used in scenarios where special processing is required. Attribute customization of ObjectMapper can be achieved by using hook interface Jackson 2ObjectMapper Builder Customizer:
@Bean
public Jackson2ObjectMapperBuilderCustomizer jackson2ObjectMapperBuilderCustomizer(){
return customizer->{
customizer.serializerByType(LocalDateTime.class,new LocalDateTimeSerializer(
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
customizer.deserializerByType(LocalDateTime.class,new LocalDateTimeDeserializer(
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
};
}
This enables customization of the ObjectMapper held in Mapping Jackson 2HttpMessageConverter, where the Local DateTime serialization and deserializer takes effect globally.
Request URL matching
In fact, in Spring MVC, matching will be done according to the URL pattern. The Ant path style is used, and the processing tool class is org. spring framework. util. AntPathMatcher. From the annotations of this kind, matching rules mainly include the following four points:
- 1. Match 1 character.
- 2. * Matches 0 or more characters.
- 3. ** 0 or more directories in the matching path.
- 4. {spring:[a-z]+} assigns the value matched by the regular expression [a-z] + to a path variable named spring.
For example:
In the form of URL s:
@GetMapping(value = "/pattern?")
public String pattern() {
return "success";
}
/pattern 404 Not Found
/patternd 200 OK
/patterndd 404 Not Found
/pattern/ 404 Not Found
/patternd/s 404 Not Found
* Formal URL s:
@GetMapping(value = "/pattern*")
public String pattern() {
return "success";
}
/pattern 200 OK
/pattern/ 200 OK
/patternd 200 OK
/pattern/a 404 Not Found
** In the form of URL s:
@GetMapping(value = "/pattern/**/p")
public String pattern() {
return "success";
}
/pattern/p 200 OK
/pattern/x/p 200 OK
/pattern/x/y/p 200 OK
URL in the form of {spring:[a-z]+}:
@GetMapping(value = "/pattern/{key:[a-c]+}")
public String pattern(@PathVariable(name = "key") String key) {
return "success";
}
/pattern/a 200 OK
/pattern/ab 200 OK
/pattern/abc 200 OK
/pattern 404 Not Found
/pattern/abcd 404 Not Found
The above four URL modes can be combined and used in a variety of ways.
URL matching also follows the principle of accurate matching, that is, there are two patterns that can match the same URL successfully, then select the most accurate URL matching and enter the corresponding controller method, for example:
@GetMapping(value = "/pattern/**/p")
public String pattern1() {
return "success";
}
@GetMapping(value = "/pattern/p")
public String pattern2() {
return "success";
}
The above two controllers, if the request URL is / pattern/p, are finally entered by pattern2.
Finally, as a tool class, org.spring framework.util.AntPathMatcher can be used independently, not only for matching URL s, but also for matching system file paths. However, it needs to be used to construct pathSeparator variables with parameters, such as:
AntPathMatcher antPathMatcher = new AntPathMatcher(File.separator);
Summary
The author spent a lot of time in combing and analyzing the source code of Spring and Spring MVC in the previous period, but in the latter period of time, we need to develop the business. We are a little rusty about the architecture, after all, things will be rusty if they are not used. This is common sense. Based on some Spring MVC source experience, this article summarizes some knowledge about request parameter processing, hoping to help myself and everyone.
Reference material:
- spring-boot-web-starter:2.0.3.RELEASE source code.
(End of this article)