posts - 41,  comments - 8,  trackbacks - 0
           Apache提供的一個插件包,可以把Action中的數據以JSON做個封裝然后返回。

          它會將整個action中的變量轉化為JSON數據(根對象在JSON中數據添加一個”root”標識)。如果要使用它,Action必須遵循以下幾點:

          1.       返回的頁面類型中”content-type”必須是”application/json”.(這個已經Internet Community采用).

          2.       JSON內容必須是符合格式要求的.

          3.       Actionfield必須有publicset方法.(是不是沒有set方法就不會將field添加到JSON數據中,有待驗證).

          4.       它支持的類型有: 基本類型(int,long...String), Date, List, Map, Primitive Arrays, 其它class, 對象數組.

          5.       JSON中任何的Object會被封裝在listmap中,數據會被封裝程Long,如果是含有的數據則會被封裝程Double,數組會被封裝程List.

          下面給出JSON的數據格式:

          {

             "doubleValue": 10.10,

             "nestedBean": {

                "name": "Mr Bean"

             },

             "list": ["A", 10, 20.20, {

                "firstName": "El Zorro"

             }],

             "array": [10, 20]

          }

          說明:

          a.       這個插件支持以下幾個注釋:

          注釋名

          簡介

          默認值

          序列化

          反序列化

          name

          配置JSONname

          empty

          yes

          no

          serialize

          serialization

          true

          yes

          no

          deserialize

          deserialization

          true

          no

          yes

          format

          格式化Date字段

          "yyyy-MM-dd'T'HH:mm:ss"

          yes

          yes

          可以通過配置來顯示指出要放在JSONfield,其中有個自己的驗證規則需要研究.

          <!-- Result fragment -->

          <result type="json">

           <param name="excludeProperties">

              login.password,

              studentList.*".sin

           </param>

          </result>

          <!-- Interceptor fragment -->

          <interceptor-ref name="json">

           <param name="enableSMD">true</param>

           <param name="excludeProperties">

              login.password,

              studentList.*".sin

           </param>

          </interceptor-ref>

          b.       根對象

           <result type="json">

           <param name="root">

              person.job

           </param>

          </result>

          也可以使用攔截器配置操作父對象

          <interceptor-ref name="json">

           <param name="root">bean1.bean2</param>

          </interceptor-ref>

          c.       JSON數據用注釋封裝

          如果wrapWithComments設置為true(默認值為false),則生成的JSON數據會變成這樣:

          /* {

             "doubleVal": 10.10,

             "nestedBean": {

                "name": "Mr Bean"

             },

             "list": ["A", 10, 20.20, {

                "firstName": "El Zorro"

             }],

             "array": [10, 20]

          } */

          這樣做可以避免js中一些潛在的風險,使用時需要:

          Var responseObject = eval("("+data.substring(data.indexOf(""/"*")+2, data.lastIndexOf(""*"/"))+")");

          d.       父類

          “root”對象中父類的field不會默認存放到JSON數據中,如果不想這樣做,需要在配置時指定ignoreHierarchyfalse:

          <result type="json">

           <param name="ignoreHierarchy">false</param>

          </result>

          e.       枚舉類型

          默認處理枚舉類型時,會被處理成JSON數據中name等于枚舉中valuevalue等于枚舉中name.

          public enum AnEnum {

               ValueA,

               ValueB

           }

           JSON: "myEnum":"ValueA"

          如果在處理枚舉類型時,在xml中配置了enumAsBean,則會被當作一個Bean處理,在JSON數據中會有一個特別的屬性”_name”值為name().這個枚舉中的所有屬性都會被處理.

          public enum AnEnum {

               ValueA("A"),

               ValueB("B");

               private String val;

               public AnEnum(val) {

                  this.val = val;

               }

               public getVal() {

                  return val;

               }

             }

           JSON: myEnum: { "_name": "ValueA", "val": "A" }

          Xml中配置:

          <result type="json">

           <param name="enumAsBean">true</param>

          </result>

          f.        例子

          a)         Action

          import java.util.HashMap;

          import java.util.Map;

          import com.opensymphony.xwork2.Action;

          public class JSONExample {

              private String field1 = "str";

              private int[] ints = {10, 20};

              private Map map = new HashMap();

              private String customName = "custom";

              //'transient' fields are not serialized

              private transient String field2;

              //fields without getter method are not serialized

              private String field3;

              public String execute() {

                  map.put("John", "Galt");

                  return Action.SUCCESS;

              }

              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 map) {

                  this.map = map;

              }

              @JSON(name="newName")

              public String getCustomName() {

                  return this.customName;

              }

          }

          b)        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>

           <package name="example" extends="json-default">

               <action name="JSONExample" class="example.JSONExample">

                  <result type="json"/>

               </action>

           </package>

          </struts>

          這里有兩個地方需要注意:

          1)      需要繼承json-default

          2)      <result>簽的定義

          c)         JSON數據

           { 

             "field1" : "str",

             "ints": [10, 20],

             "map": {

                 "John":"Galt"

             },

             "newName": "custom"

          }

          d)        JSON RPC

          JSON插件可以在js中調用action方法,返回執行結果。這個已經在dojo中有了實現,可以用Simple Method Definition調用遠程服務。來一起看看下面的例子:

          首先寫一個Action

          package smd;

          import com.googlecode.jsonplugin.annotations.SMDMethod;

          import com.opensymphony.xwork2.Action;

          public class SMDAction {

              public String smd() {

                  return Action.SUCCESS;

              }

              @SMDMethod

              public Bean doSomething(Bean bean, int quantity) {

                  bean.setPrice(quantity * 10);

                  return bean;

              }

          }

          e)         方法必須用SMDMethod加上注解,這樣才能被遠程調用,為了安全因素。這個方法會產生一個bean對象,實現修改價格的功能。Action被添加上SMD注解會生成一個SMD,同時參數也會被加上SMDMethodParameter注解。像你所看到的,Action中定義了一個空方法:smd。這個方法是作為Simple Method Definition (定義class中提供的服務),在struts.xml配置<result>時使用type屬性值為”json”

          下面是bean的定義:

          package smd;

          public class Bean {

              private String type;

              private int price;

              public String getType() {

                  return type;

              }

              public void setType(String type) {

                  this.type = type;

              }

              public int getPrice() {

                  return price;

              }

              public void setPrice(int price) {

                  this.price = price;

              }

          }

          Xml文件:

          <package name="RPC" namespace="/nodecorate" extends="json-default">

              <action name="SMDAction" class="smd.SMDAction" method="smd">

                  <interceptor-ref name="json">

                      <param name="enableSMD">true</param>

                  </interceptor-ref>

                  <result type="json">

                       <param name="enableSMD">true</param>

                  </result>

              </action>

          </package>

          這里需要注意一點:” enableSMD”這個必須在interceptorresult都要配置.

          Js代碼:

          <s:url id="smdUrl" namespace="/nodecorate" action="SMDAction" />

          <script type="text/javascript">

              //load dojo RPC

              dojo.require("dojo.rpc.*");

              //create service object(proxy) using SMD (generated by the json result)

              var service = new dojo.rpc.JsonService("${smdUrl}");

              //function called when remote method returns

              var callback = function(bean) {

                  alert("Price for " + bean.name + " is " + bean.price);

              };

              //parameter

              var bean = {name: "Mocca"};

              //execute remote method

              var defered = service.doSomething(bean, 5);

              //attach callback to defered object

              defered.addCallback(callback);

          </script>

          JsonService會發出一個請求到action加載SMD,同時遠程方法會返回一個JSON對象,這個過程是Dojoaction中的方法創建了一個Proxy。因為這是異步調用過程,當遠程方法執行的時候,它會返回一個對象到callback方法中。

          f)         代理的對象

          當使用的注解不是繼承自Java,可能你使用代理會出現一些問題。比如:當你使用aop攔截你的action的時候。在這種情況下,這個插件不會自動發現注解的方法。為了避免這種情況發生,你需要在xml中配置ignoreInterfacesfalse,這樣插件會自己查找注解的所有接口和父類。

          注意:這個參數只有在Action執行的過程是通過注解來運行的時候才應該設為false

          <action name="contact" class="package.ContactAction" method="smd">

             <interceptor-ref name="json">

                <param name="enableSMD">true</param>

                <param name="ignoreInterfaces">false</param>

             </interceptor-ref>

             <result type="json">

                <param name="enableSMD">true</param>

                <param name="ignoreInterfaces">false</param>

             </result>

             <interceptor-ref name="default"/>

          </action>

          posted on 2008-10-04 14:45 Loy Fu 閱讀(7748) 評論(2)  編輯  收藏 所屬分類: struts
          主站蜘蛛池模板: 棋牌| 长武县| 自治县| 两当县| 周宁县| 麻江县| 远安县| 丰县| 湘潭市| 施甸县| 新竹县| 离岛区| 丘北县| 九龙坡区| 宜君县| 兴宁市| 磐安县| 河西区| 和平区| 九龙坡区| 丽水市| 庆城县| 株洲县| 湖口县| 塔城市| 竹溪县| 焦作市| 延庆县| 文登市| 张家川| 南康市| 铜梁县| 旬邑县| 无为县| 岳阳市| 仙桃市| 平原县| 遂川县| 宝山区| 安平县| 奈曼旗|