SpringBoot--LocalDateTime格式转换(响应给前端)

原文网址:SpringBoot--LocalDateTime格式转换(响应给前端)_IT利刃出鞘的博客-CSDN博客

简介

说明

项目我们经常会有前后端时间转换的场景,比如:创建时间、更新时间等。一般情况下,前后端使用时间戳或者年月日的格式进行传递。

如果后端收到了前端的参数每次都手动转化为想要的格式,后端每次将数据传给前端时都手动处理为想要的格式实在是太麻烦了。

基于如上原因,本文用示例介绍SpringBoot全局格式配置,将LocalDateTime自动转化为想要的格式传给前端。

相关网址

SpringBoot--LocalDateTime格式转换(前端入参)_IT利刃出鞘的博客-CSDN博客

备注

有人说,可以这样配置:

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

  • 这种配置只适用于Date这种,不适用于LocalDateTime等。
  • LocalDateTime序列化/反序列化时默认格式为:"2020-08-19T16:30:18.823"。

时间戳格式

方案1:自定义序列化器(局部)

简介

本法只能用于将数据转为时间戳响应给前端,无法自动解析前端传进来的时间戳(无论是直接接收还是通过实体类接收都不行)。

        此方法不仅仅可以用于返给前端数据,也可以用于后端的转换:使用jackson的ObjectMapper().writeValueAsString方法将对象转为json字符串。而下边的全局配置就不可以。

配置类

package com.example.config;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;

import java.io.IOException;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;

public class LocalDateTimeConfig {
    // 序列化实现
    public static class LocalDateTimeSerializer extends JsonSerializer<LocalDateTime> {
        @Override
        public void serialize(LocalDateTime value, JsonGenerator gen, SerializerProvider serializers)
                throws IOException {
            if (value != null) {
                long timestamp = value.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
                gen.writeNumber(timestamp);
            }
        }
    }

    // 反序列化实现
    public static class LocalDateTimeDeserializer extends JsonDeserializer<LocalDateTime> {
        @Override
        public LocalDateTime deserialize(JsonParser p, DeserializationContext deserializationContext)
                throws IOException {
            long timestamp = p.getValueAsLong();
            if (timestamp > 0) {
                return LocalDateTime.ofInstant(Instant.ofEpochMilli(timestamp), ZoneId.systemDefault());
            } else {
                return null;
            }
        }
    }
}

Entity

package com.example.business.entity;

import com.example.config.LocalDateTimeConfig;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import lombok.AllArgsConstructor;
import lombok.Data;

import java.time.LocalDateTime;

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

    private String userName;

    @JsonSerialize(using = LocalDateTimeConfig.LocalDateTimeSerializer.class)
    private LocalDateTime createTime;
}

Controller

package com.example.business.controller;

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

import java.time.LocalDateTime;

@RestController
@RequestMapping("user")
public class UserController {
    @GetMapping("getUser")
    public User getUser() {
        return new User(null, "Tony", LocalDateTime.now());
    }
}

测试

postman访问:http://localhost:8080/user/getUser 

postman结果:

注意:本法只能用于将数据转为时间吹响应给前端,无法自动解析前端传进来的时间戳。示例如下:

代码

package com.example.business.entity;

import com.example.config.LocalDateTimeConfig;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import lombok.AllArgsConstructor;
import lombok.Data;

import java.time.LocalDateTime;

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

    private String userName;

    @JsonSerialize(using = LocalDateTimeConfig.LocalDateTimeSerializer.class)
    @JsonDeserialize(using = LocalDateTimeConfig.LocalDateTimeDeserializer.class)
    private LocalDateTime createTime;
}
package com.example.business.controller;

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

import java.time.LocalDateTime;

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

测试

postman访问:http://localhost:8080/user/save?userName=Tony&createTime=1631790000

postman结果:

后端结果: 

2021-09-16 19:41:26.855  WARN 93488 --- [nio-8080-exec-1] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.validation.BindException: org.springframework.validation.BeanPropertyBindingResult: 1 errors
Field error in object 'user' on field 'createTime': rejected value [1631790000]; codes [typeMismatch.user.createTime,typeMismatch.createTime,typeMismatch.java.time.LocalDateTime,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [user.createTime,createTime]; arguments []; default message [createTime]]; default message [Failed to convert value of type 'java.lang.String[]' to required type 'java.time.LocalDateTime'; nested exception is org.springframework.core.convert.ConversionFailedException: Failed to convert from type [java.lang.String] to type [@com.fasterxml.jackson.databind.annotation.JsonSerialize @com.fasterxml.jackson.databind.annotation.JsonDeserialize java.time.LocalDateTime] for value '1631790000'; nested exception is java.lang.IllegalArgumentException: Parse attempt failed for value [1631790000]]]

方案2:配置ObjectMapper(全局)

上边是本文的部分内容,为便于维护,全文已转移到此网址:SpringBoot–全局处理LocalDateTime响应格式(时间戳) - 自学精灵

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

IT利刃出鞘

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值