Summary of all ways spring MVC receives request parameters

Catalog

Summary

In the daily use of spring MVC for development, you may encounter various types of front-end request parameters. Here is a relatively comprehensive summary. The interface for processing controller parameters in spring MVC is HandlerMethodArgumentResolver, which has many subclasses, dealing with different (annotation type) parameters respectively. Here are just a few subclasses:

  • RequestParamMethodArgumentResolver: parameters annotated with @ RequestParam, MultipartFile type parameters and Simple type parameters (such as long, int, etc.) are used for resolution processing.
  • RequestResponseBodyMethodProcessor: parses the parameters that process the @ RequestBody annotation.
  • PathVariableMapMethodArgumentResolver: resolves the parameters that handle the @ PathVariable annotation.

In fact, when parsing the request parameters of a controller, the HandlerMethodArgumentResolver composite is used, which contains all enabled HandlerMethodArgumentResolver subclasses. While the HandlerMethodArgumentResolver subclass uses HttpMessageConverter (in fact, it is also a list for traversal matching resolution) subclass to perform matching resolution when parsing parameters, such as mappingjackson 2HttpMessageConverter (which uses Jackson for serialization and deserialization). What HttpMessageConverter instance the HandlerMethodArgumentResolver subclass depends on is actually determined by the content type in the request header (named as MediaType in spring MVC, see org.springframework.http.MediaType). Therefore, before processing the request parameters of the controller, we must know what the content type of the external request is. The above logic can be seen directly from the source abstractmessageconverter, methodargumentresolver and readwithmessageconverters. The idea is relatively clear. In the @ RequestMapping annotation, the products and consumers properties are related to the content type of the request or response:

  • Consumers property: Specifies the content type to process the request, such as application/json, text/html, etc., which will be accepted only if the corresponding content type value is hit.
  • Products property: Specifies the content type to be returned. Only when the (Accept) type in the request header of a request contains the specified type, the application/json;charset=UTF-8 is generally considered if the JSON data is returned.

In addition, in spring MVC, Jackson is used as the JSON toolkit by default. If you don't fully understand the operation of the whole set of source code, it is generally not recommended to modify the mapping Jackson 2HttpMessageConverter used by default (for example, some people like to use FastJson to implement HttpMessageConverter and introduce FastJson It is not recommended to do HTTP message converter).

Spring MVC request parameter receiving

In fact, the general form or JSON data request is relatively simple. Some complex processing mainly includes URL path parameters, file upload, array or list type data, etc. In addition, there are date type properties in parameter types (such as java.util.Date, java.sql.Date, java.time.LocalDate, java.time.LocalDateTime, java.time.ZonedDateTime, etc.), and when parsing, you need to customize the logic implementation of string -- > date type conversion. In fact, the reason is very simple. The cognition of date related types is not necessarily the same for each country, each time zone or even each user. Therefore, spring MVC does not provide a general solution for the resolution of date and time types. The following model classes may be used in some examples:

@Data
public class User {

 private String name;
 private Integer age;
 private List<Contact> contacts;
}

@Data
public class Contact {

 private String name;
 private String phone;
}

1.URL reference annotation @ RequestParam

When the HTTP(s) protocol uses the GET method to request, the submitted parameters are located in the Query part of the URL mode, that is, the parameters after the "? Of the URL. The format is key1 = value1 & key2 = Value2. GET method request parameters can be obtained in several ways:

@RequestParam
Query
HttpServletRequest

Assuming that the requested URL is http: / / localhost: 8080 / get? Name = Doge & age = 26, the controller is as follows:

@Slf4j
@RestController
public class SampleController {

   @GetMapping(path = "/get1")
   public void get1(@RequestParam(name = "name") String name,
   @RequestParam(name = "age") Integer age) {
      log.info("name:{},age:{}", name, age);
   }

   @GetMapping(path = "/get2")
   public void get2(UserVo vo) {
      log.info("name:{},age:{}", vo.getName(), vo.getAge());
   }

   @GetMapping(path = "/get3")
   public void get3(HttpServletRequest request) {
     String name = request.getParameter("name");
     String age = request.getParameter("age");
     log.info("name:{},age:{}", name, age);
   }

   @Data
   public static class UserVo {
     private String name;
     private Integer age;
   }
}

