热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

springsession实现分布式session共享及自定义sessionid

官方文档地址:http:projects.spring.iospring-sessionhttp:docs.spring.iospring-sessiondocscurrentre

官方文档地址:http://projects.spring.io/spring-session/
http://docs.spring.io/spring-session/docs/current/reference/html5/guides/httpsession.html

Spring Session为企业级Java应用的session管理带来了革新,使得以下的功能更加容易实现:

  • 将session所保存的状态卸载到特定的外部session存储中,如Redis、mongo或gemfire中,它们能够以独立于应用服务器的方式提供高质量的集群。
  • 当用户使用WebSocket发送请求的时候,能够保持HttpSession处于活跃状态。
  • 在非Web请求的处理代码中,能够访问session数据,比如在JMS消息的处理代码中。
  • 支持每个浏览器上使用多个session,从而能够很容易地构建更加丰富的终端用户体验。
  • 控制session id如何在客户端和服务器之间进行交换,这样的话就能很容易地编写Restful API,因为它可以从HTTP 头信息(或者参数)中获取session id,而不必再依赖于COOKIE。
话不多说,上集成代码吧(*^__^*) …
spring-session实现分布式session共享及自定义sessionid
首先加入maven引用:
<dependency>  
                <groupId>org.springframework.sessiongroupId>  
                <artifactId>spring-session-data-redisartifactId>  
                <version>1.2.2.RELEASEversion>  
                <type>pomtype>  
dependency>  
<dependency>  
                <groupId>org.springframeworkgroupId>  
                <artifactId>spring-webartifactId>  
                <version>4.2.5.RELEASEversion>  
dependency>

HttpSessionConfig:

//maxInactiveIntervalInSeconds为session过期时间,这里注意session过期时间配置在web.xml里面是不起作用的  
@Configuration  
@EnableRedisHttpSession(maxInactiveIntervalInSeconds=999)  
public class HttpSessionConfig {  
  
        //这里有个小坑,如果服务器用的是云服务器,不加这个会报错  
        @Bean  
        public static ConfigureRedisAction configureRedisAction() {  
            return ConfigureRedisAction.NO_OP;  
        }  
  
        //这里是reids连接配置  
        @Bean  
        public JedisConnectionFactory connectionFactory() {  
            JedisConnectionFactory connection = new JedisConnectionFactory();  
            connection.setPort(6379);  
            connection.setHostName("127.0.0.1");  
            connection.setPassword("ps123456");  
            connection.setDatabase(8);  
            return connection;  
        }  
  
        //session策略,这里配置的是Header方式(有提供Header,COOKIE等方式),可自定义,后面会详细讲  
        @Bean  
        public HttpSessionStrategy httpSessionStrategy() {  
                return new HeaderHttpSessionStrategy();  
        }  
  
}  

Initializer:

public class Initializer extends AbstractHttpSessionApplicationInitializer {  
                  
}  
到这里就可以把工程跑起来了,上面提到使用的session策略是HeaderHttpSessionStrategy,restful可以使用这种方式。看HeaderHttpSessionStrategy源码可以知道,HeaderHttpSessionStrategy实现了HttpSessionStrategy接口。哈~也就是说,如果要自定义策略的话,也实现HttpSessionStrategy就可以了。
getRequestedSessionId()方法,获取客户端传过来的sessionid,如果没有传spring会通过UUID的方式分配一个(这里springsession没有支持自定义sessionidspring-session实现分布式session共享及自定义sessionid),
然后onNewSession()和onInvalidateSession()就不用说了,创建和销毁嘛~
public class HeaderHttpSessionStrategy implements HttpSessionStrategy {  
    private String headerName = "x-auth-token";  
  
    public String getRequestedSessionId(HttpServletRequest request) {  
        return request.getHeader(this.headerName);  
    }  
  
    public void onNewSession(Session session, HttpServletRequest request,  
            HttpServletResponse response) {  
        response.setHeader(this.headerName, session.getId());  
    }  
  
    public void onInvalidateSession(HttpServletRequest request,  
            HttpServletResponse response) {  
        response.setHeader(this.headerName, "");  
    }  
  
    /** 
     * The name of the header to obtain the session id from. Default is "x-auth-token". 
     * 
     * @param headerName the name of the header to obtain the session id from. 
     */  
    public void setHeaderName(String headerName) {  
        Assert.notNull(headerName, "headerName cannot be null");  
        this.headerName = headerName;  
    }  
}  
好啦,下面就来说自定义sessionid吧~
一些特别的鉴权场景,需要由应用层自己控制生成sessionid,那么先看看源码~
public final class MapSession implements ExpiringSession, Serializable {  
    /** 
     * Default {@link #setMaxInactiveIntervalInSeconds(int)} (30 minutes). 
     */  
    public static final int DEFAULT_MAX_INACTIVE_INTERVAL_SECOnDS= 1800;  
  
    private String id;  
    private Map sessiOnAttrs= new HashMap();  
    private long creatiOnTime= System.currentTimeMillis();  
    private long lastAccessedTime = this.creationTime;  
  
