在 Spring MVC 中使用混合注解和 XML 方法进行请求映射

工程 | Rossen Stoyanchev | 2008年3月24日 | ...

在 Spring 2.5 中,可以使用注解来配置 Web 应用程序的所有部分。特别是在 Web 层,注解的应用尤其引人注目,因为开发人员传统上依赖 SimpleFormController 和 MultiActionController 来处理表单页面。注解的引入创造了第三种选择,一种不需要基类即可提供与先前方法相同的灵活性。

虽然使用带注解的 POJO 来实现 Controller 很容易理解,但在 URL 到 Controller 的映射方面,其优势并不那么明显。如果使用注解来定义所有的 URL 映射规则会怎么样呢?事实上,这正是集中式配置在 Spring MVC 应用程序开发人员中一直以来运行良好的一个领域。

让我们回顾一下 Spring 2.0 中 URL 到 Controller 的映射选项。

  1. Bean 名称方法(BeanNameUrlHandlerMapping)。每个 Bean 的名称就是它服务的路径。尽管简单,但如果与粗粒度的 Servlet 映射(例如 "/browse/*"、"/order/*"、"/reports/*" 等)结合使用,这种方法是可扩展的。
  2. 集中式方法(SimpleUrlHandlerMapping)。一个集中的地方用于查看 URL 模式和 Controller 映射。
  3. 约定优于配置方法(ClassNameUrlHandlerMapping)。将 URL 路径与类名匹配。因此,"/accounts/*" 被映射到一个名为 AccountsController 的 MultiActionController。无需显式映射。

Spring 2.5 通过 @RequestMapping 注解增加了第四种选择,该注解可以放置在类或方法上。当同时放置在类和方法上时,方法级别的映射会缩小类级别的映射范围。

以下是一个 SimpleFormController 风格的工作流程,其中方法级别的映射由请求方法缩小范围。


@Controller 
@RequestMapping("/editAccount")
public class EditAccountController {

    @RequestMapping(method=RequestMethod.GET)
    public Account setupForm(@RequestParam("id") Long id) {
        ...
        return account;
    }

    @RequestMapping(method=RequestMethod.POST)
    public String processSubmit(Account account) {
        ...
        return "redirect:/success.htm";
    }
}

以下是一个 MultiActionController 风格的委托,其中方法级别的映射由请求方法和相对路径共同缩小范围。


@Controller 
@RequestMapping("/accounts/*")
public class AccountsController {

    @RequestMapping(method=RequestMethod.GET)
    public List<Account> list() {...}

    @RequestMapping(method=RequestMethod.GET)
    public Account show(@RequestParam("id") Long id) {...}

    @RequestMapping(method=RequestMethod.POST)
    public String create(Account account) {...}
    ... 
}

正如你所见,当 "/accounts/*" 映射嵌入在代码中时,很难强制执行应用程序范围内的 Controller 映射约定。至少在没有严格纪律的情况下是这样。幸运的是,有一种方法可以将外部 HandlerMapping 与方法级别的 @RequestMapping 注解结合起来。下面是一个说明这种方法如何工作的示例。


<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
    <property name="mappings">
        <value>
            /accounts/*=accountsController
        </value>
    <property>
</bean>

@Controller
public class AccountsController {

    @RequestMapping(method=RequestMethod.GET)
    public List<Account> list() {...}

    @RequestMapping(method=RequestMethod.GET)
    public Account show(@RequestParam("id") Long id) {...}

    @RequestMapping(method=RequestMethod.POST)
    public String create(Account account) {...}
    ... 
}

在这里,Controller 映射驻留在中心化的基于 XML 的映射中,而 Action 方法映射通过注解指定。这种方法可以被描述为一种 POJO MultiActionController,带有基于注解的方法分派。事实上,在最近 SpringSource 的一次沟通中,Juergen 指出提供一种基于注解的 MultiActionController 的替代方案是 Spring 2.5 的一个明确设计目标,所以我想这并不令人意外!此外,目前正在进行一项工作,允许你将方法级别的 @RequestMapping 注解与 ControllerClassNameHandlerMapping 约定结合使用(请参阅 SPR-4129)。

那么,这一切的意义何在?

一种完全基于 XML 配置 Web 层的方法可能会变得冗长,但集中式、外部化的配置确实有其作用。扩展框架特定的基类,并通过深层继承层次结构来实现控制逻辑,也可能变得冗长,我们通常认为如果可以避免,就应该避免。在 Spring MVC 2.5 中,注解可以通过将方法映射规则封装在你的 Controller 类中来解决这两个问题,同时还允许你将 Controller 实现为 POJO。此外,上述混合方法表明如何获得外部化配置和基于注解的配置的最佳优势。

获取 Spring 新闻通讯

通过 Spring 新闻通讯保持联系

订阅

领先一步

VMware 提供培训和认证,助您加速进步。

了解更多

获得支持

Tanzu Spring 提供 OpenJDK™、Spring 和 Apache Tomcat® 的支持和二进制文件,只需一份简单的订阅。

了解更多

即将举行的活动

查看 Spring 社区所有即将举行的活动。

查看所有