时间格式转换
场景:前端传来String格式的日期数据data,后端用实体类User接收(其中User实体类有一个时间格式参数Data data)
此时我们要解决各个阶段的格式转换配置:
1、前端到后端:String data ——转换为—— Data data
2、后端到数据库:
3、后端到前端:Data data ——转换为—— String Data
注意:如果不设置的话默认的时间是世界标准世界(0区),而我们中国地区是东8区,相差8个小时。
一、使用@DateTimeFormat+@JsonFormat
1、当使用@DateTimeFormat时
User类:(注意Data要导util包的,别导错包了)
@Data public class User { private int id; @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") //@JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") private Date data; }
Controller
@RestController public class BeanController { @PostMapping("data") public Map data(@RequestBody User user){ //1、 查看前端到后端处理了格式没有 System.out.println(user); //2、查看后端到前端处理了格式没有 HashMap hashMap = new HashMap(); hashMap.put("id",user.getId()); hashMap.put("data",user.getData()); return hashMap; } }
启动类
@SpringBootApplication public class DemoApp { public static void main(String[] args) { SpringApplication.run(DemoApp.class,args); } }
发送请求:
结果:
这是因为@DateTimeFormat只能处理后端到前端阶段(出参),而我们前端到后端的阶段并没有进行处理。所以我们需要加上入参(前端到后端的处理过程)
当然,如果你只需要前端到后端的部分则可以只用@JsonFormat这个注解即可
2、加上@JsonFormat注解
将User实体类改为:
@Data public class User { private int id; @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") private Date data; }
此时重新访问,此时返回处理过的String类型的日期
注意:2020-01-01T03:11:11.000+0000 :以+0000结尾,此时需要加上8个小时(中国时区(东8区)和标准世界时间(0区)的相差8小时)
如果是2020-01-01T03:11:11.000+0800:以+0800结尾,此时表示已经是中国时区(东8区了),则不用再做换算。
此时后端控制台,打印了前端的String转化为Data后的日期值
shuo
此时前后端的日期格式则都设置完成了
这里网上的人可以直接得到一个这样格式的值,而我自己做出来的确是。说实在的不知道是网上的人抄来抄去,还是我自己写错了。这个等我之后再验证
2、使用配置文件进行配置(全局配置)
此时不用@DateTimeFormat+@JsonFormat注解,直接在yml中加上下面配置:
#时间戳统一转换 spring: jackson: date-format: yyyy-MM-dd HH:mm:ss time-zone: GMT+8
结果:
此时前端传来的和后端传到前端的都是处理好的了,连前端的+8小时的都不用处理了。
3、自定义格式转换器
自定义全局日期转换器可以参考:https://www.jb51.net/article/181873.htm
4、当加入数据库这个环节
4.1、概述
为什么要加入数据库这个环节?
因为数据库的data类型数据也会存在时区的问题。
例如:
jdbc:mysql://localhost:3306/food?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=Asia/Shanghai(东8区,中国的时区)
和
jdbc:mysql://localhost:3306/food?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=UTC (0区,世界标准时区)
由于时区问题,查出来的数据是相差8个小时的。后者在数据库拿到数据后会在小时上+8个小时。对于UTC、CST、GTM的概念可以网上百度。
而如果我们设置为Asia/Shanghai中国时区,则插入数据库时不会减掉8个小时,从数据库拿时不会加上8小时。
因为UTC是世界标准时间,而中国时区和标准时间相差8小时,所以这里设置数据库时区在插入查询时会根据不同的时区进行加减8小时(数据库是UTC,而我们项目设置了是GTM+8即中国时区设置为东八区)
所以在和数据库进行日期交互的时候要注意时区问题。
https://blog.csdn.net/baidu_38837718/article/details/104981617
而对于数据库的日期类型:
Mysql中经常用来存储日期的数据类型有三种:Date、Datetime、Timestamp。
【1】Date数据类型:用来存储没有时间的日期。Mysql获取和显示这个类型的格式为“YYYY-MM-DD”。支持的时间范围为“1000-00-00”到“9999-12-31”。
【2】Datetime类型:存储既有日期又有时间的数据。存储和显示的格式为 “YYYY-MM-DD HH:MM:SS”。支持的时间范围是“1000-00-00 00:00:00”到“9999-12-31 23:59:59”。
【3】Timestamp类型:也是存储既有日期又有时间的数据。存储和显示的格式跟Datetime一样。支持的时间范围是“1970-01-01 00:00:01”到“2038-01-19 03:14:07”。1、数据库中,如果使用datatime类型的日期,这是这个日期是不存储时区信息的,如果需要可以加上时区的字段。
2、data则精度只到年月日没有时分秒
3、Timestamp:和datatime类似,就是范围不同。
4.2、加入数据库后(这里使用配置文件进行配置时间类型的转换)
数据库,建立一个user数据库,字段为id——int ;data——datatime
yml
server: port: 10083 #时间戳统一转换 spring: jackson: date-format: yyyy-MM-dd HH:mm:ss time-zone: GMT+8 #设置为东八区 datasource: driver-class-name: com.mysql.cj.jdbc.Driver password: 123456 url: jdbc:mysql://localhost:3306/food?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=Asia/Shanghai username: root mybatis: mapper-locations: classpath:mappers/*.xml
pojo:
@Data public class User { private int id; private Date data; }
dao:
@Mapper public interface UserMapper { User Sel(int id); int ins(User user); }
xml:
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.spring.dao.UserMapper"> <select id="Sel" resultType="com.spring.pojo.User"> select * from user where id = #{id} </select> <insert id="ins" parameterType="com.spring.pojo.User"> INSERT INTO user (id,data) VALUES (#{id},#{data}) </insert> </mapper>
controller:这里就不写service层了
@RestController public class BeanController { @Autowired UserMapper userMapper; @GetMapping("abc") public User usersel(){ User sel = userMapper.Sel(1); return sel; } @PostMapping("data") public Map data(@RequestBody User user){ userMapper.ins(user); System.out.println(user); HashMap hashMap = new HashMap<String,Object>(); hashMap.put("id",user.getId()); hashMap.put("data",user.getData()); return hashMap; } }
启动类:
@MapperScan("com.spring.dao") //扫描的mapper @SpringBootApplication public class DemoApp { public static void main(String[] args) { SpringApplication.run(DemoApp.class,args); } }
启动调用
此时插入正常。
此时查询也正常
该案例需要注意的是数据库时区的选择。
偶吃鸡蛋饼: 这俩效率都没有ConcurrentHashMap高
哈基米,哈基米: explain select (select 1 from actor where id = 1) from (select * from film where id = 1) der; 这么骚?
清风步月: 您好博主,我看了半天registerBeanDefinitionForImportedConfigurationClass(configClass)这个方法都应该是注册成Bean而不是实例化Bean吧?他这个方法的名字也是注册啊。再者,后面结论中import进来的类也并非在invokeBeanFactoryPostProcessors中实例化啊,要不您在测试一下,又或许是我哪里没弄懂?
江湖人称小学生: 您好,这张图,原图可以分享吗
征途黯然.: 图文并茂请解的很清晰透彻,支持优质好文