struts2 rest插件详细说明

此REST插件简化了人们和电脑客户端对REST风格资源的访问。其目标是100%实现和Ruby on Rails REST URL风格相兼容的,并且可以免除使用XML作为资源的开发模式。它基于Convention Plugin来支持对action和result的自动配置。

此Rest风格的action映射强制兼容Ruby-On-Rails的风格映射。如果方法未被指定(通过“!”或者“method:”前缀),那么将基于ReST风格的约定(通过检查URL和HTTP方法)进行猜测。这里特别说明的是,此插件和codebehind plugin一起也可以正常工作,因此,不再需要使用基于XML的配置文件。

此映射支持如下参数:

struts.mapper.idParameterName - 如果设置,则它的值将被作为保存id的参数名,然后id将被从action名称中移除。不管是否指定了相关方法,此映射都会试图从url中移除标识符并将它作为一个参数保存。
struts.mapper.indexMethodName - 在没有id参数的情况下,通过GET请求调用的方法名。默认为index。
struts.mapper.getMethodName - 在具有id参数的情况下,通过GET请求调用的方法名。默认为show。
struts.mapper.postMethodName - 在没有id参数的情况下,通过POST请求调用的方法名。默认为create。
struts.mapper.putMethodName - 在具有id参数的情况下,通过PUT请求调用的方法名。默认为update。
struts.mapper.deleteMethodName - 在具有id参数的情况下,通过DELETE请求调用的方法名。默认为destory。
struts.mapper.editMethodName - 在具有id参数且指定了“edit”视图的情况下,通过GET请求调用的方法名。默认为edit。
struts.mapper.newMethodName - 在没有id参数且指定了“new”视图的情况下,通过GET请求调用的方法名。默认为editNew。


下列URL将调用Action的相关方法如下:

GET: /movies => method="index"
GET: /movies/Thrillers => method="show", id="Thrillers"
GET: /movies/Thrillers;edit => method="edit", id="Thrillers"
GET: /movies/Thrillers/edit => method="edit", id="Thrillers"
GET: /movies/new => method="editNew"
POST: /movies => method="create"
PUT: /movies/Thrillers => method="update", id="Thrillers"
DELETE: /movies/Thrillers => method="destroy", id="Thrillers"
为了模拟HTTP方法的PUT和DELETE请求,因为HTML并不支持,我们将使用一个叫做“_method”的HTTP参数。

或者,使用下表的表示方式:

HTTP methodURIClass.methodparameters
GET/movieMovie.index 
POST/movieMovie.create 
PUT/movie/ThrillersMovie.updateid="Thrillers"
DELETE/movie/ThrillersMovie.destroyid="Thrillers"
GET/movie/ThrillersMovie.showid="Thrillers"
GET/movie/Thrillers/editMovie.editid="Thrillers"
GET/movie/newMovie.editNew 

除了作为一个REST风格的URL映射器以外,此插件还对于multiple content types、通过URL扩展名的可切换性提供了内建的支持。这样,一个单一的资源就能够被作为一个multiple content types暴露出去,而不需要其他额外的工作。

例如,通过暴露一个“orders”资源,客户端可以立即通过如下方式进行访问:

http://my.company.com/myapp/orders/1
http://my.company.com/myapp/orders/1.xml
http://my.company.com/myapp/orders/1.xhtml
http://my.company.com/myapp/orders/1.json

此REST插件自动处理序列号和反序列化以及相应的格式化。

一、特性
完全实现 Ruby on Rails 的REST风格URL
支持免XML开发,不需要注解
内建序列号和反序列化支持,以支持XML和JSON
自动错误处理
针对HTTP响应的类型安全设置
自动有条件的GET支持

二、用法
在配置的包(package)中创建以“Controller”结尾的Java对象。这里的“Controller”后缀用于区别REST action和普通的Struts2 action。尽管这完全是可选的,以及它们的功能完全相同。现在,加入方法即可处理各种请求。举例说明,下面的资源action将支持使用GET和PUT请求访问/orders/34资源:

package
org.apache.struts2.rest.example;

public class OrdersController implements ModelDriven {

    private OrderManager orderManager;
    private String id;
    private Order model;

    // Handles /orders/{id} GET requests
    public HttpHeaders show() {
        model = orderManager.findOrder(id);
        return new DefaultHttpHeaders("show")
            .withETag(model.getUniqueStamp())
            .lastModified(model.getLastModified());
    }

    // Handles /orders/{id} PUT requests
    public String update() {
        orderManager.updateOrder(model);
        return "update";
    }

    // getters and setters
}

在这个例子中,使用了ModelDriven 接口,来确保只有模型——这里的Order对象,被返回给客户端。否则,OrdersController 对象将被整个序列化。

你也许在想为什么show()方法返回了一个HttpHeaders 对象,而update()方法返回了预期的结果代码字符串。REST插件添加了对action方法的支持,对于那些通过响应有更多控制的action,返回HttpHeaders 对象是一种方式。在本例中,我们想要确保响应包括ETag 头和一个最近修改日期,以便信息可以被客户端正确的缓存。HttpHeaders 对象是一个方便的方式,可以在保证在类型安全的情况下控制响应。

而且,请注意,我们没有在上述任何一个方法中,返回通常的“success”结果码。这允许我们使用Codebehind Plugin插件的特性,当访问扩展名为.xhtml的资源时,以更加直观的方式来选择结果模板去处理。在本例中,我们可以通过为相应的方法创建/orders-show.jsp 和/orders-update.jsp页面,来提供一个定制化的XHTML 资源视图。

2.1 定制ContentTypeHandlers
如果你需要处理不被默认处理器支持的扩展名时,你可以创建你自己的ContentTypeHandler 实现,并在struts.xml中进行定义即可。

