一.抛出问题:

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

    问题一.数据库存的数据类型是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; 
}

  


本文参考链接:https://www.cnblogs.com/july-sunny/p/12434937.html
评论关闭
IT序号网

微信公众号号:IT虾米 (左侧二维码扫一扫)欢迎添加!