shiro redis集群介绍

来源:互联网 发布:ubuntu terminator 编辑:程序博客网 时间:2024/05/19 22:47

本文主要针对shiro和redis的集群,讲解why shiro+redis集群以及集群的好处。完整项目的源码请查看(附件源码已撤销):研究完善的shiro redis集群项目 有源码

   下面主要讲解web项目开发中如何使用shiroredis集群shiro redis集群介绍:
当一个使用shiro开发的项目被定位为单机部署,不需要集群部署时,我们可以不考虑shiro redis集群;然而很多大型项目是需要集群部署的,以应对高并发访问量。
使用shiro开发的项目做集群,为什么需要考虑结合redis缓存呢,原因有两个,一是shiro的session管理,二是shiro的缓存管理。
shiro redis做集群的好处是可以使用redis管理shiro session,解决集群中session同步的问题,又解决集群中缓存应用的问题。
redis缓存是单独的一台服务器,管理着所有集群节点中的shiro session(会话),也管理着整套中缓存的内容。
shiro项目集群最好是使用redis或者memcached缓存替换shiro框架里的默认缓存,这样可更好的管理,提升系统性能。
附件是完整的shiro redis集群web项目,shiro redis集群源码,使用maven搭建,下载下来导入eclipse,install所依赖的jar包即可部署运行。
可运行在jetty/tomcat/jboss等web服务器上。附件是个很好的学习例子,本人根据这个例子,添加了一些新的功能,如根据session管理在线用户,session超时用户退出时清空用户对应信息等,如有需要,欢迎交流!
附件web项目截图:
shiro redis集群介绍 附代码贡献
下面是项目中几个关键类:
JedisShiroSessionRepository.java
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
packagecom.michaelliuyang.shiro.demo.session;
 
importcom.michaelliuyang.shiro.demo.JedisManager;
importcom.michaelliuyang.shiro.demo.SerializeUtil;
 
importorg.apache.shiro.cache.CacheException;
importorg.apache.shiro.session.Session;
importorg.apache.shiro.util.CollectionUtils;
 
importjava.io.Serializable;
importjava.util.ArrayList;
importjava.util.Collection;
importjava.util.Collections;
importjava.util.List;
importjava.util.Set;
 
/**
 * redis save shiro session class
 * From:<a href="http://www.zyiqibook.com">在一起:技术分享_源码分享平台</a> 欢迎到网站进行交流
 */
publicclass JedisShiroSessionRepository implementsShiroSessionRepository {
 
    privatestatic final String REDIS_SHIRO_SESSION = "shiro_session:";
    // private static final int SESSION_VAL_TIME_SPAN = 1800;
    privatestatic final int DB_INDEX = 0;
 
    privateJedisManager jedisManager;
 
    @Override
    publicvoid saveSession(Session session) {
        if(session == null|| session.getId() == null)
            thrownew NullPointerException("session is empty");
        try{
            byte[] key = SerializeUtil.serialize(buildRedisSessionKey(session
                    .getId()));
            byte[] value = SerializeUtil.serialize(session);
            longsessionTimeOut = session.getTimeout() / 1000;
            Long expireTime = sessionTimeOut + (5* 60);// +
                                                        // SESSION_VAL_TIME_SPAN
                                                        // + (5 * 60);
            getJedisManager().saveValueByKey(DB_INDEX, key, value,
                    expireTime.intValue());
        }catch (Exception e) {
            e.printStackTrace();
            System.out.println("save session error");
        }
    }
 
    @Override
    publicvoid deleteSession(Serializable id) {
        if(id == null) {
            thrownew NullPointerException("session id is empty");
        }
        try{
            getJedisManager().deleteByKey(DB_INDEX,
                    SerializeUtil.serialize(buildRedisSessionKey(id)));
        }catch (Exception e) {
            e.printStackTrace();
            System.out.println("delete session error");
        }
    }
 
    @Override
    publicSession getSession(Serializable id) {
        if(id == null)
            thrownew NullPointerException("session id is empty");
        Session session =null;
        try{
            byte[] value = getJedisManager().getValueByKey(DB_INDEX,
                    SerializeUtil.serialize(buildRedisSessionKey(id)));
            session = SerializeUtil.deserialize(value, Session.class);
        }catch (Exception e) {
            e.printStackTrace();
            System.out.println("get session error");
        }
        returnsession;
    }
 
    @Override
    publicCollection<Session> getAllSessions() {
        System.out.println("get all sessions");
        try{
            Set<byte[]> keys = jedisManager.keys("*session*");
            if(!CollectionUtils.isEmpty(keys)) {
                List<Session> values =new ArrayList<Session>(keys.size());
                for(byte[] key : keys) {
                    Session value = SerializeUtil.deserialize(getJedisManager()
                            .getValueByKey(DB_INDEX, key), Session.class);
                    System.out.println("get all sessions---活动session---"
                            + value.getId());
                    if(value != null) {
                        values.add(value);
                    }
                }
                returnCollections.unmodifiableList(values);
            }else {
                returnCollections.emptyList();
            }
        }catch (Throwable t) {
            thrownew CacheException(t);
        }
    }
 
    privateString buildRedisSessionKey(Serializable sessionId) {
        returnREDIS_SHIRO_SESSION + sessionId;
    }
 
    publicJedisManager getJedisManager() {
        returnjedisManager;
    }
 
    publicvoid setJedisManager(JedisManager jedisManager) {
        this.jedisManager = jedisManager;
    }
}

