【问题标题】:Spring MVC 3.0: How to validate path variable that is global to all request mappings efficiently?Spring MVC 3.0:如何有效地验证对所有请求映射都是全局的路径变量?
【发布时间】:2011-06-09 04:26:07
【问题描述】:

我正在尝试使用 Spring MVC 3.0,虽然我可以让它工作,但我似乎无法有效地处理这种特殊情况。

我有一个控制器,它处理“/{studyName}/module”前缀,它看起来像这样:-

@Controller
@RequestMapping(value = "/{studyName}/module")
public class ModuleController {

    @RequestMapping(...)
    public ModelAndView getA(@PathVariable String studyName, ...) {
        if (!validStudy(studyName)) { return bad request; }
        ...
    }

    @RequestMapping(...)
    public ModelAndView getB(@PathVariable String studyName, ...) {
        if (!validStudy(studyName)) { return bad request; }
        ...
    }

    @RequestMapping(...)
    public ModelAndView getC(@PathVariable String studyName, ...) {
        if (!validStudy(studyName)) { return bad request; }
        ...
    }

    @RequestMapping(...)
    public ModelAndView getD(@PathVariable String studyName, ...) {
        if (!validStudy(studyName)) { return bad request; }
        ...
    }
}

这段代码的问题是,我的 studyName 验证分散在所有方法中,也可能在其他控制器的方法中。有没有一种方法可以在一个地方对 studyName 路径变量进行验证,而无需使用 AOP 之类的东西?你如何处理这样的验证?

谢谢。

【问题讨论】:

    标签: java validation spring-mvc


    【解决方案1】:

    创建一个简单的验证类:

    public class StudyValidator {
        public boolean validateStudy(String studyName) {
            //your validate logic here
        }
    }
    

    然后将其注入ModuleController:

    class ModuleController {
        private StudyValidator sv = new StudyValidator(); //use spring injection to populate.
        boolean validStudy(String studyName) {
            return sv.validateStudy(studyName);
        }
    }
    

    简单。

    【讨论】:

    • 是的,但是我仍然需要在每个方法中调用validStudy(),这正是我现在面临的问题。
    • 我认为调用一个方法比通过 Spring 配置疯狂并设置一个完整的疯狂类来减少一行调用要少得多。为什么我们要以简单的名义让生活变得如此复杂?
    • 我误解了这个问题的目的是在多个控制器中使用通用代码的模块化。上面的 Bean 验证看起来不错! :)
    【解决方案2】:

    嗯,不确定它是否会起作用,但您可以将@Valid 注释为briefly mentioned in this link on validators.

    祝你好运!

    【讨论】:

    • 我确实看过@Valid,它似乎只使用休眠验证器4或我的自定义验证器类来验证模型。
    【解决方案3】:

    创建一个 StudyName 类,然后为 StudyName 注册一个 WebArgumentResolver 并在那里进行验证。

       public ModelAndView getA(@PathVariable StudyName studyName){
          ...
       }
    
       public class StudyNameResolver implements WebArgumentResolver{
          //have resolveArgument method do validation if resolved to a StudyName
       }
    

    【讨论】:

    • +1 让我了解 WebArgumentResolver。我之前确实看过这个,但我不愿意使用它,因为我可能必须为这个特定项目创建很多自定义解析器。
    【解决方案4】:

    目前,让这一切自动发生有点棘手,但这是可能的。您应该使用实现附录 C 的 Bean 验证 (JSR-303) 提供程序。目前是 Apache BeanValidation 或 Hibernate Validator 4.2(处于测试阶段)。

    将您选择的 bean 验证实现添加到类路径。这将是 Spring MVC 使用的 JSR-303 的实现。

    其次,使用@Valid 和任何约束注释来注释方法参数,例如@NonNull。

    这看起来像:

    public ModelAndView getB(@Valid @NonNull @PathVariable String studyName, ...) {
    

    应该可以。然后,您需要检查 Spring 错误是否有任何问题。

    或者,如果您不使用任何其他 Spring 参数,您可以使用 InitBinder 注册一个验证器,如下所示:

    @InitBinder
    public void initBinder(WebDataBinder binder) {
      binder.setValidator(new StudyNameValidator());
    }
    

    【讨论】:

    • +1 给你。我确实查看了@valid,但就我而言,我可能必须创建自定义验证注释,因为我需要检查 studyName 是否已在我的数据库中注册,因此我不能使用来自休眠验证器的内置验证。至于绑定验证器,我仍然需要在控制器的每个方法中检查“if (binder.hasErrors()) { do something }”,这正是我目前面临的问题。也许,这是目前唯一可用的优雅解决方案,但看到每个方法都重复相同的检查真的让我很烦恼。
    • 如果您的验证是检查数据库中是否存在某些东西,假设它可能存在,我只需执行查询并注册一个@ExceptionHandler 方法来处理不太可能的情况。
    • 据我所知,您还不能将 Valid 注释与 PathVariable 一起使用:jira.springsource.org/browse/SPR-6380
    【解决方案5】:

    我开始使用 spring 3 并且我确实喜欢您以这种方式进行验证的解决方案: public ModelAndView getB(@Valid @NonNull @PathVariable String studyName, ...) {

    但是,一旦路径变量无效(在本例中为 studyName = null),您如何捕获并显示该错误?

    我尝试使用绑定结果,但它不起作用。另外,你知道如何在jsp上显示错误吗?

    谢谢

    【讨论】:

      猜你喜欢
      • 2012-04-21
      • 2015-01-25
      • 2011-02-14
      • 2012-06-20
      • 1970-01-01
      • 2016-01-28
      • 2012-05-30
      • 2015-08-09
      • 2015-12-24
      相关资源
      最近更新 更多