OA系统之shiro和redis
系统采用activiti工作流,SSM框架,quartz定时任务,shiro权限管理,redis缓存。
  这篇文章不适合小白,小白请转http://jinnianshilongnian.iteye.com/,自行学习。
  这篇文章就是为了锻炼我自己的码字速度的,以后搬砖方便,不谢。
工作流看http://www.kafeitu.me/和http://jinnianshilongnian.iteye.com/ 后者有很多好的文章,包括怎么使用shiro啥的。
1、序列化工具:
主要用于对对象进行序列化和反序列化。
public class SerializationUtils {  
	public static byte[] serialize(Object o) {
		ByteArrayOutputStream out = new ByteArrayOutputStream();
		try {
			ObjectOutputStream outo = new ObjectOutputStream(out);
			outo.writeObject(o);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return out.toByteArray();
	}
	
	public static String serializeToString(Serializable obj) {
        try {
            byte[] value = serialize(obj);
            return Base64.encodeToString(value);
        } catch (Exception e) {
            throw new RuntimeException("serialize session error", e);
        }
    }
	public static Object deserialize(byte[] b) {
		ObjectInputStream oin;
		try {
			oin = new ObjectInputStream(new ByteArrayInputStream(b));
			try {
				return oin.readObject();
			} catch (ClassNotFoundException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				return null;
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return null;
		}
	}
	
	/**
	 * string 转session专用
	 * @param base64
	 * @return
	 */
	public static Session deserializeFromString(String base64) {
		try {
			byte[] objectData = Base64.decode(base64);
			return (Session)deserialize(objectData);
		} catch (Exception e) {
			throw new RuntimeException("deserialize session error", e);
		}
	}
}  
2、realm 需要自己继承AuthorizingRealm对登录和授权进行重写。
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(
			AuthenticationToken token) throws AuthenticationException {
		UsernamePasswordToken upToken = (UsernamePasswordToken) token;
		String username = upToken.getUsername();
		
		Account account = userService.getAccountByAccNum(username);
		if (null == account) {
			logger.error(MessageFormat.format(
					"{0} 在 {1,date,yyyy-MM-dd HH:mm:ss} 登录办公系统(没有该账号)。",
					username, new Date()));
			throw new UnknownAccountException("用户不存在!");
		}
		if ("1".equals(account.getIsLocked())) {
			logger.error(MessageFormat.format(
					"{0} 在 {1,date,yyyy-MM-dd HH:mm:ss} 登录办公系统(账号被锁定)。",
					username, new Date()));
			throw new LockedAccountException("用户被锁定");
		}
		logger.info(MessageFormat.format(
				"{0} 在 {1,date,yyyy-MM-dd HH:mm:ss} 登录办公系统。", username,
				new Date()));
		
		Object principal = username;
		// 2). credentials: 密码.
		Object credentials = account.getAccPwd();
		String realmName = getName();
		// 4). 盐值.
		ByteSource credentialsSalt = ByteSource.Util.bytes(username);
		
		JedisPool jedisPool = redisManager.getRedisManager().getJedisPool();
		Jedis resource = jedisPool.getResource();
		try {
			resource.set(RedisSessionDAO.getByteKey(RedisSessionDAO.SHIRO_REDIS_USER_PRE, username), SerializationUtils.serialize(account));
		} catch (Exception e) {
			logger.error("登录缓存存储失败!"+e.toString());
			e.printStackTrace();
		}finally{
			if (resource != null) {  
                jedisPool.returnBrokenResource(resource);  
            }  
		}
		SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(principal, credentials,
				credentialsSalt, realmName);
		
		// 把账号信息放到Session中,并更新缓存,用于会话管理
		Subject subject = SecurityUtils.getSubject();
		Serializable sessionId = subject.getSession().getId();
		ShiroSession session = (ShiroSession) sessionDao.doReadSessionWithoutExpire(sessionId);
		session.setAttribute("userId", account.getId());
		session.setAttribute("loginName", account.getAccNum());
		sessionDao.update(session);
		return info;
	}
	// 授权会被 shiro 回调的方法
	@SuppressWarnings("unused")
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
		// 1. 从 PrincipalCollection 中来获取登录用户的信息
		Object principal = principals.getPrimaryPrincipal();
		String userId=(String)getAvailablePrincipal(principals);
		// 因为非正常退出,即没有显式调用 SecurityUtils.getSubject().logout()
        // (可能是关闭浏览器,或超时),但此时缓存依旧存在(principals),所以会自己跑到授权方法里。
        if (!SecurityUtils.getSubject().isAuthenticated()) {
            doClearCache(principals);
            SecurityUtils.getSubject().logout();
            return null;
        }
        if (principals == null) {
            throw new AuthorizationException("parameters principals is null");
        }
        //获取已认证的用户名(登录名)
        if(StringUtils.isEmpty(userId)){
            return null;
        }
		// 2. 利用登录的用户的信息来用户当前用户的角色或权限(可能需要查询数据库)
		//String sql = "select GROUP_ID_ from act_id_membership where user_id_ = ?";
		String username = principal.toString();
		
		// 3. 调用数据库的方法, 从数据库中查询 username 对应的用户记录
		//List<String> list = jt.queryForList(sql, String.class, username);
		Set<String> roles = new HashSet<>();
		Account account = userService.getAccountByAccNum(username);
		List<PageData> allRoleByAccNum = userService.getAllRoleByAccNum(username);
		
		for(PageData tem : allRoleByAccNum){
			roles.add(tem.getString("roleCode"));
		}
		
		Set<String> stringPermissions = new HashSet<String>();
		stringPermissions.add("add");
		stringPermissions.add("del");
		stringPermissions.add("update");
		stringPermissions.add("query");
		// 3. 创建 SimpleAuthorizationInfo, 并设置其 reles 属性.
		SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
		info.setRoles(roles);
		
		//根据角色获取 角色权限 精确到 CRUD级别
		//info.addObjectPermission(new WildcardPermission("user:add"));
		JedisPool jedisPool = redisManager.getRedisManager().getJedisPool();
		Jedis resource = jedisPool.getResource();
		try {
			if (roles.size() > 0) {
				for (String module : stringPermissions) {
					info.addObjectPermission(new WildcardPermission("user:"+module));
				}
				resource.set(RedisSessionDAO.getByteKey(RedisSessionDAO.PERMISSION_PRE, username), 
						SerializationUtils.serialize(info.getObjectPermissions()));
			}
			// cacheManager.getCache("").clear();
			resource.set(RedisSessionDAO.getByteKey(RedisSessionDAO.SHIRO_REDIS_ROLE_PRE, username), 
					SerializationUtils.serialize(info.getRoles()));
		} catch (Exception e) {
			logger.error("授权失败!"+e.toString());
			e.printStackTrace();
		}finally{
			if (resource != null) {  
                jedisPool.returnBrokenResource(resource);  
            }  
		}
		// 4. 返回 SimpleAuthorizationInfo 对象.
		return info;
	}
	
	/**
	 * 更新用户授权信息缓存.
	 */
	
	// 登陆成功后强制加载shiro权限缓存 避免懒加载 先清除
	public void forceShiroToReloadUserAuthorityCache() {
		this.clearCachedAuthorizationInfo(SecurityUtils.getSubject()
				.getPrincipal());
		this.isPermitted(SecurityUtils.getSubject().getPrincipals(),
				"强制加载缓存,避免懒加载" + System.currentTimeMillis());
	}
	
3、shiro的session需要重写,并配合一个工厂类和ShiroSessionListener。为什么和怎么写就看这个博客:http://www.cnblogs.com/shihaiming/p/6406640.html
4、quartz
	我觉得最牛逼的就是那个定时启动时间的设置了,相比自己写的要好很多,当然自己写定时任务也可以(我以前不知道有quartz),用这个就是时间那里太方便了。
	你可能遇见版本不支持的问题,就是shiro是1.6的你用的2.X的,不要紧重写两个类就行了。看博客:http://blog.csdn.net/rogerjava/article/details/70920763
	有两种方式,这里就介绍一种execute。配置文件如下:
	<!--要调度的对象-->
	<bean id="jobBean" class="com.wuqidi.common.quartz.QuartzTestManager" />
	<bean id="jobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
		<property name="targetObject" ref="jobBean"/>
		<property name="targetMethod" value="execute"/><!-- 执行"jobBean"中的execute方法 -->
		<property name="concurrent" value="false"/><!--将并发设置为false-->
	</bean>
	<!-- ======================== 调度  ======================== --> 
	<bean id="trigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean"><!-- 定义 Job 何时执行 -->
 		<property name="jobDetail" ref="jobDetail" />
        <property name="cronExpression" value="0/3 * * * * ?" /><!-- 这里就是设置时间的 双击666 -->
	</bean>
	<!-- ======================== 调度工厂 ======================== --> 
	<!--  总管理类如果将lazy-init='false'那么容器启动就会执行调度程序   -->
	<bean id="startQuertz" class="org.springframework.scheduling.quartz.SchedulerFactoryBean" lazy-init="false" >
 		<property name="triggers">
 			<list>
				<ref bean="trigger" /><!--作业调度器,list下可加入其他的调度器-->
 			</list>
		</property>
	</bean>
5、缓存 搬得砖
public class RedisCacheManager implements CacheManager {
	private static final Logger logger = LoggerFactory.getLogger(RedisCacheManager.class);  
	  
    // fast lookup by name map  
    private final ConcurrentMap<String, Cache> caches = new ConcurrentHashMap<String, Cache>();  
    
    private JedisPoolManager redisManager; 
    
    public JedisPoolManager getRedisManager() {
		return redisManager;
	}
	public void setRedisManager(JedisPoolManager redisManager) {
		this.redisManager = redisManager;
	}
	@Override
	public <K, V> Cache<K, V> getCache(String name) throws CacheException {
		// TODO Auto-generated method stub
        logger.debug("获取名称为: " + name + " 的RedisCache实例");  
        System.out.println("获取名称为: " + name + " 的RedisCache实例");
        Cache c = caches.get(name);  
        if (c == null) {  
            c = new RedisCache<K, V>(redisManager);  
            caches.put(name, c);  
        }  
        return c;  
    }  
}
public class RedisCache<K,V> implements Cache<K,V> {
	private Logger logger = LoggerFactory.getLogger(this.getClass());  
    
	private JedisPoolManager cache;  
      
    private String keyPrefix = RedisSessionDAO.SHIRO_REDIS_SESSION_PRE;  
      
    /** 
     * Returns the Redis session keys 
     * prefix. 
     * @return The prefix 
     */  
    public String getKeyPrefix() {  
        return keyPrefix;  
    }  
  
    /** 
     * Sets the Redis sessions key  
     * prefix. 
     * @param keyPrefix The prefix 
     */  
    public void setKeyPrefix(String keyPrefix) {  
        this.keyPrefix = keyPrefix;  
    }  
      
    /** 
     * 通过一个JedisManager实例构造RedisCache 
     */  
    public RedisCache(JedisPoolManager cache){  
         if (cache == null) {  
             throw new IllegalArgumentException("Cache argument cannot be null.");  
         }  
         this.cache = cache;  
    }  
      
    /** 
     * Constructs a cache instance with the specified 
     * Redis manager and using a custom key prefix. 
     * @param cache The cache manager instance 
     * @param prefix The Redis key prefix 
     */  
    public RedisCache(JedisPoolManager cache,   
                String prefix){  
           
        this( cache );  
          
        // set the prefix  
        this.keyPrefix = prefix;  
    }  
      