CustomShiroSessionDAO.java
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
packagecom.michaelliuyang.shiro.demo.session;
 
importorg.apache.shiro.session.Session;
importorg.apache.shiro.session.UnknownSessionException;
importorg.apache.shiro.session.mgt.eis.AbstractSessionDAO;
 
importjava.io.Serializable;
importjava.util.Collection;
 
/**
 * custom shiro sessionDAO
 * From:<a href="http://www.zyiqibook.com">在一起:技术分享_源码分享平台</a> 欢迎到网站进行交流
 */
publicclass CustomShiroSessionDAO extends AbstractSessionDAO {
 
    privateShiroSessionRepository shiroSessionRepository;
 
    @Override
    publicvoid update(Session session) throws UnknownSessionException {
        System.out.println("update session----更新:"+session.getId());
        getShiroSessionRepository().saveSession(session);
    }
 
    @Override
    publicvoid delete(Session session) {
        if(session == null) {
            return;
        }
        Serializable id = session.getId();
        if(id != null) {
            System.out.println("delete session----:"+id);
            getShiroSessionRepository().deleteSession(id);
        }
        //TODO if session is too large,when session destory clear shiro cache
    }
 
    @Override
    publicCollection<Session> getActiveSessions() {
        returngetShiroSessionRepository().getAllSessions();
    }
 
    @Override
    protectedSerializable doCreate(Session session) {
        Serializable sessionId =this.generateSessionId(session);
        this.assignSessionId(session, sessionId);
        getShiroSessionRepository().saveSession(session);
        System.out.println("do create session----建完后:"+sessionId);
        returnsessionId;
    }
 
    @Override
    protectedSession doReadSession(Serializable sessionId) {
        System.out.println("do read session----参数:"+sessionId);
        returngetShiroSessionRepository().getSession(sessionId);
    }
 
    publicShiroSessionRepository getShiroSessionRepository() {
        returnshiroSessionRepository;
    }
 
    publicvoid setShiroSessionRepository(
            ShiroSessionRepository shiroSessionRepository) {
        this.shiroSessionRepository = shiroSessionRepository;
    }
 
}

本站另外一篇关于shiro技术的文章也可参考:Shiro登录 配置filterChainDefinitions
附上shiro的一些技术内容:
org.apache.shiro.spring.web.ShiroFilterFactoryBean在spring配置文件中各个属性含义:
    loginUrl:登录页
    successUrl:登录成功后跳转页面
    anon:匿名过滤器,不用登录也可以访问
        authc:如果继续操作,需要做对应的表单验证否则不能通过
        authcBasic:基本http验证过滤,如果不通过,跳转登录页面
        logout:登录退出过滤器
        noSessionCreation:没有session创建过滤器
        perms:权限过滤器
        port:端口过滤器,可以设置是否是指定端口如果不是跳转到登录页面
        rest:http方法过滤器,可以指定如post不能进行访问等
        roles:    角色过滤器,判断当前用户是否指定角色
        ssl:请求需要通过ssl,如果不是跳转回登录页
        user:如果访问一个已知用户,比如记住我功能,走这个过滤器
 单机/集群配置说明:
        1.如采用单机的shiro配置
          securityManager的sessionManager属性不需要注入,shiro会使用默认的serlvet容器实现的sessionManager;
          securityManager的cahceManager属性需要注入,shiro自带的本机内存缓存实现类memoryConstrainedCacheManager;
        2.如果采用集群部署方案
          securityManager的sessionManager属性需要注入,shiro自带的defaultWebSessionManager(web实现);
          securityManager的cahceManager属性需要注入,自己实现的cacheManager类customShiroCacheManager

本文附件:shiro-redis-cluster-master集群_maven项目.rar


 文摘标签:shiro redis集群,web项目,集群源码,memcached,shiro集群,redis

 本文地址:shiro redis集群介绍 附代码贡献   ,在一起 - 牵线你我,转载请保留出处!

1 0