2. Form parameters and comments @ RequestParam

Form parameters, generally corresponding to the page

Generally, the content type is specified as application/x-www-form-urlencoded, that is, URL encoding will be performed. Here are some common forms of form parameter submission.

① . non object - single parameter reception of non object type.

The corresponding controllers are 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 tell you the truth, if you have perseverance, all the complicated parameters can be submitted to multiple single parameter receivers, but it will generate a lot of redundant code and low maintainability. In this case, the parameter processor used is RequestParamMapMethodArgumentResolver.

② . object - object type parameter receiving.

We then write an interface to submit user information, which uses the model class mentioned above, mainly including user name, age and contact information list. At this time, the final code of our target controller is as follows:

@PostMapping(value = "/user")
public User saveUser(User user) {
   log.info(user.toString());
   return user;
}

We still specify the content type as application/x-www-form-urlencoded, and then we need to construct the request parameter:

{
    name:'dog',
    age:25,
    contacts[0].name:'aa',
    contacts[0].phone:12344,
    contacts[1].name:'bb',
    contacts[1].phone:212344
}

Because no annotation is used, the final parameter processor is ServletModelAttributeMethodProcessor, which encapsulates the form parameters in HttpServletRequest into MutablePropertyValues instance, instantiates the parameter type (creates User instance by constructing reflection), and fills the reflection matching attribute with the value. In addition, the list property request parameter in the request complex parameter looks strange. In fact, it is consistent with the writing method of adding the parameter finally mapped to Map type in the. properties file. So, can the entire request parameter be submitted in one field?

{
user:
    {
        name:doge,
    age:25,
    contacts:[
        {
            name:'aa',
            phone:12344
        },
        {
            name:'bb',
            phone:212344
        }
    ]
    }
}

In fact, RequestParamMethodArgumentResolver relies on the Converter instance list in WebConversionService for parameter conversion

There are still solutions. Add an org.springframework.core.convert.converter.Converter implementation:

@Component
public class StringUserConverter implements Converter<String, User> {

   @Autowaired
   private ObjectMapper objectMapper;

   @Override
   public User convert(String source) {
     try {
            return objectMapper.readValue(source, User.class);
     } catch (IOException e) {
            throw new IllegalArgumentException(e);
     }
   }
}

The above method belongs to the method of saving the nation by curve. It is not recommended to use it in the production environment. However, if the docking of some third-party interfaces cannot avoid this parameter, you can choose this implementation method.

③ . array - list or array type parameter

It is highly not recommended to use the list or array type parameters in the form of application/x-www-form-urlencoded media type form submission, unless it is for compatibility with the parameter submission processing of historical legacy systems. For example, the submitted parameters are:

list = ["string-1", "string-2", "string-3"]

The form parameters should be written as:

namevaluelist[0]string-1list[1]string-2list[2]string-3

The code of the controller is as follows:

@PostMapping(path = "/list")
public void list(@RequestParam(name="list") List<String> list) {
     log.info(list);
}

A more complex example is as follows, assuming that the message format to be submitted is as follows:

user = [{"name":"doge-1","age": 21},{"name":"doge-2","age": 22}]

Then the form parameters should be written as: namevalueuser [0]. Namedoge-1user [0]. Age21user [1]. Namedoge-2user [1]. The code of age22 controller is as follows:

@PostMapping(path = "/user")
public void saveUsers(@RequestParam(name="user") List<UserVo> users) {
 log.info(users);
}

@Data
public class UserVo{

  private String name;
  private Integer age;
}

3.JSON parameter and annotation @ RequestBody

Generally speaking, it is friendly for spring MVC to submit a JSON string directly in the request body of POST request. Just set the content type to application/json and submit an original JSON string. The controller method parameters are processed with @ RequestBody annotation:

{
        name:doge,
    age:25,
    contacts:[
        {
            name:'aa',
            phone:12344
        },
        {
            name:'bb',
            phone:212344
        }
    ]
    }

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 @ RequestBody annotation is used, the final parameter processor used is RequestResponseBodyMethodProcessor. In fact, mappingjackson 2httpmessageconverter is used for parameter type conversion. The underlying layer depends on Jackson related packages. It is recommended to use this method, which is the most commonly used and robust JSON parameter processing method.

