云中烛火

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

 

1、提供shrio用reids对缓存的管理支持

shiro提供了缓存的接口

package org.apache.shiro.cache;

import org.apache.shiro.cache.Cache;
import org.apache.shiro.cache.CacheException;

public interface CacheManager {
    <K, V> Cache<K, V> getCache(String var1) throws CacheException;
}

  

 类之间的继承

 

简单实现如下:

import org.apache.shiro.cache.Cache;
import org.apache.shiro.cache.CacheException;
import org.apache.shiro.cache.CacheManager;


public class JedisCacheManager implements CacheManager {

	private JedisManager jedisManager;
	@Override
	public <K, V> Cache<K, V> getCache(String s) throws CacheException {
		return new JedisShiroCache<>(s,getJedisManager());
	}

	public JedisManager getJedisManager() {
		return jedisManager;
	}

	public void setJedisManager(JedisManager jedisManager) {
		this.jedisManager = jedisManager;
	}
}

  

 

因为CacheManager接口中,也需要有Cache<K,V>的相应实现类

 

Cache<K,V>接口详情

import java.util.Collection;
import java.util.Set;
import org.apache.shiro.cache.CacheException;

public interface Cache<K, V> {
    V get(K var1) throws CacheException;

    V put(K var1, V var2) throws CacheException;

    V remove(K var1) throws CacheException;

    void clear() throws CacheException;

    int size();

    Set<K> keys();

    Collection<V> values();
}

  

我自己实现的类之间的继承关系

 

JedisShiroCache的结构详情:

有些方法是未实现的,因为redis里面找到所有已 *key* 开头的缓存,暂时没有找到好的方案,(jedis提供了keys 这个方法,但是返回的是 Set<String>)

  

import com.nanc.common.utils.SerializeUtil;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.shiro.cache.Cache;
import org.apache.shiro.cache.CacheException;

import java.util.Collection;
import java.util.Set;

/**
 * 因为该用redis做缓存
 * 故自己实现shiro的cache接口
 * Created by chennan on 2016/11/26.
 */
public class JedisShiroCache<K,V> implements Cache<K,V> {
	private JedisManager jedisManager;
	private String name;
	/**
	 * 为了不和其他的缓存混淆,采用追加前缀方式以作区分
	 */
	private static final String REDIS_SHIRO_CACHE = "nanc-shiro-cache:";
	private static final String REDIS_SHIRO_CACHE_PATTEN = "*nanc-shiro-cache:*";
	private static final int CACHE_VAL_TIME_SPAN = 3600;  //chache设置过期时间,防止长久未用,占用空间

	public JedisShiroCache(String nanme,JedisManager jedisManager) {
		this.name = nanme;
		this.jedisManager = jedisManager;
	}

	@Override
	public V get(K k) throws CacheException {
		byte[] valByte = new byte[0];
		try {
//			valByte = getJedisManager().get(SerializeUtil.serialize(buildCacheKey(k))); 不用这种方法存key,因为为放入reids后,前面有部分乱码
			valByte = getJedisManager().get(buildCacheKey(k).getBytes());
		} catch (Exception e) {
			e.printStackTrace();
		}
		return (V) SerializeUtil.deserialize(valByte);
	}

	@Override
	public V put(K k, V v) throws CacheException {
//		byte[] kByte = SerializeUtil.serialize(buildCacheKey(k));
		V previos = get(k);
		byte[] kByte = buildCacheKey(k).getBytes();
		byte[] vBytes = SerializeUtil.serialize(v);
		try {
			getJedisManager().set(kByte, vBytes);
			getJedisManager().expire(kByte,CACHE_VAL_TIME_SPAN);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return previos;
	}

	@Override
	public V remove(K k) throws CacheException {
		V v = get(k);
		try {
//			getJedisManager().del(SerializeUtil.serialize(buildCacheKey(k)));
			getJedisManager().del(buildCacheKey(k).getBytes());
		} catch (Exception e) {
			e.printStackTrace();
		}
		return v;
	}

	@Override
	public void clear() throws CacheException {
		/**
		 * 以正则形式找到所有的key,然后分别删除
		 */
		Set<String> set = getJedisManager().keys(REDIS_SHIRO_CACHE_PATTEN);
		if (CollectionUtils.isNotEmpty(set)) {
			for(String s : set){
				try {
					getJedisManager().del(s.getBytes());
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}
	}

	@Override
	public int size() {
		return 0;
	}

	@Override
	public Set<K> keys() {
		Set<String> set = getJedisManager().keys(REDIS_SHIRO_CACHE_PATTEN);
		return (Set<K>) set;
	}

	@Override
	public Collection<V> values() {
		return null;
	}


	public JedisManager getJedisManager() {
		return jedisManager;
	}

	public void setJedisManager(JedisManager jedisManager) {
		this.jedisManager = jedisManager;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String buildCacheKey(Object key) {
		return REDIS_SHIRO_CACHE + getName() + ":" + key;
	}
}

  

  

 

 

 

 2、提供shiro用redis对session的管理

 

 

 

 

我们只需继承或者AbstractSessionDAO或者CachingSessionDAO即可

我的类之间继承结构如下

 

MySessionDAO详情如下
package com.nanc.core.shiro.dao;
import com.nanc.core.shiro.session.ShiroSession;
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;


public class MySessionDAO extends AbstractSessionDAO {
	private ShiroSession shiroSession;

	@Override
	protected Serializable doCreate(Session session) {
		Serializable sessionId = doCreate(session);
		this.assignSessionId(session, sessionId);
		shiroSession.saveSession(session);
		return sessionId;
	}

	@Override
	protected Session doReadSession(Serializable serializable) {
		return shiroSession.getSession(serializable);
	}

	@Override
	public void update(Session session) throws UnknownSessionException {
		shiroSession.saveSession(session);
	}

	@Override
	public void delete(Session session) {
		if (session == null) {
			System.out.println("session为空了");
			return;
		}
		Serializable id = session.getId();
		if (id != null)
			shiroSession.deleteSession(id);
	}

	@Override
	public Collection<Session> getActiveSessions() {
		return shiroSession.getAllSessions();
	}


	public ShiroSession getShiroSession() {
		return shiroSession;
	}

	public void setShiroSession(ShiroSession shiroSession) {
		this.shiroSession = shiroSession;
	}
}

  

 

为了便于扩展,特抽取接口,对session进行相应的crud操作

结构如下:

 

ShiroSession详情

import org.apache.shiro.session.Session;

import java.io.Serializable;
import java.util.Collection;

/**
 * 自定义shiro session的管理接口
 *
 */
public interface ShiroSession {
	/**
	 * 存储Session
	 * @param session
	 */
	void saveSession(Session session);
	/**
	 * 删除session
	 * @param sessionId
	 */
	void deleteSession(Serializable sessionId);
	/**
	 * 获取session
	 * @param sessionId
	 * @return
	 */
	Session getSession(Serializable sessionId);
	/**
	 * 获取所有sessoin
	 * @return
	 */
	Collection<Session> getAllSessions();
}

  

 相应ShiroSession的实现类ShiroSessionRepository

 

import com.nanc.common.utils.SerializeUtil;
import com.nanc.core.shiro.cache.JedisManager;
import com.nanc.core.shiro.session.ShiroSession;
import org.apache.shiro.session.Session;
import redis.clients.jedis.Jedis;

import java.io.Serializable;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;


public class ShiroSessionRepository implements ShiroSession {
	private JedisManager jedisManager;
	public static final String REDIS_SHIRO_SESSION = "nanc-shiro-session:";
	//这里有个小BUG,因为Redis使用序列化后,Key反序列化回来发现前面有一段乱码,解决的办法是存储缓存不序列化
	public static final String REDIS_SHIRO_ALL = "*nanc-shiro-session::*";
	private static final int SESSION_VAL_TIME_SPAN = 18000;
	@Override
	public void saveSession(Session session) {
		if (null == session || null == session.getId()) {
			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 + SESSION_VAL_TIME_SPAN + (5 * 60);
			getJedisManager().set(key, value);
			getJedisManager().expire(key,expireTime.intValue());
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

	@Override
	public void deleteSession(Serializable sessionId) {
		if (null == sessionId) {
			throw new NullPointerException("sessionId 为空");
		}
		try {
			getJedisManager().del(SerializeUtil.serialize(buildRedisSessionKey(sessionId)));
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	@Override
	public Session getSession(Serializable sessionId) {
		if (null == sessionId) {
			throw new NullPointerException("sessionId 为空");
		}
		Session session = null;
		try {
			byte[] objByte = getJedisManager().get(SerializeUtil.serialize(buildRedisSessionKey(sessionId)));
			session =  SerializeUtil.deserialize(objByte,Session.class);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return session;
	}

	@Override
	public Collection<Session> getAllSessions() {
		Jedis jedis = null;
		Set<Session> sessions = new HashSet<>();
		try {
			jedis = getJedisManager().getJedis();

			Set<byte[]> byteKeys = jedis.keys((REDIS_SHIRO_ALL).getBytes());
			if (byteKeys != null && byteKeys.size() > 0) {
				for (byte[] bs : byteKeys) {
					Session obj = SerializeUtil.deserialize(jedis.get(bs),Session.class);
					if(obj instanceof Session){
						sessions.add(obj);
					}
				}
			}
		} catch (Exception e) {
			throw e;
		} finally {
			getJedisManager().returnResource(jedis);
		}
		return sessions;
	}

	public JedisManager getJedisManager() {
		return jedisManager;
	}

	public void setJedisManager(JedisManager jedisManager) {
		this.jedisManager = jedisManager;
	}

	private String buildRedisSessionKey(Serializable sessionId) {
		return REDIS_SHIRO_SESSION + sessionId;
	}
}

  

 

posted on 2016-11-26 21:33  云中烛火  阅读(331)  评论(0)    收藏  举报