读书人

[转]应用 Struts 2 开发 RESTful 服务

发布时间: 2012-10-09 10:21:45 作者: rapoo

[转]使用 Struts 2 开发 RESTful 服务

简介:?从 V2.1 开始,Struts 2 开始提供 Convention 插件,它允许根据“约定”来搜索 Action,以及管理 Action 和 Result 的映射。另外,Struts 2.1 还提供了 REST 插件,使 Struts 2 可以支持 Rails 风格的 URL,以对外提供 REST 风格的资源服务。本文作者通过代码示例演示了这些特性。

?

?

REST 是英文 Representational State Transfer 的缩写,这个术语由 Roy Thomas Fielding 博士在他的论文《Architectural Styles and the Design of Network-based Software Architectures》中提出。从这篇论文的标题可以看出:REST 是一种基于网络的软件架构风格。

提示:国内很多网络资料将 REST 翻译为“表述性状态转移”,不过笔者对这个翻译不太认同。因为这个专业术语无法传达 REST 的含义,读者可以先不要理会 REST 到底该如何翻译,尽量先去理解 REST 是什么?有什么用?然后再来看这个术语的翻译。关于 Roy Thomas Fielding 博士的原文参见如下地址:http://www.ics.uci.edu/~fielding/pubs/dissertation/top.htm。

REST 架构是针对传统 Web 应用提出的一种改进,是一种新型的分布式软件设计架构。对于异构系统如何进行整合的问题,目前主流做法都集中在使用 SOAP、WSDL 和 WS-* 规范的 Web Services。而 REST 架构实际上也是解决异构系统整合问题的一种新思路。

如果开发者在开发过程中能坚持 REST 原则,将可以得到一个使用了优质 Web 架构的系统,从而为系统提供更好的可伸缩性,并降低开发难度。关于 REST 架构的主要原则如下:

网络上的所有事物都可被抽象为资源(Resource)。 每个资源都有一个唯一的资源标识符(Resource Identifier)。 同一资源具有多种表现形式。 使用标准方法操作资源。 通过缓存来提高性能。 对资源的各种操作不会改变资源标识符。 所有的操作都是无状态的(Stateless)。

仅从上面几条原则来看 REST 架构,其实依然比较难以理解,下面笔者将从如下二个方面来介绍 REST。

通过查看 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 请求的处理结果。

?

从上面粗体字代码可以看出,BookService 提供了 4 个方法,用于实现对 Book 对象的 CRUD 操作。

下面开始定义支持 REST 的 Action 类了,这个 Action 类与前面介绍 Struts 2 的普通 Action 存在一些差异——因为该 Action 不再用 execute() 方法来处理用户请求,而是使用前面介绍的 7 个标准方法来处理用户请求。除此之外,该 Action 总是需要处理 id 请求参数,因此必须提供 id 请求参数,并为之提供对应的 setter 和 getter 方法。

因为本系统已经提供了 Book Model 类,并且为了更好的模拟 Rails 中 ActiveController(Controller)直接访问 ActiveRecord(Model)的方式,本系统采用了 ModelDriven 的开发方式,下面是本系统中支持 REST 的 Action 类的代码。

?

上面 Action 代码中粗体字代码定义了 7 个方法,这 7 个方法正是前面提到的标准方法。除此之外,该 Action 里还包含一个额外的 deleteConfirm() 方法,这个方法用于处理带 id 参数、且指定操作 deleteConfirm 资源的 GET 请求。也就是说,当用户请求 /book/1/deleteConfirm 时,该请求将由该方法负责处理。实际上,RestActionMapper 不仅可以将对 /book/1/edit 的请求映射到 Book 控制器的 edit() 方法,而 1 将作为 id 请求参数。实际上,它可以将任意 /book/1/xxx 的请求映射到 Book 控制器的 xxx() 方法,而 1 是请求参数。上面 Action 类使用了 @Results 进行修饰,这表明当 Action 的任何方法返回“success”逻辑视图时,系统将重定向到 book.action。

可能有读者会对 index()、create()、show() 三个方法的返回值感到疑惑:它们不再直接返回普通字符串作为逻辑视图名字,而是返回一个以字符串为参数的 DefaultHttpHeaders 对象?其实读者不必对 DefaultHttpHeaders 感到疑惑,其实 DefaultHttpHeaders 只是普通字符串的加强形式,用于 REST 对处理结果进行更多额外的控制。当 Action 类的处理方法返回字符串作为逻辑视图时,Struts 2 只能将其当成一个简单的视图名,仅能根据该视图名映射到实际视图资源,仅此而已。如果使用 DefaultHttpHeaders 作为逻辑视图,DefaultHttpHeaders 除了可以包含普通字符串作为逻辑视图名之外,还可以额外增加更多的控制数据,从而可以增强对 Response 的控制。关于 HttpHeaders 和 DefaultHttpHeaders 的介绍请参考 REST 插件的 API。

还有一点需要指出,上面的 BookController 控制器实现类的类名并不以 Action 结尾,而是以 Controller 结尾,因此我们可以在 struts.xml 文件中配置如下常量:

?

上面 JSP 页面非常简单,它负责迭代输出 Action 里包含的集合数据,向该应用 book.action 发送请求将看到如图 1 所示页面。



[转]应用 Struts 2 开发 RESTful 服务

Struts 2 的 REST 插件支持一种资源具有多少表示形式,当浏览者向 book.xml 发送请求将可以看到如图 2 所示页面。



[转]应用 Struts 2 开发 RESTful 服务

从图 2 可以看出,该页面正是 Action 所包含的全部数据,当使用 XML 显示时 REST 插件将会负责把这些数据转换成 XML 文档。

除此之外,REST 插件还提供了 JSON 格式的显示方式,当开发者向 book.json 发送请求将看到如图 3 所示页面。



[转]应用 Struts 2 开发 RESTful 服务

Struts 2 的 REST 插件默认支持 XHTML、XML 和 JSON 三种形式的数据。

当浏览者单击页面右边的“编辑”链接,将会向 book/idVal/edit 发送请求,这是一个包含 ID 请求参数、且指定操作 edit 资源的请求,因此将由 BookController 的 edit() 方法负责处理,处理结束后进入 book-edit.jsp 页面。浏览器里将看到如图 4 所示页面。



[转]应用 Struts 2 开发 RESTful 服务

该页面单击“修改”按钮时需要修改图书信息,也就是需要使用 PUT 操作,但由于 HTML 不支持 PUT 操作,因此需要为该表单页增加一个额外的请求参数:_method,该请求参数的值为 put。该表单页的代码如下:

?

该表单将提交给 BookController 的 update() 方法处理,update() 方法将负责修改系统里指定 ID 对应的图书信息。

与之类似的是,当请求需要执行 DELETE 操作时,一样需要增加名为 _method 的请求参数,并将该请求参数值设置为 delete

?

原文地址:http://www.ibm.com/developerworks/cn/java/j-lo-struts2rest/

读书人网 >软件架构设计

热点推荐