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. private void 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. public void 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. public class JsonDateSerializer extends JsonSerializer<Date> {
  2. private SimpleDateFormat dateFormat=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
  3. @Override
  4. public void 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. return this.createTime;
  5. }

OK,到此搞定。
你真的满意了吗,这么不优雅的解决方案,假设birthday属性是这样的,只有年月日,无时分秒

  1. @DateTimeFormat(pattern="yyyy-MM-dd")
  2. public Date getBirthday() {
  3. return this.birthday;
  4. }

这意味着,又要为它定制一个JsonDate2Serializer的转换器,然后配置上,像这样

  1. @DateTimeFormat(pattern="yyyy-MM-dd")
  2. @JsonSerialize(using=JsonDate2Serializer.class)
  3. public Date getBirthday() {
  4. return this.birthday;
  5. }

假设还有其它格式的Date字段,还得要为它定制另一个转换器。my god,请饶恕我的罪过,不要让我那么难受
经过分析源码,找到一个不错的方案,此方案将不再使用@JsonSerialize,而只利用@DateTimeFormat配置日期格式,jackson就可以正确转换,但@DateTimeFormat只能配置在get方法上,这也没什么关系。
先引入以下类,此类对jackson的ObjectMapper类做了注解扫描拦截,使它也能对加了@DateTimeFormat的get方法应用日期格式化规则

  1. package com.xxx.utils;
  2. import java.io.IOException;
  3. import java.lang.reflect.AnnotatedElement;
  4. import java.text.SimpleDateFormat;
  5. import java.util.Date;
  6. import org.springframework.format.annotation.DateTimeFormat;
  7. import org.springframework.stereotype.Component;
  8. import com.fasterxml.jackson.core.JsonGenerator;
  9. import com.fasterxml.jackson.core.JsonProcessingException;
  10. import com.fasterxml.jackson.databind.JsonSerializer;
  11. import com.fasterxml.jackson.databind.ObjectMapper;
  12. import com.fasterxml.jackson.databind.SerializerProvider;
  13. import com.fasterxml.jackson.databind.introspect.Annotated;
  14. import com.fasterxml.jackson.databind.introspect.AnnotatedMethod;
  15. import com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector;
  16. /**
  17. * json处理工具类
  18. * @author zhangle
  19. */
  20. @Component
  21. public class JsonUtil {
  22. private static final String DEFAULT_DATE_FORMAT="yyyy-MM-dd HH:mm:ss";
  23. private static final ObjectMapper mapper;
  24. public ObjectMapper getMapper() {
  25. return mapper;
  26. }
  27. static {
  28. SimpleDateFormat dateFormat = new SimpleDateFormat(DEFAULT_DATE_FORMAT);
  29. mapper = new ObjectMapper();
  30. mapper.setDateFormat(dateFormat);
  31. mapper.setAnnotationIntrospector(new JacksonAnnotationIntrospector() {
  32. @Override
  33. public Object findSerializer(Annotated a) {
  34. if(a instanceof AnnotatedMethod) {
  35. AnnotatedElement m=a.getAnnotated();
  36. DateTimeFormat an=m.getAnnotation(DateTimeFormat.class);
  37. if(an!=null) {
  38. if(!DEFAULT_DATE_FORMAT.equals(an.pattern())) {
  39. return new JsonDateSerializer(an.pattern());
  40. }
  41. }
  42. }
  43. return super.findSerializer(a);
  44. }
  45. });
  46. }
  47. public static String toJson(Object obj) {
  48. try {
  49. return mapper.writeValueAsString(obj);
  50. } catch (Exception e) {
  51. throw new RuntimeException("转换json字符失败!");
  52. }
  53. }
  54. public <T> T toObject(String json,Class<T> clazz) {
  55. try {
  56. return mapper.readValue(json, clazz);
  57. } catch (IOException e) {
  58. throw new RuntimeException("将json字符转换为对象时失败!");
  59. }
  60. }
  61. public static class JsonDateSerializer extends JsonSerializer<Date>{
  62. private SimpleDateFormat dateFormat;
  63. public JsonDateSerializer(String format) {
  64. dateFormat = new SimpleDateFormat(format);
  65. }
  66. @Override
  67. public void serialize(Date date, JsonGenerator gen, SerializerProvider provider)
  68. throws IOException, JsonProcessingException {
  69. String value = dateFormat.format(date);
  70. gen.writeString(value);
  71. }
  72. }
  73. }

