Spring MVC - 手动覆盖模型后绑定结果丢失

Spring MVC - Binding results missing after manually overriding model

我有一些代码看起来像这样

@Controller
public class FooController {

@RequestMapping(value = "/foos", method = POST)
public String createFoo(@ModelAttribute("FooDto")
    @Valid FooDto fooDto, BindingResult bindingResult, Model model) {

    var foo = fooMapper.toFooModel(fooDto);

    if (bindingResult.hasErrors()) {
        var fooDto1 = fooMapper.toFooDto(foo);

        model.addAttribute("FooDto", fooDto1); // binding result disappears
        ...
    }

    ...

还有一些针对我的控制器 class 的测试,如下所示:

@Test
void createFooWithValidationError() throws Exception {

    perform(post("/foos")).andExpect(status().isOk())
        .andExpect(model().attribute("foo", notNullValue()))
        .andExpect(model().errorCount(1)); // this fails, no error/binding result exists!
}

测试未成功,因为设置后没有绑定结果

model.addAttribute("FooDto", fooDto1);.

我知道,我可以设置

model.addAttribute("FooDto", fooDto);

因此绑定结果不会消失

但是我想知道为什么绑定结果消失了。是否有一些 spring 魔术将绑定结果绑定到我的模型属性的具体实例?是否有其他解决方法可以使上述代码正常工作?

我将深入研究 spring 代码并找到我的答案:

model.addAttribute("FooDto", fooDto1);确实调用了

public ModelMap addAttribute(String attributeName, @Nullable Object attributeValue) {
    Assert.notNull(attributeName, "Model attribute name must not be null");
    put(attributeName, attributeValue); // calls BindingAwareModelMap
    return this;
}
public class BindingAwareModelMap  {

   public Object put(String key, @Nullable Object value) {
       removeBindingResultIfNecessary(key, value); 
       return super.put(key, value);
   }

   private void removeBindingResultIfNecessary(Object key, @Nullable Object value) {
        ...
        if (bindingResult != null && bindingResult.getTarget() != value) {
            remove(bindingResultKey); // Removes the binding result if target refernces to other instance
        }
    }
}

如您所见,如果绑定结果引用了另一个实例,ModelMap 中的绑定结果条目将被删除。