Spring Boot分布式系统实践【扩展1】shiro+redis实现session共享、simplesession反序列化失败的问题定位及反思改进...
前言
調試之前請先關閉Favicon配置
spring:favicon:enabled: false不然會發現有2個請求(如果用nginx+ 瀏覽器調試的話)
序列化工具類【fastjson版本1.2.37】
```public class FastJson2JsonRedisSerializer implements RedisSerializer {
????public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");
????private Class clazz;
????public FastJson2JsonRedisSerializer(Class clazz) {
????????super();
????????this.clazz = clazz;
????}
????@Override
????public byte[] serialize(T t) throws SerializationException {
????????if (t == null) {
????????????return new byte[0];
????????}
????????return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET);
????}
????@Override
????public T deserialize(byte[] bytes) throws SerializationException {
????????if (bytes == null || bytes.length <= 0) {
????????????return null;
????????}
????????String str = new String(bytes, DEFAULT_CHARSET);
????????return (T) JSON.parseObject(str, clazz);
????}
}
public class SimpleSession implements ValidatingSession, Serializable {
????private transient Serializable id;
????private transient Date startTimestamp;
????private transient Date stopTimestamp;
????private transient Date lastAccessTime;
????private transient long timeout;
????private transient boolean expired;
????private transient String host;
????private transient Map<Object, Object> attributes;
/* Serializes this object to the specified output stream for JDK Serialization.
- @param out output stream used for Object serialization.
- @throws IOException if any of this object's fields cannot be written to the stream.
- @since 1.0
*/
private void writeObject(ObjectOutputStream out) throws IOException {
????out.defaultWriteObject();
????short alteredFieldsBitMask = getAlteredFieldsBitMask();
????out.writeShort(alteredFieldsBitMask);
????if (id != null) {
????????out.writeObject(id);
????}
????if (startTimestamp != null) {
????????out.writeObject(startTimestamp);
????}
????if (stopTimestamp != null) {
????????out.writeObject(stopTimestamp);
????}
????if (lastAccessTime != null) {
????????out.writeObject(lastAccessTime);
????}
????if (timeout != 0l) {
????????out.writeLong(timeout);
????}
????if (expired) {
????????out.writeBoolean(expired);
????}
????if (host != null) {
????????out.writeUTF(host);
????}
????if (!CollectionUtils.isEmpty(attributes)) {
????????out.writeObject(attributes);
????}
}
/*
- Reconstitutes this object based on the specified InputStream for JDK Serialization.
- @param in the input stream to use for reading data to populate this object.
- @throws IOException????????????if the input stream cannot be used.
- @throws ClassNotFoundException if a required class needed for instantiation is not available in the present JVM
- @since 1.0
*/
@SuppressWarnings({"unchecked"})
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
public class FastJson2JsonRedisSerializer implements RedisSerializer {
????private Class clazz;
????public FastJson2JsonRedisSerializer(Class clazz) {
????????super();
????????this.clazz = clazz;
????}
????@Override
????public byte[] serialize(T t) {
????????return ObjectUtils.serialize(t);
????}
????@Override
????public T deserialize(byte[] bytes) {
????????return (T) ObjectUtils.unserialize(bytes);
????}
}
/**
- 序列化對象
- @param object
- @return
*/
public static byte[] serialize(Object object) {
???ObjectOutputStream oos = null;
???ByteArrayOutputStream baos = null;
???try {
??????if (object != null){
?????????baos = new ByteArrayOutputStream();
?????????oos = new ObjectOutputStream(baos);
?????????oos.writeObject(object);
?????????return baos.toByteArray();
??????}
???} catch (Exception e) {
??????e.printStackTrace();
???}
???return null;
}
/**
- 反序列化對象
- @param bytes
- @return
*/
public static Object unserialize(byte[] bytes) {
???ByteArrayInputStream bais = null;
???try {
??????if (bytes != null && bytes.length > 0){
?????????bais = new ByteArrayInputStream(bytes);
?????????ObjectInputStream ois = new ObjectInputStream(bais);
?????????return ois.readObject();
??????}
???} catch (Exception e) {
??????e.printStackTrace();
???}
???return null;
}
@Override
protected Session newSessionInstance(SessionContext context) {
SimpleSession session = new MyRedisSession(context.getHost());
// session.setId(IdGen.uuid());
session.setTimeout(SessionUtils.SESSION_TIME);
return session;
}
??/**
?????* 通過類型轉換,將String反序列化成對象
?????* @param key
?????* @param value
?????* @return
?????*/
????public Object getObjectValue(String key,String value){
????????if(key == null || value == null){
???????????return null;
????????}
????????String clz = key.replace(FLAG_STR,"");
????????try {
???????????Class aClass = Class.forName(clz);
???????????if(aClass.equals(Date.class)){
???????????????return DateUtils.parseDate(value);
???????????}
??????????return???JSONObject.parseObject(value,aClass);
????????} catch (ClassNotFoundException e) {
????????????e.printStackTrace();
????????}
//????????如果反序列化失敗就進行json化處理
????????return JSONObject.parseObject(value);
????}
```
經過如此處理可以在所有系統里共享緩存
唯一缺點就是太復雜了,可能引起其他系統的修改導致反序列化失敗(這個下次再討論或者實驗,因為有這么復雜的功夫,就可以考慮用JWT)
還有一種方案是將復雜對象放到redis中去,實行懶加載機制(不用的復雜對象,不從redis里獲取,暫未實現測試)
轉載于:https://www.cnblogs.com/Halburt/p/10552582.html
總結
以上是生活随笔為你收集整理的Spring Boot分布式系统实践【扩展1】shiro+redis实现session共享、simplesession反序列化失败的问题定位及反思改进...的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python 内置方法 BUILT-I
- 下一篇: RISC-V踩坑记----__built