ajax里主要涉及几个概念:
1、请求url,即要执行的后台代码url,可以是servlet,jsp,也可以是struts里的action
2、数据,向url提交请求时,可能会需要向其中传参。这些参数是以json格式组织的,传入的时候作为parameter传入;
3、提交方式,get或者post;
4、回调函数:即当请求完成后,如何得到返回的数据,以及如何处理返回数据。有error,success,complete等几种;
在不使用struts2的时候,可以直接使用servlet或者jsp来实现。输出的数据一般用json格式,直接使用out.print打印到客户端,在客户端会被封装成一个对象,然后在回调函数中直接使用即可。使用示例见《javaweb开发王者归来》里hibernate高级查询中,有相应的例子;
在使用struts2的时候,因为struts2本身对servlet机制做了重新的封装,使得原来直接使用servlet来实现异步请求的思路在这里不适用。以前我在一个处理用户上传头像的功能中,将struts2的action返回到一个jsp页面,由jsp页面来实现out.print数据,这样也可以实现对返回数据的获取与处理。然而是单纯使用struts2时,却遇到了一些问题。有人提议让action直接返回null,然后通过上下文得到response再得到Writer对象,然后直接把数据写到out流中的办法。这样不失为一种方法,但为了更清楚地搞明白struts与jquery结合工作的方式,有必要搞清楚如何不借助servlet或jsp,只使用action实现ajax功能。
在实际使用过程中,$.ajax函数调用url没有出现什么问题,问题主要出现在如何获得返回值以及如何处理返回的问题里。
最初尝试使用返回SUCCESS,同时使用Writer输出json格式的字符串的方式,但是结果很奇怪,回调函数可以执行,但是却取不到任何数据。而且,回调函数只能写成success()这样的形式,无法为其赋参。一旦赋参就不执行。非常奇怪,估计是返回的数据有问题。
后来不断去查资料,见有人提到说需要在struts的配置文件里把action的返回结果的type需要置成"json"格式才能像servlet那样返回数据。
在实际尝试时出现了几个问题:
1、首先,要使用<result name="xxx" type="json"></result>这样返回结果,需要package继承json-default包。这个包一来默认没有包含在struts库中,需要单独去下,包名为:struts2-json-plugin-xxxx.jar这种。然后还需要一个包,这个包是专门用于struts转换json对象的:ezmorph-xxxx.jar。其它需要的就是一些struts2常见包了,如core,convention,json-lib,common-系列包等。
依赖关系解决了,还需要解决struts-default与json-default的冲突问题。
struts-default可以设置result类型为type="stream",这在动态生成验证码的时候有用,然而json-default却并不支持它。
解决办法是设置两个package,区别命名,并将继承json-default的那个package指定一个namespace="json"之类与main包区别。
这些工作完成后,直接访问json下的返回SUCCESS的action,会直接得到一个json格式的输出结果。输出的内容为此action里所有含有getter和setter方法的域。
前面得到了json格式的输出结果,但是还是在success回调函数那里出现问题。刚才也发现,输出的json包含了页面里所有的带setter、getter方法的域,实际上用这种方法配置的结果,只需要一个某些结果。受servlet方式的影响,很多人以为返回的应该是json格式的string,实际上需要返回的是一个JSONObject的对象。也就是需要给action配置一个JSONObject的域,并带上getter、setter方法。不仅如此,还需要给url所指向的action方法对应的struts配置文件里,在<result name="" type="json"></result>里加一个param标签:<param name="root">field_name</param>其中name为root这个属性有什么用尚不清楚,但是field_name这个必须与在action里配置的JSONObject对象的名字相同。这时再在浏览器地址栏输入ajax的url所指向的action,就会仅返回这个JSONObject变量的toString()结果。这时再在$_ajax的success里设置函数:function(data){},data里就存放着正确的json数据了。还有些博客文章里写道,要用一个eval方法将data转换成一个json对象,这里并不需要这样做,直接用data.变量名就可以访问到其中的数据。如data.username就可以访问到json对象里username域的值。
在解决问题期间参考了一些文章,都或多或少对解决问题有所帮助,尊重并感谢原作者,链接如下: