spring 请求参数及返回值 类型统一转化(序列化和反序列化)

1.实现WebMvcConfigurer 类中的configureMessageConverters和addFormatters方法

package com.pulpy.knowl.config;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.context.annotation.Configuration;
import org.springframework.format.FormatterRegistry;
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.List;
//@EnableWebMvc表示完全自己控制mvc配置,也就是说所有配置自己重写,所有默认配置都没了
//@EnableWebMvc 
@Configuration
public class HttpMessageConverterConfig implements WebMvcConfigurer {

    /**
     * 解决前端js处理大数字丢失精度问题
     * 将Long和BigInteger转换成string
     * 将LocalDatetime等时间类转出string
     * 反序列化json中string转换成LocalDatetime等时间类
     */
    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
        ObjectMapper objectMapper = NewObjectMapper.newObjectMapper();
        converter.setObjectMapper(objectMapper);
        converters.add(0, converter);//最高优先级
    }

	/**
	 * 反序列化form-data格式的string转换成LocalDateTime等时间类
     */
    @Override
    public void addFormatters(FormatterRegistry registry) {
        registry.addConverter(new LocalDateTimeConverter.StringToLocalDateTimeConverter());
        registry.addConverter(new LocalDateTimeConverter.StringToLocalDateConverter());
        registry.addConverter(new LocalDateTimeConverter.StringToLocalTimeConverter());
    }

}

2.string转各种时间类 转化器

package com.pulpy.knowl.config;

import com.pulpy.common.core.utils.StringUtils;
import org.springframework.core.convert.converter.Converter;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;

public class LocalDateTimeConverter {

    /**
     * 因为 Spring 默认不支持将 String 类型的请求参数转换为 LocalDateTime 类型,所以我们需要自定义 converter 「转换器」完整整个转换过程
     */
    public static class StringToLocalDateTimeConverter implements Converter<String, LocalDateTime> {
        @Override
        public LocalDateTime convert(String s) {
            if(StringUtils.isBlank(s)){
                return null;
            }
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern(DateConstant.PATTERN, Locale.CHINESE);
            return LocalDateTime.parse(s, formatter);
        }
    }
    
    public static class StringToLocalDateConverter implements Converter<String, LocalDate> {
        @Override
        public LocalDate convert(String s) {
            if(StringUtils.isBlank(s)){
                return null;
            }
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern(DateConstant.PATTERN_YYYY_MM_DD, Locale.CHINESE);
            return LocalDate.parse(s, formatter);
        }
    }

    public static class StringToLocalTimeConverter implements Converter<String, LocalTime> {
        @Override
        public LocalTime convert(String s) {
            if(StringUtils.isBlank(s)){
                return null;
            }
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern(DateConstant.PATTERN_HH_MM_SS, Locale.CHINESE);
            return LocalTime.parse(s, formatter);
        }
    }

}

3.创建新ObjectMapper,定义json 序列化 及 反序列化 类型

package com.pulpy.knowl.config;

import com.fasterxml.jackson.core.JsonParser;
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.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer;
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 java.math.BigInteger;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;

public class NewObjectMapper {

    public static ObjectMapper newObjectMapper() {
        ObjectMapper objectMapper = new ObjectMapper();

        objectMapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
        objectMapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);
//		result.setSerializationInclusion(JsonInclude.Include.NON_NULL);
        objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

