社会你“小峰哥“用Java实现了管理员可以修改任意用户Session的功能 下

本文涉及的产品
云数据库 Tair(兼容Redis),内存型 2GB
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
简介: 社会你“小峰哥“用Java实现了管理员可以修改任意用户Session的功能 下

5 动态修改Session实现

我们来实现下具体代码:

我们定义一个自定义session上下文MySessionContext,里面定义HashMap属性来存储session信息,格式 sessionId :session对象;

package com.java1234.custom;
import javax.servlet.http.HttpSession;
import java.util.HashMap;
/**
 * 自定义session上下文
 * @author java1234_小锋
 * @site www.java1234.com
 * @company 南通小锋网络科技有限公司
 * @create 2021-08-05 10:39
 */
public class MySessionContext {
    private static MySessionContext instance;
    // session map存储session  如果session较多,影响到系统性能的话,可以把用redis,key-value  sessionId->session对象 session对象序列化
    public static HashMap<String,HttpSession> sessionMap;
    private MySessionContext() {
        sessionMap = new HashMap<String,HttpSession>();
    }
    /**
     * 单例
     * @return
     */
    public static MySessionContext getInstance() {
        if (instance == null) {
            instance = new MySessionContext();
        }
        return instance;
    }
    /**
     * 添加session
     * @param session
     */
    public synchronized void addSession(HttpSession session) {
        if (session != null) {
            System.out.println("session添加成功!");
            sessionMap.put(session.getId(), session);
        }
    }
    /**
     * 删除session
     * @param session
     */
    public synchronized void delSession(HttpSession session) {
        if (session != null) {
            System.out.println("session删除成功!");
            sessionMap.remove(session.getId());
        }
    }
    /**
     * 根据sessionId获取session
     * @param sessionID
     * @return
     */
    public synchronized HttpSession getSession(String sessionID) {
        if (sessionID == null) {
            return null;
        }
        return sessionMap.get(sessionID);
    }
}

新建session监听器SessionListener,监听session创建和销毁;

session创建的时候,把session信息存储到自定义session上下文;session销毁时,自定义session上下文中也删除掉该session;

注意,要加@WebListener注解

package com.java1234.listener;
import com.java1234.custom.MySessionContext;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
/**
 * session监听器
 * @author java1234_小锋
 * @site www.java1234.com
 * @company 南通小锋网络科技有限公司
 * @create 2021-08-05 10:43
 */
@WebListener
public class SessionListener implements HttpSessionListener {
    // 获取自定义session上下文实例
    private MySessionContext msc = MySessionContext.getInstance();
    /**
     * session创建事件
     * @param se
     */
    @Override
    public void sessionCreated(HttpSessionEvent se) {
        System.out.println("session创建");
        HttpSession session = se.getSession();
        msc.addSession(session);  // 添加当前session到自定义session上下文
    }
    /**
     * session销毁事件
     * @param se
     */
    @Override
    public void sessionDestroyed(HttpSessionEvent se) {
        System.out.println("session销毁");
        HttpSession session = se.getSession();
        //todo 要从数据库或者redis缓存把指定sessionId的用户session信息删除
        msc.delSession(session);  // 从自定义session上下文里删除当前session
    }
}

在springboot项目中,要使得监听器有效,我们启动类要加@ServletComponentScan注解

@ServletComponentScan,自动扫描带有(@WebServlet, @WebFilter, and @WebListener)注解的类,完成注册

0c813e62b50201f45ec8548cfbac701.png

到了这里,我们来测试下监听器是否有效;

启动项目,浏览器地址栏输入:http://localhost/user/login

2e79a83fa6fa4c3b3bee63183e65bd3.png

说明监听器触发成功,session添加成功!

session的销毁方法触发,有以下三种方式;

1、超时(一般服务器设置超时时间为30分钟)服务器会销毁session;

2、点击控制台的红色按钮异常关闭服务器要销毁session

3、手动调用session的invalidate方法session.invalidate();

为了演示,我把session有效期设置成30秒;

server:
  port: 80
  servlet:
    context-path: /
    session:
      timeout: 30s

我们执行模拟登录30秒后,只要不继续请求操作,30秒后,触发session销毁事件,session删除;

2e79a83fa6fa4c3b3bee63183e65bd3.png

修改UserController,通过session获取servletContext上下文,存储用户session信息,格式 { userId : sessionId }

/**
     * 模拟用户登录
     * @return
     */
    @RequestMapping("/login")
    public String login(HttpSession session){
        User uesr=new User(1,"java1234","123456");
        session.setAttribute("currentUser",uesr);
        System.out.println(session.getId());
        ServletContext servletContext = session.getServletContext();
        // 模拟存储用户session信息到数据库 用application模拟
        servletContext.setAttribute(String.valueOf(uesr.getId()),session.getId()); // key-value 用户id-sessionId
        return "success";
    }

创建ManagerController测试:

package com.java1234.controller;
import com.java1234.custom.MySessionContext;
import com.java1234.entity.User;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpSession;
import java.util.HashMap;
/**
 * 管理员Controller控制器
 * @author java1234_小锋
 * @site www.java1234.com
 * @company 南通小锋网络科技有限公司
 * @create 2021-08-07 23:05
 */
