1.在做shiro结合redis时,报下列错误:
org.springframework.data.redis.serializer.SerializationException: Cannot deserialize;
nested exception is org.springframework.core.serializer.support.SerializationFailedException:
Failed to deserialize payload. Is the byte array a result of corresponding serialization for DefaultDeserializer?;
nested exception is java.io.InvalidClassException: com.example.demo.utils.MyByteSource; no valid constructor
2.错误最终归结为是MyByteSource这个类没有无参构造造成的,可是这个类继承的是SimpleByteSource,
//salt加密需要实现序列化
public class MyByteSource extends SimpleByteSource implements Serializable{
public MyByteSource(String string) {
super(string);
}
}
而这个类是没有提供无参构造的,所以子类是不能提供无参构造的,因为规定如下:
当父类没有提供无参的构造函数时,子类的构造函数必须显式的调用父类的构造函数
如果开发人员提供了构造函数,那么编译器默认的无参构造函数将会失效
所以要构建一个MyByteSource无参构造,就必须显式的调用父类的构造函数,而父类是没有无参构造函数的,那么就会初始化失败。
2.解决办法
解决办法就是把要继承的代码即父类的代码直接拿过来,然后添加一个构造方法,具体实现如下:
package com.example.demo.utils;
import java.io.File;
import java.io.InputStream;
import java.io.Serializable;
import java.util.Arrays;
import org.apache.shiro.codec.Base64;
import org.apache.shiro.codec.CodecSupport;
import org.apache.shiro.codec.Hex;
import org.apache.shiro.util.ByteSource;
import org.apache.shiro.util.SimpleByteSource;
//自定义salt实现 实现序列化接口
public class MyByteSource implements ByteSource,Serializable {
private byte[] bytes;
private String cachedHex;
private String cachedBase64;
//加入无参数构造方法实现序列化和反序列化
public MyByteSource(){
}
public MyByteSource(byte[] bytes) {
this.bytes = bytes;
}
public MyByteSource(char[] chars) {
this.bytes = CodecSupport.toBytes(chars);
}
public MyByteSource(String string) {
this.bytes = CodecSupport.toBytes(string);
}
public MyByteSource(ByteSource source) {
this.bytes = source.getBytes();
}
public MyByteSource(File file) {
this.bytes = (new MyByteSource.BytesHelper()).getBytes(file);
}
public MyByteSource(InputStream stream) {
this.bytes = (new MyByteSource.BytesHelper()).getBytes(stream);
}
public static boolean isCompatible(Object o) {
return o instanceof byte[] || o instanceof char[] || o instanceof String || o instanceof ByteSource || o instanceof File || o instanceof InputStream;
}
public byte[] getBytes() {
return this.bytes;
}
public boolean isEmpty() {
return this.bytes == null || this.bytes.length == 0;
}
public String toHex() {
if (this.cachedHex == null) {
this.cachedHex = Hex.encodeToString(this.getBytes());
}
return this.cachedHex;
}
public String toBase64() {
if (this.cachedBase64 == null) {
this.cachedBase64 = Base64.encodeToString(this.getBytes());
}
return this.cachedBase64;
}
public String toString() {
return this.toBase64();
}
public int hashCode() {
return this.bytes != null && this.bytes.length != 0 ? Arrays.hashCode(this.bytes) : 0;
}
public boolean equals(Object o) {
if (o == this) {
return true;
} else if (o instanceof ByteSource) {
ByteSource bs = (ByteSource)o;
return Arrays.equals(this.getBytes(), bs.getBytes());
} else {
return false;
}
}
private static final class BytesHelper extends CodecSupport {
private BytesHelper() {
}
public byte[] getBytes(File file) {
return this.toBytes(file);
}
public byte[] getBytes(InputStream stream) {
return this.toBytes(stream);
}
}
}
因为之前的父类实现了ByteSource,Serializable接口,所以我们也得实现ByteSource,Serializable接口
***注意***记得一定要清空下redis数据库,不然错误还会继续。