        objectMapper.registerModules(newJavaTimeModule(), newSimpleModule());
        return objectMapper;
    }

    public static JavaTimeModule newJavaTimeModule(){
        JavaTimeModule javaTimeModule = new JavaTimeModule();

        //序列化LocalDateTime等时间类
        javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateConstant.getFormatter(DateConstant.PATTERN)));
        javaTimeModule.addSerializer(LocalDate.class, new LocalDateSerializer(DateConstant.getFormatter(DateConstant.PATTERN_YYYY_MM_DD)));
        javaTimeModule.addSerializer(LocalTime.class, new LocalTimeSerializer(DateConstant.getFormatter(DateConstant.PATTERN_HH_MM_SS)));

        //反序列化 json格式中 字符串 为LocalDateTime等时间类
        javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateConstant.getFormatter(DateConstant.PATTERN)));
        javaTimeModule.addDeserializer(LocalDate.class, new LocalDateDeserializer(DateConstant.getFormatter(DateConstant.PATTERN_YYYY_MM_DD)));
        javaTimeModule.addDeserializer(LocalTime.class, new LocalTimeDeserializer(DateConstant.getFormatter(DateConstant.PATTERN_HH_MM_SS)));

        return javaTimeModule;
    }

    public static SimpleModule newSimpleModule(){
        SimpleModule simpleModule = new SimpleModule();

        // 序列化成json时,将所有的long变成string 因为js中得数字类型不能包含所有的java long值
        simpleModule.addSerializer(BigInteger.class, ToStringSerializer.instance);
        simpleModule.addSerializer(Long.class, ToStringSerializer.instance);
        simpleModule.addSerializer(Long.TYPE, ToStringSerializer.instance);

        return simpleModule;
    }
}

时间类工具

package com.pulpy.knowl.config;

import java.time.format.DateTimeFormatter;

public class DateConstant {

    public static DateTimeFormatter getFormatter(String formatter){
        return DateTimeFormatter.ofPattern(formatter);
    }

    public static final String PATTERN = "yyyy-MM-dd HH:mm:ss";
    public static final String PATTERN_YYYY_MM_DD = "yyyy-MM-dd";
    public static final String PATTERN_HH_MM_SS = "HH:mm:ss";

}

注意:如果需要将某系列接口进行序列化或反序列化,可以如下操作

package com.pulpy.knowl.config;

import org.springframework.http.MediaType;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import java.lang.reflect.Type;

public class CustomMappingJackson2HttpMessageConverter extends MappingJackson2HttpMessageConverter {

    /**
     * 判断该转换器是否能将请求内容转换成 Java 对象
     */
    @Override
    public boolean canRead(Class<?> clazz, MediaType mediaType) {
        if (super.canRead(clazz, mediaType)) {
            ServletRequestAttributes ra = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            if (ra != null) { // web请求
                String uri = ra.getRequest().getRequestURI();
//                if (uri.startsWith("/web/")) {
                return true;
//                }
            }
        }
        // 不需要反序列化
        return false;
    }

    /**
     * 判断该转换器是否能将请求内容转换成 Java 对象
     */
    @Override
    public boolean canRead(Type type, Class<?> contextClass, MediaType mediaType) {
        if (super.canRead(type, contextClass, mediaType)) {
            ServletRequestAttributes ra = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            if (ra != null) { // web请求
                String uri = ra.getRequest().getRequestURI();
//                if (uri.startsWith("/web/")) {
                return true;
//                }
            }
        }
        // 不需要反序列化
        return false;
    }

    /**
     * 判断该转换器是否可以将 Java 对象转换成返回内容.
     * 匹配web api(形如/web/xxxx)中的接口方法的返回参数
     */
    @Override
    public boolean canWrite(Class<?> clazz, MediaType mediaType) {
        if (super.canWrite(clazz, mediaType)) {
            ServletRequestAttributes ra = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            if (ra != null) { // web请求
                String uri = ra.getRequest().getRequestURI();
//                if (uri.startsWith("/web/")) {
                    return true;
//                }
            }
        }
        return false;
    }

}

再重新1中的configureMessageConverters方法

@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
    CustomMappingJackson2HttpMessageConverter converter = new CustomMappingJackson2HttpMessageConverter();
    ObjectMapper objectMapper = NewObjectMapper.newObjectMapper();
    converter.setObjectMapper(objectMapper);
    converters.add(0, converter);
}

你可能感兴趣的:(spring,java,servlet)