Java 困惑于如何验证SpringMVC表单,我的选项是什么?
最新的spring mvc,使用freemarker 希望有人能告诉我,在使用SpringMVC验证表单方面,我有哪些选择,推荐的方法是什么 我有一个表单,它不直接映射到模型,它有输入字段,当发布时,将用于初始化2个模型对象,然后我需要验证它们,如果它们通过,我将保存它们 如果失败,我想返回表单,用用户输入的内容预填充值并显示错误消息 我在这里和那里读过两种方法,其中一种是我做过的,并且了解它是如何工作的:Java 困惑于如何验证SpringMVC表单,我的选项是什么?,java,spring,validation,spring-mvc,freemarker,Java,Spring,Validation,Spring Mvc,Freemarker,最新的spring mvc,使用freemarker 希望有人能告诉我,在使用SpringMVC验证表单方面,我有哪些选择,推荐的方法是什么 我有一个表单,它不直接映射到模型,它有输入字段,当发布时,将用于初始化2个模型对象,然后我需要验证它们,如果它们通过,我将保存它们 如果失败,我想返回表单,用用户输入的内容预填充值并显示错误消息 我在这里和那里读过两种方法,其中一种是我做过的,并且了解它是如何工作的: @RequestMapping(...., method = RequestMethod
@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;
}
}
现在,如果我的表单直接映射到该表单,则此操作有效,但在我的情况下,我有:
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
更新
我现在已经在我的模型上使用了JSR303注释,如果我仍然可以使用这些注释,那就太好了
更新二
请阅读下面的赏金描述,了解我所寻找的赏金的摘要。基于类似的经验,我提出以下建议,同时我对您想要采取的方法的最后一步发表了评论。我使用你编号的步骤列表 步骤1:表单Bean 有两种方法。简单的方法是定义一个表单bean(我想您已经这样做了): 一种更精确的方法是实际定义
MyModel
,这样我只借用Model1
和Model2
中需要的字段,但我不确定这是否适合您的方式
步骤2:数据绑定
如果您的视图中有这样的表单
结构,Spring会为您这样做:
<form:form modelAttribute="myModel">
<form:input path="model1.somePropertyToBeSet" />
</form:form>
然后为自定义约束注册自定义验证器:
@interface Model1Constraint {}
@interface Model2Constraint {}
class MyModel1 {
@Model1Constraint
private Model1 model1;
@Model2Constraint
private Model2 model2;
// ...
}
class Model1ConstraintValidator implements ConstraintValidator<Model1Constraint, Model1> {
// implementation of isValid and initalize
}
class Model1ConstraintValidator实现ConstraintValidator{
//isValid和initalize的实现
}
Model2Constraint
也一样。使用自定义验证器,您可以检查在将MyModel
传递到请求处理方法之前需要确保的逻辑。我还假设您使用了
让Spring注册验证器;否则,您应该配置它们
步骤4:请求处理之前的自定义模型处理
您最初的想法是为这项工作使用一些数据绑定器。在您的描述中,您还提到此数据处理不依赖于来自表单数据的数据
关于设计和模块化,我不认为数据绑定器是实现这一目的的好地方。其次,由于表单没有数据依赖性,因此主要原因是允许数据绑定错误处理
因此,我的建议是,假设您现在处于公共模型和查看myMethod(@Valid MyModel model,BindingResult BindingResult)
。大概您可以在这里访问其他服务bean。因此,您可以在一些服务bean中有一个方法,该方法可以优化
或准备
(只是命名)您在这里填充的模型
。基于异常或任何适合您的其他机制,您可以使用bindingResult
再次返回错误
另一个建议是,如果您希望使用更多的DI/IoC方法,您也可以利用。但通过这种方式,您应该从拦截中的model和view
中提取MyModel
,然后继续
我希望这会有所帮助。Hibernate Validator 4.2支持方法级验证。您可以稍微重构代码,将两个模型传递到一个方法中,并验证它们 你可以吃这样的东西
public void persistUser(@NotNull @Valid Model1 model1, @NotNull @Valid Model2 model2) {
//continue ...
}
这是一个不寻常的问题,因为验证用户输入通常最有意义,因为这是我们无法控制的数据。这么说吧,我相信你已经知道了 一种选择是直接使用JSR303验证api在从用户输入、数据库等填充模型对象之后验证它们 下面是一个例子:
@RequestMapping(value=...)
public String myMethod(MyForm form, Model m) {
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
Validator validator = factory.getValidator();
Model1 model1 = createModel1FromUserInput(form);
Model2 model2 = createModel2FromUserInput(form);
Set<ConstraintViolation<?>> modelViolations = validator.validate(model1);
modelViolations.add(validator.validate(model2));
if(modelViolations.size() != 0) {
m.addAttribute("violations", modelViolations);
m.addAttribute("form", myForm); // add the form back to the model so it is populated
return "formPage";
}
return "successPage";
}
@RequestMapping(值=…)
公共字符串myMethod(MyForm表单,模型m){
ValidatorFactory=Validation.buildDefaultValidatorFactory();
Validator Validator=factory.getValidator();
Model1 Model1=createModel1FromUserInput(表单);
Model2 Model2=createModel2FromUserInput(表单);
在这里设置精彩的解释,请检查
也请检查下面的示例
@RequestMapping(value=...)
public String myMethod(MyForm form, Model m) {
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
Validator validator = factory.getValidator();
Model1 model1 = createModel1FromUserInput(form);
Model2 model2 = createModel2FromUserInput(form);
Set<ConstraintViolation<?>> modelViolations = validator.validate(model1);
modelViolations.add(validator.validate(model2));
if(modelViolations.size() != 0) {
m.addAttribute("violations", modelViolations);
m.addAttribute("form", myForm); // add the form back to the model so it is populated
return "formPage";
}
return "successPage";
}
BindingResult result = ... // not sure about the constructor
for(ConstraintViolation<?> violation : modelViolations) {
result.addError(new ObjectError(violation.getPropertyPath().toString(),violation.getMessage()));
}
<c:forEach items="${violations}" var="violation">
${violation.propertyPath}: ${violation.message} <br/>
</c:forEach>