Spring MVC @Validation 与通用控制器方法中的标记接口

Posted

技术标签:

【中文标题】Spring MVC @Validation 与通用控制器方法中的标记接口【英文标题】:Spring MVC @Validation with Marker Interface in Generic Controller Method 【发布时间】:2017-09-13 11:46:16 【问题描述】:

我有一个 Spring MVC 调查应用程序,其中每个表单 POST 调用的 Controller 方法实际上是相同的:

@PostMapping("/1")
public String processGroupOne (
        Model model,
        @ModelAttribute("pageNum") int pageNum, 
        @ModelAttribute(GlobalControllerAdvice.SESSION_ATTRIBUTE_NAME) @Validated(SurveyGroupOne.class) SurveyCommand surveyCommand, 
        BindingResult result) 
    if (result.hasErrors()) 
        LOG.debug(result.getAllErrors().toString());
        model.addAttribute("pageNum", pageNum);
        return "survey/page".concat(Integer.toString(pageNum));
    
    pageNum++;
    model.addAttribute("pageNum", pageNum);
    return "redirect:/survey/".concat(Integer.toString(pageNum));

唯一的区别是在沿途的每一站验证 SurveyCommand 对象的哪一部分。这是由传递给 @Validated() 注释的标记接口指定的。标记接口(SurveyGroupOne、SurveyGroupTwo 等)就是这样,标记:

public interface SurveyGroupOne 
public interface SurveyGroupTwo 
...

它们应用于 SurveyCommand 对象中的对象属性:

public class Person 
    @NotBlank(groups = 
                    SurveyGroupTwo.class, 
                    SurveyGroupThree.class)
    private String firstName;
    @NotBlank(groups = 
                    SurveyGroupTwo.class, 
                    SurveyGroupThree.class)
    private String lastName;
...

我的问题:我怎样才能使方法通用并且仍然使用特定于正在处理的页面的标记接口?像这样的:

@PostMapping("/pageNum")
public String processGroupOne (
        Model model,
        @PathVariable("pageNum") int pageNum, 
        @ModelAttribute(GlobalControllerAdvice.SESSION_ATTRIBUTE_NAME) 
            @Validated(__what goes here??__) SurveyCommand surveyCommand, 
        BindingResult result) 
    if (result.hasErrors()) 
        LOG.debug(result.getAllErrors().toString());
        model.addAttribute("pageNum", pageNum);
        return "survey/page".concat(Integer.toString(pageNum));
    
    pageNum++;
    model.addAttribute("pageNum", pageNum);
    return "redirect:/survey/".concat(Integer.toString(pageNum));

如何仅根据 pageNum @PathVariable(或任何其他参数)将正确的标记接口传递给 @Validated?

【问题讨论】:

【参考方案1】:

因为@Validated 是一个注解,它要求它的参数在编译期间可用,因此是静态的。您仍然可以使用它,但在这种情况下,您将有 N 个方法,其中 N 是多个步骤。要区分一个步骤,您可以use params argument of @PostMapping annotation。

还有另一种方式,您需要将Validator 注入控制器和您需要的invoke it directly with an appropriate group。

【讨论】:

以上是关于Spring MVC @Validation 与通用控制器方法中的标记接口的主要内容,如果未能解决你的问题,请参考以下文章

Spring MVC学习—Validation基于注解的声明式数据校验机制全解一万字

JSR-303 Bean Validation 介绍及 Spring MVC 服务端验证最佳实践

覆盖spring web mvc的默认Hibernate Validator

Spring MVC 3 验证 - 找不到默认提供程序

Java / Spring MVC 3 验证电子邮件地址

关于spring mvc 请求参数校验使用中的坑 。 maven 生命周期,线程池杂识