再将<mvc:annotation-driven/>改为以下配置,配置一个新的json转换器,将它的ObjectMapper对象设置为JsonUtil中的objectMapper对象,此转换器比spring内置的json转换器优先级更高,所以与json有关的转换,spring会优先使用它。

  1. <mvc:annotation-driven>
  2. <mvc:message-converters>
  3. <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
  4. <property name="objectMapper" value="#{jsonUtil.mapper}"/>
  5. <property name="supportedMediaTypes">
  6. <list>
  7. <value>text/json;charset=UTF-8</value>
  8. </list>
  9. </property>
  10. </bean>
  11. </mvc:message-converters>
  12. </mvc:annotation-driven>

接下来就可以这样配置实体类,jackson也能正确转换Date类型

  1. @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
  2. public Date getCreateTime() {
  3. return this.createTime;
  4. }
  5. @DateTimeFormat(pattern="yyyy-MM-dd")
  6. public Date getBirthday() {
  7. return this.birthday;
  8. }

完毕,一切都完美了。

以下为2014/4/21 补充

写了那么多,发现白忙活了一场,原来jackson也有一个@JsonFormat注解,将它配置到Date类型的get方法上后,jackson就会按照配置的格式转换日期类型,而不自定义转换器类,欲哭无泪啊。辛苦了那么多,其实别人早已提供,只是没有发现而已。

不说了,直接上方案吧。

1.spring配置照样是这样:

  1. <mvc:annotation-driven>

2.JsonUtil可以不用了,但如果要自己从response对象输出json,那么还是可以用,但改成了这样

  1. package com.xxx.utils;
  2. import java.io.IOException;
  3. import java.text.SimpleDateFormat;
  4. import org.springframework.stereotype.Component;
  5. import com.fasterxml.jackson.databind.ObjectMapper;
  6. /**
  7. * json处理工具类
  8. * @author zhangle
  9. */
  10. @Component
  11. public class JsonUtil {
  12. private static final String DEFAULT_DATE_FORMAT="yyyy-MM-dd HH:mm:ss";
  13. private static final ObjectMapper mapper;
  14. static {
  15. SimpleDateFormat dateFormat = new SimpleDateFormat(DEFAULT_DATE_FORMAT);
  16. mapper = new ObjectMapper();
  17. mapper.setDateFormat(dateFormat);
  18. }
  19. public static String toJson(Object obj) {
  20. try {
  21. return mapper.writeValueAsString(obj);
  22. } catch (Exception e) {
  23. throw new RuntimeException("转换json字符失败!");
  24. }
  25. }
  26. public <t> T toObject(String json,Class<t> clazz) {
  27. try {
  28. return mapper.readValue(json, clazz);
  29. } catch (IOException e) {
  30. throw new RuntimeException("将json字符转换为对象时失败!");
  31. }
  32. }
  33. }</t></t>

3.实体类的get方法就需要多一个@JsonFormat的注解配置

    1. @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
    2. @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")
    3. public Date getCreateTime() {
    4. return this.createTime;
    5. }
    6. @DateTimeFormat(pattern="yyyy-MM-dd")
    7. @JsonFormat(pattern="yyyy-MM-dd",timezone = "GMT+8")
    8. public Date getBirthday() {
    9. return this.birthday;
    10. }

