RedisTemplate 默认使用 JdkSerializationRedisSerializer 对对象进行序列化
RedisTemplate 相关源码如下:
private @Nullable RedisSerializer<?> defaultSerializer;
@SuppressWarnings("rawtypes") private @Nullable RedisSerializer keySerializer = null;
@SuppressWarnings("rawtypes") private @Nullable RedisSerializer valueSerializer = null;
@SuppressWarnings("rawtypes") private @Nullable RedisSerializer hashKeySerializer = null;
@SuppressWarnings("rawtypes") private @Nullable RedisSerializer hashValueSerializer = null;
@Override
public void afterPropertiesSet() {
super.afterPropertiesSet();
boolean defaultUsed = false;
if (defaultSerializer == null) {
defaultSerializer = new JdkSerializationRedisSerializer(
classLoader != null ? classLoader : this.getClass().getClassLoader());
}
if (enableDefaultSerializer) {
if (keySerializer == null) {
keySerializer = defaultSerializer;
defaultUsed = true;
}
if (valueSerializer == null) {
valueSerializer = defaultSerializer;
defaultUsed = true;
}
if (hashKeySerializer == null) {
hashKeySerializer = defaultSerializer;
defaultUsed = true;
}
if (hashValueSerializer == null) {
hashValueSerializer = defaultSerializer;
defaultUsed = true;
}
}
if (enableDefaultSerializer && defaultUsed) {
Assert.notNull(defaultSerializer, "default serializer null and not all serializers initialized");
}
if (scriptExecutor == null) {
this.scriptExecutor = new DefaultScriptExecutor<>(this);
}
initialized = true;
}
这里自定义 RedisTemplate,使用 GenericJackson2JsonRedisSerializer,代码如下:
@Configuration
public class RedisConfig {
//向容器中添加 **GenericJackson2JsonRedisSerializer** 对象
@Bean(name = "springSessionDefaultRedisSerializer")
public GenericJackson2JsonRedisSerializer getGenericJackson2JsonRedisSerializer() {
return new GenericJackson2JsonRedisSerializer();
}
//向容器中添加自定义的 **RedisTemplate**
@Bean
public RedisTemplate<String, Object> getRedisTemplate( RedisConnectionFactory connectionFactory) {
//创建 **RedisTemplate **对象
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
//设置 **RedisTemplate ** 的 **ConnectionFactory**
redisTemplate.setConnectionFactory(connectionFactory);
//设置 **RedisTemplate ** 的默认序列化器 **defaultSerializer**
redisTemplate.setDefaultSerializer(new GenericJackson2JsonRedisSerializer());
//设置 **key**、**hashKey **的序列化器为 **StringRedisSerializer**
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
redisTemplate.setKeySerializer(stringRedisSerializer);
redisTemplate.setHashKeySerializer(stringRedisSerializer);
return redisTemplate;
}
}
所遇异常:
1. org.springframework.data.redis.serializer.SerializationException: Could not write JSON: (was java.lang.NullPointerException) (through reference chain: com.atguigu.bookcity.pojo.CartItem["xj"]); nested exception is com.fasterxml.jackson.databind.JsonMappingException: (was java.lang.NullPointerException) (through reference chain: com.atguigu.bookcity.pojo.CartItem["xj"])
2. org.springframework.data.redis.serializer.SerializationException: Could not write JSON: (was java.lang.NullPointerException) (through reference chain: com.atguigu.bookcity.pojo.OrderItem["xj"]); nested exception is com.fasterxml.jackson.databind.JsonMappingException: (was java.lang.NullPointerException) (through reference chain: com.atguigu.bookcity.pojo.OrderItem["xj"])
原因:我定义的两个实体类 CartItem、OrderItem 中有 getXXX() 方法,但没有对应的属性,而 GenericJackson2JsonRedisSerializer 序列化会调用 getXXX() 方法为相应属性赋值,故报错
原始实体类定义如下:
package com.atguigu.bookcity.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
import java.math.BigDecimal;
/**
* @author ycjstart
* @create 2022-11-16 16:15
*/
@Data
@ToString
@NoArgsConstructor
@AllArgsConstructor
public class CartItem {
private Integer id;
private Book book;
private Integer buyCount;
private Integer userBean;
public Double getXj() {
BigDecimal bookPrice = BigDecimal.valueOf(book.getPrice());
return (bookPrice.multiply(new BigDecimal(buyCount)).doubleValue());
}
}
package com.atguigu.bookcity.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
import java.math.BigDecimal;
/**
* @author ycjstart
* @create 2022-11-16 16:18
*/
@Data
@ToString
@NoArgsConstructor
@AllArgsConstructor
public class OrderItem {
private Integer id;
private Book book;
private Integer buyCount;
private Integer orderId;
public OrderItem(Book book, Integer buyCount, Integer orderId) {
this.book = book;
this.buyCount = buyCount;
this.orderId = orderId;
}
public Double getXj() {
BigDecimal bookPrice = BigDecimal.valueOf(book.getPrice());
return bookPrice.multiply(BigDecimal.valueOf(buyCount)).doubleValue();
}
}
修改后实体类:
package com.atguigu.bookcity.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
import java.math.BigDecimal;
/**
* @author ycjstart
* @create 2022-11-16 16:15
*/
@Data
@ToString
@NoArgsConstructor
@AllArgsConstructor
public class CartItem {
private Integer id;
private Book book;
private Integer buyCount;
private Integer userBean;
public Double calculateXj() {
BigDecimal bookPrice = BigDecimal.valueOf(book.getPrice());
return (bookPrice.multiply(new BigDecimal(buyCount)).doubleValue());
}
}
package com.atguigu.bookcity.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
import java.math.BigDecimal;
/**
* @author ycjstart
* @create 2022-11-16 16:18
*/
@Data
@ToString
@NoArgsConstructor
@AllArgsConstructor
public class OrderItem {
private Integer id;
private Book book;
private Integer buyCount;
private Integer orderId;
public OrderItem(Book book, Integer buyCount, Integer orderId) {
this.book = book;
this.buyCount = buyCount;
this.orderId = orderId;
}
public Double calculateXj() {
BigDecimal bookPrice = BigDecimal.valueOf(book.getPrice());
return bookPrice.multiply(BigDecimal.valueOf(buyCount)).doubleValue();
}
}
方法名修改后,异常解决