zxpnet网站 zxpnet网站
首页
前端
后端服务器
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

zxpnet

一个爱学习的java开发攻城狮
首页
前端
后端服务器
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • 大后端课程视频归档
  • 南航面试题
  • 并发编程

  • 性能调优

  • java8语法

  • lombok

  • 日志

  • 工具类

  • spring

  • mybatis

  • springboot

    • springboot基础篇
    • springboot配置文件yaml
    • springboot web开发
    • springboot数据访问
    • springboot单元测试
    • springboot性能监控actuator
    • SpringBoot 原理解析
    • spring.factories文件
    • springboot常用注解
    • springboot序列化
      • 页面数据json返回
      • 缓存数据序列化及反序列化
      • Hibernate JPA中的序列化注解
        • 1、@Transient
        • 2、@JsonIgnoreProperties
        • 3、@JsonIgnore
        • 4、@JsonFormat
        • 5、@JsonSerialize
        • 6、@JsonDeserialize
        • hibernate懒加载和json序列化冲突
    • springboot整合swagger
    • Spring Boot 定制URL匹配规则的方法
    • springboot整合redisson分布式锁
    • springboot+线程池使用
    • springboot2应用中碰到的一些坑
    • SpringBoot面试题
  • redis

  • zookeeper

  • springcloud

  • dubbo

  • netty

  • springsecurity

  • mq消息中间件

  • shiro

  • beetle

  • 模板引擎

  • jpa

  • 数据结构与算法

  • 数据库知识与设计

  • gradle

  • maven

  • bus

  • 定时任务

  • docker

  • centos

  • 加解密

  • biz业务

  • pigx项目

  • 开源项目

  • 品达通用权限项目-黑马

  • 货币交易项目coin-尚学堂

  • php

  • backend
  • springboot
shollin
2021-07-01
目录

springboot序列化

  • 页面数据json返回
  • 缓存数据序列化及反序列化
  • Hibernate JPA中的序列化注解
    • 1、@Transient
    • 2、@JsonIgnoreProperties
    • 3、@JsonIgnore
    • 4、@JsonFormat
    • 5、@JsonSerialize
    • 6、@JsonDeserialize
    • hibernate懒加载和json序列化冲突

# 页面数据json返回

springboot开发web应用时,响应的json数据,默认采用的是jackson, 它在序列化java8时间时会出错,long序列化时,会丢失精度, hibernate代理对象为空时,也会报错等等,需要进行填坑。

/**
 * 参考: org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration
 * @author: shollin
 * @date: 2021/6/27/027 18:30
 */
@Configuration(proxyBeanMethods=false)
@ConditionalOnClass(ObjectMapper.class)
@AutoConfigureBefore(JacksonAutoConfiguration.class)
public class JacksonConfig {

    /**
     * 参考 SpringBlade-Tool
     * 修复 hibernateLazyInitializer序列化值有空的问题、 jdk8时间日期序列化问题、long序列化丢失精度问题
     * @return
     */
    @Primary
    @Bean
    public ObjectMapper objectMapper(Jackson2ObjectMapperBuilder builder) {

        SimpleModule simpleModule = new SimpleModule();

        /** 序列化配置,针对java8 时间 **/
        simpleModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        simpleModule.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
        simpleModule.addSerializer(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ofPattern("HH:mm:ss")));

        /** 反序列化配置,针对java8 时间 **/
        simpleModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        simpleModule.addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
        simpleModule.addDeserializer(LocalTime.class, new LocalTimeDeserializer(DateTimeFormatter.ofPattern("HH:mm:ss")));

        /** Long转String类型  **/
        simpleModule.addSerializer(Long.class, ToStringSerializer.instance);
        simpleModule.addSerializer(Long.TYPE, ToStringSerializer.instance);

