Redis实战之session共享

更新时间:2025-05-10 21:00:34 阅读: 评论:0

<a href=http://www.ranqi119.com/ge/78/637265.html style=Redis实战session共享"/>

Redis实战之session共享

当线上集群时候,会出现session共享问题。

虽然Tomcat提供了session copy的功能,但是缺点比较明显:

1:当Tomcat多的时候,session需要大量同步到多台集群上,占用内网宽带

2:同一个用户session,需要在多个Tomcat中都存在,浪费内存空间

如果要替换掉Tomcat的session共享,替代方案应该满足:

1:数据共享

2:内存存储

3:key\value结构

基于Redis实现共享session登录

再来回顾下将验证码保存在session中业务流程

展开全文

我们在session中存放的是:session.setAttribute("code", code); 因为session的特点,每次访问都是一个新的sessionId.我们可以直接使用code作为key.思考:那么如果换成了Redis,还能使用code作为可以吗?

将用户信息存放在session中流程:

用户信息在session中存放:session.setAttribute("user", user); 同样思考:那么如歌词找歌果换成了Redis,还能使用user作为可以吗?

将code和user信息存放在Redis中,流程如下:

验证码数据结构是:string类型的

用户对象数据类型是:hash类型的

根据上面分析,我们修改原来代码:

需要考虑的是:Redis的key规则、过期时间

1:发送验证码的时候,将验证码存放到Redis中时候,需要考虑过期时间。其核心代码如下:

stringRedisTemplate.opsForValue().set(LOGIN_CODE_KEY + phone, code, LOGIN_CODE_TTL, TimeUnit.MINUTES);

2:用户登录的时候,将校验验证码以及用户信息存放到Redis中后,返回token

需要考虑的:

1:token不能重复

2:用户过期时间

3:登录成功后,要将token返回给前端

4:用户只要访问,Redis中的过期时间就要延长-在拦截器中处理的

用户登录核心代码修改:

//2.1:校验验证码是否正确

//String c算时间ode = (String) session.getAttribute("code");

String code = stringRedisTemplate.opsForValue().get(LOGIN_CODE_KEY + phone);

if (StringUtils.isEmpty(code) || !code.equals(loginForm.getCode())) {

return Result.fail("验证码错误!");

//2.2:根据手机号查询,如果不存在,创建新用户

QueryWrapper<User> queryWrapper = new QueryWrapper<>();

queryWrapper.select("id", "phone", "nick_name");

queryWrapper.eq("phone", phone);

User user = thisnaozhong.getOne(queryWrapper);

if (Objects.isNull(user)) {

log.info("新建用户");

//新建用户

user = createUserWithPhone(phone);

//2.3:保存用户到session中

UserDTO userDTO = new UserDTO();

userDTO.setId(user.getId());

userDTO.setIcon(user.getIcon());

userDTO.setNickName(user.getNickName());

//session.setAttribute("user", 口苦的原因userDTO);

//2.3.1:获取随机的token,作为用户登录的令牌

String token = UUID.randomUUID().toString(true);

//2.3.2:将用户以hash类型存放到Redis中==》将user对象转换成map

//user对象里有非string类型的字段,用这个方法会报错的

// Map<String,Object> userMap = BeanUtil.beanToMap(userDTO);

Map<String,Object> userMap = BeanUtil.beanToMap(userDTO,new HashMap<>()

, CopyOptions.create()

.setIgnoreNullValue(true)

.se知错就改的作文tFieldValueEditor((fieldName,fieldValue)->fieldValue.toString()));

stringRedisTemplate.opsForHash().putAll(LOGIN_USER_T思维缜密OKEN_KEY+token,userMap);

//LOGIN_USER_TOKEN_TTL

stringRedisTemplate.expire(LOGIN_USER_TOKEN_KEY+token,LOGIN_USER_TOKEN_TTL,TimeUnit.MINUTES);

//2.3.3: 将token返回

return Result.ok(token);

需要注意:

在使用stringRedisTemp乐此不疲的意思late存放hash对象的时候,对象中所有的key只能是string类型,如果存在非string类型会报错的。所以这里使用了hootool的BeanUtil工具类:

Map<String,Object> userMap = BeanUtil.beanToMap(userDTO,new HashMap<>()

, CopyOptions.create()

.setIgnoreNullValue(true)

.setFieldValueEditor((fieldName,fieldValue)->fieldValue.toString()));

拦截器修改代码:

因为拦截器是我们自定义的,所以不能被spring容器管理的,RedisTemplate就不能自动注入了。我们就使用有参构造器,传递:

public class LoginRedisInterceptor implements HandlerInterceptor {

private StringRedisTemplate stringRedisTemplate;

* 因为这个类不能被spring管理,所以不能直接注入RedisTemplate对象。通过构造函数传递

* @param stringRedisTemplate

public L千呼万唤的意思oginRedisInterceptor(StringRedisTemplate stringRedisTemplate){

this.stringRedisTemplate = stringRedisTemplate;

@Override

装修设计方案

public boolean preHandle( {

//1:从请求中获取到token

String token = request.getHeader("authorization");

if(StringUtils.isEmpty(token)){

response.setStatus(401);

return false;

//2:基于token获取redis中用户对象

String key = LOGIN_USER_TOKEN_KEY+token;

Map<Object,Object> userMap = stringRedisTemplate.opsForHash().entries(key);

//3:判断

if(userMap.isEmpty()){

response.setStatus(401);

return false;

//将map转对象

UserDTO user = BeanUtil.fillBeanWithMap(userMap, new UserDTO(), false);

U小众景点serHolder.saveUser(user);

//刷新token的过期时间

stringRedisTemplate.expire(key,LOGIN_USER_TOKEN_TTL, TimeUnit.MINUTES);

return true;

@Override

public void afterCompletion( {

UserHolder.removeUser();

总结:

在使用Redis替换session的时候,需要考虑的问题:

1:选择合适的数据结构

2:选择合适的key

3:选择合适的存储粒度

大家好,我是凯哥Java(kaigejava),乐于分享技术文章,欢迎大家关注“凯哥Java”,及时了解更多。让我们一起学Java。也欢迎大家有事没事就来和凯哥聊聊~~~

本文发布于:2023-07-26 21:31:38,感谢您对本站的认可!

本文链接:http://www.ranqi119.com/ge/78/640850.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:实战   Redis   session
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2022 Comsenz Inc.Powered by © 站长QQ:55-9-10-26|友情:优美诗词|电脑我帮您|扬州装修|369文学|学编程|软件玩家|水木编程|编程频道