SpringBoot--LocalDateTime--Global format conversion / front-end input parameters

Original URL: SpringBoot--LocalDateTime--Global format conversion / front-end input parameters

Introduction

illustrate

        In projects, we often have scenarios where the front-end and back-end time are converted, such as creation time, update time, etc. In general, the front-end and back-end are passed in the format of timestamp or year-month-day.

        If the back-end receives the parameters of the front-end and manually converts it into the desired format every time, it is too troublesome for the back-end to manually process the data into the desired format every time it transmits data to the front-end.

        Based on the above reasons, this article uses an example to introduce the SpringBoot global format configuration, and automatically convert the time passed from the front end to LocalDateTime. (This article only introduces the conversion method of year-month-day format, for example: 2021-09-16 21:13:21 => LocalDateTime. The method of converting timestamp to LocalDateTime is similar).

Program introduction

There are two scenarios to configure (depending on Content-Type ):

  1. application/x-www-form-urlencoded 和 multipart/form-data
    1. This case is recorded here as: do not use @RequestBody
  2. application/json
    1. ie: interface using @RequestBody
    2. This case is recorded here as: use @RequestBody

Remark

Some people say that it can be configured like this:

spring:
  jackson:
    date-format: yyyy-MM-dd HH:mm:ss
    time-zone: GMT+8
    serialization:
      write-dates-as-timestamps: false

This configuration only applies to Date, not LocalDateTime, etc.
This format is used for Date serialization/deserialization: "2020-08-19T16:30:18.823+00:00".

Not using @RequestBody

Option 1: @ControllerAdvice+@InitBinder

configuration class

package com.example.config;

import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.InitBinder;

import java.beans.PropertyEditorSupport;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;

