• Spring中入参,出参时间戳,LocalDateTime转换


    提供ObjectMapper

    import cn.hutool.core.date.DateUtil;
    import cn.hutool.core.date.LocalDateTimeUtil;
    import com.fasterxml.jackson.annotation.JsonInclude;
    import com.fasterxml.jackson.core.JsonGenerator;
    import com.fasterxml.jackson.core.JsonParser;
    import com.fasterxml.jackson.databind.*;
    import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    import java.io.IOException;
    import java.time.Instant;
    import java.time.LocalDateTime;
    import java.time.ZoneId;
    
    /**
     * @author qhong
     * @date 2021/11/5 12:20
     **/
    @Configuration
    public class LocalDateTimeSerializerConfig {
    
        /**
         * 序列化LocalDateTime
         *
         * @return
         */
        @Bean(value = "localDateTimeObjectMapper")
        public ObjectMapper serializingObjectMapper() {
            ObjectMapper objectMapper = new ObjectMapper();
    
            // 通过该方法对mapper对象进行设置,所有序列化的对象都将按改规则进行系列化
            // Include.Include.ALWAYS 默认
            // Include.NON_DEFAULT 属性为默认值不序列化
            // Include.NON_EMPTY 属性为 空("") 或者为 NULL 都不序列化,则返回的json是没有这个字段的。这样对移动端会更省流量
            // Include.NON_NULL 属性为NULL 不序列化
            objectMapper.setSerializationInclusion(JsonInclude.Include.ALWAYS);
            // 允许忽略多传入的字段,直接忽略
            objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
            // 允许出现特殊字符和转义符
            objectMapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_CONTROL_CHARS, true);
            // 允许出现单引号
            objectMapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);
            // 兼容反斜杠,允许接受引号引起来的所有字符
            objectMapper.configure(JsonParser.Feature.ALLOW_BACKSLASH_ESCAPING_ANY_CHARACTER, true);
            JavaTimeModule javaTimeModule = new JavaTimeModule();
            javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer());
            javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer());
            objectMapper.registerModule(javaTimeModule);
            return objectMapper;
        }
    
        /**
         * 序列化实现
         */
        public static class LocalDateTimeSerializer extends JsonSerializer<LocalDateTime> {
            @Override
            public void serialize(LocalDateTime value, JsonGenerator gen, SerializerProvider serializers)
                    throws IOException {
                if (value != null) {
                    long timestamp = value.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
                    gen.writeNumber(timestamp);
                }
            }
        }
    
        /**
         * 反序列化实现
         */
        public static class LocalDateTimeDeserializer extends JsonDeserializer<LocalDateTime> {
            @Override
            public LocalDateTime deserialize(JsonParser p, DeserializationContext deserializationContext)
                    throws IOException {
                long timestamp = p.getValueAsLong();
                if (timestamp > 0) {
                    return LocalDateTime.ofInstant(Instant.ofEpochMilli(timestamp), ZoneId.systemDefault());
                } else {
                    //兼容字符串格式时间传入
                    String value = p.getValueAsString();
                    return LocalDateTimeUtil.of(DateUtil.parse(value));
                }
            }
        }
    }
    
    

    可以直接使用@Primary,强制整个系统使用上面的ObjectMapper,但是会出现与其他jar定义ObjectMapper冲突

    提供MappingJackson2HttpMessageConverter

    import com.fasterxml.jackson.databind.ObjectMapper;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.http.MediaType;
    import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
    
    import javax.annotation.Resource;
    import java.nio.charset.Charset;
    import java.util.LinkedList;
    import java.util.List;
    
    /**
     * @author qhong
     * @date 2022/4/14 19:52
     **/
    @Configuration
    public class MessageConverterConfig {
    
        @Resource(name = "localDateTimeObjectMapper")
        public ObjectMapper objectMapper;
    
        /**
         * 使用jackson序列化消息转换
         */
        @Bean
        public MappingJackson2HttpMessageConverter fastJsonHttpMessageConverters() {
            MappingJackson2HttpMessageConverter messageConverter = new MappingJackson2HttpMessageConverter();
            messageConverter.setDefaultCharset(Charset.defaultCharset());
            messageConverter.setObjectMapper(objectMapper);
    
            //支持的媒体类型
            List<MediaType> supportedMediaTypes = new LinkedList<>();
            supportedMediaTypes.add(MediaType.APPLICATION_JSON_UTF8);
    
            //页面直接请求的类型(这里是新增加的支持的匹配的类型,页面访问的时候类型为text/html)
            supportedMediaTypes.add(MediaType.TEXT_HTML);
    
            messageConverter.setSupportedMediaTypes(supportedMediaTypes);
            //@formatter:on
            return messageConverter;
        }
    }
    

    入参时间戳转换为LocalDateTime

    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.WebMvcConfigurer;
    
    import javax.annotation.Resource;
    import java.util.List;
    
    /**
     * @author qhong
     * @date 2022/4/14 19:50
     **/
    @Configuration
    public class MessageConverterOrderWebMvcConfigurer implements WebMvcConfigurer {
    
        @Resource
        private MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter;
    
        @Override
        public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
    
            //方法一:把jackson解析器放在第一位,这样匹配完了之后,就会直接返回;[是否匹配和我们解析器支持的类型有关[supportedMediaTypes]详细见源码
            // org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor#writeWithMessageConverters]
            converters.add(0, mappingJackson2HttpMessageConverter);
        }
    }
    

    返回体LocalDateTime转换为时间戳

    import com.alibaba.fastjson.JSONObject;
    import com.qhong.test.common.ResultBase;
    import lombok.SneakyThrows;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.core.MethodParameter;
    import org.springframework.core.annotation.Order;
    import org.springframework.http.MediaType;
    import org.springframework.http.converter.HttpMessageConverter;
    import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
    import org.springframework.http.server.ServerHttpRequest;
    import org.springframework.http.server.ServerHttpResponse;
    import org.springframework.web.bind.annotation.RestControllerAdvice;
    import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
    
    /**
     * @author qhong
     * @date 2022/4/14 19:50
     **/
    @Slf4j
    //这里尽量让加密的判断优先级更低一点(请求的时候,加密的优先级高一点
    @Order(1)
    @RestControllerAdvice
    public class ResponseHandle implements ResponseBodyAdvice<Object> {
    
        @Autowired
        private MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter;
    
        /**
         * 是否支持此消息响应处理器
         *
         * @return boolean
         * @Param methodParameter
         * @Param aClass
         * @author peikunkun
         * @date 2021/1/6 0006 下午 4:29
         * @since
         */
        @Override
        public boolean supports(MethodParameter methodParameter, Class<? extends HttpMessageConverter<?>> aClass) {
            return true;
        }
    
        /**
         * 在选择HttpMessageConverter之后且在调用其write方法之前调用。
         * <p>
         * 参数:正文–要写的正文
         * returnType –控制器方法的返回类型
         * selectedContentType –通过内容协商选择的内容类型
         * selectedConverterType –选择要写入响应的转换器类型
         * 请求–当前请求
         * 响应–当前响应
         * 返回值:
         * 传入的正文或经过修改的(可能是新的)实例
         */
        @SneakyThrows
        @Override
        public Object beforeBodyWrite(Object resBody, MethodParameter methodParameter, MediaType mediaType,
                                      Class<? extends HttpMessageConverter<?>> aClass, ServerHttpRequest serverHttpRequest,
                                      ServerHttpResponse serverHttpResponse) {
            try {
                if (resBody instanceof ResultBase) {
                    return JSONObject.parseObject(mappingJackson2HttpMessageConverter.getObjectMapper().writeValueAsString(resBody), ResultBase.class);
                }
            } catch (Exception e) {
                log.warn("ResponseHandle Return Error", e);
            }
            return resBody;
        }
    }
    
  • 相关阅读:
    关于学习netty的两个完整服务器客户端范例
    android-betterpickers
    ValueBar
    CircleDisplay
    JellyViewPager
    十天学习PHP之第二天
    android-測试so动态库(九)
    实习题
    android 编程小技巧(持续中)
    Codeforces Round #253 (Div. 2)——Borya and Hanabi
  • 原文地址:https://www.cnblogs.com/hongdada/p/16148412.html
Copyright © 2020-2023  润新知