    /** 
     * Defaults to 30 minutes. 
     */  
    private int maxInactiveInterval = DEFAULT_MAX_INACTIVE_INTERVAL_SECONDS;  
  
    /** 
     * Creates a new instance with a secure randomly generated identifier. 
     */  
    public MapSession() {  
        this(UUID.randomUUID().toString());  
    }  
  
    /** 
     * Creates a new instance with the specified id. This is preferred to the default 
     * constructor when the id is known to prevent unnecessary consumption on entropy 
     * which can be slow. 
     * 
     * @param id the identifier to use 
     */  
    public MapSession(String id) {  
        this.id = id;  
    }  
看org.springframework.session.MapSession发现,新建session的时候,构造 方法默认就是使用UUID做id,并调用MapSession(String id)构造方法给id赋值。
在看org.springframework.session.SessionRepository接口:
public interface SessionRepositoryextends Session> {  
  
    S createSession();  
  
    void save(S session);  
      
    S getSession(String id);  
  
    void delete(String id);  
}  
发现并没有S createSession(String id);的方法,后面通过改源码的方式实现了自定义id的功能。加了一个S createSession(String id);的方法,并通过getRequestedSessionId();把id拿过来传参。这里就不详讲了,因为这种方式特别不友好。
Another way:
可以自定义一个session策略,在用户id和sessionid之间加一个映射保存在redis,在onNewSession()创建映射关系,在getRequestedSessionId()时找用户id对应的sessionid返回。
下面是MyHttpSessionStrategy代码,HttpSessionConfig里面的httpSessionStrategy()改为自己写的就可以了。
public class MyHttpSessionStrategy implements HttpSessionStrategy {  
  
    private final Logger logger = LoggerFactory.getLogger(WlwHttpSessionStrategy.class);  
  
    //这用Qualifier注解,如果你的工程还集成了spring-data-redis,需要指定一下用哪一个  
    @Qualifier("sessionRedisTemplate")  
    @Autowired  
    private RedisTemplate redisTemplate;  
//过期时间,与session过期时间保持一致  
    private Long maxInactiveIntervalInSecOnds= 999L;  
    private String xxxRedisName = "spring:session:xxx:";  
    //当客户端没有传xxx参数的时候,避免创建多个无用的session占用redis空间  
    private String defaultSessiOnId= "default-sessionid";  
  
    /** 
     * 客户端传过来的是xxx,需要通过xxx查找映射关系,拿到sessionid返回 
     */  
    public String getRequestedSessionId(HttpServletRequest request) {  
        String xxx = request.getParameter("xxx");  
        ValueOperations vops = redisTemplate.opsForValue();  
        if (xxx != null && !xxx.equals("")) {  
            String sessionid = vops.get(xxxRedisName + xxx);  
            if(sessionid!=null){  
                redisTemplate.expire(xxxRedisName + xxx, maxInactiveIntervalInSeconds, TimeUnit.SECONDS);  
            }  
            return sessionid;  
        } else {  
            return vops.get(xxxRedisName+defaultSessionId);  
        }  
    }  
  
    /** 
     * 创建session时,保存xxx和sessionid的映射关系 
     */  
    public void onNewSession(Session session, HttpServletRequest request,  
                             HttpServletResponse response) {  
        String xxx = request.getParameter("xxx");  
        String sessionid = session.getId();  
        ValueOperations vops = redisTemplate.opsForValue();  
        if (xxx != null && !xxx.equals("")) {  
            //保存xxx和sessionid映射关系  
            vops.set(xxxRedisName + xxx, sessionid);  
            redisTemplate.expire(xxxRedisName + xxx, maxInactiveIntervalInSeconds, TimeUnit.SECONDS);  
        }else{  
            //没有传xxx时,保存为默认  
            vops.set(xxxRedisName+defaultSessionId, sessionid);  
            redisTemplate.expire(xxxRedisName+defaultSessionId, maxInactiveIntervalInSeconds, TimeUnit.SECONDS);  
        }  
    }  
  
    public void onInvalidateSession(HttpServletRequest request,  
                                    HttpServletResponse response) {  
        String xxx = request.getParameter("xxx");  
        redisTemplate.expire(xxxRedisName + xxx, 0, TimeUnit.SECONDS);  
    }  
  
} 

好了,完工了。。。


推荐阅读
  • 本文探讨了利用Java实现WebSocket实时消息推送技术的方法。与传统的轮询、长连接或短连接等方案相比,WebSocket提供了一种更为高效和低延迟的双向通信机制。通过建立持久连接,服务器能够主动向客户端推送数据,从而实现真正的实时消息传递。此外,本文还介绍了WebSocket在实际应用中的优势和应用场景,并提供了详细的实现步骤和技术细节。 ... [详细]
  • Ceph API微服务实现RBD块设备的高效创建与安全删除
    本文旨在实现Ceph块存储中RBD块设备的高效创建与安全删除功能。开发环境为CentOS 7,使用 IntelliJ IDEA 进行开发。首先介绍了 librbd 的基本概念及其在 Ceph 中的作用,随后详细描述了项目 Gradle 配置的优化过程,确保了开发环境的稳定性和兼容性。通过这一系列步骤,我们成功实现了 RBD 块设备的快速创建与安全删除,提升了系统的整体性能和可靠性。 ... [详细]
  • 本文深入探讨了ASP.NET Web API与RESTful架构的设计与实现。ASP.NET Web API 是一个强大的框架,能够简化HTTP服务的开发,使其能够广泛支持各种客户端设备。通过详细分析其核心原理和最佳实践,本文为开发者提供了构建高效、可扩展且易于维护的Web服务的指导。此外,还讨论了如何利用RESTful原则优化API设计,确保系统的灵活性和互操作性。 ... [详细]
  • 开机自启动的几种方式
    0x01快速自启动目录快速启动目录自启动方式源于Windows中的一个目录,这个目录一般叫启动或者Startup。位于该目录下的PE文件会在开机后进行自启动 ... [详细]
  • 秒建一个后台管理系统?用这5个开源免费的Java项目就够了
    秒建一个后台管理系统?用这5个开源免费的Java项目就够了 ... [详细]
  • 基于Net Core 3.0与Web API的前后端分离开发:Vue.js在前端的应用
    本文介绍了如何使用Net Core 3.0和Web API进行前后端分离开发,并重点探讨了Vue.js在前端的应用。后端采用MySQL数据库和EF Core框架进行数据操作,开发环境为Windows 10和Visual Studio 2019,MySQL服务器版本为8.0.16。文章详细描述了API项目的创建过程、启动步骤以及必要的插件安装,为开发者提供了一套完整的开发指南。 ... [详细]
  • 如何使用 `org.apache.tomcat.websocket.server.WsServerContainer.findMapping()` 方法及其代码示例解析 ... [详细]
  • 深入探索Node.js新框架:Nest.js第六篇
    在本文中,我们将深入探讨Node.js的新框架Nest.js,并通过一个完整的示例来展示其强大功能。我们将使用多个装饰器创建一个基本控制器,该控制器提供了多种方法来访问和操作内部数据,涵盖了常见的CRUD操作。此外,我们还将详细介绍Nest.js的核心概念和最佳实践,帮助读者更好地理解和应用这一现代框架。 ... [详细]
  • 基于Node.js的高性能实时消息推送系统通过集成Socket.IO和Express框架,实现了高效的高并发消息转发功能。该系统能够支持大量用户同时在线,并确保消息的实时性和可靠性,适用于需要即时通信的应用场景。 ... [详细]
  • PyQt5 QTextEdit:深入解析Python中多功能GUI库的应用与实现
    本文详细探讨了 PyQt5 中 QTextEdit 组件在 Python 多功能 GUI 库中的应用与实现。PyQt5 是 Qt 框架的 Python 绑定,提供了超过 620 个类和 6000 个函数及方法,广泛应用于跨平台应用程序开发。QTextEdit 作为其中的重要组件,支持丰富的文本编辑功能,如富文本格式、文本高亮和自定义样式等。PyQt5 的流行性不仅在于其强大的功能,还在于其易用性和灵活性,使其成为开发复杂用户界面的理想选择。 ... [详细]
  • REST API 时代落幕,GraphQL 持续引领未来
    尽管REST API已广泛使用多年,但在深入了解GraphQL及其解决的核心问题后,我深感其将引领未来的API设计趋势。GraphQL不仅提高了数据查询的效率,还增强了灵活性和性能,有望成为API开发的新标准。 ... [详细]
  • 本文将带你快速了解 SpringMVC 框架的基本使用方法,通过实现一个简单的 Controller 并在浏览器中访问,展示 SpringMVC 的强大与简便。 ... [详细]
  • 微信公众号推送模板40036问题
    返回码错误码描述说明40001invalidcredential不合法的调用凭证40002invalidgrant_type不合法的grant_type40003invalidop ... [详细]
  • 本文深入探讨了在Spring Boot中处理RESTful风格的表单请求的方法,包括请求参数处理、请求映射以及RESTful设计原则的应用。文章详细介绍了如何利用HTTP动词(如GET、POST、PUT、DELETE)来操作资源,并结合Spring Boot的注解(如@GetMapping、@PostMapping等)实现高效、清晰的请求处理逻辑。通过实例分析,展示了如何在实际项目中应用这些技术,提高开发效率和代码可维护性。 ... [详细]
  • 深入解析 Vue 中的 Axios 请求库
    本文深入探讨了 Vue 中的 Axios 请求库,详细解析了其核心功能与使用方法。Axios 是一个基于 Promise 的 HTTP 客户端,支持浏览器和 Node.js 环境。文章首先介绍了 Axios 的基本概念,随后通过具体示例展示了如何在 Vue 项目中集成和使用 Axios 进行数据请求。无论你是初学者还是有经验的开发者,本文都能为你解决 Vue.js 相关问题提供有价值的参考。 ... [详细]
author-avatar
没搜摸索摸索_685
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有