Spring MVC 3.0:如何有效地验证对所有请求映射都是全局的路径变量?

Posted

技术标签:

【中文标题】Spring MVC 3.0:如何有效地验证对所有请求映射都是全局的路径变量?【英文标题】:Spring MVC 3.0: How to validate path variable that is global to all request mappings efficiently? 【发布时间】: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 之类的东西?你如何处理这样的验证?

谢谢。

【问题讨论】:

【参考方案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上显示错误吗?

谢谢

【讨论】:

以上是关于Spring MVC 3.0:如何有效地验证对所有请求映射都是全局的路径变量?的主要内容,如果未能解决你的问题,请参考以下文章

如何有效地调试对 MailChimp 3.0 服务器的 JQuery GET 请求?

Spring MVC 3.0 基本认证实现

Spring MVC 从 2.5 到 3.0

如何使用 Spring Ldap Authentication 和 spring mvc 对用户进行身份验证

使用 Spring MVC 3.0 和 @EJB 注释而没有映射名称?

Spring MVC 代码注入验证器