为了账号安全,请及时绑定邮箱和手机立即绑定

在 Spring MVC 中创建的模型对象究竟在哪里?

在 Spring MVC 中创建的模型对象究竟在哪里?

红糖糍粑 2021-08-25 15:09:37
在阅读了 docs.spring.org 参考中的一些教程和初始文档后,我了解到它是在开发人员创建的 POJO 类的控制器中创建的。但是在阅读本文时,我遇到了以下段落:一个@ModelAttribute上的方法参数指示参数应该从模型中检索。如果模型中不存在该参数,则应首先实例化该参数,然后将其添加到模型中。一旦出现在模型中,参数的字段应该从具有匹配名称的所有请求参数中填充。这在 Spring MVC 中称为数据绑定,这是一种非常有用的机制,可以使您不必单独解析每个表单字段。@RequestMapping(value="/owners/{ownerId}/pets/{petId}/edit", method = RequestMethod.POST)public String processSubmit(@ModelAttribute Pet pet) {   }在段落中,最令人不安的是这句话:“如果模型中不存在……”数据怎么会出现在模型中?(因为我们还没有创建模型 - 它将由我们创建。)此外,我还看到一些控制器方法接受Model类型作为参数。这意味着什么?它是否Model在某处创建?如果是这样,谁在为我们创造它?
查看完整描述

2 回答

?
莫回无

TA贡献1865条经验 获得超7个赞

如果模型中不存在该参数,则应首先实例化该参数,然后将其添加到模型中。


该段描述了以下代码:


if (mavContainer.containsAttribute(name)) {

    attribute = mavContainer.getModel().get(name);

} else {

    // Create attribute instance

    try {

        attribute = createAttribute(name, parameter, binderFactory, webRequest);

    }

    catch (BindException ex) {

        ...

    }

}

...

mavContainer.addAllAttributes(attribute);

(取自ModelAttributeMethodProcessor#resolveArgument)


对于每个请求,Spring 都会初始化一个ModelAndViewContainer实例,该实例记录在控制器方法调用过程中由HandlerMethodArgumentResolvers 和HandlerMethodReturnValueHandlers做出的与模型和视图相关的决策。


新创建的ModelAndViewContainer对象最初填充有flash 属性(如果有):


ModelAndViewContainer mavContainer = new ModelAndViewContainer();

mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request));

这意味着如果模型中已经存在该参数,则不会对其进行初始化。


为了证明这一点,让我们来看一个实际的例子。


本Pet类:


public class Pet {

    private String petId;

    private String ownerId;

    private String hiddenField;


    public Pet() {

         System.out.println("A new Pet instance was created!");

    }


    // setters and toString

}

本PetController类:


@RestController

public class PetController {


    @GetMapping(value = "/internal")

    public void invokeInternal(@ModelAttribute Pet pet) {

        System.out.println(pet);

    }


    @PostMapping(value = "/owners/{ownerId}/pets/{petId}/edit")

    public RedirectView editPet(@ModelAttribute Pet pet, RedirectAttributes attributes) {

        System.out.println(pet);

        pet.setHiddenField("XXX");


        attributes.addFlashAttribute("pet", pet);

        return new RedirectView("/internal");

    }


}

让我们向 URI 发出 POST 请求/owners/123/pets/456/edit并查看结果:


A new Pet instance was created!

Pet[456,123,null]

Pet[456,123,XXX]

A new Pet instance was created!

Spring 创建了一个ModelAndViewContainer并且没有找到任何东西来填充实例(这是来自客户端的请求;没有任何重定向)。由于模型是空的,Spring 必须Pet通过调用打印该行的默认构造函数来创建一个新对象。


Pet[456,123,null]

一旦出现在模型中,参数的字段应该从具有匹配名称的所有请求参数中填充。


我们印了给定的Pet,以确保所有的领域petId,并ownerId已被正确绑定。


Pet[456,123,XXX]

我们开始hiddenField检查我们的理论并重定向到invokeInternal同样需要@ModelAttribute. 正如我们所见,第二个方法接收了为第一个方法创建的实例(具有自己的隐藏值)。


查看完整回答
反对 回复 2021-08-25
?
繁星coding

TA贡献1797条经验 获得超4个赞

这证明在我们的控制器/处理程序为特定 URL 调用之前就创建了一个 ModelMap 实例[一个模型对象]


 public class ModelAndViewContainer {


    private boolean ignoreDefaultModelOnRedirect = false;


    @Nullable

    private Object view;


    private final ModelMap defaultModel = new BindingAwareModelMap();

      ....

      .....

   }

如果我们看到上面的代码片段(取自 spring-webmvc-5.0.8 jar)。BindingAwareModelMap 模型对象很早就创建好了。


为了更好地理解为类BindingAwareModelMap添加注释


   /**

     * Subclass of {@link org.springframework.ui.ExtendedModelMap} that automatically removes

     * a {@link org.springframework.validation.BindingResult} object if the corresponding

     * target attribute gets replaced through regular {@link Map} operations.

     *

     * <p>This is the class exposed to handler methods by Spring MVC, typically consumed through

     * a declaration of the {@link org.springframework.ui.Model} interface. There is no need to

     * build it within user code; a plain {@link org.springframework.ui.ModelMap} or even a just

     * a regular {@link Map} with String keys will be good enough to return a user model.

     *

     @SuppressWarnings("serial")

      public class BindingAwareModelMap extends ExtendedModelMap {

      ....

      ....

     }


查看完整回答
反对 回复 2021-08-25
  • 2 回答
  • 0 关注
  • 239 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信