Springboot global date format processing, a bit fragrant!

Posted May 26, 20206 min read

This article is included in the personal blog: http://www.chengxy-nds.top , which aims to share technical information and learn and progress together

Recently, several colleagues in the department have suffered some grievances and have resigned. They have been reluctant to leave after working for three years. After all the procedures have been completed, they are sent out of the company after the greeting. There is a bad hunch in my heart, this is definitely not so simple. After I took over the projects of these big brothers, I fulfilled my hunch. At this moment, I actually regret it a little bit, why didn't I beat them when I said goodbye! Hahaha ~ And this impulse to beat people became more and more intense when I started to optimize the projects of several brothers.

Insert picture description here

There is a pit

The technical department organizes the code walk-through and optimization every month. Previously, they reviewed and optimized their own projects, but now the projects of several older brothers have fallen on my head. The most painful thing for programmers is to take over other people's projects, but also to do optimization and transformation, because this is no simpler than refactoring the project. However, with the military order ahead, there is no way to put it on your head!

The first optimization point made me a little bit crashed. The skills of these big guys are very strong, and they have always been my role models. However, almost all date formatting in the project uses SimpleDateFormat like this, like the following The code is implemented in this way, emm ~, how can the injured man do everything, hahaha ~

SvcOrderDailyStatisticsPo orderDailyStatisticsPo = new SvcOrderDailyStatisticsPo();
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
Date stationTime = dateFormat.parse(dateFormat.format(svcWorkOrderPo.getPayEndTime()));
orderDailyStatisticsPo.setStatisticalDate(stationTime);

Moreover, the time and date APIs in the project are also confusing. Considering that java.util.Date and java.util.Calendar do not support time zones and are not thread safe, the calculation of dates is relatively cumbersome and the technical department is consistent It is required to use java.time`` LocalDateTime after JDK1.8. But many people still use java.util.Date and java.util.Calendar to process dates.

Optimization

Time formatting is very frequently used. How to make time formatting simple and without reinventing the wheel, then it should be abstracted out as a global date formatting process. The following is a brief introduction to the following types in combination with practice Optimization.

Test address:http://127.0.0.1:8080/timeTest

@GetMapping("/timeTest")
    public OrderInfo timeTest() {
        OrderInfo order = new OrderInfo();
        order.setCreateTime(LocalDateTime.now());
        order.setUpdateTime(new Date());
        return order;
    }
1. @JsonFormat annotation

Using @ JsonFormat annotation to format time should be regarded as a basic operation. Most developers use this method, which is simple and convenient.

