shiro继承redis进行session的管理:
package ;
import ;
import org.;
import org.;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import .GenericJackson2JsonRedisSerializer;
import .Jackson2JsonRedisSerializer;
import ;
import ;
@Configuration
@EnableCaching
@Data
public class RedisConfiguration extends CachingConfigurerSupport {
private Logger logger = (());
/**
* 配置redis 连接
*/
@Bean
@ConditionalOnMissingBean(name = "redisTemplate")
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
// 1.创建 redisTemplate 模版
RedisTemplate<String, Object> template = new RedisTemplate<>();
// 2.关联 redisConnectionFactory
(factory);
// 3.创建 自定义序列化类
MyRedisSerializer myRedisSerializer = new MyRedisSerializer();
// 7.设置 value 的转化格式和 key 的转化格式 默认使用的是JdkSerializationRedisSerializer
(myRedisSerializer);
(myRedisSerializer);
// 设置键(key)的序列化采用StringRedisSerializer。
(new StringRedisSerializer());
(new StringRedisSerializer());
(myRedisSerializer);
();
return template;
}
@Bean
@ConditionalOnMissingBean()
public RedisTemplate<String, String> stringRedisTemplate(RedisConnectionFactory factory) {
return new StringRedisTemplate(factory);
}
}
默认使用JdkSerializationRedisSerializer
,这个序列化模式会将value序列化成字节码
,这样缓存shiro的session就没有什么问题,当是redis数据库的数据将是字节码,不方便观察。
如果改用GenericJackson2JsonRedisSerializer或者Jackson2JsonRedisSerializer,项目启动运行没有任何问题,但是在在访问过程中,突然性的报错:
: Unrecognized field "valid" (class ), not marked as ignorable (10 known properties: "attributeKeys", "timeout", "startTimestamp", "expired", "lastAccessTime", "host", "id", "stopTimestamp", "attributes", "attributesLazy"])
这是由于是反序列化报错的原因。无法反序列化接口的动态代理类,原因应该是动态代理类没有缺省构造函数。
处理方式:
- 解决session序列化问题方法也很简单,
setValueSerializer
不配置就可以了。
如果想要redis数据库的数据为json字符串,那么可以在其他用到缓存的地方使用StringRedisTemplate
,或者再定义一个template。
2. 自定义序列化和反序列化方法。
MyRedisSerializer 序列化成字节数组
import ;
import ;
import .*;
/**
* 重写序列化 序列化为字节码
* zhw
*/
public class MyRedisSerializer implements RedisSerializer {
@Override
public byte[] serialize(Object o) throws SerializationException {
ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
ObjectOutputStream objOut;
try {
objOut = new ObjectOutputStream(byteOut);
(o);
} catch (IOException e) {
();
}
return ();
}
@Override
public Object deserialize(byte[] bytes) throws SerializationException {
if(bytes == null) return null;
ByteArrayInputStream byteIn = new ByteArrayInputStream(bytes);
ObjectInputStream objIn;
Object obj;
try {
objIn = new ObjectInputStream(byteIn);
obj =();
} catch (IOException | ClassNotFoundException e) {
();
return null;
}
return obj;
}
}
FastJsonRedisSerializer:序列化成json字符串
import ;
import ;
import ;
import ;
import ;
import ;
/**
* 重写序列化 序列化为json字符串
* zhw
*/
public class FastJsonRedisSerializer implements RedisSerializer {
public static final Charset DEFAULT_CHARSET = ("UTF-8");
private Class<T> clazz;
public FastJsonRedisSerializer(Class<T> clazz) {
super();
= clazz;
}
@Override
public byte[] serialize(Object o) throws SerializationException {
if (o == null) {
return new byte[0];
}
return (o, ).getBytes(DEFAULT_CHARSET);
}
@Override
public T deserialize(byte[] bytes) throws SerializationException {
if (bytes == null || <= 0) {
return null;
}
String str = new String(bytes, DEFAULT_CHARSET);
return (str, clazz);
}
}
多个项目彼此之间需使用同一个redis,一个项目往redis存入数据,另一个项目从redis中获取数据,如果使用的不是同一个redis的序列化方式,这样导致,另一个项目是无法从redis中获取到该key所对应的数据。