对于如何验证spring mvc表单感到困惑,我的选择是什么?

Bla*_*man 5 java validation spring freemarker spring-mvc

最新的春季mvc,使用freemarker.

希望有人可以告诉我在使用spring mvc验证表单方面我的选择是什么,以及建议的方法是做什么.

我有一个不直接映射到模型的表单,它有输入字段,当发布时,将用于初始化我需要验证的2个模型对象,如果它们通过,我将保存它们.

如果它们失败,我想返回到表单,用用户输入的内容预填充值并显示错误消息.

我已经在这里和那里阅读了大约2种方法,其中一次我已经完成并理解它是如何工作的:

@RequestMapping(...., method = RequestMethod.POST)
public ModelAndView myMethod(@Valid MyModel, BindingResult bindingResult) {
  ModelAndView mav = new ModelAndView("some/view");
  mav.addObject("mymodel", myModel);

  if(bindingResult.hasErrors()) {
     return mav;
  }

}
Run Code Online (Sandbox Code Playgroud)

现在,如果我的表单直接映射到表单,这有效,但在我的情况下,我有:

  1. 表单字段不映射到任何特定模型,它们具有来自2个模型的一些属性.

  2. 在验证发生之前,我需要手动创建2个模型,从表单中设置值,并手动设置一些属性:

  3. 在两个模型(model1,model2)上调用validate,并将这些错误消息附加到错误集合中,如果事情不起作用,我需要将其传递回相同的视图页面.

  4. 当表单发布时,我必须做一些数据库调用,并根据这些结果可能需要向错误集合添加其他消息.

有人能告诉我如何进行这种验证吗?

下面的伪代码:

   Model1 model1 = new Model1();
   Model2 model2 = new Model2();

   // manually or somehow automatically set the posted form values to model1 and model2.

   // set some fields manually, not from posted form
   model1.setProperty10(GlobalSettings.getDefaultProperty10());
   model2.setProperty11(GlobalSettings.getDefaultProperty11());

   // db calls, if they fail, add to errors collection

   if(bindingResult.hasErrors()) {
     return mav;
   }

   // validation passed, save
   Model1Service.save(model1);
   Model2Service.save(model2);

   redirect to another view
Run Code Online (Sandbox Code Playgroud)

更新

我现在已经在我的模型上使用了JSR 303注释,如果我可以使用那些仍然很好.

更新II

请阅读下面的赏金说明,了解我正在寻找的内容.

nob*_*beh 8

根据类似的经验,我提出以下建议,并且我对你想采取的方法的最后一步有评论.我使用您编号的步骤列表.

第1步:表单Bean

有两种方法可以做到这一点.简单的方法是定义一个表单bean(我认为你已经完成了):

class MyModel {
  private Model1 model1;
  private Model2 model2;
  // standard Java bean stuff
}
Run Code Online (Sandbox Code Playgroud)

更精确的方法是真正定义MyModel,这样我只借用,从需要的字段Model1Model2,但我不知道这是否适合你的方式.

第2步:数据绑定

如果您form在视图中有这样的结构,Spring会为您执行此操作:

<form:form modelAttribute="myModel">
  <form:input path="model1.somePropertyToBeSet" />
</form:form>
Run Code Online (Sandbox Code Playgroud)

第3步:验证

使用Spring自定义验证,您可以定义自定义约束:

@interface Model1Constraint {}
@interface Model2Constraint {}

class MyModel1 {

  @Model1Constraint
  private Model1 model1;

  @Model2Constraint
  private Model2 model2;

  // ...

}
Run Code Online (Sandbox Code Playgroud)

然后为自定义约束注册自定义验证器:

class Model1ConstraintValidator implements ConstraintValidator<Model1Constraint, Model1> {
// implementation of isValid and initalize
}
Run Code Online (Sandbox Code Playgroud)

同样的Model2Constraint.使用自定义验证器,您可以检查在MyModel传递到请求处理方法之前需要确保的逻辑.我还假设你曾经<mvc:annotation-driven />有过Spring注册验证器; 否则,你应该配置它们.

第4步:在请求处理之前自定义模型处理

您最初的想法是使用一些数据绑定器来完成这项工作.在您的描述中,您还提到此数据处理依赖于来自表单数据的数据.

关于设计和模块化,我不认为数据绑定器是出于此目的的好地方.其次,由于表单没有数据依赖性,您的主要原因是允许数据绑定错误处理.

所以,我的建议是,让我们说现在你进去了public ModelAndView myMethod(@Valid MyModel model, BindingResult bindingResult).据推测,您可以在此处访问其他服务bean.因此,您可以在某个服务bean中使用一个方法,该方法可以refineprepare(只是命名)model您在此处填充的内容.基于异常或任何其他适合您的机制,您可以使用bindingResult再次返回错误.

作为另一个建议,如果你想要更多的DI/IoC方法,你也可以利用Spring拦截器.但是这样,你应该MyModelModelAndView拦截中提取并继续.

我希望这有帮助.