4.URL path parameter and annotation @ PathVariable

The URL path parameter, or request path parameter, is obtained based on 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, by matching the actual requested URL and URL template, the userId can be extracted as 1. In spring MVC, path parameter in URL template is called PathVariable, corresponding annotation @ PathVariable, and corresponding parameter processor is PathVariable methodargumentresolver. Note that @ PathVariable is parsed according to the value(name) attribute, regardless of the order of URL parameters.

Take a simple example:

http://localhost:9001/user/zhang/12

The controllers in the background are 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 software architecture style of representative state transfer (rest). I think this style is relatively flexible and clear (the meaning and function of interface can be fully understood from URL and request method). Here are two relatively special ways to use it.

① . conditional URL parameter

In fact, the path parameter supports regular expressions. For example, when we use the / sex/{sex} interface, we require that sex must be 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 will enter the findUser2() controller method. Other requests with the path prefix are illegal and will return a 404 status code. Here is just an introduction to the use of the simplest URL parameter regular expression. A more powerful use can be explored by yourself.

② . use of @ MatrixVariable

MatrixVariable is also a kind of URL parameter, corresponding to the annotation @MatrixVariable, but it is not a value in the URL (the value here is specified as the part between two "/"), but a part of the value, which is separated by ";" and set by "=" for K-V. Let's say it's a little abstract. For example, if we need to call a programmer whose name is doge, gender is male, and grouping is code animal, the URL of GET request can be expressed as: call/doge;gender=male;group=programmer. The controller 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 above example, try to request the interface and find that it reports an error: 400 Bad Request - Missing matrix variable 'gender' for method parameter of type String. This is because the use of @ MatrixVariable annotation is unsafe, and support for it is turned off by default in spring MVC. To enable support for @ MatrixVariable, you need to set the requestmappinghandlermapping ා setremovesemicoloncontent method to false:

@Configuration
public class CustomMvcConfiguration implements InitializingBean {

  @Autowired
  private RequestMappingHandlerMapping requestMappingHandlerMapping;

  @Override
  public void afterPropertiesSet() throws Exception {
    requestMappingHandlerMapping.setRemoveSemicolonContent(false);
  }
}

Unless there is a special need, @ MatrixVariable is not recommended.

5. File upload and MultipartFile

When using POSTMAN to simulate a request for file upload, you need to select form data and POST to submit

key is file1, value is doge.jpg picture

Suppose we have a picture file called doge.jpg on disk D. 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

The main properties of the MultipartFile instance are content disposition, content type and content length. In addition, InputStream is used to read the last part of the request body (byte sequence of the file). Parameter processor uses RequestPartMethodArgumentResolver (remember, @ RequestPart and MultipartFile must use this parameter processor). In other cases, @ RequestParam and MultipartFile or just MultipartFile (the name of the parameter must be the same as the name described in the content disposition in the POST form) can also be used to receive the uploaded file data, mainly through RequestParamMethodArgumentResolver for parsing and processing. Its function is relatively powerful, which can be seen in detail Supportsiparameter method. The controller method codes in these two cases are 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;
}

6. Request header and annotation @ RequestHeader

The value of the request header is obtained mainly through the parameters of the @ RequestHeader annotation. The parameter processor is RequestHeaderMethodArgumentResolver, and the Key of the request header needs to be specified in the annotation. Simple and practical as follows:

key by Content-Type

value by application/json

Controller method code:

@PostMapping(value = "/header")
public String header(@RequestHeader(name = "Content-Type") String Content-Type) {
    return Content-Type;
}

7. Cookies and comments @ CookieValue

The value of the Cookie is obtained mainly through the parameters of the @ CookieValue annotation. The parameter processor is ServletCookieValueMethodArgumentResolver, and the Key of the 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;
}

8.Model type parameter and @ ModelAttribute

The processor of Model type parameter is ModelMethodProcessor. In fact, this parameter is directly returned to the Model (ModelMap type) in the ModelAndViewContainer instance. Because different interfaces and class functions are to be bridged, the callback instance is BindingAwareModelMap type, which inherits from ModelMap and implements the Model interface at the same time. 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 output INFO log content is: true. Also note that the property items added in the ModelMap or Model will be attached to the HttpRequestServlet instance and brought to the page for rendering.

