zoukankan      html  css  js  c++  java
  • 【SpringBoot】SpringBoot 处理后端返回的小数(全局配置 + 定制化配置)

    一.抛出问题:

      现在的项目中,存在这样的几个问题:

        问题一.数据库存的数据类型是BigDecimal,或者代码中计算需要返回BigDecimal的值,由于BigDecimal返回给前端可能存在精度丢失情况

        问题二.BigDecimal再后台计算后,通常需要保留两位小数或者三位小数返回给前端,每个数据都需要处理,代码太过于冗余;

    二.解决方式:

      问题一的解决方案:

        使用全局的序列化配置,统一将BigDecimal的数据类型转换为String类型,前端将String解析为小数即可;

        代码如下

        

    package com.gabriel.stage.config;
    
    import com.fasterxml.jackson.databind.DeserializationFeature;
    import com.fasterxml.jackson.databind.ObjectMapper;
    import com.fasterxml.jackson.databind.module.SimpleModule;
    import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
    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 com.google.common.collect.ImmutableList;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.http.MediaType;
    import org.springframework.http.converter.HttpMessageConverter;
    import org.springframework.http.converter.StringHttpMessageConverter;
    import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
    import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
    
    import java.math.BigDecimal;
    import java.math.BigInteger;
    import java.nio.charset.StandardCharsets;
    import java.time.LocalDate;
    import java.time.LocalDateTime;
    import java.time.LocalTime;
    import java.time.format.DateTimeFormatter;
    import java.util.List;
    
    /**
     * @author Gabriel
     * @date 2020-01-08
     * @description  自定义SpringMvc转换器 解决数据转换问题(例如BigDecimal转换为String,解决精度问题)
     * 注意:springboot2.x以后继承 WebMvcConfigurationSupport 会覆盖"所有的WebMvc默认的配置,比如WebMvcConfigure",因此不推荐该中方法
     */
    //@Configuration
    public class WebMvcConfig extends WebMvcConfigurationSupport {
    
    
        /**
         * Date格式化字符串
         */
        private static final DateTimeFormatter DATE_FORMAT = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        /**
         * DateTime格式化字符串
         */
        private static final DateTimeFormatter DATETIME_FORMAT = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        /**
         * Time格式化字符串
         */
        private static final DateTimeFormatter TIME_FORMAT = DateTimeFormatter.ofPattern("HH:mm:ss");
    
        @Override
        public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
            super.configureMessageConverters(converters);
            final MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
            ObjectMapper objectMapper = converter.getObjectMapper();
    
            // 反序列化失败
            objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    
            // long 转换为字符串
            SimpleModule simpleModule = new SimpleModule();
            simpleModule.addSerializer(BigInteger.class, ToStringSerializer.instance);
            simpleModule.addSerializer(Long.class, ToStringSerializer.instance);
            simpleModule.addSerializer(Long.TYPE, ToStringSerializer.instance);
    
            // 浮点型使用字符串
            simpleModule.addSerializer(Double.class, ToStringSerializer.instance);
            simpleModule.addSerializer(Double.TYPE, ToStringSerializer.instance);
            simpleModule.addSerializer(BigDecimal.class, ToStringSerializer.instance);
    
            // java8 时间格式化
            simpleModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DATETIME_FORMAT));
            simpleModule.addSerializer(LocalDate.class, new LocalDateSerializer(DATE_FORMAT));
            simpleModule.addSerializer(LocalTime.class, new LocalTimeSerializer(TIME_FORMAT));
    
            objectMapper.registerModule(simpleModule);
    
            // 为mapper注册一个带有SerializerModifier的Factory,处理null值
            objectMapper.setSerializerFactory(objectMapper.getSerializerFactory()
                    //CustomizeBeanSerializerModifier 自定义序列化修改器
                    .withSerializerModifier(new CustomizeBeanSerializerModifier()));
    
            // 处理中文乱码问题
            converter.setSupportedMediaTypes(ImmutableList.of(MediaType.APPLICATION_JSON_UTF8));
    
            converter.setObjectMapper(objectMapper);
            converters.add(converter);
            converters.add(new StringHttpMessageConverter(StandardCharsets.UTF_8));
        }
    }

      问题二的解决方案:

        自定义序列器,使用  @JsonSerialize(using = 自定义序列化器类.class)去序列化指定的属性

        代码如下

    package com.in.g.data.config;
    
    import com.fasterxml.jackson.core.JsonGenerator;
    import com.fasterxml.jackson.core.JsonProcessingException;
    import com.fasterxml.jackson.databind.JsonSerializer;
    import com.fasterxml.jackson.databind.SerializerProvider;
    
    import java.io.IOException;
    import java.math.BigDecimal;
    
    /**
     * @author: Gabriel
     * @date: 2020/3/7 15:28
     * @description 小数保留2位返回给前端序列化器
     */
    public class Decimal2Serializer extends JsonSerializer<Object> {
    
        /**
         * 将返回的BigDecimal保留两位小数,再返回给前端
         * @param value
         * @param jsonGenerator
         * @param serializerProvider
         * @throws IOException
         * @throws JsonProcessingException
         */
        @Override
        public void serialize(Object value, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException, JsonProcessingException {
            if (value != null) {
                BigDecimal bigDecimal = new BigDecimal(value.toString()).setScale(2,BigDecimal.ROUND_HALF_UP);
                jsonGenerator.writeString(bigDecimal.toString());
            }
        }
    }
    package com.gabriel.stage.vo;
    
    import com.fasterxml.jackson.databind.annotation.JsonSerialize;
    import com.gabriel.stage.config.Decimal2Serializer;
    import lombok.Data;
    
    import java.math.BigDecimal;
    
    /**
     * @author: Gabriel
     * @date: 2020/3/7 15:45
     * @description
     */
    @Data
    public class TestVO {
    
        @JsonSerialize(using = Decimal2Serializer.class)
        private BigDecimal bigDecimal;
    }

      

  • 相关阅读:
    管理员技术(三): 配置静态网络地址、 使用yum软件源 、 升级Linux内核、查找并处理文件、查找并提取文件内容
    管理员技术(二): 访问练习用虚拟机、 命令行基础技巧 、 挂载并访问光盘设备、ls列表及文档创建、复制删除移动
    管理员技术(一):装机预备技能、安装一台RHEL7虚拟机、使用RHEL7图形桌面、Linux命令行基本操作
    基础(三):yum(RedHat系列)和apt-get(Debian系列 )用法及区别
    基础(二):Linux系统/etc/init.d目录和/etc/rc.local脚本
    基础(一):SCSI硬盘与IDE硬盘有什么区别
    高级运维(六):源码安装Redis缓存服务、常用Redis数据库操作指令、配置Redis主从服务器
    错题
    count 【mysql】
    自连接和子查询
  • 原文地址:https://www.cnblogs.com/july-sunny/p/12434937.html
Copyright © 2011-2022 走看看