@ControllerAdvice
public class LocalDateTimeAdvice {
    @InitBinder
    protected void initBinder(WebDataBinder binder) {
        binder.registerCustomEditor(LocalDateTime.class, new PropertyEditorSupport() {
            @Override
            public void setAsText(String text) throws IllegalArgumentException {
                setValue(LocalDateTime.parse(text, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
            }
        });

        binder.registerCustomEditor(LocalDate.class, new PropertyEditorSupport() {
            @Override
            public void setAsText(String text) throws IllegalArgumentException {
                setValue(LocalDate.parse(text, DateTimeFormatter.ofPattern("yyyy-MM-dd")));
            }
        });

        binder.registerCustomEditor(LocalTime.class, new PropertyEditorSupport() {
            @Override
            public void setAsText(String text) throws IllegalArgumentException {
                setValue(LocalTime.parse(text, DateTimeFormatter.ofPattern("HH:mm:ss")));
            }
        });
    }
}

Entity

package com.example.business.entity;

import lombok.AllArgsConstructor;
import lombok.Data;

import java.time.LocalDateTime;

@Data
@AllArgsConstructor
public class User {
    private Long id;

    private String userName;

    private LocalDateTime createTime;
}

Controller

package com.example.business.controller;

import com.example.business.entity.User;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("user")
public class UserController {
    @PostMapping("save")
    public User save(User user) {
        System.out.println("保存用户:" + user);
        return user;
    }
}

test

postman访问:http://localhost:8080/user/save?userName=Tony&createTime=2021-09-16 21:13:21

postman result:

Backend result:

Option 2: Custom parameter converter (Converter)

Implement org.springframework.core.convert.converter.Converter, a custom parameter converter.

configuration class

package com.example.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.convert.converter.Converter;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

@Configuration
public class LocalDateTimeConfig {

    @Bean
    public Converter<String, LocalDateTime> localDateTimeConverter() {
        return new LocalDateTimeConverter();
    }

    public static class LocalDateTimeConverter implements Converter<String, LocalDateTime> {
        @Override
        public LocalDateTime convert(String s) {
            return LocalDateTime.parse(s, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        }
    }
}

Entity

package com.example.business.entity;

import lombok.AllArgsConstructor;
import lombok.Data;

import java.time.LocalDateTime;

@Data
@AllArgsConstructor
public class User {
    private Long id;

    private String userName;

    private LocalDateTime createTime;
}

Controller

package com.example.business.controller;

import com.example.business.entity.User;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("user")
public class UserController {
    @PostMapping("save")
    public User save(User user) {
        System.out.println("保存用户:" + user);
        return user;
    }
}

test

postman访问:http://localhost:8080/user/save?userName=Tony&createTime=2021-09-16 21:13:21

postman result:

backend result

Use @RequestBody

Scenario 1: Configure ObjectMapper

Method 1: Use only configuration classes

This method only needs to configure ObjectMapper, Entity does not need to add @JsonFormat.

configuration class

package com.example.common.config;

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.deser.std.DateDeserializers;
import com.fasterxml.jackson.databind.ser.std.DateSerializer;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;
import lombok.SneakyThrows;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.Date;

@Configuration
public class JackSonConfig {
    @Bean
    public ObjectMapper ObjectMapper() {
        ObjectMapper objectMapper = new ObjectMapper();
        JavaTimeModule javaTimeModule = new JavaTimeModule();

        // 序列化
        javaTimeModule.addSerializer(
                LocalDateTime.class,
                new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        javaTimeModule.addSerializer(
                LocalDate.class,
                new LocalDateSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
        javaTimeModule.addSerializer(
                LocalTime.class,
                new LocalTimeSerializer(DateTimeFormatter.ofPattern("HH:mm:ss")));
        javaTimeModule.addSerializer(
                Date.class,
                new DateSerializer(false, new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")));

        // 反序列化
        javaTimeModule.addDeserializer(
                LocalDateTime.class,
                new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        javaTimeModule.addDeserializer(
                LocalDate.class,
                new LocalDateDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
        javaTimeModule.addDeserializer(
                LocalTime.class,
                new LocalTimeDeserializer(DateTimeFormatter.ofPattern("HH:mm:ss")));
        javaTimeModule.addDeserializer(Date.class, new DateDeserializers.DateDeserializer(){
            @SneakyThrows
            @Override
            public Date deserialize(JsonParser jsonParser, DeserializationContext dc){
                String text = jsonParser.getText().trim();
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                return sdf.parse(text);
            }
        });

        objectMapper.registerModule(javaTimeModule);
        return objectMapper;
    }

}

Entity

package com.example.business.entity;

import lombok.Data;

import java.time.LocalDateTime;

@Data
public class User {
    private Long id;

    private String userName;

    private LocalDateTime createTime;
}

Controller

package com.example.business.controller;

import com.example.business.entity.User;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("user")
public class UserController {
    @PostMapping("save")
    public User save(@RequestBody User user) {
        System.out.println("保存用户:" + user);
        return user;
    }
}

test

backend result

保存用户:User(id=null, userName=Tony, createTime=2021-09-16T21:13:21)

Method 2: Configuration class + @JsonFormat

This method needs to configure ObjectMapper, and Entity also needs to add @JsonFormat.

configuration class

package com.example.common.config;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.module.paramnames.ParameterNamesModule;
import org.springframework.boot.jackson.JsonComponent;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class JacksonConfig {

    @Bean
    public ObjectMapper serializingObjectMapper() {
        ObjectMapper objectMapper = new ObjectMapper();
        // 自动扫描并注册相关模块
        objectMapper.findAndRegisterModules();

        // 手动注册相关模块
        // objectMapper.registerModule(new ParameterNamesModule());
        // objectMapper.registerModule(new Jdk8Module());
        // objectMapper.registerModule(new JavaTimeModule());
        return objectMapper;
    }

}

Entity

package com.example.business.entity;

import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;

import java.time.LocalDateTime;

@Data
public class User {
    private Long id;

    private String userName;

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

Controller

package com.example.business.controller;

import com.example.business.entity.User;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("user")
public class UserController {
    @PostMapping("save")
    public User save(@RequestBody User user) {
        System.out.println("保存用户:" + user);
        return user;
    }
}

test

backend result

保存用户:User(id=null, userName=Tony, createTime=2021-09-16T21:13:21)

Guess you like

Origin blog.csdn.net/feiying0canglang/article/details/123967073