1. 程式人生 > >spring mvc 使用及json 日期轉換解決方案

spring mvc 使用及json 日期轉換解決方案

第一步:建立CustomObjectMapper類

  1. /**  
  2.  * 解決SpringMVC使用@ResponseBody返回json時,日期格式預設顯示為時間戳的問題。需配合<mvc:message-converters>使用  
  3.  *   
  4.  * @author hellostory  
  5.  * @date 2013-10-31 下午04:17:52  
  6.  */  
  7. @Component("customObjectMapper")  
  8. public class CustomObjectMapper extends ObjectMapper {  
  9.     public CustomObjectMapper() {  
  10.         CustomSerializerFactory factory = new CustomSerializerFactory();  
  11.         factory.addGenericMapping(Date.class, new JsonSerializer<Date>() {  
  12.             @Override  
  13.             public void serialize(Date value, JsonGenerator jsonGenerator,  
  14.                     SerializerProvider provider) throws IOException, JsonProcessingException {  
  15.                 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  
  16.                 jsonGenerator.writeString(sdf.format(value));  
  17.             }  
  18.         });  
  19.         this.setSerializerFactory(factory);  
  20.     }  
  21. }  

第二步:配置如下:

  1. <mvc:annotation-driven
    >
  2.     <mvc:message-converters>
  3.         <beanclass="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
  4.             <propertyname="objectMapper"ref="customObjectMapper"></property>
  5.         </bean>
  6.     </mvc:message-converters>
  7. </mvc:annotation-driven>

效果如下:

格式化前:


格式化後:


------------------------------------------------------------------------------------------------------------------------------------------------------------

又到搭新開發環境的時候,總是不免去網上搜下目前最新的框架。spring是web開發必用的框架,於是乎下載了目前最新的spring4.0.3,同時越來越不想用struts2,想試試spring mvc,也將spring-webmvc4.0.3下了下來,投入兩天時間學習後,發現還是挺優雅的,特別是從3.0後,spring mvc使用註解方式配製,以及對rest風格的支援,真是完美致極。
下面將這兩天研究到的問題做個總結,供參考。
1.request物件的獲取
方式1:
在controller方法上加入request引數,spring會自動注入,如:public String list(HttpServletRequest request,HttpServletResponse response)
方式2:在controller類中加入@Resource private HttpServletRequest request 屬性,spring會自動注入,這樣不知道會不會出現執行緒問題,因為一個controller例項會為多個請求服務,暫未測試。
方式3:在controller方法中直接寫程式碼獲取 HttpServletRequest request = ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest();
方式4:在controller中加入以下方法,此方法會在執行此controller的處理方法之前執行

  1. @ModelAttribute
  2. privatevoid initServlet(HttpServletRequest request,HttpServletResponse response) {  
  3.     //String p=request.getParameter("p");
  4.     //this.req=request;//例項變數,有執行緒安全問題,可以使用ThreadLocal模式儲存
  5. }  

2.response物件的獲取

可以參照以上request的獲取方式1和方式4,方式2和方式3對response物件無效!
3.表單提交之資料填充

直接在方法上加入實體物件引數,spring會自動填充物件中的屬性,物件屬性名要與<input>的name一致才會填充,如:public boolean doAdd(Demo demo)

4.表單提交之資料轉換-Date型別

在實體類的屬性或get方法上加入 @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss"),那麼表單中的日期字串就會正確的轉換為Date型別了。還有@NumberFormat註解,暫時沒用,就不介紹了,一看就知道是對數字轉換用的。

5.json資料返回
在方法上加入@ResponseBody,同時方法返回值為實體物件,spring會自動將物件轉換為json格式,並返回到客戶端。如下所示:
  1. @RequestMapping("/json1")  
  2. @ResponseBody
  3. public Demo json1() {  
  4.     Demo demo=new Demo();  
  5.     demo.setBirthday(new Date());  
  6.     demo.setCreateTime(new Date());  
  7.     demo.setHeight(170);  
  8.     demo.setName("tomcat");   
  9.     demo.setRemark("json測試");   
  10.     demo.setStatus((short)1);   
  11.     return demo;  
  12. }  
注意:spring配置檔案要加上:<mvc:annotation-driven/>,同時還要引入jackson-core.jar,jackson-databind.jar,jackson-annotations.jar(2.x的包)才會自動轉換json
這種方式是spring提供的,我們還可以自定義輸出json,以上第二條不是說了獲取response物件嗎,拿到response物件後,任由開發人員宰割,想怎麼返回就怎麼返回。
方法不要有返回值,如下:
  1. @RequestMapping("/json2")  
  2. publicvoid json2() {  
  3.     Demo demo=new Demo();  
  4.     demo.setBirthday(new Date());  
  5.     demo.setCreateTime(new Date());  
  6.     demo.setHeight(170);  
  7.     demo.setName("tomcat");  
  8.     demo.setRemark("json測試");  
  9.     demo.setStatus((short)1);  
  10.     String json=JsonUtil.toJson(obj);//;json處理工具類
  11.     HttpServletResponse response = //獲取response物件
  12.     response.getWriter().print(json);  
  13. }  
OK,一切很完美。接著噁心的問題迎面而來,date型別轉換為json字串時,返回的是long time值,如果你想返回“yyyy-MM-dd HH:mm:ss”格式的字串,又要自定義了。我很奇怪,不是有@DateTimeFormat註解嗎,為什麼不利用它。難道@DateTimeFormat只在表單提交時,將字串轉換為date型別,而date型別轉換為json字串時,就不用了。帶著疑惑查原始碼,原來spring使用jackson轉換json字元,而@DateTimeFormat是spring-context包中的類,jackson如何轉換,spring不方便作過多幹涉,於是只能遵守jackson的轉換規則,自定義日期轉換器。
先寫一個日期轉換器,如下:
  1. publicclass JsonDateSerializer extends JsonSerializer<Date> {  
  2.    private SimpleDateFormat dateFormat=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  
  3.    @Override
  4.    publicvoid serialize(Date date, JsonGenerator gen, SerializerProvider provider)  
  5.            throws IOException, JsonProcessingException {  
  6.        String value = dateFormat.format(date);  
  7.        gen.writeString(value);  
  8.    }  
  9. }  
在實體類的get方法上配置使用轉換器,如下:
  1. @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")  
  2. @JsonSerialize(using=JsonDateSerializer.class)  
  3. public Date getCreateTime() {  
  4.     returnthis.createTime;  
  5. }  
OK,到此搞定。
你真的滿意了嗎,這麼不優雅的解決方案,假設birthday屬性是這樣的,只有年月日,無時分秒
  1. @DateTimeFormat(pattern="yyyy-MM-dd")  
  2. public Date getBirthday() {  
  3.     returnthis.birthday;  
  4. }  
這意味著,又要為它定製一個JsonDate2Serializer的轉換器,然後配置上,像這樣
  1. @DateTimeFormat(pattern="yyyy-MM-dd")  
  2. @JsonSerialize(using=JsonDate2Serializer.class)  
  3. public Date getBirthday() {  
  4.     returnthis.birthday;  
  5. }  
假設還有其它格式的Date欄位,還得要為它定製另一個轉換器。my god,請饒恕我的罪過,不要讓我那麼難受
經過分析原始碼,找到一個不錯的方案,此方案將不再使用@JsonSerialize,而只利用@DateTimeFormat配置日期格式,jackson就可以正確轉換,但@DateTimeFormat只能配置在get方法上,這也沒什麼關係。
先引入以下類,此類對jackson的ObjectMapper類做了註解掃描攔截,使它也能對加了@DateTimeFormat的get方法應用日期格式化規則
  1. package com.xxx.