jackson序列化时传入前端Long类型缺失精度问题

无拦截器

因为我们id是Long类型的会存在精度缺失,所以全局转换下


import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;

/**
 * @author baoyuankai
 */
@Configuration
public class JacksonConfig {

    /**
     * Jackson全局转化long类型为String,解决jackson序列化时传入前端Long类型缺失精度问题
     */
    @Bean
    public Jackson2ObjectMapperBuilderCustomizer jackson2ObjectMapperBuilderCustomizer() {
        Jackson2ObjectMapperBuilderCustomizer cunstomizer = new Jackson2ObjectMapperBuilderCustomizer() {
            @Override
            public void customize(Jackson2ObjectMapperBuilder jacksonObjectMapperBuilder) {
                //变成字符串
                jacksonObjectMapperBuilder.serializerByType(Long.class, ToStringSerializer.instance);
            }
        };
        return cunstomizer;
    }

拦截器

/**
 * 自定义请求头拦截器,将Header数据封装到线程变量中方便获取
 * @author 
 */
@Configuration
public class HeaderInterceptor implements AsyncHandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        SecurityContextHolder.setUserId(request.getHeader(SecurityConstants.USER_ID));
        return true;
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
        SecurityContextHolder.remove();
    }
}

/**
 *@Author: 
 *定义日志切面
 */
//@Component
//@Aspect
@Slf4j
public class WebLogAspect {

    // 以 controller 包下定义的所有请求为切入点
    @Pointcut("execution (* com.controllers..*.*(..))")
    public void webLog() {
    }

    @Before("webLog()")
    public void doBefore(JoinPoint joinPoint) throws Throwable {

        // 开始打印请求日志
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();

        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();


        // 打印请求相关参数
        LogUtil.logApplicationInfo("========================================== Start ==========================================");
        // 打印请求 userId
        LogUtil.logApplicationInfo("请求userId        : %s", request.getHeader(SecurityConstants.USER_ID));
        // 打印请求 url
        LogUtil.logApplicationInfo("请求地址        : %s", request.getRequestURL().toString());
        // 打印 Http method
        LogUtil.logApplicationInfo("请求方式        : %s", request.getMethod());
        // 打印调用 controller 的全路径以及执行方法
        LogUtil.logApplicationInfo("请求方法所在路径 : %s.%s", joinPoint.getSignature().getDeclaringTypeName(), joinPoint.getSignature().getName());

        ParameterNameDiscoverer pnd = new DefaultParameterNameDiscoverer();
        String[] keys = pnd.getParameterNames(method);
        Object[] values = joinPoint.getArgs();
        Map<String, Object> paramsMap = new HashMap<>();

        if (values != null) {
            for (int i = 0; i < values.length; i++) {
                if (values[i] instanceof BindingResult ||
                        values[i] instanceof HttpServletRequest ||
                        values[i] instanceof HttpServletResponse ||
                        values[i] instanceof MultipartFile ||
                        values[i] instanceof MultipartFile[]) {
                    continue;
                }
                paramsMap.put(keys[i], values[i]);
            }
        }


        // 打印请求入参
        LogUtil.logApplicationInfo("请求参数        : %s", JSON.toJSONString(paramsMap));

    }

    @Around("webLog()")
    public Object doAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        long startTime = System.currentTimeMillis();

        Object result = proceedingJoinPoint.proceed();
        // 打印出参
        LogUtil.logApplicationInfo("响应参数        : %s", JSON.toJSONString(result));
        // 执行耗时
        LogUtil.logApplicationInfo("响应时间        : %s ms", System.currentTimeMillis() - startTime);
        LogUtil.logApplicationInfo("=========================================== End ===========================================");
        LogUtil.logApplicationInfo("");
        return result;
    }

    @After("webLog()")
    public void doAfter() throws Throwable {
//        ThreadLocalUtil.clear();
//        LogUtil.logApplicationInfo("=========================================== End ===========================================");
        // 每个请求之间空一行
//        LogUtil.logApplicationInfo("");
    }
/**
 * 拦截器配置
 * @author 
 */
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {

    @Autowired
    private HeaderInterceptor headerInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        //拦截路径可自行配置多个 可用 ,分隔开
        InterceptorRegistration interceptorRegistration = registry.addInterceptor(headerInterceptor);
        interceptorRegistration.addPathPatterns("/**"); // 需要拦截的路径
        interceptorRegistration.excludePathPatterns(    // 不拦截的路径
                // 放行swagger相关的路径
                "/swagger-ui/**",
                "/swagger-resources/**",
                "/v3/api-docs"
        );
    }

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        //配置拦截器访问静态资源
        registry.addResourceHandler("doc.html").addResourceLocations("classpath:/META-INF/resources/");
        registry.addResourceHandler("/favicon.ico").addResourceLocations("classpath:/META-INF/resources/");
        registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
    }


    @Override
    public void extendMessageConverters(List<HttpMessageConverter<?>> converters){
        MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
        ObjectMapper objectMapper = converter.getObjectMapper();
        // 生成JSON时,将所有Long转换成String
        SimpleModule simpleModule = new SimpleModule();
        simpleModule.addSerializer(Long.class, ToStringSerializer.instance);
        simpleModule.addSerializer(Long.TYPE, ToStringSerializer.instance);
        objectMapper.registerModule(simpleModule);
//        // 时间格式化
//        objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
//        objectMapper.setDateFormat(new SimpleDateFormat(DateUtil.PATTERN_TIME));
        // 设置格式化内容
        converter.setObjectMapper(objectMapper);
        converters.add(0, converter);
    }


//    /**
//     * 开启跨域
//     */
//    @Override
//    public void addCorsMappings(CorsRegistry registry) {
//        // 设置允许跨域的路由
//        registry.addMapping("/**")
//                // 设置允许跨域请求的域名
//                .allowedOriginPatterns("*")
//                // 是否允许证书(cookies)
//                .allowCredentials(true)
//                // 设置允许的方法
//                .allowedMethods("*")
//                // 跨域允许时间
//                .maxAge(3600);
//    }