shiro redis集群介绍

本文主要针对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/ jbossweb服务器上。附件是个很好的学习例子,本人根据这个例子,添加了一些新的功能,如根据session管理在线用户,session超时用户退出时清空用户对应信息等,如有需要,欢迎交流!

下面是项目中几个关键类:
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
package com.michaelliuyang.shiro.demo.session;
 
import com.michaelliuyang.shiro.demo.JedisManager;
import com.michaelliuyang.shiro.demo.SerializeUtil;
 
import org.apache.shiro.cache.CacheException;
import org.apache.shiro.session.Session;
import org.apache.shiro.util.CollectionUtils;
 
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Set;
 
/**
  * redis save shiro session class
  * From:<a href="http://www.zyiqibook.com">在一起:技术分享_源码分享平台</a> 欢迎到网站进行交流
  */
public class JedisShiroSessionRepository implements ShiroSessionRepository {
 
     private static final String REDIS_SHIRO_SESSION = "shiro_session:" ;
     // private static final int SESSION_VAL_TIME_SPAN = 1800;
     private static final int DB_INDEX = 0 ;
 
     private JedisManager jedisManager;
 
     @Override
     public void saveSession(Session session) {
         if (session == null || session.getId() == null )
             throw new NullPointerException( "session is empty" );
         try {
             byte [] key = SerializeUtil.serialize(buildRedisSessionKey(session
                     .getId()));
             byte [] value = SerializeUtil.serialize(session);
             long sessionTimeOut = 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
     public void deleteSession(Serializable id) {
         if (id == null ) {
             throw new 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
     public Session getSession(Serializable id) {
         if (id == null )
             throw new 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" );
         }
         return session;
     }
 
     @Override
     public Collection<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);
                     }
                 }
                 return Collections.unmodifiableList(values);
             } else {
                 return Collections.emptyList();
             }
         } catch (Throwable t) {
             throw new CacheException(t);
         }
     }
 
     private String buildRedisSessionKey(Serializable sessionId) {
         return REDIS_SHIRO_SESSION + sessionId;
     }
 
     public JedisManager getJedisManager() {
         return jedisManager;
     }
 
     public void 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
package com.michaelliuyang.shiro.demo.session;
 
import org.apache.shiro.session.Session;
import org.apache.shiro.session.UnknownSessionException;
import org.apache.shiro.session.mgt.eis.AbstractSessionDAO;
 
import java.io.Serializable;
import java.util.Collection;
 
/**
  * custom shiro sessionDAO
  * From:<a href="http://www.zyiqibook.com">在一起:技术分享_源码分享平台</a> 欢迎到网站进行交流
  */
public class CustomShiroSessionDAO extends AbstractSessionDAO {
 
     private ShiroSessionRepository shiroSessionRepository;
 
     @Override
     public void update(Session session) throws UnknownSessionException {
         System.out.println( "update session----更新:" +session.getId());
         getShiroSessionRepository().saveSession(session);
     }
 
     @Override
     public void 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
     public Collection<Session> getActiveSessions() {
         return getShiroSessionRepository().getAllSessions();
     }
 
     @Override
     protected Serializable doCreate(Session session) {
         Serializable sessionId = this .generateSessionId(session);
         this .assignSessionId(session, sessionId);
         getShiroSessionRepository().saveSession(session);
         System.out.println( "do create session----建完后:" +sessionId);
         return sessionId;
     }
 
     @Override
     protected Session doReadSession(Serializable sessionId) {
         System.out.println( "do read session----参数:" +sessionId);
         return getShiroSessionRepository().getSession(sessionId);
     }
 
     public ShiroSessionRepository getShiroSessionRepository() {
         return shiroSessionRepository;
     }
 
     public void 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
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值