前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >妙用Spring Request Bean实现分布式会话管理

妙用Spring Request Bean实现分布式会话管理

作者头像
十毛
发布2019-03-27 11:46:05
6550
发布2019-03-27 11:46:05
举报

实现分布式会话的常用模式,是把会话信息集中保存在Redis服务器中,业务服务器实现为负状态模式,方便会话的一致性。利用Spring中的request bean,可以非常优雅地实现会话信息的自动管理。

会话信息管理(LazyRedisSession)

import com.google.common.base.Strings;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Scope;
import org.springframework.context.annotation.ScopedProxyMode;
import org.springframework.stereotype.Component;
import org.springframework.web.context.WebApplicationContext;
import redis.clients.jedis.JedisCommands;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 基于Redis的懒加载会话信息(没有与Redis实时保持统统不).
 *
 * @author tenmao
 */
@Slf4j
@Scope(value = WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS)
@Getter
@Component
public class LazyRedisSession {
    private static final String PREFIX = "com.tenmao.redis.";

    @Resource
    private JedisCommands jedisCommands;

    @Resource
    private HttpServletRequest request;

    private String sessionId;

    private Map<String, String> attributes = new ConcurrentHashMap<>();

    @PostConstruct
    private void init() {
        //这里是从HttpServletRequest中获取会话ID,实际项目中,也可以从ThreadLocal或者MDC中获取
        sessionId = request.getHeader("Session-Id");
        log.info("redis session loaded for session [{}]", sessionId);
        if (!Strings.isNullOrEmpty(sessionId)) {
            final Map<String, String> attributesInRedis = jedisCommands.hgetAll(PREFIX + sessionId);
            attributes.putAll(attributesInRedis);
        }
    }

    @PreDestroy
    private void close() {
        log.info("redis session saved to redis session [{}]", sessionId);
        if (!Strings.isNullOrEmpty(sessionId)) {
            jedisCommands.del(PREFIX + sessionId);
            if (!attributes.isEmpty()) {
                jedisCommands.hmset(PREFIX + sessionId, attributes);
            }
        }
    }

    /**
     * Binds an object to this session, using the name specified.
     * If an object of the same name is already bound to the session,
     * the object is replaced.
     *
     * @param name  the name to which the object is bound;
     *              cannot be null
     * @param value the string to be bound
     */
    public void setAttribute(String name, String value) {
        attributes.put(name, value);
    }

    /**
     * Returns the object bound with the specified name in this session, or
     * <code>null</code> if no object is bound under the name.
     *
     * @param name a string specifying the name of the object
     * @return the string with the specified name
     */
    public String getAttribute(String name) {
        return attributes.get(name);
    }
}

使用

使用方式特别简单,就把LazeRedisSession当做普通的bean注入到其他Bean中就可以了

@RestController
@RequestMapping("test")
public class TestController {
    @Resource
    private LazyRedisSession lazyRedisSession;
    @RequestMapping(value = "/ping", method = RequestMethod.GET)
    public String ping(@RequestParam String name) {
        final String lastName = lazyRedisSession.getAttribute("name");
        lazyRedisSession.setAttribute("name", name);
        return lastName;
    }
}

ps: 这个方法在实践中特别好用,如果你有其他的方法,还请不吝赐教

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018.09.30 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 会话信息管理(LazyRedisSession)
  • 使用
相关产品与服务
云数据库 Redis
腾讯云数据库 Redis(TencentDB for Redis)是腾讯云打造的兼容 Redis 协议的缓存和存储服务。丰富的数据结构能帮助您完成不同类型的业务场景开发。支持主从热备,提供自动容灾切换、数据备份、故障迁移、实例监控、在线扩容、数据回档等全套的数据库服务。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档