Struts 2 的 REST 支持基础教程
从 Struts 2.1 开始,Struts 2 改为使用 Convention 插件来支持零配置。Convention 插件彻底地抛弃了配置信息,不仅不需要使用 struts.xml 文件进行配置,甚至不需要使用 Annotation 进行配置。而是由 Struts 2 根据约定来自动配置。Convention 这个单词的翻译过来就是“约定”的意思。有 Ruby On Rails 开发经验的读者知道 Rails 有一条重要原则:约定优于配置。Rails 开发者只需要按约定开发 ActiveRecord、ActiveController 即可,无需进行配置。很明显,Struts 2 的 Convention 插件借鉴了 Rails 的创意,甚至连插件的名称都借鉴了“约定优于配置”原则。
由于 Struts 2 的 Convention 插件的主要特点是“约定优于配置”,当我们已经习惯了 Struts 2 的基本开发方法之后,如果希望改为使用 Convention 插件也非常容易,我们只要放弃 Stuts 2.1 应用原有的配置文件,改为按 Convention 插件的约定来定义 Action 即可。以 Convention 插件为基础,Struts 2.1 又新增了 REST 插件,允许 Struts 2 应用对外提供 REST 服务。REST 插件也无需使用 XML 进行配置管理。Struts 2.1 通过 REST 插件完全可以提供让人和机器客户端共同使用的资源,并支持 Ruby On Rails 风格的 URL。
Convention 这个单词的翻译过来就是“约定”的意思。有 Ruby On Rails 开发经验的读者知道 Rails 有一条重要原则:约定优于配置。Rails 开发者只需要按约定开发 ActiveRecord、ActiveController 即可,无需进行配置。很明显,Struts 2 的 Convention 插件借鉴了 Rails 的创意,甚至连插件的名称都借鉴了“约定优于配置”原则。
从本质上来看,Struts 2 依然是一个 MVC 框架,最初设计 Struts 2 时并没有按 REST 架构进行设计,因此 Struts 2 本质上并不是一个 REST 框架。由于 Struts 2 提供了良好的可扩展性,因此允许通过 REST 插件将其扩展成支持 REST 的框架。REST 插件的核心是 RestActionMapper,它负责将 Rails 风格的 URL 转换为传统请求的 URL。
用 WinRAR 打开 struts2-rest-plugin-2.1.6 文件,看到该文件里包含一个 struts-plugin.xml 文件,该文件中包含如下一行:
<!-- 定义支持 REST 的 ActionMapper --> <bean type="org.apache.struts2.dispatcher.mapper.ActionMapper" name="rest" class="org.apache.struts2.rest.RestActionMapper" />
通过查看 RestActionMapper 的 API 说明,我们发现它可接受如下几个参数:
- struts.mapper.idParameterName:用于设置 ID 请求参数的参数名,该属性值默认是 id。
- struts.mapper.indexMethodName:设置不带 id 请求参数的 GET 请求调用 Action 的哪个方法。该属性值默认是 index。
- struts.mapper.getMethodName:设置带 id 请求参数的 GET 请求调用 Action 的哪个方法。该属性值默认是 show。
- struts.mapper.postMethodName:设置不带 id 请求参数的 POST 请求调用 Action 的哪个方法。该属性值默认是 create。
- struts.mapper.putMethodName:设置带 id 请求参数的 PUT 请求调用 Action 的哪个方法。该属性值默认是 update。
- struts.mapper.deleteMethodName:设置带 id 请求参数的 DELETE 请求调用 Action 的哪个方法。该属性值默认是 destroy。
- struts.mapper.editMethodName:设置带 id 请求参数、且指定操作 edit 资源的 GET 请求调用 Action 的哪个方法。该属性值默认是 edit。
- struts.mapper.newMethodName:设置不带 id 请求参数、且指定操作 edit 资源的 GET 请求调用 Action 的哪个方法。该属性值默认是 editNew。
在 RestActionMapper 的方法列表中,我们看到 setIdParameterName、setIndexMethodName、setGetMethodName、 setPostMethodName、setPutMethodName、setDeleteMethodName、 setEditMethodName、setNewMethodName 等方法,这些方法对应为上面列出的方法提供 setter 支持。
通常情况下,我们没有必要改变 RestActionMapper 的参数,直接使用这些参数的默认值就可支持 Rails 风格的 REST。根据前面介绍可以看出:支持 REST 风格的 Action 至少包含如下 7 个方法:
- index:处理不带 id 请求参数的 GET 请求。
- show:处理带 id 请求参数的 GET 请求。
- create:处理不带 id 请求参数的 POST 请求。
- update:处理带 id 请求参数的 PUT 请求。
- destroy:处理带 id 请求参数的 DELETE 请求。
- edit:处理带 id 请求参数,且指定操作 edit 资源的 GET 请求。
- editNew:处理不带 id 请求参数,且指定操作 edit 资源的 GET 请求。
如果请求需要向服务器发送 id 请求参数,直接将请求参数的值附加在 URL 中即可。表 1 显示了 RestActionMapper 对不同 HTTP 请求的处理结果。
表 1. RestActionMapper 对 HTTP 请求的处理
| HTTP 方法 | URI | 调用 Action 的方法 | 请求参数 |
| GET | /book | index | |
| POST | /book | create | |
| PUT | /book/2 | update | id=2 |
| DELETE | /book/2 | destroy | id=2 |
| GET | /book/2 | show | id=2 |
| GET | /book/2/edit | edit | id=2 |
| GET | /book/new | editNew |
不幸地是,标准 HTML 语言目前根本不支持 PUT 和 DELETE 两个操作,为了弥补这种不足,REST 插件允许开发者提交请求时额外增加一个 _method 请求参数,该参数值可以为 PUT 或 DELETE,用于模拟 HTTP 协议的 PUT 和 DELETE 操作。

