使用JSON 進行數據傳輸
一、選擇的意義
在異步應用程序中發送和接收信息時,可以選擇以純文本和 XML 作爲數據格式。爲了更好的使用ajax, 我們將學習一種有用的數據格式 JavaScript Object Notation (JSON ),以及如何使用它更輕鬆地在應用程序中移動數據和對象。JSON 是一種簡單的數據交換格式,在某些方面,它的作用與XML 非常類似,但比XML 更爲簡單,JSON 的語法簡化了數據交換的難度,而且提供了一種 僞對象 的方式。
Java 的對象 < - >JavaScript 對象(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 表示名稱/ 值對:
{ "firstName":"Brett" }
|
這個示例非常基本,而且實際上比等效的純文本名稱/ 值對佔用更多的空間:
firstName=Brett
|
但是,當將多個名稱/ 值對串在一起時,JSON 就會體現出它的價值了。首先,可以創建包含多個名稱/ 值對的記錄 ,比如:
{"firstName": "Brett", "lastName":"McLaughlin", "email": "[email protected]"}
|
從語法方面來看,這與名稱/ 值對相比並沒有很大的優勢,但是在這種情況下 JSON 更容易使用,而且可讀性更好。例如,它明確地表示以上三個值都是同一記錄的一部分;花括號使這些值有了某種聯繫。
當需要表示一組值時,JSON
不但能夠提高可讀性,而且可以減少複雜性。例如,假設您希望表示一個人名列表。在 XML
中,需要許多開始標記和結束標記;如果使用典型的名稱/
值對(就像在本系列前面文章中看到的那種名稱/
值對),那麼必須建立一種專有的數據格式,或者將鍵名稱修改爲
person1-firstName
這樣的形式。
如果使用 JSON ,就只需將多個帶花括號的記錄分組在一起:
{ "people": [
{ "firstName": "Brett", "lastName":"McLaughlin", "email": "[email protected]" },
{ "firstName": "Jason", "lastName":"Hunter", "email": "[email protected]" },
{ "firstName": "Elliotte", "lastName":"Harold", "email": "[email protected]" }
]}
|
這不難理解。在這個示例中,只有一個名爲
people
的變量,值是包含三個條目的數組,每個條目是一個人的記錄,其中包含名、姓和電子郵件地址。上面的示例演示如何用括號將記錄組合成一個值。當然,可以使用相同的語法表示多個值(每個值包含多個記錄):
{ "programmers": [
{ "firstName": "Brett", "lastName":"McLaughlin", "email": "[email protected]" },
{ "firstName": "Jason", "lastName":"Hunter", "email": "[email protected]" },
{ "firstName": "Elliotte", "lastName":"Harold", "email": "[email protected]" }
],
"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’}] }
掌握了 JSON 格式之後,在 JavaScript 中使用它就很簡單了。JSON 是 JavaScript 原生格式,這意味着 在 JavaScript 中處理 JSON 數據不需要任何特殊的 API 或工具包。
例如,可以創建一個新的 JavaScript 變量,然後將 JSON 格式的數據字符串直接賦值給它:
var people =
{ "programmers": [
{ "firstName": "Brett", "lastName":"McLaughlin", "email": "[email protected]" },
{ "firstName": "Jason", "lastName":"Hunter", "email": "[email protected]" },
{ "firstName": "Elliotte", "lastName":"Harold", "email": "[email protected]" }
],
"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 。
正如可以用點號和括號訪問數據,也可以按照同樣的方式輕鬆地修改數據:
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 對象 - |
。。。。 |
Java 中 轉換爲Json 對象<--Java 對象 |
Js 中 Json 對象 <--Json 文本
|
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>