【问题标题】:Spring MVC validation errors are not displayed in Freemarker templateSpring MVC 验证错误未显示在 Freemarker 模板中
【发布时间】:2026-01-04 05:25:02
【问题描述】:

如果控制器返回绑定错误,我正在尝试在使用 freemarker 模板构建的“用户注册”页面中显示验证错误。

我的控制器代码如下:

@Controller
@RequestMapping("/")
public class UserController  {

@Autowired
private UserService userService;

@Autowired
private SecurityService securityService;

@Autowired
private UserValidator userValidator;

@RequestMapping(value = "/registration", method = RequestMethod.GET)
   public String registration(Model model) {
   model.addAttribute("userForm", new User()); 
   return "registration";
  }

@RequestMapping(value = "/registration", method = RequestMethod.POST)
public String registration(@ModelAttribute("useraccount") User userForm,     BindingResult bindingResult, Model model) {

    userValidator.validate(userForm, bindingResult);

    if (bindingResult.hasErrors()) {

        return "registration";
        }

    userService.save(userForm);

    securityService.autologin(userForm.getUsername(), userForm.getPasswordConfirm());

    return "redirect:/explore";
}

虽然这是我正在尝试构建的registration.ftl freemarker 模板:

 <div>
<fieldset>
    <h1>Create your Account</h1>
    <form id="regForm" class="idealform" action="registration" method="post" name='useraccount'>
            Username: <input type="text" name="username" /> <errors path="username" cssClass="error"/><br/>
            Password: <input type="text" name="password" /><errors path="password" cssClass="error"/><br/>
               <label class="main-label" style="width: 91px;">&nbsp;</label>
        <input type="submit" value="submit">
    </form>
</fieldset>

我也尝试了这里推荐的解决方案:

Displaying Spring MVC validation errors in Freemarker templates

registration.ftl 变成:

  <#assign form=JspTaglibs["http://www.springframework.org/tags/form"] />

  <#macro formErrors>
  <#assign formErrors><@form.errors path="*" /></#assign>
  <#if formErrors?has_content>
    <div id="errors">
     <@spring.message "admin.error.globalMessage" />
    </div>
  </#if>
 </#macro>

<div>
<fieldset>
    <h1>Create your Account</h1>
    <@form.form id="regForm" class="idealform" action="registration"   method="post" name='useraccount'>
            Username: <input type="text" name="username" path="username" />    <br/>

            Password: <input type="text" name="password" path="password" /><br/>

    <@formErrors />
        <label class="main-label" style="width: 91px;">&nbsp;</label>
        <input type="submit" value="submit">
    </@form.form>
</fieldset>

</div>

但仍然不显示验证消息。

您能就这个问题与我分享您的想法吗? 非常感谢。

【问题讨论】:

    标签: validation spring-mvc spring-security freemarker


    【解决方案1】:

    我把你的控制器代码改写成这样:

    @Controller
    @RequestMapping("/")
    public class UserController {
    
    @Autowired
    private UserService userService;
    
    @Autowired
    private SecurityService securityService;
    
    @Autowired
    private UserValidator userValidator;
    
    @RequestMapping(value = "/registration", method = RequestMethod.GET)
    public String registration(@ModelAttribute(name = "userForm") User user) {
        return "registration";
    }
    
    @RequestMapping(value = "/registration", method = RequestMethod.POST)
    public String registration(@ModelAttribute(name = "userForm") User user, BindingResult result) {
        userValidator.validate(user, result);
    
        if (result.hasErrors()) {
            return "registration";
        }
    
        userService.save(user);
    
        securityService.autologin(user.getUsername(), user.getPasswordConfirm());
    
        return "redirect:/explore";
    }
    }
    

    1) 如果您使用不带参数的构造函数,则无需使用model.addAttribute("modelName", model),而是可以使用指定名称属性的@ModelAttribute 注释(默认情况下,名称来自类名)。您只需确保此模型处于一致状态。此外,您需要传递与您在视图中使用的名称完全相同的名称(freemarker 模板)。

    现在“registration.ftl”

    ...
    <#import "/spring.ftl" as spring/>
    ...
    <fieldset>
      <h1>Create your Account</h1>
      <form id="regForm" class="idealform" action="<@spring.url '/registration'/>" method="post">
        <@spring.bind 'userForm.username'/>
        Username: <input type="text" name="${spring.status.expression}" value="${spring.status.value?html}"/>
        <#list spring.status.errorMessages as error>
          <span class="error">${error}</span>
          <br>
        </#list>
        <@spring.bind 'userForm.password'/>
        Password: <input type="password" name="${spring.status.expression}" value="${spring.status.value?html}"/>
        <#list spring.status.errorMessages as error>
          <span class="error">${error}</span>
          <br>
        </#list>
        <label class="main-label" style="width: 91px;">&nbsp;</label>
        <input type="submit" value="submit">
      </form>
    </fieldset>
    ...
    

    1)您需要&lt;#import "/spring.ftl" as spring/&gt; 才能添加非常有用的spring 用户定义指令。
    2)使用&lt;@spring.bind 'userForm.username'&gt; 指令将以下输入绑定到您的模型。这里“userForm”是您的模型,“username”是您要绑定的字段。该指令还声明了新变量“spring.status”,其中包含一个“表达式”变量——对于一个路径,一个“值”——以填充表单以防它返回错误,以及来自 BindingResult 的“errorMessages”。
    3)如果您使用消息源来支持不同的语言,您应该将&lt;span class="error"&gt;${error}&lt;/span&gt; 更改为&lt;@spring.message '${error}'/&gt; 之类的东西,否则您将只得到消息代码。

    希望对您有所帮助。

    【讨论】: