iis服务器助手广告广告
返回顶部
首页 > 资讯 > 精选 >spring-session自定义序列化方法是什么
  • 567
分享到

spring-session自定义序列化方法是什么

2023-06-22 05:06:16 567人浏览 独家记忆
摘要

本篇内容介绍了“spring-session自定义序列化方法是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!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("<(.*)>");      }         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;    }         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;     }}

配置spring-session序列化

在之前的配置文件上进行修改

 <bean id="springSessionDefaultRedisSerializer" class="cn.nsu.edu.web.four.session.serializer.SessionSerializer"/>    <bean id="jedisConnectionFactory"          class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory" destroy-method="destroy">        <property name="hostName" value="${redis.host}"/>        <property name="port" value="${redis.port}"/>        <property name="timeout" value="${redis.timeout}"/>        <property name="passWord" value="${redis.password}"/>        <property name="database" value="${redis.database}"/>        <property name="usePool" value="true"/>        <property name="poolConfig" ref="redisPoolConfig"/>     </bean>      <bean id="redisTemplate" class="org.springframework.data.redis.core.StringRedisTemplate">        <property name="connectionFactory" ref="jedisConnectionFactory"/>        <property name="defaultSerializer" ref="springSessionDefaultRedisSerializer"/>        <!--指定序列化类-->        <property name="valueSerializer" ref="springSessionDefaultRedisSerializer"/>        <property name="hashValueSerializer" ref="springSessionDefaultRedisSerializer"/>    </bean>

spring-session序列化问题排查

严重: Servlet.service() for servlet [spring] in context with path [/] threw exception
org.springframework.data.redis.serializer.SerializationException: Cannot serialize; nested exception is org.springframework.core.serializer.support.SerializationFailedException: Failed to serialize object using DefaultSerializer; nested exception is java.lang.IllegalArgumentException: DefaultSerializer requires a Serializable payload but received an object of type [com.moGoroom.service.vo.criteria.QueryBSPromotionListVO]
at org.springframework.data.redis.serializer.JdkSerializationRedisSerializer.serialize(JdkSerializationRedisSerializer.java:52)
at org.springframework.data.redis.core.AbstractOperations.rawHashValue(AbstractOperations.java:146)
at org.springframework.data.redis.core.DefaultHashOperations.putAll(DefaultHashOperations.java:128)
at org.springframework.data.redis.core.DefaultBoundHashOperations.putAll(DefaultBoundHashOperations.java:85)
at org.springframework.session.data.redis.RedisOperationsSessionRepository$RedisSession.saveDelta(RedisOperationsSessionRepository.java:778)
at org.springframework.session.data.redis.RedisOperationsSessionRepository$RedisSession.access$000(RedisOperationsSessionRepository.java:670)
at org.springframework.session.data.redis.RedisOperationsSessionRepository.save(RedisOperationsSessionRepository.java:388)
at org.springframework.session.data.redis.RedisOperationsSessionRepository.save(RedisOperationsSessionRepository.java:245)
at org.springframework.session.web.Http.SessionRepositoryFilter$SessionRepositoryRequestWrapper.commitSession(SessionRepositoryFilter.java:245)
at org.springframework.session.web.http.SessionRepositoryFilter$SessionRepositoryRequestWrapper.access$100(SessionRepositoryFilter.java:217)
at org.springframework.session.web.http.SessionRepositoryFilter.doFilterInternal(SessionRepositoryFilter.java:170)
at org.springframework.session.web.http.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:80)
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:344)
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:261)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:100)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:953)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1041)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:603)
at org.apache.Tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:310)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
Caused by: org.springframework.core.serializer.support.SerializationFailedException: Failed to serialize object using DefaultSerializer; nested exception is java.lang.IllegalArgumentException: DefaultSerializer requires a Serializable payload but received an object of type [com.mogoroom.service.vo.criteria.QueryBSPromotionListVO]
at org.springframework.core.serializer.support.SerializinGConverter.convert(SerializingConverter.java:67)
at org.springframework.core.serializer.support.SerializingConverter.convert(SerializingConverter.java:34)
at org.springframework.data.redis.serializer.JdkSerializationRedisSerializer.serialize(JdkSerializationRedisSerializer.java:50)
... 29 more
Caused by: java.lang.IllegalArgumentException: DefaultSerializer requires a Serializable payload but received an object of type [com.mogoroom.service.vo.criteria.QueryBSPromotionListVO]
at org.springframework.core.serializer.DefaultSerializer.serialize(DefaultSerializer.java:41)
at org.springframework.core.serializer.support.SerializingConverter.convert(SerializingConverter.java:62)
... 31 more

问题

spring session 异常信息没有打印到日志中 用是默认jdk序列化。由于实体没有序列话,导致异常,但是没有输入到日志,导致定位到问题。

在代码中 request.getSession().setAttribute()是不会出现异常的 spring session 一次请求返回的时候,才会commit,才会触发spring session提交。

代码如下:onResponseCommitted

  private final class SessionRepositoryResponseWrapper   extends OnCommittedResponseWrapper {   private final SessionRepositoryRequestWrapper request;     SessionRepositoryResponseWrapper(SessionRepositoryRequestWrapper request,    httpservletResponse response) {   super(response);   if (request == null) {    throw new IllegalArgumentException("request cannot be null");   }   this.request = request;  }   @Override  protected void onResponseCommitted() {   this.request.commitSession();  } }  OnCommittedResponseWrapper abstract class OnCommittedResponseWrapper extends HttpServletResponseWrapper {    private void doOnResponseCommitted() {  if (!this.disableOnCommitted) {   onResponseCommitted();   disableOnResponseCommitted();  } } }

doOnResponseCommitted相关依赖出发方法

spring-session自定义序列化方法是什么

解决方法

filter抓下日志

chain.doFilter(wrappedRequest, response); }catch (Exception ex){logger.error("xxf",ex);}

“spring-session自定义序列化方法是什么”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注编程网网站,小编将为大家输出更多高质量的实用文章!

--结束END--

本文标题: spring-session自定义序列化方法是什么

本文链接: https://www.lsjlt.com/news/302579.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • spring-session自定义序列化方法是什么
    本篇内容介绍了“spring-session自定义序列化方法是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!spring-session...
    99+
    2023-06-22
  • spring-session自定义序列化方式
    目录spring-session自定义序列化自定义序列方法使用jackson库配置spring-session序列化spring-session序列化问题排查问题解决方法spring...
    99+
    2024-04-02
  • Redis中怎么自定义序列化方法
    在Redis中,可以通过自定义序列化方法来对存储的数据进行序列化和反序列化。一种常见的方式是使用JSON格式来进行序列化,可以通过以...
    99+
    2024-04-29
    Redis
  • 自定义Go Json的序列化方法译文
    编译自 Custom JSON Marshalling in Go。 前言 我们知道,通过tag,可以有条件地实现定制Go JSON序列化的方式,比如json:"...
    99+
    2024-04-02
  • 如何自定义Go Json的序列化方法
    这篇文章主要讲解了“如何自定义Go Json的序列化方法”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“如何自定义Go Json的序列化方法”吧!我们知道,通过tag,可以...
    99+
    2023-07-02
  • java优先队列自定义排序的方法是什么
    Java中的优先队列(PriorityQueue)默认使用元素的自然顺序进行排序。如果想自定义排序规则,需要通过实现Comparat...
    99+
    2023-09-07
    java
  • C#序列化怎么自定义
    在C#中,可以通过实现ISerializable接口来自定义对象的序列化方式。ISerializable接口要求实现GetObjec...
    99+
    2024-03-01
    C#
  • SpringBoot @JsonDeserialize自定义Json序列化方式
    目录@JsonDeserialize自定义Json序列化1.问题2.现象3.解决办法@JsonSerialize与@JsonDeserialize使用1.以注解方式使用2.自定义实现...
    99+
    2024-04-02
  • pgsql自定义排序的方法是什么
    在 PostgreSQL 中,可以通过创建自定义排序规则来实现自定义排序。以下是实现自定义排序的一般方法: 创建自定义排序规则函...
    99+
    2024-04-09
    pgsql
  • redis自定义持久化的方法是什么
    Redis提供了两种自定义持久化的方法:RDB和AOF。1. RDB(Redis Database)是一种快照持久化方式,通过将Re...
    99+
    2023-09-06
    redis
  • springboot jackson自定义序列化和反序列化实例
    目录jackson自定义序列化和反序列序列化JsonSerializer最后请求http返回对象反序列化JsonDeserializer小结一下springboot 自定义序列化器j...
    99+
    2024-04-02
  • c++ sort自定义排序的方法是什么
    在C++中,可以使用std::sort函数来对容器进行排序。如果需要自定义排序方法,可以使用函数指针、函数对象或lambda表达式来...
    99+
    2023-10-21
    c++
  • Spring session redis 修改默认的序列化方法(案例)
    目录一、配置Spring-session-redis 的关键配置如下:二、查看 RedisHttpSessionConfiguration 源代码如下:三、RedisTemplate...
    99+
    2023-05-14
    Spring session redis 修改序列化 Spring session redis 序列化
  • 搭建spring自定义脚手架的方法是什么
    搭建Spring自定义脚手架的方法主要有以下步骤: 创建项目模板:根据项目需求,创建一个基础的项目模板,包括项目结构、配置文件、...
    99+
    2024-03-15
    spring
  • 如何自定义Jackson序列化 @JsonSerialize
    目录自定义Jackson序列化 @JsonSerializejackson自定义全局序列化、反序列化创建序列化类创建反序列化类将两个类注册进入jackson核心对象objectMap...
    99+
    2024-04-02
  • golang序列化方法是什么
    这篇文章主要讲解了“golang序列化方法是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“golang序列化方法是什么”吧!golang序列化方法有:1、利用Gob包管理gob流,gob...
    99+
    2023-07-04
  • jpa自定义排序查询的方法是什么
    在JPA中,可以使用以下方法自定义排序查询:1. 使用@Query注解:可以在查询方法上添加@Query注解,通过JPQL或者SQL...
    99+
    2023-09-16
    jpa
  • golang序列化和反序列化的方法是什么
    Go语言中序列化和反序列化可以通过将数据转换为字节流格式来实现,常见方法有“JSON序列化和反序列化”、“XML序列化和反序列化”、“gob序列化和反序列化”和“Protocol Buffers序列化和反序列化”四种:1、使用“json.M...
    99+
    2023-12-18
    golang反序列化 golang序列化 Golang go语言
  • springboot序列化和反序列化怎么定义
    在Spring Boot中,序列化和反序列化可以通过以下方式进行定义:1. 实现Serializable接口:在需要进行序列化和反序...
    99+
    2023-08-14
    springboot
  • Spring Cloud自定义引导属性源的方法是什么
    本篇内容介绍了“Spring Cloud自定义引导属性源的方法是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!引导过程添加的外部配置的默...
    99+
    2023-06-05
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作