<bean name="yaml" type="org.apache.struts2.rest.handler.ContentTypeHandler" class="com.mycompany.MyYamlContentHandler" />

如果内建的内容类型处理器无法满足你的需要,那么你可以提供另一个处理器,覆盖对任何扩展名的默认处理方式,并使用它自己的别名进行声明,例如:

<bean name="myXml" type="org.apache.struts2.rest.handler.ContentTypeHandler" class="com.mycompany.MyXmlContentHandler" />

然后,只需要告知REST插件使用你自己的处理器,去覆盖特定扩展的处理器即可。在struts.properties文件中,可以做如下配置:

struts.rest.handlerOverride.xml=myXml

2.2 关于struts.xml
配置Struts以使用REST action映射器:

<constant name="struts.mapper.class" value="rest" />

因为REST插件使用Convention plugin,需要在Struts.xml中进行相关设置:

<constant name="struts.convention.action.suffix" value="Controller"/>
<constant name="struts.convention.action.mapAllMatches" value="true"/>
<constant name="struts.convention.default.parent.package" value="rest-default"/>

对于上述例子而言,package设置如下:

<constant name="struts.convention.package.locators" value="example"/>

三、示例
此插件是随struts2-rest-showcase 应用程序一起发布的,用以演示一个简单的REST web应用程序。

该示例和不同于一般,控制器将被映射到一个关联的HTTP(PUT,DELETE)方法。

看下图可以让你更容易的理解REST的工作方式:

四、配置
配置可以定制,具体可以查看开发指南文档。要获得更多的配置项信息,可以查看Convention Plugin的文档。

设置描述默认可能值
struts.rest.handlerOverride.EXTENSION处理EXTENSION 值的ContentTypeHandler 实现的别名N/A任何声明了的ContentTypeHandler实现的别名
struts.rest.defaultExtension当没有在request中显示指定的时候默认使用扩展类型xml任意扩展名
struts.rest.validationFailureStatusCode校验失败后返回的HTTP状态码400任意HTTP的数字状态码

五、安装
复制插件的jar包到应用程序的/WEB-INF/lib 即可。此插件依赖于Convention Plugin,因此,如果没有类似于Maven2那样的支持传递依赖的构建系统的话,你可能也需要加入Convention Plugin的jar包。

六、资源
http://www.b-simple.de/documents - 精短的RESTful Rails 教程(PDF格式, 有多种语言)
RESTful Web Services - 来自 O'Reilly 的一本书
Go Light with Apache Struts 2 and REST - Don Brown 在 ApacheCon US 2008 年会上的幻灯片简报

 

---------------------------------------------------------------------------------------------------------------

--------------------------------------------------------------------------------------

删除在这里要多说一下,因为现在并不支持DELETE和PUT两个操作,所以,我们要在表单中多传一个值来模拟这种方式,方法就是在你的<form>标记中加入一个隐藏域:<input type="hidden" name="_method" value="DELETE"/>,这样,在提交表单的时候,Struts2就会知道你当前的请求方式是DELETE,而执行destory()方法。更新也是一样的,加入PUT隐藏域就可以了。下面这个例子:

Html代码 复制代码 收藏代码
  1. <table cellspacing="0"cellpadding="0"border="1"> 
  2.     <tr> 
  3.         <th>序号</th><th>描述</th><th>发布日期</th><th>操作</th> 
  4.     </tr> 
  5.     <s:iteratorvar="i"value="#request.JobCollectionList"status="s"> 
  6.     <s:formmethod="POST"theme="simple"action="users/operate-history/job-collection/%{#i.job.id}"> 
  7.     <s:hiddenname="_method"value="DELETE"/> 
  8.     <tr> 
  9.         <td><s:propertyvalue="#s.index+1"/></td> 
  10.         <td><s:propertyvalue="#i.job.jobDescription"/></td> 
  11.         <td><s:datename="#i.job.publishDate"format="yyyy-MM-dd"/></td> 
  12.         <td><s:submitvalue="删除"/></td> 
  13.     </tr> 
  14.     </s:form> 
  15.    </s:iterator> 
  16. </table> 
<table cellspacing="0" cellpadding="0" border="1">
	<tr>
		<th>序号</th><th>描述</th><th>发布日期</th><th>操作</th>
	</tr>
    <s:iterator var="i" value="#request.JobCollectionList" status="s">
	<s:form method="POST" theme="simple" action="users/operate-history/job-collection/%{#i.job.id}">
	<s:hidden name="_method" value="DELETE"/>
	<tr>
		<td><s:property value="#s.index+1"/></td>
		<td><s:property value="#i.job.jobDescription"/></td>
		<td><s:date name="#i.job.publishDate" format="yyyy-MM-dd" /></td>
		<td><s:submit value="删除"/></td>
	</tr>
	</s:form>
   </s:iterator>
</table>

 

以上使用迭代标签将内容输出之后,动态的绑定了action属性:action="users/operate-history/job-collection/%{#i.job.id},目的就是传入相应的id,这样发出请求之后,Action类中的id属性就会赋予相应的值,并且加入了隐藏域以模拟DELETE请求。在destroy()方法中,取得id,就可以调用业务逻辑对象来进行删除记录的操作了。

 

也可以用:href="user/${u.id}?_method=DELETE"这种方式。



其他请求大同小异,这里不再多说。

==========================================================

=====================================

有意思的是,使用http://localhost:8080/bee/action-name/1/XXX这种请求方式,其实XXX可以是任何合法的名字,不仅仅只有editNew和edit,名字你可以自己定,Struts2会查找XXX为名字的方法来调用,比如请求http://localhost:8080/bee/test/1/abc,那么TestAction的public String abc()就会被调用。

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值