    /** 
     * 获得byte[]型的key 
     * @param key 
     * @return 
     */  
    private byte[] getByteKey(K key) {
        if (key instanceof String) {
            String preKey = this.keyPrefix + key;
            return preKey.getBytes();
        } else if(key instanceof PrincipalCollection){
            String preKey = this.keyPrefix + key.toString();
            return preKey.getBytes();
        }else{
        	return SerializationUtils.serialize(key);  
        }
    }
      
    @Override  
    public V get(K key) throws CacheException {  
    	Jedis resource = null;
    	JedisPool jedisPool = null;
        logger.debug("根据key从Redis中获取对象 key [" + key + "]");  
        System.out.println("根据key从Redis中获取对象 key [" + key + "]");
        try {  
            if (key == null) {  
                return null;  
            }else{  
            	
            	jedisPool = cache.getJedisPool();
            	resource = jedisPool.getResource();
            	System.out.println((new String(getByteKey(key))));
            	
                byte[] rawValue = resource.get(getByteKey(key));//cache.get(getByteKey(key));  
                
                if(rawValue==null || rawValue.length <= 0){return null;}
                @SuppressWarnings("unchecked")  
                V value = (V)SerializationUtils.deserialize(rawValue);  
                return value;  
            }  
        } catch (Throwable t) {  
        	if (resource != null) {  
       		 jedisPool.returnBrokenResource(resource);  
            }  
            throw new CacheException(t);  
        }  
  
    }  
  
    @Override  
    public V put(K key, V value) throws CacheException {  
    	Jedis resource = null;
    	JedisPool jedisPool = null;
        logger.debug("根据key从存储 key [" + key + "]");  
        System.out.println("根据key从存储 key [" + key + "]");
         try {  
        	 	jedisPool = cache.getJedisPool();
         		resource = jedisPool.getResource();
                //cache.set(getByteKey(key), SerializationUtils.serialize(value));  
                resource.set(this.getByteKey(key),SerializationUtils.serialize(value));  
                return value;  
            } catch (Throwable t) { 
            	if (resource != null) {  
           		 jedisPool.returnBrokenResource(resource);  
                }  
                throw new CacheException(t);  
            }  
    }  
  
    @Override  
    public V remove(K key) throws CacheException {  
    	Jedis resource = null;
    	JedisPool jedisPool = null;
        logger.debug("从redis中删除 key [" + key + "]"); 
        System.out.println("从redis中删除 key [" + key + "]");
        try {  
        	jedisPool = cache.getJedisPool();
        	resource = jedisPool.getResource();
            V previous = get(key);  
            //cache.del(getByteKey(key)); 
            resource.del(getByteKey(key));
            return previous;  
        } catch (Throwable t) {  
        	if (resource != null) {  
       		 jedisPool.returnBrokenResource(resource);  
            }  
            throw new CacheException(t);  
        }  
    }  
  
    @Override  
    public void clear() throws CacheException {  
    	Jedis resource = null;
    	JedisPool jedisPool = null;
        logger.debug("从redis中删除所有元素");  
        System.out.println("从redis中删除所有元素");
        try {  
        	jedisPool = cache.getJedisPool();
        	resource = jedisPool.getResource();
            resource.flushDB();
        } catch (Throwable t) { 
        	if (resource != null) {  
       		 jedisPool.returnBrokenResource(resource);  
            }  
            throw new CacheException(t);  
        }  
    }  
  
    @Override  
    public int size() {  
    	Jedis resource = null;
    	JedisPool jedisPool = null;
        try {  
        	jedisPool = cache.getJedisPool();
        	resource = jedisPool.getResource();
            Long longSize = new Long(resource.dbSize());  
            return longSize.intValue();  
        } catch (Throwable t) {  
        	if (resource != null) {  
          		 jedisPool.returnBrokenResource(resource);  
               }  
            throw new CacheException(t);  
        }  
    }  
  
    @SuppressWarnings("unchecked")  
    @Override  
    public Set<K> keys() {  
    	Jedis resource = null;
    	JedisPool jedisPool = null;
        try {  
        	jedisPool = cache.getJedisPool();
        	resource = jedisPool.getResource();
            Set<byte[]> keys = resource.keys((this.keyPrefix + "*").getBytes());  
           // Set<byte[]> keys = cache.keys(this.keyPrefix + "*");  
            if (CollectionUtils.isEmpty(keys)) {  
                return Collections.emptySet();  
            }else{  
                Set<K> newKeys = new HashSet<K>();  
                for(byte[] key:keys){  
                    newKeys.add((K)key);  
                }  
                return newKeys;  
            }  
        } catch (Throwable t) {
        	if (resource != null) {  
       		 jedisPool.returnBrokenResource(resource);  
            }  
            throw new CacheException(t);  
        }  
    }  
  
    @Override  
    public Collection<V> values() {  
    	Jedis resource = null;
    	JedisPool jedisPool = null;
        try {  
        	jedisPool = cache.getJedisPool();
        	resource = jedisPool.getResource();
            Set<byte[]> keys = resource.keys((this.keyPrefix + "*").getBytes());  
            if (!CollectionUtils.isEmpty(keys)) {  
                List<V> values = new ArrayList<V>(keys.size());  
                for (byte[] key : keys) {  
                    @SuppressWarnings("unchecked")  
                    V value = get((K)key);  
                    if (value != null) {  
                        values.add(value);  
                    }  
                }  
                return Collections.unmodifiableList(values);  
            } else {  
                return Collections.emptyList();  
            }  
        } catch (Throwable t) {
        	 if (resource != null) {  
        		 jedisPool.returnBrokenResource(resource);  
             }  
            throw new CacheException(t);  
        }  
    }  
}
6、sessiondao
CachingSessionDAO 据说能减少访问redis的次数,但是  没体会到。。。然后问了同事,同事说shiro的过滤设置下静态资源,恩,我之前就已经设置了。反正就是多次访问的问题没有解决,doread方法。
public class RedisSessionDAO extends CachingSessionDAO{
	private static Logger logger = LoggerFactory.getLogger(RedisSessionDAO.class); 
	
