2015年10月17日 星期六

spring4 @ResponseBody json date format

預設的 @ResponseBody  的日期型態 在 json 時是回傳 時間long值~

然後想改一下,就突然發現事情沒有想得那麼簡單Orz...

先講最簡單也是最基礎的寫法如下~
使用 MappingJacksonHttpMessageConverter
但是~他不知道在那一版就被 @deprecated 掉~猜大概是 3.x吧~
然後要講清楚,spring 的 json 是用 Jackson 的,若是使用 MappingJacksonHttpMessageConverter,就要搭配 jackson 1.x 版使用...jar檔大概是 jackson-core-asl-1.8.0.jar, jackson-mapper-asl-1.8.0.jar 之類的...

    <!-- messageConverters beans -->   
    <beans:bean id="stringHttpMessageConverter"
        class="org.springframework.http.converter.StringHttpMessageConverter">
    </beans:bean>
   
    <!-- orgin for @ResponseBody json converter use jackson 1.x  -->
    <beans:bean id="mappingJacksonHttpMessageConverter"
        class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
    </beans:bean>
   
    <!--
        AnnotationMethodHandlerAdapter messageConverters for @ResponseBody
    -->
    <beans:bean
        class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
        <beans:property name="messageConverters">
            <beans:list>
                <beans:ref bean="stringHttpMessageConverter" />
                <beans:ref bean="mappingJacksonHttpMessageConverter" />
            </beans:list>
        </beans:property>
    </beans:bean>


為了趕上時代,所以....=.=b,就決定使用新的 converter...
MappingJackson2HttpMessageConverter
很微妙的多了個 2...Google網路上有許多寫法,但...貼上去都會死XD...最後總算試出一套可以用Orz...
在此前提,要記得先抓 Jackson 2.x 的 jar檔(好像release到2.6+了),然後他們官網居然不放 binary 的jar...就去jar檔網站下載了比較快Orz...其實2.x版很多喔~不過就第一眼google到是 2.2的就可以動...要注意的是~他 2.x 包的 jar 分類跟 1.x 不一樣了!有三個~
jackson-annotations-2.2.4.jar
jackson-core-2.2.2.jar
jackson-databind-2.2.4.jar

然後spring 的設定也要改囉~從網路上貼來的,再加一點點中式英文註解XD...
(這套的設定要 spring 3.2+ 才能的樣子, xsd 有不一樣)
這個的mvc 還多寫了好幾道,算是很方便@@~

    <!-- messageConverters beans -->   
    <beans:bean id="stringHttpMessageConverter"
        class="org.springframework.http.converter.StringHttpMessageConverter">
    </beans:bean>
    <!--
        AnnotationMethodHandlerAdapter messageConverters for @ResponseBody
    -->
    <beans:bean
        class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
        <beans:property name="messageConverters">
            <beans:list>
                <beans:ref bean="stringHttpMessageConverter" />
                <beans:ref bean="acmJacksonConverter" />
            </beans:list>
        </beans:property>
    </beans:bean>
   
    <!-- @ResponseBody json Date format needs jackson-core/databind/annoation.jar 2.x -->
    <!-- set JSON date format to ISO-8601 e.g. 1970-01-01T00:00:00.000+0000 -->
    <beans:bean id="sourceObjectMapper" class="com.fasterxml.jackson.databind.ObjectMapper"/>
    <beans:bean id="acmObjectMapper" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
        <beans:property name="targetObject" ref="sourceObjectMapper"/>
        <beans:property name="targetMethod" value="disable"/>
        <beans:property name="arguments" value="WRITE_DATES_AS_TIMESTAMPS"/>
    </beans:bean>
    <beans:bean id="acmJacksonConverter" class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
        <beans:property name="objectMapper" ref="acmObjectMapper"/>
    </beans:bean>
   
    <mvc:annotation-driven>
        <mvc:message-converters>
            <!-- We configure the Jackson mapper to output dates in ISO801 format. This requires adding our
            customized Jackson mapper to the list of Spring MVC message converters. But, if we just add our bean here
            all by itself, it will handle requests it should not handle, e.g. encoding strings.  So we need to add the
            other standard message converters here too, and make sure to put the customized Jackson converter AFTER the
            string converter. -->
   
            <beans:bean class="org.springframework.http.converter.ByteArrayHttpMessageConverter"/>
            <beans:bean class="org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter"/>
            <beans:bean class="org.springframework.http.converter.StringHttpMessageConverter"/>
            <beans:bean class="org.springframework.http.converter.ResourceHttpMessageConverter"/>
            <beans:bean class="org.springframework.http.converter.xml.SourceHttpMessageConverter"/>
            <beans:ref bean="acmJacksonConverter"/>
            <beans:bean class="org.springframework.http.converter.support.AllEncompassingFormHttpMessageConverter"/>
            <!-- atom feed requires com.sun.syndication package ...   -->
            <!--<bean class="org.springframework.http.converter.feed.AtomFeedHttpMessageConverter"/>-->
            <beans:bean class="org.springframework.http.converter.BufferedImageHttpMessageConverter"/>
            <beans:bean class="org.springframework.http.converter.FormHttpMessageConverter"/>
            <beans:bean class="org.springframework.http.converter.xml.Jaxb2CollectionHttpMessageConverter"/>
            <!-- marshalling converter requires spring oxm -->
            <!--<bean class="org.springframework.http.converter.xml.MarshallingHttpMessageConverter"/>-->
        </mvc:message-converters>
    </mvc:annotation-driven>

在此他 default 的 date format 就會變成 1970-01-01T00:00:00.000+0000...
若是需要 特別指定 某vo 裡面的 date指定~ 也很方便~只要直接加 annotation..
import com.fasterxml.jackson.annotation.JsonFormat;

    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd")
    private Date birthDate;

雖然把這套件加進去有點麻煩~但對開發上來說還蠻好用的~~

沒有留言: