2011年6月9日 星期四

Spring + Json

為了使用Json, 今天在spring xml 加入下面的設定,

<bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
    <property name="mediaTypes">
        <map>
            <entry key="json" value="application/json" />
            <entry key="xml" value="text/xml" />
            <entry key="htm" value="text/html" />
            <entry key="html" value="text/html" />
        </map>
    </property>
    <property name="defaultContentType" value="text/html" />
    <property name="viewResolvers">
        <list>
            <bean class="org.springframework.web.servlet.view.BeanNameViewResolver"/>
            <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
                <property name="requestContextAttribute"><value>rc</value></property>
                <property name="viewClass" value="org.springframework.web.servlet.view.JstlView" />
                <property name="prefix" value="/WEB-INF/jsp/"/>
                <property name="suffix" value=".jsp"/>
            </bean>
        </list>
    </property>
    <property name="defaultViews">
        <list>
            <bean class="org.springframework.web.servlet.view.json.MappingJacksonJsonView" />
        </list>
    </property>
    <property name="ignoreAcceptHeader" value="true" />
</bean>


卻出現 exception 如下
Exception sending context initialized event to listener instance of class org.springframework.web.context.ContextLoaderListener org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.web.servlet.view.ContentNegotiatingViewResolver#0' defined in ServletContext resource [/WEB-INF/config/webmvc-config.xml]: Cannot create inner bean 'org.springframework.web.servlet.view.json.MappingJacksonJsonView#17b0998' of type [org.springframework.web.servlet.view.json.MappingJacksonJsonView] while setting bean property 'defaultViews' with key [0]; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.web.servlet.view.json.MappingJacksonJsonView#17b0998' defined in ServletContext resource [/WEB-INF/config/webmvc-config.xml]: Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [org.springframework.web.servlet.view.json.MappingJacksonJsonView]: Constructor threw exception; nested exception is java.lang.NoClassDefFoundError: org/codehaus/jackson/map/ObjectMapper
...
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.web.servlet.view.json.MappingJacksonJsonView#17b0998' defined in ServletContext resource [/WEB-INF/config/webmvc-config.xml]: Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [org.springframework.web.servlet.view.json.MappingJacksonJsonView]: Constructor threw exception; nested exception is java.lang.NoClassDefFoundError: org/codehaus/jackson/map/ObjectMapper


是因為少了Jackson Library的關係, 可按此下載


Json 簡單的範例如下:
Java Code
@RequestMapping(value={"JsonTester"})
@ResponseBody
public ObjectNode jsonTester() {
    ObjectNode rootNode = new ObjectMapper().createObjectNode();
    rootNode.put("result", true);


    return rootNode ;
}

html code(via jQuery)
$(document).ready(function() {
    $.post("JsonTester.json",function(data) {
        if (data.result) {
           alert("成功");
        } else {
            alert("失敗");
       }
    });
});


@ResponseBody會依據收到的的 Accept Header 自動將回傳物件轉為客戶端可接受的型態.
此例會將 Java 物件轉為 Json 物件.

Spring 內建了數種轉換物件, 詳情可參考 Spring 說明文件


以下為回傳HashMap的範例:

Java Code:
@RequestMapping(value={"GetMap"})
@ResponseBody
public ObjectNode getMap(String inputValue) {
ObjectNode rootNode = new ObjectMapper().createObjectNode();


HashMap<String, String> result = myService.getMap(inputValue);
rootNode.put("result", true);
rootNode.putPOJO("myMap", result);


return rootNode ;
}



html code (via jQuery):
$.getJSON("GetMap.json", {inputValue: variable }, function(data) {
        if (data.result) {
            $.each(data.myMap, function(key, value){
                alert(key + "-" + value) ;
            });
        } else {
            alert("Get Map failed");
        }
})



ContentNegotiatingViewResolver 會依據
1. URL 的結尾(extension)

2. Accept header

3. 以上都沒有辦法判斷的話, 使用 defaultContentType

來判斷 request 的要求是那一種型態.



沒有留言: