好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

SpringMVC @RequestBody Date类型的Json转换方式

SpringMVC @RequestBody Date类型的Json转换

正常使用Json或Gson对Date类型序列化成字符串时,得到的是类似]Dec 5, 2017 8:03:34 PM]这种形式的字符串,前端得到了这种格式的很难明白这个具体是什么时间,可读性很低。

同时如果用这种形式的字符串来反序列化为Date对象,也会失败,这个过程是不可逆的。如何将Date对象序列化为指定格式的字符串,比如]yyyy-MM-dd]格式的字符串,以Gson的使用为例来说明。

对于Gson对象,可以使用GsonBuilder来实例化

通过GsonBuilder设置DateFormat的格式

?

1

Gson gson = new GsonBuilder().setDateFormat( "yyyy-MM-dd HH:mm:ss" ).create();

经过这样设置后,使用toJson(Object obj)方法对Date对象序列化时,会输出]yyyy-MM-dd HH:mm:ss]格式的字符串;

也可以将]yyyy-MM-dd HH:mm:ss]格式的字符串反序列化为一个Date对象。值得注意的是,当一个Date对象未指定]HH:mm:ss]时,会使用当前时间来填充以补齐格式长度。

以上讲的是Date对象的序列化和反序列化为字符串的方法,在SpingMVC框架中并不适用,下面讲SpringMVC中Date的序列化和反序列化。

SpringMVC中,如果前端以GET的形式传递字符串,后端想将此字符串反序列化为Date对象,最常用的就是注册Formatter对象

以零配置框架为例

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

public class String2DateFormatter implements Formatter<Date> {

     private static final String DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss" ;

     private static final String DATE_FORMAT = "yyyy-MM-dd" ;

     @Override

     public String print(Date object, Locale locale) {

         return new GsonBuilder().setDateFormat(DATE_TIME_FORMAT).create().toJson(object);

     }

     @Override

     public Date parse(String text, Locale locale) throws ParseException {

         if (text.length() > 10 ) {

             return new SimpleDateFormat(DATE_TIME_FORMAT).parse(text);

         } else {

             return new SimpleDateFormat(DATE_FORMAT).parse(text);

         }

     }

}

public class MvcContextConfig extends WebMvcConfigurerAdapter {

     ......

     @Override

     public void addFormatters(FormatterRegistry registry) {

         registry.addFormatter( new String2DateFormatter());

     }

     ......

}

当然也可以用配置文件的形式配置,具体方法请百度。

当前端传递字符串,Controller用Date类型的参数接受时,会使用Formatter将字符串反序列化为Date对象。

如果前端以POST形式传递一个Json对象,对象内部有一个Date属性,前端传递的是字符串,后端用一个标识@RequestBody的复合对象接收时,Formatter是不会起作用的。

此时起作用的是HttpMessageConverter的实现类。正常情况下项目内有Jackson或Gson依赖,能够将Json反序列化为复合对象。

如果依赖了Jackson,且使用Jackson的HttpMessageConverter反序列化Json,那么仅支持反序列化简单数据类型的属性,不支持Date类型;但是如果是Gson类型,是支持]yyyy-MM-dd HH:mm:ss]格式的反序列化的,确定不支持]yyyy-MM-dd]格式,其他格式不确定。

也就是说依赖Gson可以将前端的]yyyy-MM-dd HH:mm:ss]格式的字符串反序列化为Date对象,但是将Date对象返回给前端时,解析得到的还是类似]Dec 5, 2017 8:03:34 PM]这种形式的字符串,并不可取。

当我们使用Jackson作为Json对象的序列化和反序列化的解析器时

以零配置形式框架下的代码实现为例讲解

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

public class MvcContextConfig extends WebMvcConfigurerAdapter {

     ......

     @Override

     public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {

         StringHttpMessageConverter stringConverter = new StringHttpMessageConverter(Charset.forName( "UTF-8" ));

         stringConverter.setWriteAcceptCharset( false );

         converters.add(stringConverter);

         converters.add( new ByteArrayHttpMessageConverter());

         converters.add( new ResourceHttpMessageConverter());

         converters.add( new MappingJackson2XmlHttpMessageConverter());

         //设置Date类型使用HttpMessageConverter转换后的格式,或者注册一个GsonHttpMessageConverter,能直接支持字符串到日期的转换

         //当指定了日期字符串格式后,如果传的日志格式不符合,则会解析错误

         converters.add( new MappingJackson2HttpMessageConverter(

             new ObjectMapper().setDateFormat( new SimpleDateFormat( "yyyy-MM-dd HH:mm:ss" ))));

         //GsonHttpMessageConverter不支持yyyy-MM-dd形式的字符串转换为日期

         //converters.add(new GsonHttpMessageConverter());

     }

     ......

}

当我们选择使用Jackson作为Json的解析器时,需要注册一个MappingJackson2HttpMessageConverter,对内部默认的objectMapper对象做一个拓展,需要指定日期格式化器,当我们指定了具体的格式时,只支持这种格式的转换,其他的格式转换时会报错。

因此需要前端在传递日期字符串时,加上默认的时间,比如]2017-12-2 0],虽然多了点工作,但是能确保格式转换的正确。

当然并不是一定要]yyyy-MM-dd HH:mm:ss],其他的格式也都支持的,比如]yyyy-MM-dd]等等,具体可以看项目需求自定义,前端传递日期字符串的格式需要符合自定义的格式。

当配置了DateFormat时,传递对象给前端,对象内部有Date属性,也会将其序列化为这个格式的字符串。

XML文件形式配置HttpMessageConverter的方法可自行百度。

@RequestBody接收json字符串,自动将日期字符串转换为java.util.Date

1.配置springMVC可以接收json字符串

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

<? xml version = "1.0" encoding = "UTF-8" ?>

< beans

  xmlns = "http://HdhCmsTestspringframework.org/schema/beans"

  xmlns:xsi = "http://HdhCmsTestw3.org/2001/XMLSchema-instance"

  xmlns:p = "http://HdhCmsTestspringframework.org/schema/p"

  xmlns:context = "http://HdhCmsTestspringframework.org/schema/context"

  xmlns:aop = "http://HdhCmsTestspringframework.org/schema/aop"

  xmlns:tx = "http://HdhCmsTestspringframework.org/schema/tx"

  xmlns:mvc = "http://HdhCmsTestspringframework.org/schema/mvc"

  xsi:schemaLocation="http://HdhCmsTestspringframework.org/schema/beans

  http://HdhCmsTestspringframework.org/schema/beans/spring-beans-3.1.xsd

  http://HdhCmsTestspringframework.org/schema/context

  http://HdhCmsTestspringframework.org/schema/context/spring-context-3.1.xsd

  http://HdhCmsTestspringframework.org/schema/tx

  http://HdhCmsTestspringframework.org/schema/tx/spring-tx-3.1.xsd

  http://HdhCmsTestspringframework.org/schema/aop

  http://HdhCmsTestspringframework.org/schema/aop/spring-aop-3.1.xsd

  http://HdhCmsTestspringframework.org/schema/mvc

  http://HdhCmsTestspringframework.org/schema/mvc/spring-mvc-3.1.xsd">

  <!-- 解决@ResponseBody返回中文乱码,解决@RequestBody接收Json字符串自动转换为实体、List、Map格式转换器 -->

  < bean

   class = "org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter" >

   < property name = "messageConverters" >

    < list >

     <!--

     <bean

      class="org.springframework.http.converter.StringHttpMessageConverter">

      <property name="supportedMediaTypes">

       <list>

        <value>text/html;charset=UTF-8</value>

       </list>

      </property>

     </bean>

     -->

     < bean

      class = "org.springframework.http.converter.json.MappingJacksonHttpMessageConverter" >

      < property name = "supportedMediaTypes" >

       < list >

        < value >application/json;charset=UTF-8</ value >

       </ list >

      </ property >

     </ bean >

    </ list >

   </ property >

  </ bean >

  <!-- 扫描包,应用Spring的注解 -->

  < context:component-scan base-package = "com.mvc.action" ></ context:component-scan >

  < bean class = "org.springframework.web.servlet.view.InternalResourceViewResolver"

   p:viewClass = "org.springframework.web.servlet.view.JstlView"

   p:prefix = "/"

   p:suffix = ".jsp" >

  </ bean >

  <!-- SpringMVC自定义拦截器,使SpringMVC开启CORS支持 -->

  <!--

  <mvc:interceptors>

   <mvc:interceptor>

    <mvc:mapping path="/*"/>

    <bean class="com.mvc.dao.CorsInterceptor"></bean>

   </mvc:interceptor>

  </mvc:interceptors>

  -->

  < context:annotation-config />

  < mvc:annotation-driven />

</ beans >

2.@Controller类代码

?

1

2

3

4

5

6

7

8

9

10

11

12

13

@RequestMapping (value= "/addDicAppUsers.do" )

  @ResponseBody

  public boolean addDicAppUsers( @RequestBody DicAppUsersModel dicAppUsersModel)

  {

   if (dicAppUsersService.addDicAppUsers(dicAppUsersModel))

   {

    return true ;

   }

   else

   {

    return false ;

   }

  }

3.实体类对象代码

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

package com.mvc.model;

import java.util.Date;

import org.codehaus.jackson.map.annotate.JsonDeserialize;

import org.codehaus.jackson.map.annotate.JsonSerialize;

import com.mvc.imp.DateJsonDeserializer;

import com.mvc.imp.DateJsonSerializer;

 

/**

  * 用户视图类

  * @author suyunlong

  *

  */

@SuppressWarnings ( "serial" )

public class DicAppUsersModel implements java.io.Serializable

{

  private long id;

  private String loginid;

  private String loginname;

  private String loginpassword;

  private String loginunitcode;

  private String workplace;

  @JsonSerialize (using=DateJsonSerializer. class )

  @JsonDeserialize (using=DateJsonDeserializer. class )

  private Date addtime;

  private long sourceid;

  @JsonSerialize (using=DateJsonSerializer. class )

  @JsonDeserialize (using=DateJsonDeserializer. class )

  private Date createdate;

  public DicAppUsersModel() {

   super ();

  }

  public DicAppUsersModel( long id, String loginid, String loginname,

    String loginpassword, String loginunitcode, String workplace,

    Date addtime, long sourceid, Date createdate) {

   super ();

   this .id = id;

   this .loginid = loginid;

   this .loginname = loginname;

   this .loginpassword = loginpassword;

   this .loginunitcode = loginunitcode;

   this .workplace = workplace;

   this .addtime = addtime;

   this .sourceid = sourceid;

   this .createdate = createdate;

  }

  public long getId() {

   return id;

  }

  public void setId( long id) {

   this .id = id;

  }

  public String getLoginid() {

   return loginid;

  }

  public void setLoginid(String loginid) {

   this .loginid = loginid;

  }

  public String getLoginname() {

   return loginname;

  }

  public void setLoginname(String loginname) {

   this .loginname = loginname;

  }

  public String getLoginpassword() {

   return loginpassword;

  }

  public void setLoginpassword(String loginpassword) {

   this .loginpassword = loginpassword;

  }

  public String getLoginunitcode() {

   return loginunitcode;

  }

  public void setLoginunitcode(String loginunitcode) {

   this .loginunitcode = loginunitcode;

  }

  public String getWorkplace() {

   return workplace;

  }

  public void setWorkplace(String workplace) {

   this .workplace = workplace;

  }

  public Date getAddtime() {

   return addtime;

  }

  public void setAddtime(Date addtime) {

   this .addtime = addtime;

  }

  public long getSourceid() {

   return sourceid;

  }

  public void setSourceid( long sourceid) {

   this .sourceid = sourceid;

  }

  public Date getCreatedate() {

   return createdate;

  }

  public void setCreatedate(Date createdate) {

   this .createdate = createdate;

  }

}

4.DateJsonSerializer类代码

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

package com.mvc.imp;

import java.io.IOException;

import java.text.SimpleDateFormat;

import java.util.Date;

import org.codehaus.jackson.JsonGenerator;

import org.codehaus.jackson.JsonProcessingException;

import org.codehaus.jackson.map.JsonSerializer;

import org.codehaus.jackson.map.SerializerProvider;

 

public class DateJsonSerializer extends JsonSerializer<Date>

{

  public static final SimpleDateFormat format= new SimpleDateFormat( "yyyy-MM-dd HH:mm:ss" );

  public void serialize(Date date,JsonGenerator jsonGenerator,SerializerProvider serializerProvider)

    throws IOException,JsonProcessingException

  {

   jsonGenerator.writeString(format.format(date)); 

     } 

}

5.DateJsonDeserializer类代码

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

package com.mvc.imp;

import java.io.IOException;

import java.text.SimpleDateFormat;

import java.util.Date;

import org.codehaus.jackson.JsonParser;

import org.codehaus.jackson.JsonProcessingException;

import org.codehaus.jackson.map.DeserializationContext;

import org.codehaus.jackson.map.JsonDeserializer;

 

public class DateJsonDeserializer extends JsonDeserializer<Date>

{

  public static final SimpleDateFormat format= new SimpleDateFormat( "yyyy-MM-dd HH:mm:ss" );

  public Date deserialize(JsonParser jsonParser,DeserializationContext deserializationContext)

    throws IOException,JsonProcessingException

  {

   try

   {

    return format.parse(jsonParser.getText());

   }

   catch (Exception e)

   {

    System.out.println(e.getMessage());

    throw new RuntimeException(e);

   }

  }

}

这样,就可以把接收到的json日期字符串转换为Date了。后面,就可以直接通过Date类型保存日期数据了。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持。

原文链接:https://jiangjibo.blog.csdn.net/article/details/78724737

查看更多关于SpringMVC @RequestBody Date类型的Json转换方式的详细内容...

  阅读:37次