Spring MVC Thymeleaf错误模板覆盖内联表单错误消息

时间:2017-12-12 22:07:57

标签: spring forms validation spring-mvc thymeleaf

我正致力于验证表单并显示未使用Thymeleaf通过验证的字段的内联错误。我使用的是Spring Boot 1.5.8。

我有一个User对象将绑定到表单。它包含以下字段:usernameemail。这是表格声明,

<form role="form" class="form" method="post"
    th:action="@{'/admin/user/new'}" th:object="${user}">

我设置了一个这样的错误控制器,因为我想要一个catch all error页面。我还在src/main/resources/templates/error.html创建了一个模板。这是因为根据此github issue,错误页面上的安全上下文丢失了,尽管它表明问题应该在我的版本中修复。如果没有此控制器,则会显示默认错误模板,但我无法访问安全上下文。使用此控制器和error.html模板将处理任何随机错误。

@Controller
public class ErrorController extends BasicErrorController {

    /**
     * This Bean declaration provides the Spring Security Context to 4xx responses. This is reported as
     * fixed in Spring Boot 2.0.0:
     *
     * https://github.com/spring-projects/spring-boot/issues/1048
     *
     * @param springSecurityFilterChain
     * @return
     */
    @Bean
    public FilterRegistrationBean getSpringSecurityFilterChainBindedToError(
                    @Qualifier("springSecurityFilterChain") Filter springSecurityFilterChain) {

            FilterRegistrationBean registration = new FilterRegistrationBean();
            registration.setFilter(springSecurityFilterChain);
            registration.setDispatcherTypes(EnumSet.allOf(DispatcherType.class));
            return registration;
    }

    @Autowired
    public ErrorController(ErrorAttributes errorAttributes) {
        super(errorAttributes, new ErrorProperties());
    }

    @RequestMapping(value = "/error")
    public String error(Model model) {
        return "/error";
    }

    @Override
    public String getErrorPath() {
        return "/__dummyErrorPath";
    }

}

对于此示例,我只是尝试验证email字段,并在此字段旁边验证失败时显示消息。类字段在User

上看起来像这样
@NotNull
@Email
private String email;

Thymeleaf字段看起来像这样,

<div th:fragment="email" class="form-group">
    <label>Email*</label>
    <input class="form-control" type="text" th:field="*{email}" th:required="required" />
    <span class="error" th:if="${#fields.hasErrors('email')}" th:errors="*{email}">...</span>
</div>

新的用户表单控制器方法如下所示,

@GetMapping("admin/user/new")
public String newUser(Model model, HttpServletRequest request) {
    model.addAttribute("user", new User());
    return "admin/user/new";
}

相应的POST方法如下所示,

@PostMapping("admin/user/new")
public String newUser(@Valid @ModelAttribute User user, final ModelMap model, BindingResult bindingResult) {
    Assert.notNull(user, "User must not be null");
    if (bindingResult.hasErrors()) {
        return "admin/user/new";
    }
    userService.save(user);
    model.clear();
    return "redirect:/admin/user/list";
}

在这个POST方法中,我检查BindingResult是否有错误。如果确实如此,我希望使用显示的内联错误消息呈现admin/user/new模板。但是,我正在捕获所有错误模板。该网址仍显示/admin/user/new,刷新页面仍会显示错误模板。

我的主要问题是如何在可能的情况下使用catch all error页面并仍然显示内联错误?

2 个答案:

答案 0 :(得分:1)

我认为BindingResult需要直接遵循参数列表中的Valid annotation'd参数。

请参阅Why does BindingResult have to follow @Valid?

我会给你一个去吧

答案 1 :(得分:0)

在html-view中使用它怎么办?

<div th:if="${param.error}"
     th:text="${session['SPRING_SECURITY_LAST_EXCEPTION'].message}">
</div>