原文地址:
http://cometd.org/documentation/2.x/cometd-java/json
CometD 2 JSON 庫插件能力
由 sbordet 提交于星期二,2011/8/16-9:11。
CometD 2 JSON 庫插件能力
自版本 2.4.0開始,CometD 允許自定義JSON 庫,用于把傳入 JSON 轉(zhuǎn)換成Bayeux 消息以及用 Bayeux 消息生成 JSON 。
這里有兩種實現(xiàn)方法,一種是利用jetty的org.eclipse.jetty.util.ajax.JSON類,一種是Jackson庫。默認的方法是利用jetty庫。
這兩個庫幾乎一樣快,但也有區(qū)別,在特殊CometD情況下,jetty的庫解析要比jackson快,但生成要比它慢。
Jackson庫有豐富的API去自定義json且它是用注解的方式解析,所以如果你想用自定義的類作為bayeux消息的數(shù)據(jù)(代替java.util.Map對象),它將會很有優(yōu)勢。請閱讀jackson的文檔獲取詳細信息。
Jetty庫也允許插入自定義的序列化和反序列化,也行太簡單但不失為重新的方法(你想自定義類必須實現(xiàn)jetty庫的接口)。請閱讀org.eclipse.jetty.util.ajax.JSON的文檔獲取詳細信息。
CometD json上下文 API
Json庫在CometD java客戶端實現(xiàn)中被用來生成json和把json解析成org.cometd.bayeux.Message實例。
執(zhí)行生成/解析的json類的客戶端必須實現(xiàn)org.cometd.common.JSONContext.Client
類似的,在服務(wù)端,一個org.cometd.common.JSONContext.Server的實現(xiàn)產(chǎn)生json或把json解析成org.cometd.bayeux.server.ServerMessage實例。
客戶端配置
在客戶端,org.cometd.common.JSONContext.Client實例必須直接傳到配置的傳輸中,如果省略,默認使用jetty庫。
例如:
HttpClient httpClient = ...;
Map clientOptions = new HashMap();
// Use the Jackson implementation
JSONContext.Client jsonContext = newJacksonJSONContextClient();
clientOptions.put(ClientTransport.JSON_CONTEXT, jsonContext);
ClientTransport transport = new LongPollingTransport(clientOptions,httpClient);
BayeuxClient client = new BayeuxClient(cometdURL, transport);
org.cometd.common.JSONContext.Client必須被所有的客戶端傳輸共享(因為唯一的傳輸必須在任何時候都要被使用)。
你可以自定義json實現(xiàn)并添加你自己序列化和反序列化方法,例如:
public class MyJacksonJSONContextClient extends org.cometd.common.JacksonJSONContextClient
{
public MyJacksonJSONContextClient()
{
org.codehaus.jackson.map.ObjectMapper objectMapper = getObjectMapper();
objectMapper.registerModule(new MyModule());
}
private class MyModule extends org.codehaus.jackson.map.module.SimpleModule
{
public MyModule()
{
// Add your custom serializers/deserializers here
addSerializer(Foo.class, new FooSerializer());
}
}
}
服務(wù)端配置
在服務(wù)端,實現(xiàn)org.cometd.common.JSONContext.Server的類可能在CometdServlet的初始化參數(shù)中指定了,如果省略,默認使用jetty庫。
例如:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
version="2.5">
<servlet>
<servlet-name>cometd</servlet-name>
<servlet-class>org.cometd.server.CometdServlet</servlet-class>
... other parameters
<init-param>
<param-name>jsonContext</param-name>
<param-value>org.cometd.server.JacksonJSONContextServer</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>cometd</servlet-name>
<url-pattern>/cometd/*</url-pattern>
</servlet-mapping>
</web-app>
這個類必須被默認的初始化參數(shù)構(gòu)造器實例化并實現(xiàn)org.cometd.common.JSONContext.Server,
以及它可以用添加序列化和反序列化的擴展來自定義。
可移植性注意事項
它能夠從一個json的實現(xiàn)庫轉(zhuǎn)換成另一個json庫,例如從jetty庫換成jackson庫,提供如此功能,應(yīng)用程序的代碼編寫要特別小心。
從1.8.4版本開始,jackson當序列化json數(shù)組時只能提供java.util.List的實例。
但是jetty庫在序列化json數(shù)組能提供Object[]。
類似的,jackson能提供lava.lang.Integer,而jetty庫能提供java.lang.Long。
為了編寫可移植的應(yīng)用程序代碼,我們使用下面的代碼模式:
Message message = ...;
Map<String, Object> data = message.getDataAsMap();
// Expecting a JSON array
// WRONG
Object[] array = (Object[])data.get("array");
// CORRECT
Object field = data.get("array");
Object[] array = field instanceof List ? ((List)field).toArray() : (Object[])field;
// Expecting a long
// WRONG
long value = (Long)data.get("value");
// CORRECT
long value = ((Number)data.get("value")).longValue();