        builder.simpleDateFormat(DatePattern.NORM_DATETIME_PATTERN);
        //创建ObjectMapper
        ObjectMapper objectMapper = builder.createXmlMapper(false).build();
        //设置地点为中国
        objectMapper.setLocale(Locale.CHINA);
        //去掉默认的时间戳格式
        objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
        //设置为中国上海时区
        objectMapper.setTimeZone(TimeZone.getTimeZone(ZoneId.systemDefault()));
        //序列化时,日期的统一格式
        objectMapper.setDateFormat(new SimpleDateFormat(DatePattern.NORM_DATETIME_PATTERN, Locale.CHINA));
        //序列化处理
        objectMapper.configure(JsonReadFeature.ALLOW_UNESCAPED_CONTROL_CHARS.mappedFeature(), true);
        objectMapper.configure(JsonReadFeature.ALLOW_BACKSLASH_ESCAPING_ANY_CHARACTER.mappedFeature(), true);
        objectMapper.findAndRegisterModules();
        //失败处理
        objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
        objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        //单引号处理
        objectMapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);
        //反序列化时,属性不存在的兼容处理
        objectMapper.getDeserializationConfig().withoutFeatures(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
        //日期格式化
        objectMapper.registerModule(simpleModule);
        objectMapper.findAndRegisterModules();
        return objectMapper;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63

# 缓存数据序列化及反序列化

RedisAutoConfiguration会自动生成 StringRedisTemplate 和RedisTemplate<Object, Object> 放入容器, 这里定义RedisTemplate<String, Object>,一般key为String,将值用

/**
 * redis入口配置文件  参考:
 * @author zxp
 * @date 2021/7/1 16:15
 */
@EnableCaching
@Configuration(proxyBeanMethods = false)
@AutoConfigureBefore(RedisAutoConfiguration.class)
public class ZxpRedisConfig {


    /**
     * value 值 序列化
     * @return RedisSerializer
     */
    @Bean
    public RedisSerializer<Object> redisSerializer(ObjectProvider<ObjectMapper> objectProvider) {

        // jackson findAndRegisterModules,use copy
        ObjectMapper objectMapper = objectProvider.getIfAvailable(ObjectMapper::new).copy();
        // findAndRegisterModules
        objectMapper.findAndRegisterModules();
        // class type info to json
        GenericJackson2JsonRedisSerializer.registerNullValueSerializer(objectMapper, null);
        objectMapper.activateDefaultTyping(objectMapper.getPolymorphicTypeValidator(), ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
        return new GenericJackson2JsonRedisSerializer(objectMapper);
    }

    @Bean(name = "redisTemplate")
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory,
                                                       RedisSerializer<Object> redisSerializer) {

        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
        RedisKeySerializer redisKeySerializer = new RedisKeySerializer();

        // key 序列化 采用StringRedisSerializer, key必须为String类型,不然会报错
        redisTemplate.setKeySerializer(redisKeySerializer);
        redisTemplate.setHashKeySerializer(redisKeySerializer);

        // value 序列化
        redisTemplate.setValueSerializer(redisSerializer);
        redisTemplate.setHashValueSerializer(redisSerializer);
        redisTemplate.setConnectionFactory(redisConnectionFactory);
        return redisTemplate;
    }

    @Bean
    public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
        RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig()
                .entryTtl(Duration.ofHours(1));
        return RedisCacheManager
                .builder(RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory))
                .cacheDefaults(redisCacheConfiguration).build();
    }

    @Bean(name = "redisUtil")
    @ConditionalOnBean(RedisTemplate.class)
    public RedisUtil redisUtils(RedisTemplate<String, Object> redisTemplate) {
        return new RedisUtil(redisTemplate);
    }

}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63

# Hibernate JPA中的序列化注解

@Transient、@JsonIgnoreProperties、@JsonIgnore、@JsonFormat、@JsonSerialize等注解解释 @jsonignore的作用: 作用是json序列化时将java bean中的一些属性忽略掉,序列化和反序列化都受影响。 只要在Set方法前增加以下注解即可:

@JsonIgnore  
public Set xxxs() {
    return this.xxxYyyy;
}
1
2
3
4

# 1、@Transient

@Transient表示该属性并非一个到数据库表的字段的映射,ORM框架将忽略该属性; 如果一个属性并非数据库表的字段映射,就务必将其标示为@Transient,否则ORM框架默认其注解为@Basic;

# 2、@JsonIgnoreProperties

此注解是类注解,作用是json序列化时将java bean中的一些属性忽略掉,序列化和反序列化都受影响。@JsonIgnoreProperties(ignoreUnknown = true),将这个注解写在类上之后,就会忽略类中不存在的字段。 这个注解还可以指定要忽略的字段,例如@JsonIgnoreProperties({ “password”, “secretKey” })

# 3、@JsonIgnore

此注解用于属性或者方法上(最好是属性上),作用和上面的@JsonIgnoreProperties一样。@JsonIgnore注解用来忽略某些字段,可以用在变量或者Getter方法上,用在Setter方法时,和变量效果一样。这个注解一般用在我们要忽略的字段上。

# 4、@JsonFormat

此注解用于属性或者方法上(最好是属性上),可以帮我们完成格式转换,可以方便的把Date类型直接转化为我们想要的模式, 例如对于Date类型字段,如果不适用JsonFormat默认在rest返回的是long, 如果我们使用@JsonFormat(timezone = “GMT+8”, pattern = “yyyy-MM-dd HH:mm:ss”),就返回"2018-11-16 22:58:15"

# 5、@JsonSerialize

此注解用于属性或者getter方法上,用于在序列化时嵌入我们自定义的代码,比如序列化一个double时在其后面限制两位小数点。

# 6、@JsonDeserialize

此注解用于属性或者setter方法上,用于在反序列化时可以嵌入我们自定义的代码,类似于上面的@JsonSerialize

# hibernate懒加载和json序列化冲突

因为懒加载这个对象属性只是一个代理对象,如果json直接当作一个存在的属性去序列化就会出现错误,jpa 默认会使用 hibernate,在 jpa 工作过程中,就会创造代理类来继承 Type ,并添加 handler 和 hibernatelazyinitializer 这两个无须 json 化的属性,所以这里需要用JsonIgnoreProperties 把这两个属性忽略掉。 。。。

或者在class上加上

@JsonIgnoreProperties(value={"hibernateLazyInitializer","handler","fieldHandler"})
public class ProductPrice {

}
1
2
3
4

或者在这个对象的属性上面增加 @JsonIgnore 注解

@JsonIgnore
public Set<User> getUsers() {
	return this.users;
}
1
2
3
4

实际我们要做的目的就是为了在MappingJackson2HttpMessageConverter通过aop转化为json的时候不去理这个属性

springboot常用注解
springboot整合swagger

← springboot常用注解 springboot整合swagger→

最近更新
01
国际象棋
09-15
02
成语
09-15
03
自然拼读
09-15
更多文章>
Theme by Vdoing | Copyright © 2019-2023 zxpnet | 粤ICP备14079330号-1
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式