/**
* @Author:xiaofu
* @Description:
* /
public class OrderInfo {

    @JsonFormat(locale = "zh", timezone = "GMT + 8", pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime createTime;

    @JsonFormat(locale = "zh", timezone = "GMT + 8", pattern = "yyyy-MM-dd HH:mm:ss")
    private Date updateTime;

    public LocalDateTime getCreateTime() {
        return createTime;
    }

    public void setCreateTime(LocalDateTime createTime) {
        this.createTime = createTime;
    }

    public Date getUpdateTime() {
        return updateTime;
    }

    public void setUpdateTime(Date updateTime) {
        this.updateTime = updateTime;
    }
}

Test the results and find that both the Date type and the LocalDateTime type are formatted successfully, but there is still a problem. This is still relatively cumbersome. The date field of each entity class must be annotated with @ JsonFormat. Duplicate work The amount is not small. Then look down ~
Insert picture description here

2. Global configuration(1)

Springboot has provided us with the date format${spring.jackson.date-format:yyyy-MM-dd HH:mm:ss}, here we need to perform global configuration, the configuration is relatively simple, and there is no need to be in the entity Add the @JsonFormat annotation to the class properties.

/**
* @Author:xiaofu
* @Description:
* /
public class OrderInfo {

    //@ JsonFormat(locale = "zh", timezone = "GMT + 8", pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime createTime;

    //@ JsonFormat(locale = "zh", timezone = "GMT + 8", pattern = "yyyy-MM-dd HH:mm:ss")
    private Date updateTime;

    public LocalDateTime getCreateTime() {
        return createTime;
    }

    public void setCreateTime(LocalDateTime createTime) {
        this.createTime = createTime;
    }

    public Date getUpdateTime() {
        return updateTime;
    }

    public void setUpdateTime(Date updateTime) {
        this.updateTime = updateTime;
    }
}

You only need to define a configuration class with @ Configuration and inject two Beans to complete the global date formatting process. This method is also currently used in my project.

/**
* @Author:xiaofu
* @Description:
* /
@Configuration
public class LocalDateTimeSerializerConfig {

    @Value("${spring.jackson.date-format:yyyy-MM-dd HH:mm:ss}")
    private String pattern;

    @Bean
    public LocalDateTimeSerializer localDateTimeDeserializer() {
        return new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(pattern));
    }

    @Bean
    public Jackson2ObjectMapperBuilderCustomizer jackson2ObjectMapperBuilderCustomizer() {
        return builder-> builder.serializerByType(LocalDateTime.class, localDateTimeDeserializer());
    }
}

This way can support the coexistence of Date type and LocalDateTime type, then there is a problem that the global time format is now yyyy-MM-dd HH:mm:ss, but some fields need yyyy-MM- What is the format of dd?

Then you need to use it with the @ JsonFormat annotation. You can add the @ JsonFormat annotation in a specific field attribute. Because the @ JsonFormat annotation has a higher priority, the time format marked by the @@ sonson annotation will be the main one.

3. Global configuration(2)

The implementation of this global configuration is the same as the effect above, but it should be noted that after using this configuration, the field manual configuration @ JsonFormat` annotation will no longer take effect.

/**
* @Author:xiaofu
* @Description:
* /
public class OrderInfo {

    //@ JsonFormat(locale = "zh", timezone = "GMT + 8", pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime createTime;

    //@ JsonFormat(locale = "zh", timezone = "GMT + 8", pattern = "yyyy-MM-dd HH:mm:ss")
    private Date updateTime;

    public LocalDateTime getCreateTime() {
        return createTime;
    }

    public void setCreateTime(LocalDateTime createTime) {
        this.createTime = createTime;
    }

    public Date getUpdateTime() {
        return updateTime;
    }

    public void setUpdateTime(Date updateTime) {
        this.updateTime = updateTime;
    }
}

/**
* @Author:xiaofu
* @Description:
* /
@Configuration
public class LocalDateTimeSerializerConfig {

    @Value("${spring.jackson.date-format:yyyy-MM-dd HH:mm:ss}")
    private String pattern;

    @Bean
    @Primary
    public ObjectMapper serializingObjectMapper() {
        ObjectMapper objectMapper = new ObjectMapper();
        JavaTimeModule javaTimeModule = new JavaTimeModule();
        javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer());
        javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer());
        objectMapper.registerModule(javaTimeModule);
        return objectMapper;
    }

    public class LocalDateTimeSerializer extends JsonSerializer <LocalDateTime> {
        @Override
        public void serialize(LocalDateTime value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
            gen.writeString(value.format(ofPattern(pattern)));
        }
    }

    public class LocalDateTimeDeserializer extends JsonDeserializer <LocalDateTime> {
        @Override
        public LocalDateTime deserialize(JsonParser p, DeserializationContext deserializationContext) throws IOException {
            return LocalDateTime.parse(p.getValueAsString(), ofPattern(pattern));
        }
    }
}

to sum up

I shared a little trick in the development process of the Springboot project, and I also talk about the pits encountered in the optimization of the project. Although optimizing the code of other people is a relatively painful thing, I can really learn in this process. To many skills, it is also very helpful for the improvement of personal skills, because they are all dry goods that can really improve the development efficiency.