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
中的绑定结果条目将被删除。
我有一些代码看起来像这样
@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
中的绑定结果条目将被删除。