使用这个的是由于后端的id是使用的长整型(long)存储的,但是由于js的原因会导致精度丢失
例如下面:
出参类型定义:
模拟查询得到的返回参数
调用接口结果:发现id后面的几位没了,并且日期的格式也不是我们想要的
这种情况一般来说是会将这长整型转换成String给到前端,前端请求的时候再将String的转换成long类型(这个Spring框架会为我们去自动类型处理的,不合法的格式会报错)
因此涉及到了Spring 中的消息转换器,有两种配置方法
第一种:
注入一个HttpMessageConverters 的自定义bean到Spring 容器
package com.example.household_supplies.config;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
@Configuration
public class HttpMessageConvertersConfiguration {
@Bean
public HttpMessageConverters customConverters() {
MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter = new MappingJackson2HttpMessageConverter();
ObjectMapper objectMapper = new ObjectMapper();
SimpleModule simpleModule = new SimpleModule();
//JSON Long ==> String
simpleModule.addSerializer(Long.class, ToStringSerializer.instance);
simpleModule.addSerializer(BigInteger.class, ToStringSerializer.instance);
// date 格式化(不需要的话可以删除这一行)
simpleModule.addSerializer(Date.class, new DateFormatSerializer());
objectMapper.registerModule(simpleModule);
mappingJackson2HttpMessageConverter.setObjectMapper(objectMapper);
//设置中文编码格式
List<MediaType> list = new ArrayList<MediaType>();
list.add(MediaType.APPLICATION_JSON);
mappingJackson2HttpMessageConverter.setSupportedMediaTypes(list);
return new HttpMessageConverters(new HttpMessageConverter[]{mappingJackson2HttpMessageConverter});
}
}
配置后实现的效果:
第二种:
配置Spring Mvc config
package com.example.household_supplies.config;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import java.util.Date;
import java.util.List;
@Configuration
@EnableWebMvc // 如果使用第一种这个注解一定需要去除掉
public class SpringWebMvcConfig implements WebMvcConfigurer {
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
ObjectMapper objectMapper = new ObjectMapper();
SimpleModule simpleModule = new SimpleModule();
// 长整型系列化器ToStringSerializer
simpleModule.addSerializer(Long.TYPE, ToStringSerializer.instance);
simpleModule.addSerializer(Long.class, ToStringSerializer.instance);
// 日期类型的处理(不需要的话可以删除这一行)
simpleModule.addSerializer(Date.class, new DateFormatSerializer());
objectMapper.registerModule(simpleModule);
converter.setObjectMapper(objectMapper);
converters.add(converter);
}
}
配置后实现的效果:
上面的配置里面有我自定义的date类型的序列化器DateFormatSerializer 会将所有的date类型都转换为"yyyy-MM-dd"格式,根据自己需求即可
package com.example.household_supplies.config;
import cn.hutool.core.date.DateUtil;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import java.io.IOException;
import java.util.Date;
/**
* @ClassName DateFormatSerializer
* @Description TODO
* @Author Wang Li Hong
* @date 2024/1/12 18:02
* @Version 1.0
*/
public class DateFormatSerializer extends JsonSerializer<Date> {
@Override
public void serialize(Date date, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
if (date != null) {
String format = DateUtil.format(date, "yyyy-MM-dd");
jsonGenerator.writeString(format);
}
}
}
总结:
上面的两种方法都可以实现统一对我们返回的参数做转换,例如我们需要将长整型(long、bigint)返回给前端存在精度丢失,然后我们可以把他转换为String类型给前端。或者某些场景,前端的日期格式都为某一个统一的格式,也可以在这里配置。
我个人更推荐第一种吧,因为第二种方式是配置了内置的消息转换器,似乎会有一些不可预料的问题。
目前出现了openapi报错的问题(已经确认了是Spring Mvc配置消息转换器导致的,我注掉这段配置就正常了)
并且遇到了一些其他的基础类型的默认转换器不存在导致以前的也不行了的问题,可以添加一些内置的Model去处理,但是并不全面。所以第一种可能影响较小吧
有错误的话,感谢指正!