	public final static String PRINCIPALS_SESSION_KEY 
	= "org.apache.shiro.subject.support.DefaultSubjectContext.PRINCIPALS_SESSION_KEY";// 保存 principal
	public final static String AUTHENTICATED_SESSION_KEY 
	= "org.apache.shiro.subject.support.DefaultSubjectContext.AUTHENTICATED_SESSION_KEY";// 保存 boolean是否登陆
	
	
    /**shiro-redis的session对象前缀  */  
    public final static String SHIRO_REDIS_SESSION_PRE = "shiro_redis_session:";  
      
    /**存放uid的对象前缀 */  
    public final static String SHIRO_SHESSIONID_PRE = "shiro_sessionid:";  
      
    /**存放uid 当前状态的前缀 */  
    public final static String UID_PRE = "uid:";  
      
    /**存放用户权限的前缀 */  
    public final static String PERMISSION_PRE ="permission:";
    
    /**存放用户实体的前缀 */  
    public final static String SHIRO_REDIS_USER_PRE ="shiro_redis_user:";
    
    /**存放用户角色的前缀 */  
    public final static String SHIRO_REDIS_ROLE_PRE ="shiro_redis_role:";
    
    private String expire;  
  
    public void setExpire(String expire) {
		this.expire = expire;
	}
	private JedisPoolManager redisManager;  
  
    public void setRedisManager(JedisPoolManager redisManager) {
		this.redisManager = redisManager;
	}
    public JedisPoolManager getRedisManager() {
		return redisManager;
	}
    
    //**************************************************************************
    // 保存到Redis中key的前缀 prefix+sessionId
    //private String prefix = "";
    // 设置会话的过期时间
    //private int seconds = 0;
    /**
     * 重写CachingSessionDAO中readSession方法,如果Session中没有登陆信息就调用doReadSession方法从Redis中重读
     */
    @Override
    public Session readSession(Serializable sessionId) throws UnknownSessionException {
        Session session = getCachedSession(sessionId);
        if (session == null
                || session.getAttribute(PRINCIPALS_SESSION_KEY) == null) {
            session = this.doReadSession(sessionId);
            if (session == null) {
                throw new UnknownSessionException("There is no session with id [" + sessionId + "]");
            } else {
                // 缓存
                cache(session, session.getId());
            }
        }
        return session;
    }
    @SuppressWarnings("static-access")
	public Session doReadSessionWithoutExpire(Serializable sessionId) {
        Session session = null;
        Jedis jedis = null;
        JedisPool jedisPool = null;
        try {
        	jedisPool = redisManager.getJedisPool();
        	jedis     = jedisPool.getResource();
        	
            String key = SHIRO_REDIS_SESSION_PRE + sessionId;
           /* String value = jedis.get(key);
            if (StringUtils.isNotBlank(value)) {
                session = SerializationUtils.deserializeFromString(value);
            }*/
            byte[] value = jedis.get(this.getByteKey(this.SHIRO_REDIS_SESSION_PRE , sessionId));
            if (StringUtils.isNotBlank(new String(value))) {
                session =  (Session) SerializationUtils.deserialize(value);
                logger.info("sessionId {} ttl {}: ", sessionId, jedis.ttl(key));
                // 重置Redis中缓存过期时间
                jedis.expire(key, 1800000);
                logger.info("sessionId {} name {} 被读取", sessionId, session.getClass().getName());
            }
        } catch (Exception e) {
            logger.warn("读取Session失败", e);
        } finally {
        	jedisPool.returnResource(jedis);
        }
        return session;
    }
    /**
     * 更新会话;如更新会话最后访问时间/停止会话/设置超时时间/设置移除属性等会调用
     */
    @Override
    protected void doUpdate(Session session) {
    	Long redisExpire = (long) (1800000/1000);  
        int timeout = redisExpire.intValue(); 
        
        //如果会话过期/停止 没必要再更新了
        try {
            if (session instanceof ValidatingSession && !((ValidatingSession) session).isValid()) {
                return;
            }
        } catch (Exception e) {
            logger.error("ValidatingSession error");
        }
        Jedis jedis = null;
        JedisPool jedisPool = redisManager.getJedisPool();
        jedis = jedisPool.getResource();
        try {
            if (session instanceof ShiroSession) {
                // 如果没有主要字段(除lastAccessTime以外其他字段)发生改变
                ShiroSession ss = (ShiroSession) session;
                if (!ss.isChanged()) {
                    return;
                }
                Transaction tx = null;
                try {
                    // 开启事务
                    tx = jedis.multi();
                    ss.setChanged(false);
                    tx.setex(SHIRO_REDIS_SESSION_PRE + session.getId(), timeout, SerializationUtils.serializeToString(ss));
                    logger.info("sessionId {} name {} 被更新", session.getId(), session.getClass().getName());
                    // 执行事务
                    tx.exec();
                } catch (Exception e) {
                    if (tx != null) {
                        // 取消执行事务
                        tx.discard();
                    }
                    throw e;
                }
            } else if (session instanceof Serializable) {
                
                jedis.setex(SHIRO_REDIS_SESSION_PRE + session.getId(), timeout, SerializationUtils.serializeToString((Serializable) session));
                logger.info("sessionId {} name {} 作为非ShiroSession对象被更新, ", session.getId(), session.getClass().getName());
            } else {
                logger.warn("sessionId {} name {} 不能被序列化 更新失败", session.getId(), session.getClass().getName());
            }
        } catch (Exception e) {
            logger.warn("更新Session失败", e);
        } finally {
        	jedisPool.returnResource(jedis);
        }
    }
    /**
     * 删除会话;当会话过期/会话停止(如用户退出时)会调用
     */
    @Override
    protected void doDelete(Session session) {
        Jedis jedis = null;
        JedisPool jedisPool = redisManager.getJedisPool();
        try {
            jedis = jedisPool.getResource();
            jedis.del(SHIRO_REDIS_SESSION_PRE + session.getId());
            logger.debug("Session {} 被删除", session.getId());
        } catch (Exception e) {
            logger.warn("修改Session失败", e);
        } finally {
        	jedisPool.returnResource(jedis);
        }
    }
    /**
     * 删除cache中缓存的Session
     */
    public void uncache(Serializable sessionId) {
        Session session = this.readSession(sessionId);
        super.uncache(session);
        logger.info("取消session {} 的缓存", sessionId);
    }
    /**
     * 获取当前所有活跃用户,如果用户量多此方法影响性能
     */
    @Override
    public Collection<Session> getActiveSessions() {
        Jedis jedis = null;
        JedisPool jedisPool = redisManager.getJedisPool();
        try {
            jedis = jedisPool.getResource();
            Set<String> keys = jedis.keys(SHIRO_REDIS_SESSION_PRE + "*");
            if (CollectionUtils.isEmpty(keys)) {
                return null;
            }
            List<String> valueList = jedis.mget(keys.toArray(new String[0]));
            Collection<Session> retu = new ArrayList<Session>();
            for(String tem : valueList){
            	retu.add(SerializationUtils.deserializeFromString(tem));
            }
            return retu;
        } catch (Exception e) {
            logger.warn("统计Session信息失败", e);
        } finally {
        	jedisPool.returnResource(jedis);
        }
        return null;
    }
    
    //****************************************************************
    
    
    
      
    @Override  
    public void update(Session session) throws UnknownSessionException {  
    	//super.update(session);
    	System.out.println("update" + session.getId());  
        this.saveSession(session);  
    }  
  
    /** 
     * save session 
     *  
     * @param session 
     * @throws UnknownSessionException 
     */  
    private void saveSession(Session session) throws UnknownSessionException {  
        if (session == null || session.getId() == null) {  
            logger.error("session or session id is null");  
            return;  
        }  
        System.out.println("save" + session.getId());  
        session.setTimeout(1800000);  
        Long redisExpire = (long) (1800000/1000);  
        int timeout = redisExpire.intValue();  
            JedisPool jedisPool = this.redisManager.getJedisPool();  
        Jedis jedis = null;  
        try {  
            jedis =  jedisPool.getResource();             
            //保存用户会话  
            jedis.setex(this.getByteKey(this.SHIRO_REDIS_SESSION_PRE,session.getId()), timeout, SerializationUtils.serialize(session));  
            String uid = this.getUserId(session);  
            if (null != uid && !"".equals(uid)){  
                //保存用户会话对应的UID  
                jedis.setex(this.getByteKey(this.SHIRO_SHESSIONID_PRE,session.getId()),timeout, uid.getBytes());  
                //保存在线UID  
                jedis.setex(this.getByteKey(this.UID_PRE,uid), timeout,"online".getBytes());  
            }  
            jedisPool.returnResource(jedis);  
        }catch(Exception ex){  
            if (jedis != null) {  
                jedisPool.returnBrokenResource(jedis);  
            }  
            throw new JedisException(ex);  
        }  
    }  
      
    @Override  
    public void delete(Session session) {  
        if (session == null || session.getId() == null) {  
            logger.error("session or session id is null");  
            return;  
        }  
        System.out.println("delete" + session.getId());  
        
        JedisPool jedisPool = this.redisManager.getJedisPool();  
        Jedis jedis = null;  
        try {  
            jedis =  jedisPool.getResource();  
              
            //删除用户会话  
            jedis.del(this.getByteKey(this.SHIRO_REDIS_SESSION_PRE,session.getId()));  
            //获取缓存的用户会话对应的UID  
            byte[] uid = jedis.get(this.getByteKey(this.SHIRO_SHESSIONID_PRE,session.getId()));  
            System.out.println("delete" + new String(uid));  
            //删除用户会话对应的UID  
            jedis.del(this.getByteKey(this.SHIRO_SHESSIONID_PRE,session.getId()));  
              
            //删除在线UID  
            jedis.del(this.getByteKey(this.UID_PRE,new String(uid)));  
              
            //删除用户缓存的权限  
            jedis.del(this.getByteKey(this.PERMISSION_PRE, new String(uid)));  
            
            jedis.del(this.getByteKey(this.SHIRO_REDIS_ROLE_PRE, new String(uid)));  
            
            jedis.del(this.getByteKey(this.SHIRO_REDIS_USER_PRE, new String(uid)));  
              
            jedisPool.returnResource(jedis);  
        }catch(Exception ex){  
            if (jedis != null) {  
                jedisPool.returnBrokenResource(jedis);  
            }  
            throw new JedisException(ex);  
        }  
      
    }  
      
    public boolean isOnLine(String uid){  
          
        Set<byte[]>keys = redisManager.keys(this.UID_PRE + uid);  
        if (keys != null && keys.size() > 0){  
          return true;  
        }  
        return false;  
    }  
  
    /**
     * 如DefaultSessionManager在创建完session后会调用该方法;
     * 如保存到关系数据库/文件系统/NoSQL数据库;即可以实现会话的持久化;
     * 返回会话ID;主要此处返回的ID.equals(session.getId());
     */
    @Override  
    protected Serializable doCreate(Session session) {  
    	System.out.println("create" + session.getId());  
        Serializable sessionId = this.generateSessionId(session);  
        this.assignSessionId(session, sessionId);  
        this.saveSession(session);  
        return session.getId();  
    }  
  
    
    /*从redi获取数据 如果没有从数据库获取*/
    @SuppressWarnings("unused")
	@Override  
    protected Session doReadSession(Serializable sessionId) {  
    	
    	logger.info("获取seesion,id=[{}]",sessionId.toString());  
    	
        if (sessionId == null) {  
            logger.error("session id is null");  
            return null;  
        }  
        System.out.println("read" + sessionId);  
        logger.debug("Redis.SessionId=" + new String(getByteKey(this.SHIRO_REDIS_SESSION_PRE,sessionId)));  
          
        Jedis jedis = null;
        Session session = null;
        try {
            jedis = redisManager.getJedisPool().getResource();
            String key = this.SHIRO_REDIS_SESSION_PRE + sessionId;
            byte[] value = jedis.get(this.getByteKey(this.SHIRO_REDIS_SESSION_PRE , sessionId.toString()));
            if (StringUtils.isNotBlank(new String(value))) {
                session =  (Session) SerializationUtils.deserialize(value);
                logger.info("sessionId {} ttl {}: ", sessionId, jedis.ttl(key));
                // 重置Redis中缓存过期时间
                jedis.expire(key, 1800000);
                logger.info("sessionId {} name {} 被读取", sessionId, session.getClass().getName());
            }
        } catch (Exception e) {
            logger.warn("读取Session失败", e);
            System.out.println("读取Session失败"+ e.toString());
        } finally {
        	redisManager.getJedisPool().returnResource(jedis);
        }
        return session;  
    }  
      
    /** 
     * 获得byte[]型的key 
     *  
     * @param key 
     * @return 
     */  
    public static byte[] getByteKey(String preKey,Serializable sessionId) {  
        String key = preKey + sessionId;  
        return key.getBytes();  
      
    }  
      
    /** 
     * 获取用户唯一标识 
     * @param session 
     * @return 
     */  
    public String getUserId(Session session) {
        SimplePrincipalCollection pricipal = (SimplePrincipalCollection) session.getAttribute("org.apache.shiro.subject.support.DefaultSubjectContext_PRINCIPALS_SESSION_KEY");
        if (null != pricipal) {
            return pricipal.getPrimaryPrincipal().toString();
        }
        return null;
    }
    
}
7、jedis池
写到这如果你已经采用3.X版本,此时我会跟你说直接用close即可,return关闭方法已经过时。
public class JedisPoolManager {
	private static Logger log = LoggerFactory.getLogger(JedisPoolManager.class);  
	  
