使用JSON 进行数据传输
一、选择的意义
在异步应用程序中发送和接收信息时,可以选择以纯文本和?XML?作为数据格式。为了更好的使用ajax,?我们将学习一种有用的数据格式?JavaScript Object Notation?(JSON?),以及如何使用它更轻松地在应用程序中移动数据和对象。JSON?是一种简单的数据交换格式,在某些方面,它的作用与XML?非常类似,但比XML?更为简单,JSON?的语法简化了数据交换的难度,而且提供了一种?伪对象?的方式。
Java?的对象?< - >JavaScript?对象(json?数据格式)
二、JSON?基础
简单地说,?JSON?可以将?JavaScript?对象中表示的一组数据转换为字符串(伪对象)?,然后就可以在函数之间轻松地传递这个字符串,或者?在异步应用程序中将字符串从?Web?客户端传递给服务器端程序?。这个字符串看起来有点儿古怪(稍后会看到几个示例),但是?JavaScript?很容易解释它,而且?JSON?可以表示比名称/?值对更复杂的结构。例如,可以表示数组和复杂的对象,而不仅仅是键和值的简单列表。
关于?JSON?对象
1?、使用JavaScript?语法创建对象
//?定义一个函数,作为构造函数
fucntion person(name,sex)
{
??this.name=name;
??this.sex=sex;
}
//?创建一个实例
var p=new Person(‘?张三’,’?男’);
//?输出Person?实例
??alert(p.name);
注意:通过该方式创建的对象是一般的脚本对象
2?、从JavaScript1.2?开始创建对象有了一种更快捷的语法(Json?的语法)?,如下:
var?obj=?{?name:?"?张三?"?,?"sex"?:?'?男?'?}?;????
alert(obj.sex);
?
关于数组
1?、早期的JavaScript?数组
var arr=new Array();
arr[0]=’a’;
arr[1]=’bbc’
我们也可以通过如下方式创建数组
var arr=new Array(‘a’,’bbc’);
2?、使用JSON?语法,则可以通过如下方式创建数组
????var arr=[‘a’,’bbc’];
简单?JSON?示例
按照最简单的形式,可以用下面这样的?JSON?表示名称/?值对:
{ "firstName":"Brett" }?
这个示例非常基本,而且实际上比等效的纯文本名称/?值对占用更多的空间:
firstName=Brett
?
但是,当将多个名称/?值对串在一起时,JSON?就会体现出它的价值了。首先,可以创建包含多个名称/?值对的记录?,比如:
{"firstName": "Brett", "lastName":"McLaughlin", "email": "brett@newInstance.com"}?
从语法方面来看,这与名称/?值对相比并没有很大的优势,但是在这种情况下?JSON?更容易使用,而且可读性更好。例如,它明确地表示以上三个值都是同一记录的一部分;花括号使这些值有了某种联系。
值的数组
当需要表示一组值时,JSON?不但能够提高可读性,而且可以减少复杂性。例如,假设您希望表示一个人名列表。在?XML?中,需要许多开始标记和结束标记;如果使用典型的名称/?值对(就像在本系列前面文章中看到的那种名称/?值对),那么必须建立一种专有的数据格式,或者将键名称修改为?person1-firstName?这样的形式。
如果使用?JSON?,就只需将多个带花括号的记录分组在一起:
{ "people": [??{ "firstName": "Brett", "lastName":"McLaughlin", "email": "brett@newInstance.com" },??{ "firstName": "Jason", "lastName":"Hunter", "email": "jason@servlets.com" },??{ "firstName": "Elliotte", "lastName":"Harold", "email": "elharo@macfaq.com" }]}
这不难理解。在这个示例中,只有一个名为?people?的变量,值是包含三个条目的数组,每个条目是一个人的记录,其中包含名、姓和电子邮件地址。上面的示例演示如何用括号将记录组合成一个值。当然,可以使用相同的语法表示多个值(每个值包含多个记录):
{ "programmers": [??{ "firstName": "Brett", "lastName":"McLaughlin", "email": "brett@newInstance.com" },??{ "firstName": "Jason", "lastName":"Hunter", "email": "jason@servlets.com" },??{ "firstName": "Elliotte", "lastName":"Harold", "email": "elharo@macfaq.com" }],
"authors": [
??{ "firstName": "Isaac", "lastName": "Asimov", "genre": "science fiction" },??{ "firstName": "Tad", "lastName": "Williams", "genre": "fantasy" },??{ "firstName": "Frank", "lastName": "Peretti", "genre": "christian fiction" }],
"musicians": [
??{ "firstName": "Eric", "lastName": "Clapton", "instrument": "guitar" },??{ "firstName": "Sergei", "lastName": "Rachmaninoff", "instrument": "piano" }]
}
这里最值得注意的是,能够表示多个值,每个值进而包含多个值。但是还应该注意,在不同的主条目(programmers?、authors?和musicians?)之间,记录中实际的名称/?值对可以不一样。JSON?是完全动态的,允许在?JSON?结构的中间改变表示数据的方式。甚至可以声明如下的Json?对象
var?obj2=?{?people:?{?name:?'?张三?'?,sex:?"?男?"?}}
alert(obj2.people.name);
在处理?JSON?格式的数据时,没有需要遵守的预定义的约束。所以,在同样的数据结构中,可以改变表示数据的方式,甚至可以以不同方式表示同一事物。
{deptid:?'?1?'?,deptname:?'?开发部?'?,deptnum:?'?2?'?,deptdesc:?'?开发相关?',
emps:[{empid:1,empname:'?张三?',sex:’?男?’,age:’20’},{empid:2,empname:'?张三?',sex:’?男?’,age:’20’},?{empid:3,empname:'?张三?',sex:’?男?’,age:’20’}]?}
?
?
?
三、在JavaScript?中使用JSON
掌握了?JSON?格式之后,在?JavaScript?中使用它就很简单了。JSON?是?JavaScript?原生格式,这意味着?在?JavaScript?中处理?JSON数据不需要任何特殊的?API?或工具包。
将JSON?数据赋值给变量
例如,可以创建一个新的?JavaScript?变量,然后将?JSON?格式的数据字符串直接赋值给它:
var people =
??{ "programmers": [????{ "firstName": "Brett", "lastName":"McLaughlin", "email": "brett@newInstance.com" },????{ "firstName": "Jason", "lastName":"Hunter", "email": "jason@servlets.com" },????{ "firstName": "Elliotte", "lastName":"Harold", "email": "elharo@macfaq.com" }???],
??"authors": [
????{ "firstName": "Isaac", "lastName": "Asimov", "genre": "science fiction" },????{ "firstName": "Tad", "lastName": "Williams", "genre": "fantasy" },????{ "firstName": "Frank", "lastName": "Peretti", "genre": "christian fiction" }???],
??"musicians": [
????{ "firstName": "Eric", "lastName": "Clapton", "instrument": "guitar" },????{ "firstName": "Sergei", "lastName": "Rachmaninoff", "instrument": "piano" }???]
??}
这非常简单;现在?people?包含前面看到的?JSON?格式的数据。但是,这还不够,因为访问数据的方式似乎还不明显。
访问数据
尽管看起来不明显,但是上面的长字符串实际上只是一个数组;将这个数组放进?JavaScript?变量之后,就可以很轻松地访问它。实际上,只需用点号表示法来表示数组元素。所以,要想访问?programmers?列表的第一个条目的姓氏,只需在?JavaScript?中使用下面这样的代码:
people.programmers[0].lastName;
注意,数组索引是从零开始的。所以,这行代码首先访问?people?变量中的数据;然后移动到称为?programmers的条目,再移动到第一个记录(?[0]?);最后,访问?lastName?键的值。结果是字符串值?“McLaughlin”?。
下面是使用同一变量的几个示例。
people.authors[1].genre????????????????????????????// Value is "fantasy"
people.musicians[3].lastName????????????
// Undefined. This refers to the fourth entry,and there isn't one
people.programmers[2].firstName??????????// Value is "Elliotte"
利用这样的语法,可以处理任何?JSON?格式的数据,而不需要使用任何额外的?JavaScript?工具包或?API?。
修改?JSON?数据
正如可以用点号和括号访问数据,也可以按照同样的方式轻松地修改数据:
people.musicians[1].lastName = "Rachmaninov";
?
在将字符串转换为?JavaScript json?格式对象之后,就可以像这样修改变量中的数据。
注意:json?格式的对象和json?文本是不同的
var obj={name:"?张三?","sex":'?男?'};????//json?格式的对象
var?str="?{?name:?"?张三?"?,?"sex"?:?'?男?'?}"?;?//json?格式的字符串(?json?格式的文本)
转换回字符串
当然,如果不能轻松地将对象转换回本文提到的文本格式,那么所有数据修改都没有太大的价值。在?JavaScript?中这种转换也很简单:
var newJSONtext = people.toJSONString();
这样就行了!现在就获得了一个可以在任何地方使用的文本字符串,例如,可以将它用作?Ajax?应用程序中的请求字符串。
更重要的是,可以将任何?JavaScript?对象转换为?JSON?文本。并非只能处理原来用?JSON?字符串赋值的变量。为了对名为myObject?的对象进行转换,只需执行相同形式的命令:
<script type="text/javascript">
???function Car(make,model,year,color)
????{
??????this.make=make;??
??????this.model=model;??
??????this.year=year;??
??????this.color=color;
????}??
?????function showCar()
????{
?????var carr = new Car("Dodge","Coronet R/T",1968,"yellow");??
?????alert(carr.toJSONString());??
????}
</script>
这就是?JSON?与其他数据格式之间最大的差异。如果使用?JSON?,只需调用一个简单的函数,就可以获得经过格式化的数据,可以直接使用了。对于其他数据格式,需要在原始数据和格式化数据之间进行转换。即使使用?Document Object Model?这样的?API(提供了将自己的数据结构转换为文本的函数),也需要学习这个?API?并使用?API?的对象,而不是使用原生的?JavaScript?对象和语法。
最终结论是,如果要处理大量?JavaScript?对象,那么?JSON?几乎肯定是一个好选择,这样就可以轻松地将数据转换为可以在请求中发送给服务器端程序的格式(Ajax)?。
?
四、JSON?在Ajax?中的应用
????JSON?(JavaScript Object Notation?)一种简单的数据格式,比xml?更轻巧。?JSON?是?JavaScript?原生格式,这意味着在?JavaScript?中处理?JSON?数据不需要任何特殊的?API?或工具包。
通过以上学习我们知道JSON?的规则很简单:对象是一个无序的“‘名称/?值’对”集合。一个对象以“{?”(左括号)开始,“}?”(右括号)结束。每个“名称”后跟一个“:?”(冒号);“‘名称/?值’对”之间使用“,?”(逗号)分隔。
1?、通过Json?格式来声明对象和操作对象
案例:
??js?代码
function showJSON()
{???
????var user =????
????{????
????????"username":"andy",
????????"age":20,
????????"info": { "tel": "123456", "cellphone": "98765"},
????????"addresses":???
????????????[???
????????????????{"city":"beijing","postcode":"222333"},
????????????????{"city":"newyork","postcode":"555666"}
????????????]???
????}
????alert(user.username);
????alert(user.age);
?????alert(user.info.cellphone);
????alert(user.address[0].city);
????alert(user.address[0].postcode);
}???
这表示一个user?对象,拥有username, age, info, address?等属性。
同样也可以用JSON?来简单的修改数据,修改上面的例子
js?代码
function showJSON() {???
????var user =????
????{????
????????"username":"andy",???
????????"age":20,???
????????"info": { "tel": "123456", "cellphone": "98765"},???
?????????"address":???
????????????[???
????????????????{"city":"beijing","postcode":"222333"},???
????????????????{"city":"newyork","postcode":"555666"}???
????????????]???
????}???
???????
????alert(user.username);???
????alert(user.age);???
????alert(user.info.cellphone);???
????alert(user.address[0].city);???
????alert(user.address[0].postcode);???
???????
????user.username = "Tom";???
????alert(user.username);???
}?
2?、一般对象转换成JSON?格式的字符
JSON?提供了json.js?包,下载http://www.json.org/json.js?后,将其引入然后就可以简单的使用object.toJSONString()转换成JSON?数据。
js?代码
function Car(make, model, year, color) {???
?????this.make??=??make;???
?????this.model??=??model;???
?????this.year??=??year;???
??????this.color??=??color;???
}???
function showCar() {???
????var carr = new Car("Dodge", "Coronet R/T", 1968, "yellow");???
????alert(carr.toJSONString());???
}???
?
2?、js?对象?和JSON?格式的js?对象?、JSON?格式的js?对象?和JSON?文本的转换
可以使用eval?来转换JSON?字符到JSON?格式的Object
js?代码
function myEval() {???
????var str = '{ "name": "?张三", "sex": "?男" }';???
????var obj = eval('(' + str + ')');???
????alert(obj.toJSONString());???
}???
或者使用parseJSON()?方法
function myparse()
{???
????var str= '{ "name": "?张三", "sex": "?男" }';???
????var obj=str.parseJSON();???//?把其Json?文本解析成为json?对象???
????alert(obj.toJSONString()); //?把json?对象转换成?JSON?文本???
}???
?
3?、从Java?类产生json?对象(json-lib)
Jar?包:
从Java?类产生json?对象要使用json-lib jar?包
??????json?的jar?包
????????????json-lib-2.2.2-jdk15.jar
??????json-lib?的依赖包:
????????????commons-logging.jar
????????????common.lang.jar
????????????commons-beanutils.jar
????????????commons-collections-3.0.jar
????????????ezmorph-0.9.2.jar
作用:
??json-lib?可以在服务器端?把java?对象转换成json?对象、从json?对象转化到Java?对象,?比如:
json-lib?可以将java?中的Array,Collections,Object,XML?转化成json?对象,反之也可以将json?对象转化成java?对象.
配置:
需要把json-lib-2.2.2-jdk15.jar?以及依赖都要放到项目的lib?库下
常用的JSON API:
(1)?、JSONObject
//java?对象或满足一定格式的字符串("{username:'admin',password:'12345',..}")?转化为JSONObject?对象,?用法:
JSONObject json=JSONObject.fromObject(userinfo);
//?从json?对象中根据键名取对应的值, username?为键名
json.getObject("username");
//json?对象到java?对象的转化(jsonobject-->po)
Userinfo userinfo=(Dept)JSONObject.toBean(jsonObject,Userinfo.class);
//Json?对象转化成json?文本字符串
String josStr=JSONObject.fromObject(userinfo).toString();
(2)?、JSONArray
boolean[] boolArray={true,false};
????List list = new ArrayList();??
????Map map=new HashMap();
????bject[] test={new Userinfo(),new Userinfo()};
?
????//?转化为java?的数组Array?为json?对象
????JSONArray jsonArray = JSONArray.fromObject(boolArray);??
????//System.out.println(jsonArray.toString());
????JSONArray jsonArray1=JSONArray.fromObject("['1','2','3']");
????//System.out.println(jsonArray1.toString());
???
?????list.add("first");??
????list.add("second");??
????list.add(new Userinfo());
????//?转换java?的List?为json?对象
????JSONArray jsonList = JSONArray.fromObject(list);??
????System.out.println(jsonList);??
????//?转换java?的Map?为json?对象
?????map.put("name", "windfree");
????map.put("bool", Boolean.TRUE);
????map.put("int",new Integer(0));
????map.put( "arr", new String[]{"a","b"} );
????map.put("func", "function (i){ return this.arr[i]; }");
????map.put("bean",test);
????JSONObject jsonMap = JSONObject.fromObject(map);??
?????//System.out.println(jsonMap);??
思考?:?什么时候在客户端及服务器端使用json?格式的数据
4?、下面使用prototype?写一个JSON?的ajax?例子
案例:???
在页面中写一个ajax?的请求
js?代码:
function sendRequest()
{???
????var url = "/WLLTWebApp/?JsonTestServlet?";???
????var mailAjax = new Ajax.Request(???
????????url,???
????????{???
????????????method: 'get',???
????????????onComplete: jsonResponse???
????????}???
????);???
}????
function jsonResponse(originalRequest) {???
????alert(originalRequest.responseText);???
????var myobj = originalRequest.responseText.parseJSON();???
????alert(myobj.name);???
}?
服务器端代码:
先写一个servlet,java?代码
package org.wllt.www.actions;
?
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
?
import net.sf.json.JSONObject;
import net.sf.json.JsonConfig;
import org.wllt.www.beans.Userinfo;
public class JsonTestServlet extends HttpServlet
{
????public JsonTestServlet(){??}
??public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
????????response.setContentType("text/html;charset=GBK");
????????System.out.println(request.getParameter("someParameter"));
????????PrintWriter out =response.getWriter();
????????//(1)?使用?JSON API?包中?JSONObject?的?fromObject?方法把?Java?对象转换成?JSon?对象
?????????//Userinfo info=new Userinfo("admin","123456");
????????//JSONObject obj=JSONObject.fromObject(info);
????????//out.println(obj);
?????????//(2)?或者使用
?????????out.print("{ /"username/": /"?张三/", /"password/": /"123/" }");
????????out.println("?未来蓝图欢迎你!?");
????????out.flush();
????????out.close();
????}
????public void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException
????{
????????this.doPost(request, response);
????}
}
?
View
?
Controller
??
?
?
Java?中
转换为Json?对象-->Java?对象
浏
览
器
Js?中
Json?文本或js?对象-->?Json?对象?-
?????????????????????????????????Request?(?String?)?
?
。。。。
??
?
Java?中
转换为Json?对象<--Java?对象
Js?中
Json?对象????????<--Json?文本
?
???????????????????????????????????????Response?(?String?)?
?
?
?
prototype-1.5.1.js?中提供了JSON?的方法,String.evalJSON(),?可以不使用json.js?中的函数对从服务器端响应到页面的json?文本对象,?修改上面的方法
js?代码
function jsonResponse(originalRequest)
{???
????alert(originalRequest.responseText);???
????var myobj = originalRequest.responseText.evalJSON(true);???
????alert(myobj.name);???
}??
5?、JSON?服务器端的数据格式转化的应用
JSON?还提供了java?的jar?包?http://www.json.org/java/index.html API?也很简单,下面举个案例:
在javascript?中填加请求参数
js?代码
function Car(make, model, year, color) {???
?????this.make??=??make;???
?????this.model??=??model;???
?????this.year??=??year;???
?????this.color??=??color;???
}???
function sendRequest()
{???
????var carr = new Car("Dodge", "Coronet R/T", 1968, "yellow");???
????var pars = "car=" + carr.toJSONString();???
??
????var url = "/MyWebApp/JSONTest1";???
????var mailAjax = new Ajax.Request(???
????????url,???
????????{???
????????????method: 'get',???
????????????parameters: pars,???
????????????onComplete: jsonResponse???
????????}???
????);???
}???
使用JSON?请求字符串就可以简单的生成JSONObject?并进行解析(?要使用json-lib.jar)
java?代码
private void doService(HttpServletRequest request, HttpServletResponse response) throws IOException {???
????????String s3 = request.getParameter("car");???
????????try {???
????????????JSONObject jsonObj = new JSONObject(s3);???
????????????System.out.println(jsonObj.getString("model"));???
????????????System.out.println(jsonObj.getInt("year"));???
????????} catch (JSONException e) {???
????????????e.printStackTrace();???
????????}???
????????response.getWriter().print("{/"name/": /"?张三/",/"sex/": /"?男/" }");???
????}???
同样可以使用JSONObject?生成JSON?字符串,修改servlet
java?代码
private void doService(HttpServletRequest request, HttpServletResponse response) throws IOException {???
????????String s3 = request.getParameter("car");???
????????try {???
????????????JSONObject jsonObj = new JSONObject(s3);???
????????????System.out.println(jsonObj.getString("model"));???
????????????System.out.println(jsonObj.getInt("year"));???
????????} catch (JSONException e) {???
????????????e.printStackTrace();???
????????}???
?????????JSONObject resultJSON = new JSONObject();???
????????try {???
????????????resultJSON.append("name", "?张三")???
??????????????????????.append("sex", "?男")
??????????????????????.append("age", new Integer(22));???
????????????System.out.println(resultJSON.toString());???
????????}catch(JSONException e) {???
????????????e.printStackTrace();???
????????}???
????????response.getWriter().print(resultJSON.toString());???
????}???
js?代码
function jsonResponse(originalRequest)
{???
????alert(originalRequest.responseText);???
????var myobj = originalRequest.responseText.evalJSON(true);???
????alert(myobj.name);???
????alert(myobj.age);???
}??
?
?
五、Struts 2?中使用Json ajax?支持
JSON?插件提供了一种名为json?的ResultType?,一旦为某个Action?指定了一个类型为json?的Result?,则该Result?无需映射到任何视图资源。因为JSON?插件会负责将Action?里的状态信息序列化成JSON?格式的数据,并将该数据返回给客户端页面的?JavaScript?。
?
简单地说,JSON?插件允许我们在JavaScript?中异步调用Action?,而且Action?不再需要使用视图资源来显示该Action?里的状态信息,而是由JSON?插件负责将Action?里的状态信息返回给调用页面——通过这种方式,就可以完成Ajax?交互。
Struts2?提供了一种可插拔方式来管理插件,安装Struts2?的JSON?插件与安装普通插件并没有太大的区别,一样只需要将Struts2?插件的JAR?文件复制到Web?应用的WEB-INF/lib?路径下即可。
安装JSON?插件按如下步骤进行:
(1?)登陆http://code.google.com/p/jsonplugin/downloads/list?站点,下载Struts2?的JSON?插件的最新版本,当前最新版本是0.7?,我们可以下载该版本的JSON?插件。
(2?)将下载到的jsonplugin-0.7.jar?文件复制到Web?应用的WEB-INF?路径下,即可完成JSON?插件的安装。
?
实现Action?逻辑
假设deptnew.html?输入页面中包含了四个表单域,这四个表单域对于四个请求参数,因此应该使用Action?来的dept?对象封装这四个请求参数。四个表单域的name?分别为dept.deptid?、dept.deptname?、dept.deptnum和dept.deptdesc?。
?
处理该请求的Action?类代码如下:
package org.wllt.ajax.actions;
?
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import org.wllt.ajax.beans.Dept;
import com.googlecode.jsonplugin.annotations.JSON;
import com.opensymphony.xwork2.Action;
?
public class JSONExample
{
???//?封装请求参数的三个属性
???private String field1;
???private transient String field2;
???private String field3;
?
???//?封装处理结果的属性
???private int[] ints ={10, 20};
???private Map map = new HashMap();
???private String customName = "custom";
???//?日期格式的属性
???private Date date;
?
??
???private Dept dept;
??
??
???//?三个请求参数对应的?setter?和?getter?方法
???@JSON(serialize=false)
????public String getField1(){
???return field1;
???}
???public void setField1(String field1)
{
?????this.field1 = field1;
}
???//?封装处理结果的属性的?setter?和?getter?方法
???public int[] getInts()
???{
??return ints;
???}
???public void setInts(int[] ints)
???{
??this.ints = ints;
???}
???@JSON(format="yyyy-MM-dd")
???public Map getMap()
???{
??return map;
???}
???public void setMap(Map map)
???{
?????this.map = map;
???}
public String getField2() {
?????return field2;
}
public void setField2(String field2) {
?????this.field2 = field2;
}
public String getField3() {
?????return field3;
}
public void setField3(String field3) {
?????this.field3 = field3;
}
????public Dept getDept() {
?????return dept;
}
public void setDept(Dept dept) {
?????this.dept = dept;
}
???//?使用注释语法来改变该属性序列化后的属性名
?????@JSON(name="newName")
????public String getCustomName()
????{
??return this.customName;
????}
????@JSON(format="yyyy-MM-dd")
public Date getDate() {
?????return date;
}
public void setDate(Date date) {
?????this.date = date;
}
public String execute()
{
?????map.put("name", "yeeku");
?????map.put("curdate",new Date());
????return Action.SUCCESS;
}
}
在上面代码中,使用了JSON?注释,注释时指定了name?域,name?域指定Action?属性被序列化成JSON?对象的属性名。除此之外,JSON?注释还支持如下几个域:
Name?:?Action?属性被序列化成JSON?对象的属性名
serialize?:设置是否序列化该属性(?默认的action?的所有属性都会序列化成json?文本响应到原页面,也可以根据需要设定某些属性不序列化?)?。也可以通过在配置json?类型的结果的时候定义需要不序列化的属性:
????????<result name="success" type="json">
?????????<param name="excludeProperties">service,joindate,dept</param>
???????</result>
deserialize?:设置是否反序列化该属性。
format?:设置用于格式化输出、解析日期表单域的格式。例如"yyyy-MM-dd'T'HH:mm:ss"?。
???????一般需要注释到需要转换日期格式属性的get?方法上面
配置该Action?与配置普通Action?存在小小的区别,为该Action?配置结果类型为json?的Result?。而这个Result?无需配置任何视图资源,?只需要把通过该结果把json?文本响应到原页面。
?
配置该Action?的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.locale"?value?=?"zh_CN"?/>
????<?constant?name?=?"struts.action.extension"?value?=?"do,action"?/>
????<?package?name?=?"json"?extends?=?"json-default"?>
???
????????<?action?name?=?"dept"?class?=?"org.wllt.ajax.actions.DeptAction"?>
?????????????<?result?type?=?"json"?/>
????????????</?action?>
????</?package?>
????</?struts?>
?
?
在上面配置文件中有两个值得注意的地方:
?
第一个地方是配置struts.i18n.encoding?常量时,不再是使用GBK?编码,而是UTF-8?编码,这是因为Ajax的POST?请求都是以UTF-8?的方式进行编码的。
?
第二个地方是配置包时,自己的包继承了json-default?包,而不再继承默认的default?包,这是因为只有在该包下才有json?类型的Result?。
?
?
?
?
?
实现JSP?页面first.jsp?:
?
为了简单地访问DOM?节点,这里用了JavaScript?框架Prototype.js.
<?html?>
??<?head?>
????<?title?>?使用?JSON?插件?</?title?>
????<?meta?http-equiv?=?"content-type"?content?=?"text/html; charset=UTF-8"?>
????<?script?src?=?"./js/prototype.js"?type?=?"text/javascript"?>
</?script?>
<?script?language?=?"JavaScript"?>
??function?gotClick()
??{
????//?请求的地址
????var?url=?'./dept.do'?;
????//?将?Form?中所有?Input?对象的值转化为一个?URL String?,方便把?Form?转为用?URL Get?方式?//?的?Ajax提交,常用?Ajax?提交?Form?的例子?:
????var?params=Form.serialize(?'form1'?);
????//?创建?Ajax.Request?对象,对应于发送请求
????var?myAjax=?new?Ajax.Request(url,?{
????????????//?请求方式:?POST
????????????method:?'post'?,
???????????//?请求参数
???????????parameters:params,
???????????//?指定回调函数
???????????onComplete: processResponse,
???????????//?是否异步发送请求
???????????asynchronous:?true
???????}?);
??}
??function?processResponse(request)
??{
???$(?"show"?).innerHTML=request.responseText;
??}
</?script?>
</?head?>
<?body?>
??<?form?id?=?"form1"?name?=?"form1"?method?=?"post"?>
??部门编号?<?INPUT?TYPE?=?"text"?name?=?"dept.deptid"?id?=?"deptid"?/><?br?>
??部门名称?<?INPUT?TYPE?=?"text"?name?=?"dept.deptname"?id?=?"deptname"?/><?br?>
??部门编制?<?INPUT?TYPE?=?"text"?name?=?"dept.deptnum"?id?=?"deptnum"?/><?br?>
??部门描述?<?INPUT?TYPE?=?"text"?name?=?"dept.deptdesc"?id?=?"deptdesc"?/><?br?>
??<?INPUT?TYPE?=?"button"?value?=?"?提交?"?onClick?=?"gotClick();"?/>
??</?form?>
??<?div?id?=?"show"?>
??</?div?>
</?body?>
</?html?>
?
六、当json?碰到hibernate?延时加载
在开发Struts2.0+hibernate3.2+spring2.0?项目过程中,遇到了?failed to lazily initialize a collection of role: org.wllt.www.pojo.Dept.emps, no session or session was closed?这个异常的出现,通过以下方法可以解决这个问题:
1?、是把对应一对多的那两个列lazy=true?改为lazy?=false?即可;
2?、对于查询中如果用的是xxx.load?(class?,id?)则改为xxx,get(class?,id)?;
3?、在web.xml?文件中加入:
???<filter>
??????<filter-name>hibernateFilter</filter-name>
??????<filter-class>
org.springframework.orm.hibernate3.support.OpenSessionInViewFilter
</filter-class>
???????????<init-param>
????????????<param-name>singleSession</param-name>
????????????<param-value>false</param-value>
??????????</init-param>
?
<!--?这个?--???<init-param>?一定要加不然很可能会报错?:???org.springframework.dao.InvalidDataAccessApiUsageException:Write operations are not allowed in read-only mode (FlushMode.NEVER) - turn your Session into FlushMode.AUTO or remove 'readOnly' marker from transaction definition
-->
?????</filter>
?????<filter-mapping>
?????????<filter-name>hibernateFilter</filter-name>
?????????<url-pattern>*.wllt</url-pattern>
?????</filter-mapping>
对以上方法进行一一测试,到后来结果都是一样,出现同样的异常,其实spring?能很好地解决这个问题,Spring?框架为Hibernate?延迟加载与DAO?模式的整合提供了一种方便的解决方法。以一个Web?应用为例,Spring?提供了OpenSessionInViewFilter?和OpenSessionInViewInterceptor?。我们可以随意选择一个类来实现相同的功能。两种方法唯一的不同就在于interceptor?在Spring?容器中运行并被配置在web?应用的上下文中,而Filter在Spring?之前运行并被配置在web.xml?中。不管用哪个,他们都在请求将当前会话与当前(数据库)线程绑定时打开Hibernate?会话。一旦已绑定到线程,这个打开了的Hibernate?会话可以在DAO?实现类中透明地使用。这个会话会为延迟加载数据库中值对象的视图保持打开状态。一旦这个逻辑视图完成了,Hibernate?会话会在Filter的doFilter?方法或者Interceptor?的postHandle?方法中被关闭。用spring?解决这个问题而且不用把lazy?设置为false?,提高性能。
?
方法是:在web.xml?中加入以下配置:
<filter>????
<filter-name>hibernateFilter</filter-name>????
<filter-class>????
org.springframework.orm.hibernate3.support.OpenSessionInViewFilter?????
</filter-class>????
</filter>?????
<filter-mapping>????
<filter-name>hibernateFilter</filter-name>????
<url-pattern>*.action</url-pattern>????
</filter-mapping>
?
如果把这个配置随意地加到web.xml?的最后,会出现相应的错误,其实该过滤器和Struts2?的过滤器有顺序的问题,应该是:
OpenSessionInViewFilter
FilterDispatcher
的顺序,最后调整过滤器的顺序,问题解决。
注意:有些时候会出现一些页面或者一些其他的action?过滤不到,可以修改如下:
<url-pattern>/*</url-pattern>