spring mvc4使用及json 日期转换解决方案的更多相关文章

  1. spring mvc 使用及json 日期转换解决方案

    http://blog.csdn.net/z69183787/article/details/40375479

  2. json日期转换

    //调用 ChangeDateFormat(CreatTime) //json日期转换 function ChangeDateFormat(jsondate) { jsondate = jsondat ...

  3. Newtonsoft.Json日期转换

    在使用EasyUI做后台时,使用表格datagrid,用Newtonsoft.Json转换为Json格式后,时间显示为2013-06-15 T00:00:00形式. 后来研究了一下Newtonsoft ...

  4. [Spring MVC] 表单提交日期转换问题,比如可能导致封装实体类时400错误

    三种格式的InitBinder @InitBinder//https://stackoverflow.com/questions/20616319/the-request-sent-by-the-cl ...

  5. json日期格式问题的办法

    //json日期转换 格式(2015-01-01) <input class="easyui-datebox" name="sbdj_txtShebaoka_Lin ...

  6. java中json和字符串互转及日期转换 练习

    一:以下是用到的jar名称: commons-beanutils-1.6.jar commons-collections-3.2.1.jar commons-lang-2.6.jar commons- ...

  7. Struts2、Spring MVC4 框架下的ajax统一异常处理

    本文算是struts2 异常处理3板斧.spring mvc4:异常处理 后续篇章,普通页面出错后可以跳到统一的错误处理页面,但是ajax就不行了,ajax的本意就是不让当前页面发生跳转,仅局部刷新, ...

  8. SpringMVC配置全局日期转换器,处理日期转换异常

    Spring 3.1.1使用Mvc配置全局日期转换器,处理日期转换异常链接地址: https://www.2cto.com/kf/201308/236837.html spring3.0配置日期转换可 ...

  9. 个人永久性免费-Excel催化剂功能第90波-xml与json数据结构转换表格结构

    在网络时代,大量的数据交互以xml和json格式提供,特别是系统间的数据交互和网络WebAPI.WebService接口的数据提供,都是通过结构化的xml或json提供给其他应用调用返回数据.若能提供 ...

随机推荐

  1. Qt开发陷阱一QSTACKWIDGET

    原始日期:2015-10-14 00:55 1.使用QStackWidget控件的setCurrentIndex方法时,要注意参数0对应着ui上StackWidget的page1,而不是page0,没 ...

  2. 使用CoApp创建NuGet C++静态库包

    NuGet是微软开发平台下的包管理软件,使用它你可以非常方便的将一些第三方的库.框架整合进自己的项目中,省去了不少麻烦的配置过程.但是从官方文档上来看,貌似NuGet对C++的支持不是很好,并且在现阶 ...

  3. 第一个spark+scala程序

    import org.apache.spark._import SparkContext._import java.util.{Calendar,Properties,Date,Locale}impo ...

  4. (转载)CloseableHttpClient设置Timeout

    参考文档: http://blog.csdn.net/zheng0518/article/details/46469051 https://segmentfault.com/a/11900000005 ...

  5. webpack初步介绍

    我们通过npm -g可以安装一个webpack的东西. npm -g叫做全局安装,通常是安装CLI程序(commond line interface). 我们只用过一次,装了cnpm.此时就能在CMD ...

  6. 在Linux环境如何在不解压情况下搜索多个zip包中匹配的字符串内容

    今天有个生产文件需要查日志,但因为是比较久远的故障,日志已经被归档为zip包放到某个目录下了,在不知道具体日期时间的情况下,总不能一个一个解压搜索吧.于是就研究一下怎么在多个压缩包里搜索字符串了.目前 ...

  7. 【亲测】appium_v1.4.16版本自动化适配android7.0系统

    要解决的问题:appium在androidV7.0系统上运行时报错 Failure [INSTALL_FAILED_ALREADY_EXISTS: Attempt to re-install io.a ...

  8. Java之分支和循环

    Java中的分支语句: if语句: if语句的四种写法: (1) if(表达式_布尔值) { ... } (2) if(表达式_布尔值) { ... } else { ... } (3) if(表达式 ...

  9. Luogu 1402 酒店之王(二分图最大匹配)

    Luogu 1402 酒店之王(二分图最大匹配) Description XX酒店的老板想成为酒店之王,本着这种希望,第一步要将酒店变得人性化.由于很多来住店的旅客有自己喜好的房间色调.阳光等,也有自 ...

  10. 理解梯度下降法(Gradient Decent)

    1. 什么是梯度下降法?   梯度下降法(Gradient Decent)是一种常用的最优化方法,是求解无约束问题最古老也是最常用的方法之一.也被称之为最速下降法.梯度下降法在机器学习中十分常见,多用 ...