    private JedisPool jedisPool;  
    /** 
     * redis的List集合 ,向key这个list添加元素 
     */  
    public long rpush(String key, String string) {  
        Jedis jedis = null;  
        try {  
            jedis = jedisPool.getResource();  
            long ret = jedis.rpush(key, string);  
            jedisPool.returnResource(jedis);  
            return ret;  
        } catch (Exception e) {  
            log.error(e.toString());  
            if (jedis != null) {  
                jedisPool.returnBrokenResource(jedis);  
            }  
            throw new JedisException(e.toString());  
        }  
    }  
    /** 
     * 获取key这个List,从第几个元素到第几个元素 LRANGE key start 
     * stop返回列表key中指定区间内的元素,区间以偏移量start和stop指定。 
     * 下标(index)参数start和stop都以0为底,也就是说,以0表示列表的第一个元素,以1表示列表的第二个元素,以此类推。 
     * 也可以使用负数下标,以-1表示列表的最后一个元素,-2表示列表的倒数第二个元素,以此类推。 
     */  
    public List<String> lrange(String key, long start, long end) {  
        Jedis jedis = null;  
        try {  
            jedis = jedisPool.getResource();  
            List<String> ret = jedis.lrange(key, start, end);  
            jedisPool.returnResource(jedis);  
            return ret;  
        } catch (Exception e) {  
            log.error(e.toString());  
            if (jedis != null) {  
                jedisPool.returnBrokenResource(jedis);  
            }  
            throw new JedisException(e);  
        }  
    }  
    /** 
     * 将哈希表key中的域field的值设为value。 
     */  
    public void hset(String key, String field, String value) {  
        Jedis jedis = null;  
        try {  
            jedis = jedisPool.getResource();  
            jedis.hset(key, field, value);  
            jedisPool.returnResource(jedis);  
        } catch (Exception e) {  
            log.error(e.toString());  
            if (jedis != null) {  
                jedisPool.returnBrokenResource(jedis);  
            }  
            throw new JedisException(e);  
        }  
    }  
    /** 
     * 向key赋值 
     */  
    public void set(String key, String value) {  
        Jedis jedis = null;  
        try {  
            jedis = jedisPool.getResource();  
            jedis.set(key, value);  
            jedisPool.returnResource(jedis);  
        } catch (Exception e) {  
            log.error(e.toString());  
            if (jedis != null) {  
                jedisPool.returnBrokenResource(jedis);  
            }  
            throw new JedisException(e);  
        }  
    }  
    /** 
     * 向key赋值 
     */  
    public void set(byte[] key, byte[] value) {  
        Jedis jedis = null;  
        try {  
            jedis = jedisPool.getResource();  
            jedis.set(key, value);  
            jedisPool.returnResource(jedis);  
        } catch (Exception e) {  
            log.error(e.toString());  
            if (jedis != null) {  
                jedisPool.returnBrokenResource(jedis);  
            }  
            throw new JedisException(e);  
        }  
    }  
    /** 
     * 获取key的值 
     */  
    public String get(String key) {  
        Jedis jedis = null;  
        try {  
            jedis = jedisPool.getResource();  
            String value = jedis.get(key);  
            jedisPool.returnResource(jedis);  
            return value;  
        } catch (Exception e) {  
            log.error(e.toString());  
            if (jedis != null) {  
                jedisPool.returnBrokenResource(jedis);  
            }  
            throw new JedisException(e);  
        }  
    }  
    /** 
     * 获取key的值 
     */  
    public byte[] get(byte[] key) {  
        Jedis jedis = null;  
        try {  
            jedis = jedisPool.getResource();  
            byte[] value = jedis.get(key);  
            jedisPool.returnResource(jedis);  
            return value;  
        } catch (Exception e) {  
            log.error(e.toString());  
            if (jedis != null) {  
                jedisPool.returnBrokenResource(jedis);  
            }  
            throw new JedisException(e);  
        }  
  
    }  
    /** 
     * 将多个field - value(域-值)对设置到哈希表key中。 
     */  
    public void hmset(String key, Map<String, String> map) {  
        Jedis jedis = null;  
        try {  
             jedis = jedisPool.getResource();  
            jedis.hmset(key, map);  
            jedisPool.returnResource(jedis);  
        } catch (Exception e) {  
            log.error(e.toString());  
            if (jedis != null) {  
                jedisPool.returnBrokenResource(jedis);  
            }  
            throw new JedisException(e);  
        }  
    }  
    /** 
      * 给key赋值,并生命周期设置为seconds 
     */  
    public void setex(String key, int seconds, String value) {  
        Jedis jedis = null;  
        try {  
             jedis = jedisPool.getResource();  
            jedis.setex(key, seconds, value);  
            jedisPool.returnResource(jedis);  
         } catch (Exception e) {  
            log.error(e.toString());  
            if (jedis != null) {  
                jedisPool.returnBrokenResource(jedis);  
            }  
            throw new JedisException(e);  
        }  
    }  
    /** 
     * 给key赋值,并生命周期设置为seconds 
     */  
    public byte[] setex(byte[] key, byte[] value, int seconds) {  
        Jedis jedis = null;  
        try {  
             jedis = jedisPool.getResource();  
            jedis.setex(key, seconds, value);  
            jedisPool.returnResource(jedis);  
            return value;  
        } catch (Exception e) {  
            log.error(e.toString());  
            if (jedis != null) {  
                jedisPool.returnBrokenResource(jedis);  
            }  
            throw new JedisException(e);  
        }  
          
  
    }  
    /** 
     * 为给定key设置生命周期 
     */  
    public void expire(String key, int seconds) {  
        Jedis jedis = null;  
        try {  
             jedis = jedisPool.getResource();  
            jedis.expire(key, seconds);  
            jedisPool.returnResource(jedis);  
        } catch (Exception e) {  
            log.error(e.toString());  
            if (jedis != null) {  
                jedisPool.returnBrokenResource(jedis);  
            }  
             throw new JedisException(e);  
        }  
    }  
    /** 
     * 检查key是否存在 
     */  
    public boolean exists(String key) {  
        Jedis jedis = null;  
        try {  
            jedis = jedisPool.getResource();  
            boolean bool = jedis.exists(key);  
            jedisPool.returnResource(jedis);  
            return bool;  
        } catch (Exception e) {  
            log.error(e.toString());  
            if (jedis != null) {  
                jedisPool.returnBrokenResource(jedis);  
            }  
            throw new JedisException(e);  
        }  
    }  
        /** 
     * 检查key是否存在 
     */  
    public boolean exists(byte[] key) {  
        Jedis jedis = null;  
        try {  
            jedis = jedisPool.getResource();  
            Set<byte[]> hashSet = jedis.keys(key);  
            jedisPool.returnResource(jedis);  
            if (null != hashSet && hashSet.size() >0 ){  
                return true;  
            }else{  
                return false;  
            }  
  
        } catch (Exception e) {  
             log.error(e.toString());  
            if (jedis != null) {  
                jedisPool.returnBrokenResource(jedis);  
            }  
            throw new JedisException(e);  
        }  
    }  
    /** 
     * 返回key值的类型 none(key不存在),string(字符串),list(列表),set(集合),zset(有序集),hash(哈希表) 
     */  
    public String type(String key) {  
        Jedis jedis = null;  
        try {  
            jedis = jedisPool.getResource();  
            String type = jedis.type(key);  
            jedisPool.returnResource(jedis);  
            return type;  
        } catch (Exception e) {  
            log.error(e.toString());  
            if (jedis != null) {  
                jedisPool.returnBrokenResource(jedis);  
            }  
            throw new JedisException(e);  
        }  
    }  
    /** 
     * 从哈希表key中获取field的value 
     */  
    public String hget(String key, String field) {  
        Jedis jedis = null;  
        try {  
             jedis = jedisPool.getResource();  
            String value = jedis.hget(key, field);  
            jedisPool.returnResource(jedis);  
            return value;  
        } catch (Exception e) {  
            log.error(e.toString());  
            if (jedis != null) {  
                jedisPool.returnBrokenResource(jedis);  
            }  
            throw new JedisException(e);  
        }  
    }  
    /** 
     * 返回哈希表key中,所有的域和值 
     */  
    public Map<String, String> hgetAll(String key) {  
        Jedis jedis = null;  
        try {  
             jedis = jedisPool.getResource();  
            Map<String, String> map = jedis.hgetAll(key);  
            jedisPool.returnResource(jedis);  
            return map;  
        } catch (Exception e) {  
             log.error(e.toString());  
            if (jedis != null) {  
                jedisPool.returnBrokenResource(jedis);  
            }  
            throw new JedisException(e);  
        }  
  
    }  
    /** 
     * 返回哈希表key中,所有的域和值 
     */  
    public Set<?> smembers(String key) {  
        Jedis jedis = null;  
        try {  
            jedis = jedisPool.getResource();  
             Set<?> set = jedis.smembers(key);  
            jedisPool.returnResource(jedis);  
            return set;  
        } catch (Exception e) {  
            log.error(e.toString());  
            if (jedis != null) {  
                jedisPool.returnBrokenResource(jedis);  
            }  
             throw new JedisException(e);  
        }  
    }     
    /** 
     * 返回匹配的 keys 列表 
     */  
     public Set<byte[]> keys(String pattern) {  
        Jedis jedis = null;  
        try {  
            jedis = jedisPool.getResource();  
            Set<byte[]> keys = jedis.keys(pattern.getBytes());  
            jedisPool.returnResource(jedis);  
            return keys;  
        } catch (Exception e) {  
            log.error(e.toString());  
            if (jedis != null) {  
                jedisPool.returnBrokenResource(jedis);  
            }  
            throw new JedisException(e);  
        }  
  
    }  
    /** 
     * 移除set集合中的member元素 
     */  
    public void delSetObj(String key, String field) {  
        Jedis jedis = null;  
        try {  
            jedis = jedisPool.getResource();  
            jedis.srem(key, field);  
            jedisPool.returnResource(jedis);  
        } catch (Exception e) {  
            log.error(e.toString());  
            if (jedis != null) {  
                jedisPool.returnBrokenResource(jedis);  
            }  
            throw new JedisException(e);  
        }  
    }  
    /** 
     * 删除元素 
     */  
    public void del(byte[] key) {  
         Jedis jedis = null;  
        try {  
            jedis = jedisPool.getResource();  
            jedis.del(key);  
            jedisPool.returnResource(jedis);  
        } catch (Exception e) {  
            log.error(e.toString());  
            if (jedis != null) {  
                jedisPool.returnBrokenResource(jedis);  
            }  
            throw new JedisException(e);  
        }  
    }  
    /** 
     * 判断member元素是否是集合key的成员。是(true),否则(false) 
     */  
    public boolean isNotField(String key, String field) {  
        Jedis jedis = null;  
        try {  
            jedis = jedisPool.getResource();  
             boolean bool = jedis.sismember(key, field);  
            jedisPool.returnResource(jedis);  
             return bool;  
        } catch (Exception e) {  
             log.error(e.toString());  
            if (jedis != null) {  
                jedisPool.returnBrokenResource(jedis);  
            }  
            throw new JedisException(e);  
        }  
    }  
    /** 
     * 如果key已经存在并且是一个字符串,将value追加到key原来的值之后 
     */  
    public void append(String key, String value) {  
        Jedis jedis = null;  
        try {  
            jedis = jedisPool.getResource();  
            jedis.append(key, value);  
            jedisPool.returnResource(jedis);  
        } catch (Exception e) {  
            log.error(e.toString());  
            if (jedis != null) {  
                jedisPool.returnBrokenResource(jedis);  
            }  
            throw new JedisException(e);  
        }  
    }  
    /** 
     * 清空当前的redis 库 
     */  
    public void flushDB() {  
        Jedis jedis = null;  
        try {  
            jedis = jedisPool.getResource();  
            jedis.flushDB();  
            jedisPool.returnResource(jedis);  
        } catch (Exception e) {  
            log.error(e.toString());  
            if (jedis != null) {  
                jedisPool.returnBrokenResource(jedis);  
            }  
            throw new JedisException(e);  
        }  
  
     }  
    /** 
     * 返回当前redis库所存储数据的大小 
     */  
    @SuppressWarnings("deprecation")
	public Long dbSize() {  
          
        Long dbSize = 0L;  
          
        Jedis jedis = null;  
        try {  
            jedis = jedisPool.getResource();  
             jedis.dbSize();  
            jedisPool.returnResource(jedis);  
            return dbSize;  
        } catch (Exception e) {  
            log.error(e.toString());  
            if (jedis != null) {  
                jedisPool.returnBrokenResource(jedis);  
            }  
            throw new JedisException(e);  
        }  
  
    }  
    /** 
     * 关闭 Redis 
     */  
    public void destory() {  
        jedisPool.destroy();  
    }  
  
    public JedisPool getJedisPool() {  
        return jedisPool;  
    }  
    public void setJedisPool(JedisPool jedisPool) {  
        this.jedisPool = jedisPool;  
    }  
}
8、好了 上配置文件
 <!-- 加载配置属性文件 里面配置了redis和数据库的地址啥的-->
    <context:property-placeholder ignore-unresolvable="true" location="classpath:config.properties" />
    
    <bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig"> 
        <property name="maxIdle" value="20" /> 
        <property name="maxTotal" value="500" /> 
        <property name="minIdle" value="8" /> 
        <property name="blockWhenExhausted" value="true" /> 
        <property name="maxWaitMillis" value="30000" /> 
        <property name="testOnBorrow" value="true" />  
    </bean> 
    <bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"> 
        <property name="hostName" value="${jedis.JedisServerIp}" /> 
        <property name="port"     value="${jedis.JedisServerPort}"/>
<!--    <property name="timeout" value="${jedis.timeout}"/>-->
        <property name="password" value="${jedis.auth}"></property>
        <property name="poolConfig" ref="jedisPoolConfig" /> 
        <property name="usePool" value="true"/> 
    </bean> 
    <!-- JedisPool  configuration-->
    <bean id="jedisPool" class="redis.clients.jedis.JedisPool">  
        <constructor-arg index="0" ref="jedisPoolConfig" />  
        <constructor-arg index="1" value="${jedis.JedisServerIp}"/>  
        <constructor-arg index="2" value="${jedis.JedisServerPort}"/>  
        <constructor-arg index="3" value="${jedis.timeout}"/>  
        <constructor-arg index="4" value="${jedis.auth}"/>  
    </bean>  
    
    <!-- JedisPool manager -->
    <bean id="jedisPoolManager" class="com.securityframework.support.JedisPoolManager">
        <property name="jedisPool" ref="jedisPool"></property>
    </bean>
    <!--redisCacheManager要实现org.apache.shiro.cache.CacheManager接口,让shiro使用redis的缓存-->
    <bean id="redisCacheManager" class="com.securityframework.support.RedisCacheManager">
        <property name="redisManager" ref="jedisPoolManager"></property>
    </bean>				
    <!-- Redis session dao -->
	<!--redisSessionDAO继承实现了org.apache.shiro.session.mgt.eis.SessionDAO的AbstractSessionDAO-->
    <bean id="redisSessionDAO" class="com.securityframework.support.RedisSessionDAO">
        <property name="redisManager" ref  ="jedisPoolManager"         />
        <property name="expire"       value="${shiro.session.timeout}" />
    </bean>
    
好了拜拜。
 
                    
                     
                    
                 
                    
                
 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号