首页 > 解决方案 > 为什么控制器需要在绑定错误上添加模型

问题描述

在用户注册期间的 Spring-Boot 控制器中,如果存在绑定错误,我的控制器会将用户返回到注册页面,但在我的实现中,模型似乎丢失了。

例如,我经常在教程中看到

    @PostMapping
public String registerUserAccount(@ModelAttribute("user") @Valid UserRegistrationDto userDto, 
                                  BindingResult result){

    User existing = userService.findByEmail(userDto.getEmail());
    if (existing != null){
        result.rejectValue("email", null, "There is already an account registered with that email");
    }

    if (result.hasErrors()){
        return "registration";
    }

    userService.save(userDto);
    return "redirect:/registration?success";
}

其中,如果有绑定错误返回“注册”

我的控制器非常相似:

    @PostMapping("/user/register")
public String registerNewUser(@ModelAttribute("user") @Valid RegisterUserDTO registerUserDTO,
                              BindingResult bindingResult,
                              Model model,
                              HttpServletRequest request,
                              Errors errors) {
    User existing = userService.findUserByEmail(registerUserDTO.getEmail());
    if (existing != null) {
        bindingResult.rejectValue("email", null, "There is already an account with that Email");
    }
    if (bindingResult.hasErrors()) {
        return "register";
    }
    userService.createUser(registerUserDTO);
    return "redirect:/registration?success";
 }
}

但是,当我返回“注册”时,堆栈上会出现绑定错误,这与我的第一个与对象相关的百里香标签相对应。

如果我更改 POST 控制器以显式添加模型:

        if (bindingResult.hasErrors()) {
        model.addAttribute(registerUserDTO);
        return "register";
    }

然后它开始工作,返回带有模型和先前输入数据的页面。

为什么我必须明确地将模型添加到退货中?

更新

这也不起作用:

    @PostMapping("/user/register")
public String registerNewUser(@ModelAttribute("user") @Valid RegisterUserDTO registerUserDTO,
                              BindingResult bindingResult) {
    User existing = userService.findUserByEmail(registerUserDTO.getEmail());
    if (existing != null) {
        bindingResult.rejectValue("email", null, "There is already an account with that Email");
    }
    if (bindingResult.hasErrors()) {
        return "register";

标签: javaspringspring-bootthymeleaf

解决方案


这有效:

    @PostMapping("/user/register")
    public String registerNewUser(@ModelAttribute("registerUserDTO") @Valid RegisterUserDTO registerUserDTO,
                              BindingResult bindingResult) {
    User existing = userService.findUserByEmail(registerUserDTO.getEmail());
    if (existing != null) {
           bindingResult.rejectValue("email", null, "There is already an account with that Email");
    }
    if (bindingResult.hasErrors()) {
        return "register";
    }
    userService.createUser(registerUserDTO);
    return "redirect:/registration?success";
}

正如 M.Denium 指出的那样,@ModelAttribute 名称需要与 GET 控制器中使用的支持对象的实例名称相同。在我的 GET 控制器中,我有:

    @GetMapping("/user/register")
String registerForm(Model model) {
    RegisterUserDTO registerUserDTO = new RegisterUserDTO();
    model.addAttribute(registerUserDTO);
    return "register";
}

所以@ModelAttribute需要匹配,即@ModelAttribute(" registerUserDTO ")


推荐阅读