`
杨胜寒
  • 浏览: 284523 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

Struts-json-plugin使用手册(翻译自官方文档)

阅读更多

为了在网上找到struts-json-plugin-xx.jar的源码,可真是费了九牛二虎之力,最后也还是没能如愿以偿,最后只得在Apache-SVN上一页一页的翻看源码来完成上一篇文章,真是悲惨...不过凡事不总是那么绝对——我想这也是生活的魅力所在,居然让我不经意间发现了Apache官网上的一篇关于struts-json-plugin的使用说明文档,非常的详细,非常的全面,不仅有配置说明,还有一个范例工程,赶紧将其拿出来与大家分享。

 

JSON 插件提供了一个 "json" 结果类型来把 action 序列化成 JSON. 这一序列化的过程是递归的, 意即整个对象图,从 action 类开始 (未包括基类) 将会被序列化 (可以用 "root" 属性来指定自己的根对象). 如果使用了 json 拦截器, action 将可通过请求中的 JSON 内容组装出来, 该拦截器遵循以下几条规则:

  1. "content-type" 必须为 "application/json"
  2. JSON 内容必须是格式良好的, 参考 json.org 中的语法.
  3. Action 里必须有欲获取值的属性的相应 public 的 "setter" 方法.
  4. 所支持的类型有: 原始类型 (int,long...String), Date, List, Map, 原始类型数组, 其他的类 (将会支持更多), 和其他类型的数组.
  5. JSON 中的任何将要被填入到 list 或 map 中的对象会是 Map 类型(属性映射到值), 任何整数都是 Long 类型, 任何小数会是 Double 类型, 任何数组会是 List 类型.

给定下面的 JSON 字符串:

 

{
   "doubleValue": 10.10,
   "nestedBean": {
      "name": "Mr Bean"
   },
   "list": ["A", 10, 20.20, {
      "firstName": "El Zorro"
   }],
   "array": [10, 20] 
}

 

action 中必须有一个 "setDoubleValue" 方法, 参数为 "float" 或者 "double"(拦截器将会把值转换为相应的类型). 还必须有一个 "setNestedBean" 方法,它的参数类型可以为任何类类型, 其中含有参数为 "String" 的 "setName" 方法. 还必须有一个参数为 "List" 的 "setList" 方法, 这个 List 中将会包含: "A" (String), 10 (Long), 20.20 (Double), Map ("firstName" -> "El Zorro"). "setArray" 方法可以是 "List", 或任何数字类型数组作参数的.
序列化你的对象成 javascript 的 JSON, 参考 json2

安装

本插件可通过把插件 jar 包到你的应用的 /WEB-INF/lib 目录来完成安装. 没有别的文件需要拷贝或被创建.

使用 maven 的话, 加入下列到你的 pom 中:

 

 

<dependencies>
   ...
   <dependency>
       <groupId>org.apache.struts</groupId>
       <artifactId>struts2-json-plugin</artifactId>
       <version>STRUTS_VERSION</version>
   </dependency>
   ...
</dependencies>

 

定制化序列化和反序列化

使用 JSON 注解来达到定制序列化和反序列化过程. 可用的 JSON 注解如下:

 

 

名称 描述 默认值 序列化 反序列化
name 定制字段名 empty yes no
serialize 标识为可被序列化 true yes no
deserialize 标识为可被反序列化 true no yes
format 用于格式化或解析 Date 字段的格式 "yyyy-MM-dd'T'HH:mm:ss" yes yes

 

 

排除属性

 

逗号分隔的正则表达式列表可传递给 JSON Result 和 Interceptor(拦截器), 被任何 一个正则表达式匹配的属性将会在序列化过程时忽略掉:

 

<!-- 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>

 

包含属性

逗号分隔的正则表达式列表可被传递给 JSON Result, 用于限制哪些属性可用于序列化. 只有当能够匹配任何一个正则表达式的属性才会包含在序列化输出中.

注:
排除属性表达式优先于包含属性的表达式. 那就是说, 如果包含和排除表达式应用于同一个结果, 包含表达式对于被排除表达式匹配到的属性是不起作用的.

 

 

<!-- Result fragment -->
<result type="json">
  <param name="includeProperties">
    ^entries\[\d+\]\.clientNumber,
    ^entries\[\d+\]\.scheduleNumber,
    ^entries\[\d+\]\.createUserId
  </param>
</result>

 

 

根对象 

使用 "root" 属性(OGNL 表达式) 指定被用于序列化的根对象.

 

<result type="json">
  <param name="root">
    person.job
  </param>
</result>

 

 

"root" 属性(OGNL 表达式) 也可以用于拦截器来指定被组装的对象, 确保这个对象不会是 null.

 

<interceptor-ref name="json">
  <param name="root">bean1.bean2</param>
</interceptor-ref>

 

 

包装

可能会有某些原因,你想要用些文本对 JSON 输出包装一下, 像用注释包裹, 加上前缀, 或使用文件上载让结果显示在 textarea 之中. 用 wrapPrefix 在开始处加上内容,wrapPostfix 添加内容在尾端. 这两个参数优先使用,而 "wrapWithComments" 和 "prefix" 自从 0.34 后就不推荐使用. 例子:

进行注释:

 

<result type="json">
  <param name="wrapPrefix">/*</param>
  <param name="wrapSuffix">*/</param>
</result>

 

添加前缀:

 

<result type="json">
  <param name="wrapPrefix">{}&&</param>
</result>

 

 

包裹上传的文件内容:

 

<result type="json">
  <param name="wrapPrefix"><![CDATA[<html><body><textarea>]]></param>
  <param name="wrapSuffix"><![CDATA[</textarea></body></html>]]></param>
</result>

 

包裹以注释

wrapWithComments 自 0.34 不推荐使用, 建议用 wrapPrefixwrapSuffix.
wrapWithComments 可使得安全的 JSON 文本变得不安全. 例如,

 

["*/ alert('XSS'); /*"]

谢谢 Douglas Crockford 的提示! 应考虑用 prefix.

假如被序列化的 JSON 是 {name: 'El Zorro'}. 那么此时输出就会是: {}&& ({name: 'El Zorro'}

假如 "wrapWithComments" (默认为 false) 属性被设为 true, 生成的被包裹上注释的 JSON 就如下:

 

/* {
   "doubleVal": 10.10,
   "nestedBean": {
      "name": "Mr Bean"
   },
   "list": ["A", 10, 20.20, {
      "firstName": "El Zorro"
   }],
   "array": [10, 20] 
} */

 

 欲取消上面的注释,可用:

 
var responseObject = eval("("+data.substring(data.indexOf("\/\*")+2, data.lastIndexOf("\*\/"))+")");
 
 
前缀
 
prefix 从 0.34 后不建议用, 请用 wrapPrefixwrapSuffix.

假如参数 prefix 被设置为 true, 生成的 JSON 将被附上前缀 "{}&& ". 这有助于防止被劫持. 详细内容请看 this Dojo Ticket:

 

<result type="json">
  <param name="prefix">true</param>
</result>

  

 

基类
 

默认时,定义在 "root" 对象的基类中的属性不会被序列化, 要序列化来自于所有基类(直到 Object) 中的属性,需在 JSON result 里设置 "ignoreHierarchy" 为 false:

 

<result type="json">
  <param name="ignoreHierarchy">false</param>
</result>

 

枚举类型

默认的, Enum 被序列化为 name=value 对,这里的 value = name().

 

public enum AnEnum {
     ValueA,
     ValueB
  }

  JSON:  "myEnum":"ValueA"

 

使用 result 的参数 "enumAsBean" 可使得 Enum 像一个 bean 一样的被序列化,特定的属性为 _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" }

 

在 struts.xml 中启用该参数:

 

<result type="json">
  <param name="enumAsBean">true</param>
</result>

 

 

压缩输出.

设置 enableGZIP 属性为 true 可用 gzip 压缩响应输出. 在请求后 "Accept-Encoding" 头中必须包含 "gzip" 才能正常工作.

 

<result type="json">
  <param name="enableGZIP">true</param>
</result>

 

防止浏览器缓存响应数据

noCache 设置为 true(默认为 false) 会设置如下响应头:

 

  • Cache-Control: no-cache
  • Expires: 0
  • Pragma: No-cache
  •  

    <result type="json">
      <param name="noCache">true</param>
    </result>
    

     

     

    排除值为 null 的属性

    默认的,为 null 的字段也被序列化,生成像 {property_name: null}. 这能够通过设置 excludeNullProperties 为 true 来防止.

     

    <result type="json">
      <param name="excludeNullProperties">true</param>
    </result>
    

     

     

    状态和错误代码

    使用 statusCode 来设置响应状态代码:

     

    <result type="json">
      <param name="statusCode">304</param>
    </result>
    

     

     

    同时可用 errorCode 来发送一个错误(the server might end up sending something to the client which is not the serialized JSON):

     

    <result type="json">
      <param name="errorCode">404</param>
    </result>
    

     

    JSONP

    To enable JSONP, set the parameter callbackParameter in either the JSON Result or the Interceptor. A parameter with that name will be read from the request, and it value will be used as the JSONP function. Assuming that a request is made with the parameter "callback"="exec": 

     

    <result type="json">
      <param name="callbackParameter">callback</param>
    </result>
    

     

    And that the serialized JSON is {name: 'El Zorro'}. Then the output will be: exec({name: 'El Zorro'})

    Content Type

    Content type will be set to application/json-rpc by default if SMD is being used, or application/json otherwise. Sometimes it is necessary to set the content type to something else, like when uploading files with Dojo and YUI. Use the contentType parameter in those cases.

     

    <result type="json">
      <param name="contentType">text/html</param>
    </result>  

     

     

    以上是前辈"隔叶黄莺 Unmi Blog"对该文档的翻译,感谢前辈的无私奉献!除上述翻译的部分,原文中还有三个具体的范例,除了示范普通的JSON调用外,还有一个JSON RPC范例,笔者看的不是很明白,所以这里不敢多说什么。原文地址:https://cwiki.apache.org/confluence/display/WW/JSON+Plugin,感兴趣的童鞋可以去看看。

     

     

     

    2
    1
    分享到:
    评论

    相关推荐

    Global site tag (gtag.js) - Google Analytics