SpringBoot series (III) parsing complex parameters
preface
When we write the interface, we will pass in complex parameters, such as Map and Model. Such similar parameters will be parsed by the corresponding parameter parser, and finally the parsed value will be put into the request field. Let's explore the principle together.
Tip: the following is the main content of this article. The following cases can be used for reference
1, Code example
Now, let's start our exploration journey with a demo. Please see below:
controller:
@GetMapping(value = "/params") public String hello(Model model, Map<String,Object> map){ model.addAttribute("hello","zhangsan"); map.put("world","lisi"); return "forward:/test/render"; } @GetMapping(value = "/render") @ResponseBody public String success(HttpServletRequest request){ Object hello = request.getAttribute("hello"); Object world = request.getAttribute("world"); System.out.println(hello); System.out.println(world); return "aaa"; }
Output result:
zhangsan lisi
2, Principle analysis
Let's first look at the method call stack:
Next, let's analyze the getMethodArgumentValues method:
protected Object[] getMethodArgumentValues(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception { MethodParameter[] parameters = getMethodParameters(); if (ObjectUtils.isEmpty(parameters)) { return EMPTY_ARGS; } Object[] args = new Object[parameters.length]; for (int i = 0; i < parameters.length; i++) { MethodParameter parameter = parameters[i]; parameter.initParameterNameDiscovery(this.parameterNameDiscoverer); args[i] = findProvidedArgument(parameter, providedArgs); if (args[i] != null) { continue; } //one ⃣ find a parser that can be used to parse the parameter if (!this.resolvers.supportsParameter(parameter)) { throw new IllegalStateException(formatArgumentError(parameter, "No suitable resolver")); } try { //two ⃣ Resolve the parameter and put it into mavContainer args[i] = this.resolvers.resolveArgument(parameter, mavContainer, request, this.dataBinderFactory); } catch (Exception ex) { // Leave stack trace for later, exception may actually be resolved and handled... if (logger.isDebugEnabled()) { String exMsg = ex.getMessage(); if (exMsg != null && !exMsg.contains(parameter.getExecutable().toGenericString())) { logger.debug(formatArgumentError(parameter, exMsg)); } } throw ex; } } //three ⃣ Return the parsed parameters return args; }
1. For key points 1 ⃣ 7078 28326 16529 1046 9070 14429 13408 18111 6785 15408 7788
As we can see from the figure, the red line can support the two parameters passed in our code example.
2. For key points 2 ⃣ Next, let's take a look at its schematic diagram:
Next step:
Then proceed to the next step:
From here, we can see that the parsed value is put into the BindingAwareModelMap. Let's take a look at the value of the args array finally parsed:
As can be seen from the figure, the parameters of Map and Model are finally parsed and put into BindingAwareModelMap. Then obtain the return value through the reflection execution target method, as shown in the following figure:
Next, call the getModelAndView method, take out the value in mavContainer, encapsulate it into a ModelAndView, and return it as follows:
Then execute the processDispatchResult method as follows:
Here comes the most critical step, as shown in the following figure:
As we can see from the figure, we put the value in the model in ModelAndView into the request field.
summary
The above introduces the analysis principle of SpringBoot on complex parameters. debug step by step according to the above steps, and you can clearly understand the analysis of each complex parameter.