【问题标题】:Can't show error message after failed spring mvc form validationspring mvc表单验证失败后无法显示错误消息
【发布时间】:2012-04-08 02:32:20
【问题描述】:

我有商业模式课程:

public class User {
     @Size(min = 3, max = 20, message = "Username must be between 3 and 20 characters long")
     @Pattern(regexp = "^[a-zA-Z0-9]+$", message = "Username must be alphanumeric with no spaces")
     @Column(name = "name")
     private String name;

     @Id
     @GeneratedValue
     @Column(name = "user_id")
     private Long userID;

     @OneToMany(cascade = CascadeType.ALL)
     @JoinTable(name = "userDic", joinColumns = { @JoinColumn(name = "user_id", referencedColumnName = "user_id") }, inverseJoinColumns = {
 @JoinColumn(name = "acc_id", referencedColumnName = "acc_id") })
     @LazyCollection(value = LazyCollectionOption.FALSE)
     private Set<Account> allAccounts; //............. //constructors , setters , getters here

在 jsp 中新用户的输入是通过 spring 形式发生的:

<form:form method="post" action="AddUser" modelAttribute="user">
        <table>
            <tr>
                <td><form:label path="name">First Name</form:label></td>
                <td><form:input path="name" /></td>
                <td><form:errors path="*" /></td>
            </tr>
            <tr>
                <td colspan="2"><input type="submit" value="Add User" /></td>
            </tr>
        </table>
    </form:form>

这里是处理这个jsp的控制器:

@Controller
@SessionAttributes
public class AdminServlet
{

    /* private UserValidator validator;

     @InitBinder("user")
     protected void initBinder(WebDataBinder binder)
     {
         binder.setValidator(validator);
     }*/

    @RequestMapping(value = "/")
    public ModelAndView showUsers() throws ClassNotFoundException, SQLException
    {
        ModelAndView mav = new ModelAndView();
        mav.setViewName("index");
        mav.addObject("ATMUsers", MainService.getAllUsers());
        mav.addObject("user", new User());
        return mav;
    }

    @RequestMapping(value = "/AddUser", method = RequestMethod.POST)
    public String AddUser(@ModelAttribute("user") @Valid User user, BindingResult result)
    {
        if (!result.hasErrors())
            MainService.AddUser(user);
        return "redirect:/";
    }

}

字段 name 的验证正确进行。但是控制器只是重新加载页面,我没有看到任何类型的错误消息。

如果我取消注释控制器中关于 UserValidatorInitBinder 的代码,我会收到错误,但它不是 &lt;form:errors path="*" /&gt; 中的文本,而是 java 异常

javax.validation.ConstraintViolationException:在组 [javax.validation.groups.Default, ] 的持续时间内,类 [com.antonbanking.business.User] 的验证失败。

问题是我做错了什么才得到验证错误消息?顺便说一句full code is available in github.

【问题讨论】:

标签: java jpa spring-mvc validation bean-validation


【解决方案1】:

我自己解决问题 - 问题是 AdminServlet.AddUser 的回报。因为我创建了"redirect:/",这导致创建了包括 BindingResult 在内的全新对象,因此所有有关错误的信息都被删除了。
改变后

    @RequestMapping(value = "/AddUser", method = RequestMethod.POST)
    public String AddUser(@ModelAttribute("user") @Valid User user, BindingResult result)
    {
        if (!result.hasErrors())
            MainService.AddUser(user);
        return "redirect:/";
    }

    @RequestMapping(value = "/AddUser", method = RequestMethod.POST)
    public ModelAndView AddUser(@ModelAttribute("user") @Valid User user, BindingResult result)
    {
        ModelAndView mav = new ModelAndView();
        mav.setViewName("index");
        mav.addObject("ATMUsers", MainService.getAllUsers());
        if (result.hasErrors())
            mav.addObject("user", user);
        else
        {
            mav.addObject("user", new User());
            MainService.AddUser(user);
        }
        return mav;
    }

一切开始正常工作。

【讨论】:

    【解决方案2】:

    MainService.AddUser(user); 周围捕获异常并在 catch 子句中将错误添加到 BindingResult 对象或重定向。

    BindingResult (addError or reject* from Errors) 另见Validation (without annotation)

    【讨论】:

    • 我试图实施您的建议,这迫使我在两个地方捕获 ConstraintViolationException:1. Hibernate 级别 - 实际上发生异常以关闭打开的会话(因为它不是 HibernateException 它未能被捕获)2 . 在我重新抛出它并在MainService.AddUser(user) 中再次捕获但毕竟我仍然得到异常 - 现在是另一个异常 - dl.dropbox.com/u/25516021/Error2.txt。一般来说,我认为这不是好方法 - 在两个地方捕获相同的异常。
    • 也在你提供的链接中(顺便说一句,我已经读过这个 - 验证(没有注释))我找不到任何需要捕获 ConstraintViolationException 的例子......
    • 您可以从控制器中捕获未经检查的异常(扩展 RuntimeException),而不是捕获并重新抛出异常...
    • 我捕获并重新抛出的原因是因为我第一次捕获回滚并正确关闭事务(Hibernate),第二次将错误添加到 BindingResult(控制器级别)。如果我只在控制器中捕获错误,那么我将得到关于未关闭会话(休眠会话)的异常
    • org.hibernate.AssertionFailure: null id in com.antonbanking.business.User entry (don't flush the Session after an exception occurs) - 如果我只在控制器中捕获,这就是我得到的结果
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-23
    • 2015-04-17
    • 2018-12-16
    • 1970-01-01
    • 2018-09-20
    • 1970-01-01
    相关资源
    最近更新 更多