Struts 与 dojo 整合研究
1, Struts 的 dojo 标签
Struts 框架有一些 Ajax 的插件,例如:
· Ajax Parts - The AjaxParts Taglib (APT) is a component of the Java Web Parts (JWP) project ( http://javawebparts.sourceforge.net ) that allows for 100% declarative
(read: no Javascript coding required!) AJAX functionality within a Java-based webapp.
· Dojo - The Ajax Tags Dojo Plugin was represented as a theme for Struts 2.0. For Struts 2.1, the Dojo tags are bundled as a plugin.
· YUI – The Yahoo User Interface (YUI) Plugin has only a few tags are available so far, but the YUI tags tend to be easier to use than the Dojo versions.
· jQuery - The jQuery Plugin provide ajax functionality and UI Widgets an JavaScript Grid based on the jQuery javascript framework..
其中 Ajax Tags Dojo Plugin 在 struts2.1 中已经被废除了,主要是由于 dojo 之前的版本不稳定,最新的 dojo 插件 ( struts2-dojo-plugin-2.2.3.jar ) 也只支持 dojo0.4
版本的核心,一共 11 个标签 ,如果不用 struts 的 dojo 标签就设计到数据转换的问题,下面第 2 点说明。
2, struts 与 dojo 的数据转换方法
1) json 格式的数据比 xml 在 web2.0 的应用中性能要好,主要是因为 javascript 对 json 的解析和序列化比 xml 要方便,因此考虑用 json 做前后端的数据传输格
式。另外由于后端处理 request 的时候和是否是 Ajax 请求并无关系,主要是在后台返回 response 的时候,前台的 script 对数据格式有一定的要求,所以本文主要
分析后台在应用 Struts 之后返回 json 数据给前台的处理方法。
2) 那么在前台与后台传输 json 格式的数据时候,关于后台的数据转换问题,有几种常做的方法 :
a, 让 Struts 直接返回 stream 给前台,做法是:应用 Struts 的 ”stream” 这种 result type ,让 action 返回一个 inputStream 给前台,这个
stream 里写一个 json 格式的字符串,其中 json 格式的字符串,可以在后台拼字符串,或者应用 json 格式转换插件将 object 转换成 json 格式的字符串,这样的
开源插件有很多种( http://json.org/ 网站上有各种序列化 json 的插件的链接)。
b, 让 Struts 直接返回一个 JSON 的 response ,这需要使用 JSON 插件! JSON 插件提供了一种名为 json 的Action Result Type 。一旦为Action 指定了该
结果处理类型,JSON 插件就会自动将Action 里的数据序列化成JSON 格式的数据,并返回给客户端物理视图的JavaScript 。简单的说,JSON 插件允许我们在JavaScript 中
异步的调用Action ,而且Action 不需要指定视图来显示Action 的信息显示。而是由JSON 插件来负责具体将Action 里面具体的信息返回给调用页面。
3, Jsonplugin 的用法 (https://cwiki.apache.org/confluence/display/WW/JSON%20Plugin )
在反序列化时,我一直没有试出来,最后在研究struts2-json-plugin-2.2.3.jar插件的源码之后,发现这个插件的反序列化做的还是比较粗放的,不能精确的反序列化对象,最后
还是用struts2的域模型驱动来实现的这个功能。
下面来看代码:
1,所需jar包: (主要是struts的jar包和jsonplugin的jar包,有一些别的包是做其他实验用的)
2, Action的代码:
package com.action; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.struts2.json.annotations.JSON; import com.bean.Address; import com.bean.Movie; import com.opensymphony.xwork2.Action; import com.opensymphony.xwork2.ActionSupport; public class JSONExample extends ActionSupport{ private String field1 = null; private int[] ints = { 10, 20 }; private Map<String , Movie> map = null; private String customName = "custom"; private Movie movie = null; private List<Movie> movieList = null; private Date todayDate = new Date(); // 'transient' fields are not serialized private transient String field2; // fields without getter method are not serialized private String field3; public String execute() { System.out.println("execute method begin!"); System.out.println("map 是 "+getMap().getClass().getName()+"类型"); System.out.println("map = "+getMap()); System.out.println("movieList 是 "+getMovieList().getClass().getName()+"类型"); System.out.println("movieList = "+getMovieList()); System.out.println("execute method end!"); return Action.SUCCESS; } // @JSON(serialize=false) public String getField1() { return field1; } public void setField1(String field1) { this.field1 = field1; } public int[] getInts() { return ints; } public void setInts(int[] ints) { this.ints = ints; } public Map getMap() { return map; } public void setMap(Map<String, Movie> map) { this.map = map; } //@JSON(name = "newName") public String getCustomName() { return this.customName; } public Movie getMovie() { return movie; } public void setMovie(Movie movie) { this.movie = movie; } public List getMovieList() { return movieList; } public void setMovieList(List<Movie> movieList) { this.movieList = movieList; } @JSON(format="yyyy/MM/dd") public Date getTodayDate() { return todayDate; } public void setTodayDate(Date todayDate) { this.todayDate = todayDate; } }
3,struts.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN" "http://struts.apache.org/dtds/struts-2.0.dtd"> <struts> <constant name="struts.devMode" value="true"/> <package name="stream" extends="json-default"> <action name="JSONExample" class="com.action.JSONExample"> <result type="json"> <!-- <param name="root"> moive </param> <param name="excludeProperties"> moive,field1 </param> <param name="ignoreHierarchy"> false </param> --> </result> </action> </package> </struts>
这里配置好之后,在前台请求JSONExample之后struts2就会返回json格式的数据给前台了!至于dojo怎么处理这个json格式的数据那就是你的事了!其实这个例子就是wiki文档的例子,我自己做了一些实验而已,jsonRPC的应用也是一个不错的研究点,下次有心得还是会和大家一起分享讨论!
下面的源码是核心源码,jar包和dojo大家可以自己下载。我用的是struts2 2.2.3版得dojo是1.6.1的,其中需要说明的是,struts2的不同版本需要不同的jsonplugin插件,一般自带的包里就可以。
主要源码在附件中下载:
附录:
1 ,在后台可以用 json_java 包 做parse Java to json的工作!
2 , json-lib-2.1-jdk15.jar 也是一个后台做 json 和 java 对象之间转换的包, struts 文档有介绍!
3 , jsonplugin-0.34.jar 包是做转换和提供 json result type!
struts2-json-plugin-2.2.3.jar 的包结构与上面的包结构一么一样,是同样的功能,不同的开源项目?
这两个包都 Provides a result type 'json' that serializes an action into JSON, and a 'json' interceptor that populates an action form a request containing a json string.
4 , struts2jsonresult.jar 提供 json result type!是另外一种做json序列化的选择,有兴趣的可以去wiki上看看文档 http://code.google.com/p/struts2jsonresult/w/list
It provides a "json" result type that serializes beans into JSON!
jsonplugin( jsonplugin-0.34.jar, struts2-json-plugin-2.2.3.jar )与 struts2jsonresult.jar 的 Difference :
存在的问题:
1, 反序列化未实现,即前台 dojo 直接发 json 的数据格式的请求,让 jsonplugin 自动序列化成 java 对象的工作。但可用struts2的域模型驱动来做,比较好做,jsonplugin插件并不是最佳的反序列化的选择!
2, 调研 jsonRPC 的应用(之后会上传,期待你的关注哦^_^)
3, 本文源码文件也许没有组织好,文章也写的比较粗放,欢迎大家指正!