struts2: 玩转 rest-plugin

2024-06-11 02:58
文章标签 玩转 struts2 plugin rest

本文主要是介绍struts2: 玩转 rest-plugin,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

近期使用struts2的rest-plugin,参考官方示例struts2-rest-showcase,做了一个restful service小项目,但官网提供的这个示例过于简单,埋下了巨坑无数,下面是一些遇到的问题及解决办法:

注:下面这些问题,很多是相互关联的,要解决一个,得同时解决另一个。 

一、与config-browser-plugin、convension-plugin、非rest Action 共存的问题

rest-plugin的气场实在太强,一旦使用,config-browser-plugin、convension-plugin这二个plugin就挂了

解决思路:将所有rest服务,都放在/rest/路径下,用package的namespace把它隔离出来,其它常规的action,放在其它路径,这样二者就不冲突了

复制代码
 1     <!-- Overwrite Convention -->
 2     <constant name="struts.convention.action.suffix" value="Controller" />
 3     <constant name="struts.convention.action.mapAllMatches" value="true" />
 4     <!--<constant name="struts.rest.content.restrictToGET" value="false" />-->
 5     <constant name="struts.convention.default.parent.package" value="rest-default" />
 6     <constant name="struts.convention.package.locators" value="action" />
 7     <!-- <constant name="struts.rest.namespace" value="/rest" /> -->
 8     <constant name="struts.convention.action.includeJars" value=".*?/_wl_cls_gen.*?jar(!/)?" />
 9     <constant name="struts.convention.exclude.parentClassLoader" value="true" />
10     <constant name="struts.convention.action.fileProtocols" value="jar,zip,vfsfile,vfszip" />
11 
12     <constant name="struts.mapper.class" value="org.apache.struts2.dispatcher.mapper.PrefixBasedActionMapper" />
13     <constant name="struts.mapper.prefixMapping" value="/rest:rest,:struts" />
14     <constant name="struts.mapper.alwaysSelectFullNamespace" value="false" />
15 
16         <package name="default" namespace="/rest" extends="rest-default" />
复制代码

 

二、拦截器及ModelDrive的问题

如果自定义拦截器(比如:自定义异常拦截器),默认情况下是无法拦截rest的Action

解决办法:

a) strut2.xml中定义二个package:rest-package、page-package,并在这二个package中,加上自己的拦截器,完整strut2.xml参考下面的内容:

View Code

b) 所有rest Action继承自一个自定义基类,所有常规page的Action,继承自另一个自定义基类

这二个基类用@ParentPackage 指定package,分别对应struts2.xml中的配置,这样运行时,不管是rest action,还是非rest action,都能被拦截器拦截

View Code
View Code

另外:官方的示例为了简便,在setId方法里,直接给Model赋值了,但这有点误导,因为拦截器拦截到的方法,并不是setId(),而是show()/index()之类的方法,所以应该在show方法里,调用 model = xxx.getModel(id),否则按原来的写法,如果getModel这里报错 -> setId()报错,但show()方法并没有出错,拦截器会认为没有异常发生。

View Code

 

三、返回XML节点的别名(alias)问题

默认情况下,返回的xml根节点为dto对应的完整package名,看上去很别扭

解决方法:

dto的class上,用@XStreamAlias指定别名

View Code

然后再创建自己的XmlHandler,为了节省系统开销,下面的代码用了一个单例:

View Code
View Code

注:别名一定要在toObject方法里,明确指定,否则别名的注解不起作用。

最后在struts2.xml里,还要注册bean,参考前面完整的xml内容。

 

四、返回JSON的Date属性格式化的问题

默认情况下,如果model有日期型属性,返回的json格式十分长,看上去太臃肿,类似的,可以自己定义ContentTypeHandler来解决

View Code
View Code

 

五、restful service 该返回哪种视图,xhtml? json? xml?

通常用rest-plugin,是为了开发rest-service,但是官网的示例返回的默认都是页面视图,这个显然不适合,最理想情况是,如果在页面上操作,操作完以后,应该返回页面视图(即: xxx.xhtml),如果是用xml参数进来的,应该返回xml视图(即: xxx.xml),如果是ajax用json post过来的,应该返回到json视图(即:xxx.json)

解决办法:根据Request的Header来判断来源,然后做相应的分支处理

View Code

 

六、json post到service,model取不到值的问题

这个问题最恶心,连官方默认提供的org.apache.struts2.rest.handler.JsonLibHandler都有问题,原因在json反序列化的机制,大家可以感受下这段代码:

View Code

输出结果:

id:null,clientName:null,amount:0,createTime:Wed Oct 22 15:05:12 CST 2014

29791
----
id:3,clientName:Bob,amount:33,createTime:Wed Oct 22 11:04:48 CST 2014
2137470
----

id:null,clientName:null,amount:0,createTime:Wed Oct 22 15:05:12 CST 2014
29791

虽然传递的参数是Object,因java只有值传递,这里传递的值即为对象的“指针地址值”,但是json内部反序列化时,入口并非这个指针值,而是xxx.getClass(),即类型指针,导致最后toObject执行完,原来的指针是啥还是啥,跟反序列过程中"新创建"出来的新Object instance,完全豪无关联。因此,不得不改造成

View Code

手动把新对象的属性,复制到target对象上,这样就保证了反序列后的结果,在toObject执行完以后,会反映到target上。

注:可能有朋友会问了,为什么只有json会这样,xml不会呢?再仔细看下XStreamHandler的toObject方法

View Code

最后一行xstream.fromXML(in, target);这是开始xml->object的入口,这里传递的就是target的地址对应的值,而不是象json那样是xxx.getClass()。如果进一步看源码,最后会发现执行的是com.thoughtworks.xstream.core.TreeUnmarshaller类里的

View Code

整个过程,都没有新对象实例创建,所以相应的变化,能一直保持到toObject调用完成后。

 

七、id参数太单一的问题

这个其实并不是大太的问题,GET方式下,url里本来就不适合传递过多参数,实在想用多个参数,做个约定,比如  /orders/show/a-b-c,即id值为"a-b-c",然后拆解一下,a,b,c对应不同的含义即可

POST方式,更不成问题,直接post过来一段xml或json,最终映射成model,想要多少参数都不是问题

 

最后给出源码示例:struts-rest-ex-src.zip (基于官网的rest-showcase修改而来)

这篇关于struts2: 玩转 rest-plugin的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1050023

相关文章

maven中的maven-antrun-plugin插件示例详解

《maven中的maven-antrun-plugin插件示例详解》maven-antrun-plugin是Maven生态中一个强大的工具,尤其适合需要复用Ant脚本或实现复杂构建逻辑的场景... 目录1. 核心功能2. 典型使用场景3. 配置示例4. 关键配置项5. 优缺点分析6. 最佳实践7. 常见问题

解决Maven项目报错:failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.13.0的问题

《解决Maven项目报错:failedtoexecutegoalorg.apache.maven.plugins:maven-compiler-plugin:3.13.0的问题》这篇文章主要介... 目录Maven项目报错:failed to execute goal org.apache.maven.pl

Maven pom.xml文件中build,plugin标签的使用小结

《Mavenpom.xml文件中build,plugin标签的使用小结》本文主要介绍了Mavenpom.xml文件中build,plugin标签的使用小结,文中通过示例代码介绍的非常详细,对大家的学... 目录<build> 标签Plugins插件<build> 标签<build> 标签是 pom.XML

秒变高手:玩转CentOS 7软件更换的方法大全

在 CentOS 7 中更换软件源可以通过以下步骤完成。更换源可以加快软件包的下载速度,特别是当默认源速度较慢时。以下是详细步骤: 前言 为了帮助您解决在使用CentOS 7安装不了软件速度慢的问题,我们推出了这份由浪浪云赞助的教程——“CentOS7如何更换软件源加快下载速度”。 浪浪云,以他们卓越的弹性计算、云存储和网络服务受到广泛好评,他们的支持和帮助使得我们可以将最前沿的技术知识分

struts2中的json返回指定的多个参数

要返回指定的多个参数,就必须在struts.xml中的配置如下: <action name="goodsType_*" class="goodsTypeAction" method="{1}"> <!-- 查询商品类别信息==分页 --> <result type="json" name="goodsType_findPgae"> <!--在这一行进行指定,其中lis是一个List集合,但

struts2的时候

在使用struts2的时候,我们在jsp中经常写这样的代码片段:      学生姓名:            考试名称:            考试分数:         其中studentScores.student.stuName是对应后台action的熟悉,action是这样写的   public class StudentExamAc

Jenkins 通过 Version Number Plugin 自动生成和管理构建的版本号

步骤 1:安装 Version Number Plugin 登录 Jenkins 的管理界面。进入 “Manage Jenkins” -> “Manage Plugins”。在 “Available” 选项卡中搜索 “Version Number Plugin”。选中并安装插件,完成后可能需要重启 Jenkins。 步骤 2:配置版本号生成 打开项目配置页面。在下方找到 “Build Env

Struts2常用标签总结--转载

Struts2常用标签总结 一 介绍 1.Struts2的作用 Struts2标签库提供了主题、模板支持,极大地简化了视图页面的编写,而且,struts2的主题、模板都提供了很好的扩展性。实现了更好的代码复用。Struts2允许在页面中使用自定义组件,这完全能满足项目中页面显示复杂,多变的需求。 Struts2的标签库有一个巨大的改进之处,struts2标签库的标签不依赖于

【JavaScript】函数中的arguments对象与Rest参数

arguments   JavaScript函数可以使用任意数量的参数(允许未知数量的函数参数)。在ES6之前,JavaScript有一个变量来访问这些未知或可变数目的参数,这是一个类似数组的对象,并非一个数组,称为arguments,与传递给函数的参数相对应。传递给JavaScript函数的所有参数都可以使用arguments对象来引用。      在上面的函数中,num1和num2

Struts2和Spring整合中出现的问题

今天做了一个Struts2和Spring整合的练习,中间出了一点问题,贴出来供其它人参考。(该文章写于2010年) 代码写好后启动Tomcat服务器时报错: 严重: Exception starting filter struts2java.lang.RuntimeException: java.lang.RuntimeException: java.lang.RuntimeExceptio