@ModelAttribute parameter

@The parameter processor of ModelAttribute annotation processing is ModelAttributeMethodProcessor,

@The function source code of ModelAttribute is as follows:

Annotation that binds a method patameter or method return value to a named model attribute, 
exposed to a web view

In short, it is to bind method parameters or method return values to Model(Map) in the form of key value, which is different from the following three situations:

  1. @ModelAttribute is used on the method (return value). The method has no return value (void type). 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 will be added to the Model(Map) parameter, and the key is specified by the value of @ ModelAttribute. Otherwise, the return value type string will be used (the initial letter becomes lowercase, if the return value type is integer, then the key is integer).
  3. @When ModelAttribute is used in method parameters, you can get the value of @ ModelAttribute that has been set in the same controller.

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 execution order is determined by the loading order (the specific order is the priority with parameters, and it is sorted in ascending order according to the method initial). For 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";
  }
}

Call this interface, and the console output log is as follows:

after..........
before..........
afterArg..........
beforeArg..........
modelAttribute..........
beforeArg..........beforeArgValue
{after=afterValue, before=beforeValue, afterArg=afterArgValue, beforeArg=beforeArgValue}

It can be verified that the collation and parameter settings, and the results obtained are consistent with the previous analysis.

9.Errors or BindingResult parameter

Errors is actually the parent interface of BindingResult. BindingResult is mainly used to call back the property item of JSR parameter validation exception. If JSR validation exception is found, MethodArgumentNotValidException exception will be thrown and 400(Bad Request) will be returned. See DefaultHandlerExceptionResolver of global exception processor. The parameter processor of type errors is ErrorsMethodArgumentResolver.

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;
}

Call the interface console Warn log as follows:

name=errors,message=errors name must not be empty!

In general, it is not recommended to handle the property items of JSR verification exception in this way, because it involves a lot of repeated hard coding work. It is recommended that: the method always inherits the ResponseEntityExceptionHandler to overwrite the corresponding method or the method 2 uses @ ExceptionHandler and @ (Rest)ControllerAdvice annotation to handle the exception at the same time. For example:

@RestControllerAdvice
public class ApplicationRestControllerAdvice{

  @ExceptionHandler(BusinessException.class)
  public Response handleBusinessException(BusinessException e, HttpServletRequest request){
        // Handle exceptions and return values here
  }
}

10.@Value

The parameters of the controller method can be parameters decorated with @ Value annotation. The attribute values will be assembled and converted from the Environment instance to the corresponding parameters (that is, the source of the parameters is not the request body). The parameter processor is ExpressionValueMethodArgumentResolver.

for instance:

@GetMapping(value = "/value")
public String value(@Value(value = "${spring.application.name}") String name) {
 log.info("spring.application.name={}", name);
 return name;
}

The spring.application.name property is generally specified in the configuration file and added to the global Environment when the configuration file property is loaded.

11.Map type parameter

The scope of Map type parameters is relatively wide, corresponding to a series of parameter processors. Pay attention to the difference between Map type with partial annotation and Map type parameters without annotation. The two processing methods are different. Here are some typical examples of Map type parameter processing.

① . Map parameter without any annotation

In this case, the parameter directly calls back the ModelMap instance in ModelAndViewContainer. The parameter processor is MapMethodProcessor, and the attributes added to the Map parameter will be brought to the page.

② . Map parameter annotated with @ RequestParam

In this case, the parameter processor is RequestParamMapMethodArgumentResolver, and the request mode needs to specify the content type as x-www-form-urlencoded, instead of application/json mode:

{
    name:'aa',
    age:12
}

The controller code is:

@PostMapping(value = "/map")
public String mapArgs(@RequestParam Map<String, Object> map) {
 log.info("{}", map);
 return map.toString();
}

③ . use the map < string, Object > parameter of @ RequestHeader annotation

In this case, the parameter processor is RequestHeaderMapMethodArgumentResolver, which is used to get the key value of all request headers.

④ . map < string, Object > parameter annotated with @ PathVariable

In this case, the parameter processor is PathVariableMapMethodArgumentResolver, which is used to obtain all path parameters encapsulated as key value structures.

⑤ . MultipartFile Collection - bulk file upload