@RequestMapping("/manager")
@RestController
public class ManagerController {
    /**
     * 模拟用户登录
     * @return
     */
    @RequestMapping("/modifySession")
    public String modifySession(HttpSession session){
        ServletContext servletContext = session.getServletContext();
        String userId="1"; // 修改userId=1的用户
        String sessionId = (String)servletContext.getAttribute(userId);  // 从servletContext上下文 根据userId获取sessionId
        System.out.println("sessionId:"+sessionId);
        HashMap<String, HttpSession> sessionMap = MySessionContext.sessionMap; // 获取sessionMap
        HttpSession currentSession = sessionMap.get(sessionId); // 根据sessionId获取用户session
        User user = (User)currentSession.getAttribute("currentUser"); // 根据session得到用户信息
        user.setLevel("vip"); // 修改内容
        return "success";
    }
}

浏览器地址栏:http://localhost/user/login 模拟登录


浏览器地126b3723a5b3439b201dcd91ca10a09.png址栏:http://localhost/user/getUserInfo 获取用户信息

df65e1a0f8a26d590936d5210d00fe7.png

我们另外开一个浏览器地址栏:http://localhost/manager/modifySession 模拟管理员修改session

c0af42081778f09ac9e2b8e81213e6e.png

然后刷新getUserInfo;

18e48cca88f0a0c2bcfe7e3b449c685.png

我们发现session会话信息变了。测试成功!

6 高并发下的性能优化

在高并发下,同一时刻登录用户会很多,如果把session都放内存,会影响性能,甚至内存溢出;所以session可以存储到redis;

另外如下图的两个存储介质,也要存储到redis,以达到最佳性能;

810cba2134eeec163c667115c6ebf38.png

7 完整源码+配套视频教程分享

源码和文档+视频我放在了Github和码云上面,大家有需要参考源码的直接pull下,IDEA工具;

码云地址:https://gitee.com/java_1234/modify-session

Github地址: https://github.com/java1234/modify-session

8 留了一点小作业

如果你是一个有理想的程序员,不妨可以升级下锋哥的实例;

第一:搭建一个高可用的redis集群环境;

第二:springboot+redis实现session存储到redis高速缓存;

第三:如上图的两个存储介质也存储到redis;

原文地址:老板发了我2千奖金,原因是我用Java实现管理员可以修改任意用户Session功能

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
目录
相关文章
|
11天前
|
存储 小程序 前端开发
微信小程序与Java后端实现微信授权登录功能
微信小程序极大地简化了登录注册流程。对于用户而言,仅仅需要点击授权按钮,便能够完成登录操作,无需经历繁琐的注册步骤以及输入账号密码等一系列复杂操作,这种便捷的登录方式极大地提升了用户的使用体验
116 12
|
2月前
|
Java
java实现从HDFS上下载文件及文件夹的功能,以流形式输出,便于用户自定义保存任何路径下
java实现从HDFS上下载文件及文件夹的功能,以流形式输出,便于用户自定义保存任何路径下
117 34
|
3月前
|
安全 Java 测试技术
🎉Java零基础:全面解析枚举的强大功能
【10月更文挑战第19天】本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!
144 60
|
3月前
|
Java
Java 8 引入的 Streams 功能强大,提供了一种简洁高效的处理数据集合的方式
Java 8 引入的 Streams 功能强大,提供了一种简洁高效的处理数据集合的方式。本文介绍了 Streams 的基本概念和使用方法,包括创建 Streams、中间操作和终端操作,并通过多个案例详细解析了过滤、映射、归并、排序、分组和并行处理等操作,帮助读者更好地理解和掌握这一重要特性。
62 2
|
3月前
|
存储 安全 搜索推荐
理解Session和Cookie:Java Web开发中的用户状态管理
理解Session和Cookie:Java Web开发中的用户状态管理
107 4
|
4月前
|
Java 程序员
在Java编程中,关键字不仅是简单的词汇,更是赋予代码强大功能的“魔法咒语”。
【10月更文挑战第13天】在Java编程中,关键字不仅是简单的词汇,更是赋予代码强大功能的“魔法咒语”。本文介绍了Java关键字的基本概念及其重要性,并通过定义类和对象、控制流程、访问修饰符等示例,展示了关键字的实际应用。掌握这些关键字,是成为优秀Java程序员的基础。
59 3
|
4月前
|
Java 数据安全/隐私保护
Java ffmpeg 实现视频加文字/图片水印功能
【10月更文挑战第22天】在 Java 中使用 FFmpeg 实现视频加文字或图片水印功能,需先安装 FFmpeg 并添加依赖(如 JavaCV)。通过构建 FFmpeg 命令行参数,使用 `drawtext` 滤镜添加文字水印,或使用 `overlay` 滤镜添加图片水印。示例代码展示了如何使用 JavaCV 实现文字水印。
308 1
|
安全 算法 Java
Java 17 新功能介绍(LTS)
Java 17 新功能介绍(LTS)
731 0
Java 17 新功能介绍(LTS)
|
Java 测试技术 API
Java 18 新功能介绍
Java 18 新功能介绍
340 0
Java 18 新功能介绍
|
JavaScript 前端开发 算法
超详细 Java 15 新功能介绍
超详细 Java 15 新功能介绍
188 0
超详细 Java 15 新功能介绍