写项目遇到的通用问题
时间类型不一致的问题 前端得到后端的时间数据相差了16个小时 存放进数据库的时间发现与当前系统时间相差了8个小时
这些问题都是时区的问题 对于Java中时区有4个 UTC GMT CSA Asia/shanghai 要知道UTC GMT 和东8区都是有8个小时的时差的。
首先,存放入数据库的时间与当前系统时间相差8个小时,是因为MySQL这些中间件大多默认的是UTC,然后再Java中用new Date(),获取的时间是由当前系统决定的,所以有8个小时的时差,解决方案就是去修改中间件的时区,这里提供的方法是修改配置信息,这里用的是docker容器,且使用了数据卷,所以直接进入mysql的数据卷,在_data目录下新建一个目录,目录名可以随便取,但是后缀必须是.cnf。
接着,由于后端在返回给前端数据时一般用到序列化,然而直接用springboot的默认序列化,采用的也是UTC,所以也有8个时差,加起来前端就16个小时的时差,所以要解决springboot的序列化问题,有三种方式:第一种加注解@JsonFormat 用里面的2个属性值 timezone=GWT+8 这里必须是GWT+8 不能写UTC+8,这是规定,不然识别不了,虽然这2者在数值上差不多;第二种方式是在配置文件里面写,提高复用性,第三种方式就是自定义序列化器 实现这个接口。
package com.atguigu.tingshu.common.config.date;import com.atguigu.tingshu.common.execption.GuiguException;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.deser.std.DateDeserializers;
import com.fasterxml.jackson.databind.ser.std.DateSerializer;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
import org.springframework.stereotype.Component;import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;
import java.util.logging.SimpleFormatter;/*** ClassName: CustomerDateHandler* Package: com.atguigu.tingshu.common.config.date* Description:** @Author 陈宇侨* @Create 2025/5/11 15:05* @Version 1.0*/
@Component
public class CustomerDateHandler implements Jackson2ObjectMapperBuilderCustomizer {@Overridepublic void customize(Jackson2ObjectMapperBuilder jacksonObjectMapperBuilder) {//1.创建时间模版对象JavaTimeModule javaTimeModule = new JavaTimeModule();//2.对时间格式进行序列化javaTimeModule.addSerializer(Date.class,new DateSerializer(){//自定义对时间类型做序列化操作/**** @param value :指的是序列化的对象里面Date类型的字段以及值* @param g :json生成器:用来负责将数据输出到json中去* @param provider :暂时用不到* @throws IOException*/@Overridepublic void serialize(Date value, JsonGenerator g, SerializerProvider provider) throws IOException {
// super.serialize(value, g, provider);// 处理时间时区 处理日期时间格式SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");simpleDateFormat.setTimeZone(TimeZone.getTimeZone("GMT+8"));String format = simpleDateFormat.format(value);g.writeString(format);}});// 对时间格式进行反序列化javaTimeModule.addDeserializer(Date.class,new DateDeserializers.DateDeserializer(){/**** @param p Json的解析器* @param ctxt* @return* @throws IOException*/@Overridepublic Date deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {String text = p.getText();SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");dateFormat.setTimeZone(TimeZone.getTimeZone("GMT+8"));try {Date parseDate = dateFormat.parse(text);return parseDate;} catch (ParseException e) {throw new GuiguException(201,"时间格式不对,无法解析");}}});// 将时间模式注册到builder中jacksonObjectMapperBuilder.modulesToInstall(javaTimeModule);}
}