When uploading a batch file, we usually need to receive a MultipartFile collection. There are two options:

  1. Using the MultipartHttpServletRequest parameter, directly call the getFiles method to get the MultipartFile list.
  2. Use @ RequestParam annotation to modify the MultipartFile list. The parameter processor is RequestParamMethodArgumentResolver, which is actually the encapsulation of the first way.

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();
}

12. Date type parameter processing

Date parameter processing is the most complex in the request parameter processing. Because the general date processing logic is not universal, too many customized processing makes it difficult to have a unified standard processing logic to process and convert date type parameters. However, here are a few general methods to deal with various exotic date formats. The following examples all use the date time API introduced in Jdk8. The usage of the date time API around java.util.Date is similar.

① . receive as string

This is the most original but effective way to receive in the form of string, and then handle the type conversion by yourself. 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;
}

The disadvantage of using the string to receive and then convert is that there are too many template codes, the coding style is not concise enough, and the repetitive work is too much.

② . use annotation @ DateTimeFormat or @ JsonFormat

@When the DateTimeFormat annotation is used with @ RequestBody's parameters, an InvalidFormatException exception will be thrown, indicating that the conversion fails. This is because when processing this annotation, only Form form submission (content type is x-www-form-urlencoded) is supported. For example:

@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 something like this
@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 scenarios, so it is more recommended to use the @ JsonFormat annotation, but pay attention to the need to specify the time zone (timezone attribute, for example, GMT+8 in the East eighth zone in China), otherwise it may cause time difference. 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;
}

③ . Jackson serialization and deserialization customization

Because spring MVC uses Jackson to handle the parameter conversion of @ RequestBody by default, we can implement the conversion of date type by customizing serializer and deserializer, so we can submit the request parameters in the form of application/json. The example here is that the string in the conversion request Json parameter is of type LocalDateTime, 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"));
  }
}

④ . best practices

In fact, the best practice is to directly modify the ObjectMapper in the mappingjackson 2httpmessageconverter For date types, the default serializer and deserializer can be processed, which can take effect globally. There is no need to use other annotations or custom serialization schemes (of course, some special processing customization is required), or other annotations or custom serialization schemes can be used in scenarios requiring special processing. Using the hook interface Jackson2ObjectMapperBuilderCustomizer, you can customize the properties of the ObjectMapper in the container

@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")));
  };
}

In this way, the ObjectMapper held in mappingjackson 2httpmessageconverter can be customized. The local datetime serializer and deserializer above take effect globally.

13. Request URL matching

In fact, spring MVC will match according to the URL pattern, using the Ant path style. The processing tool class is org.springframework.util.AntPathMatcher. From such comments, the matching rules mainly include the following four points:

  1. ? match 1 character.
  2. *Matches 0 or more characters.
  3. **Match 0 or more directories in the path.
  4. Regular support, such as {spring:[a-z] +}, assigns the value of regular expression [a-z] + to the path variable named spring.

For example:

① . URL in the form of '?':

@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

② . URL in the form of '*':

@GetMapping(value = "/pattern/**/p")
public String pattern() {
  return "success";
}

/pattern/p 200 OK
/pattern/x/p 200 OK
/pattern/x/y/p 200 OK

③ {spring: URL in the form of [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

④ URL in the form of "* *" * "**

@GetMapping(value = "/pattern/**/p")
public String pattern() {
  return "success";
}

/pattern/p 200 OK
/pattern/x/p 200 OK
/pattern/x/y/p 200 OK

The above four URL patterns can be used in combination, and they can be varied.

URL matching also follows the principle of exact 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";
}

For the above two controllers, if the request URL is / pattern/p, the final entry method is pattern2.

Finally, as a tool class, org.springframework.util.AntPathMatcher can be used alone, not only for matching URL s, but also for matching system file paths. However, it is necessary to use its structure with parameters to change the internal pathSeparator variables, such as:

AntPathMatcher antPathMatcher = new AntPathMatcher(File.separator);

Standing on the shoulders of giants picking apples:

https://mp.weixin.qq.com/s/whHcZyzo2nYXsoa2j3Lfrw

Tags: Java Spring JSON Attribute

Posted on Sun, 08 Mar 2020 01:59:19 -0500 by disaster77