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>

好了拜拜。

原文地址:https://www.cnblogs.com/core404/p/7515882.html