您现在的位置是:主页 > Web前端技术 > Web前端技术
spring-session自定义序列化方法是什么开发技术
IDCBT2021-12-23【服务器技术】人已围观
简介本篇内容介绍了“spring-session自定义序列化方法是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希
本篇内容介绍了“spring-session自定义序列化方法是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!
spring-session自定义序列化spring-session默认采用jdk序列化方法,该方法效率低下、内存占用大,且需要额外修改代码。故需要自定义序列化方法
自定义序列方法使用jackson库首先需要一个类作为序列化的工具,需要实现
RedisSerializer
该接口在反序列化时没有提供对应的class对象,因此使用jackson反序列化时,都会返回成Object对象
因此我的解决思路是,在序列化时,获取对应bean的class,将其和bean序列化后的结果一并返回,存入redis
反序列化时,首先将byte数组转化成字符串,在从中截取存入的class字符串,作为参数传入jackson反序列化方法中
问题:对于带有泛型的bean,无法将其转化成真正适合的类型
解决方案:对于list,map,set等集合类,获取其第一个元素的class,存入redis
缺点:要求集合类元素必须是同一个子类,不能来自于同一个父类
问题:spring-session在删除attribute时,并没有真正从redis中删除,只是将value置为null,此时也会调用该类做序列化
解决方案:查看spring-session源码得知,对于null值得处理方法为直接返回一个个数为0的byte数组,反序列化时直接返回null即可
import cn.nsu.edu.web.four.config.BaseStatic; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.type.TypeFactory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.serializer.RedisSerializer; import org.springframework.data.redis.serializer.SerializationException; import org.springframework.data.redis.serializer.SerializationUtils; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.util.*; import java.util.regex.Matcher; import java.util.regex.Pattern; public class SessionSerializer implements RedisSerializer<Object> { @Autowired private ObjectMapper mapper; private Logger logger = LoggerFactory.getLogger(getClass()); private final String separator = "="; private final String classPrefix = "<"; private final String classSuffix = ">"; private final String classSeparator = ","; private Pattern pattern; public SessionSerializer() { pattern = Pattern.compile("<(.*)>"); } /** * 获取class,包含集合类的泛型 * <p>暂只支持最多两个泛型,同时集合内数据必须为同一个实现类,不可将泛型声明成父类</p> * * @param obj 将要序列化的对象 * @return 没有泛型,形式为java.lang.String<> * <p>一个泛型,形式为java.lang.String<java.lang.String></p> * <p>两个个泛型,形式为java.lang.String<java.lang.String,java.lang.String></p> */ private String getBegin(Object obj) { StringBuilder builder = new StringBuilder(obj.getClass().toString().substring(6) + classPrefix); if (obj instanceof List) { List list = ((List) obj); if (!list.isEmpty()) { Object temp = list.get(0); builder.append(temp.getClass().toString().substring(6)); } } else if (obj instanceof Map) { Map map = ((Map) obj); Iterator iterator = map.keySet().iterator(); if (iterator.hasNext()) { Object key = iterator.next(); Object value = map.get(key); builder.append(key.getClass().toString().substring(6)).append(classSeparator).append(value.getClass().toString().substring(6)); } } else if (obj instanceof Set) { Set set = ((Set) obj); Iterator iterator = set.iterator(); if (iterator.hasNext()) { Object value = iterator.next(); builder.append(value.getClass().toString().substring(6)); } } builder.append(classSuffix); return builder.toString(); } @Override public byte[] serialize(Object o) throws SerializationException { if (o == null) return new byte[0]; try { String builder = getBegin(o) + separator + mapper.writeValueAsString(o); return builder.getBytes(BaseStatic.CHARSET); } catch (UnsupportedEncodingException | JsonProcessingException e) { e.printStackTrace(); } return null; } @Override public Object deserialize(byte[] bytes) throws SerializationException { if (bytes == null || bytes.length == 0) return null;//已被删除的session try { String temp = new String(bytes, BaseStatic.CHARSET); String cl[] = getClass(temp); if (cl == null) { throw new RuntimeException("错误的序列化结果=" + temp); } if (cl.length == 1) { return mapper.readValue(temp.substring(temp.indexOf(separator) + 1), Class.forName(cl[0])); } else if (cl.length == 2) { TypeFactory factory = mapper.getTypeFactory(); JavaType type = factory.constructParametricType(Class.forName(cl[0]), Class.forName(cl[1])); return mapper.readValue(temp.substring(temp.indexOf(separator) + 1), type); } else if (cl.length == 3) { TypeFactory factory = mapper.getTypeFactory(); JavaType type = factory.constructParametricType(Class.forName(cl[0]), Class.forName(cl[1]), Class.forName(cl[2])); return mapper.readValue(temp.substring(temp.indexOf(separator) + 1), type); } } catch (ClassNotFoundException | IOException e) { e.printStackTrace(); } return null; } /** * 解析字符串,获取class * <p>一个类型,java.lang.String<>={}</p> * <p>两个类型,后面为泛型,java.lang.String<java.lang.String>={}</p> * <p>三个类型,后面为泛型,java.lang.String<java.lang.String,java.lang.String>={}</p> * * @param value 包含class的字符串 * @return 返回所有类的数组 */ private String[] getClass(String value) { int index = value.indexOf(classPrefix); if (index != -1) { Matcher matcher = pattern.matcher(value.subSequence(index, value.indexOf(classSuffix) + 1)); if (matcher.find()) { String temp = matcher.group(1); if (temp.isEmpty()) {//没有泛型 return new String[]{value.substring(0, index)}; } else if (temp.contains(classSeparator)) {//两个泛型 int nextIndex = temp.indexOf(classSeparator); return new String[]{ value.substring(0, index), temp.substring(0, nextIndex), temp.substring(nextIndex + 1) }; } else {//一个泛型 return new String[]{ value.substring(0, index), temp }; } } } return null; } }标签:很赞哦! ()