初步学习shiro+redis+springMVC的集成配置,做一下记录文档吧
2016-11-10 08:38
567 查看
为了使用redis实现session共享机制,上网找了不少资料,最后发现了一篇比较详细的blog介绍:http://blog.csdn.net/lishehe/article/details/45223823,可以参考参考;按照里面的逐步配置后发现有问题,少了一个redisManager的文件实现类,找了一些其他的资料中文件,可能和作者的配置不太相符合,只能放弃,作参考价值,后来发现有shiro-redis的官方文档:https://github.com/alexxiyang/shiro-redis,这个就比较简洁明了,而且相关的实现类源码都可以下载,发现竟然如此简单就可以了。一番重新配置后,运行了项目,还是报异常,是shiro认证的原因,NOTE Shiro-redis don't support SimpleAuthenticationInfo created by this constructororg.apache.shiro.authc.SimpleAuthenticationInfo.SimpleAuthenticationInfo(Object principal, Object hashedCredentials, ByteSource credentialsSalt, String realmName). Please useorg.apache.shiro.authc.SimpleAuthenticationInfo.SimpleAuthenticationInfo(Object principal, Object hashedCredentials, String realmName) instead.官方文档是这么标注的,不信邪,无视了,寻着异常一步一步debug下去,发现是认证成功后保存session出的问题,无法将TBSysPermission
bean对象序列化,找到该bean文件,实现一下Serializable接口,按照提示添加一行
xml文件配置:
bean对象序列化,找到该bean文件,实现一下Serializable接口,按照提示添加一行
private static final long serialVersionUID = 1L;搞定,项目成功运行,session共享实现完成。
package com.zkzy.redis; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; import org.apache.shiro.cache.Cache; import org.apache.shiro.cache.CacheException; import org.apache.shiro.util.CollectionUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class RedisCache implements Cache { private Logger logger = LoggerFactory.getLogger(this.getClass()); /** * The wrapped Jedis instance. */ private RedisManager cache; /** * The Redis key prefix for the sessions */ private String keyPrefix = "shiro_redis_session:"; /** * 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(RedisManager 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(RedisManager 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{ return SerializeUtils.serialize(key); } } @Override public V get(K key) throws CacheException { logger.debug("根据key从Redis中获取对象 key [" + key + "]"); try { if (key == null) { return null; }else{ byte[] rawValue = cache.get(getByteKey(key)); @SuppressWarnings("unchecked") V value = (V)SerializeUtils.deserialize(rawValue); return value; } } catch (Throwable t) { throw new CacheException(t); } } @Override public V put(K key, V value) throws CacheException { logger.debug("根据key从存储 key [" + key + "]"); try { cache.set(getByteKey(key), SerializeUtils.serialize(value)); return value; } catch (Throwable t) { throw new CacheException(t); } } @Override public V remove(K key) throws CacheException { logger.debug("从redis中删除 key [" + key + "]"); try { V previous = get(key); cache.del(getByteKey(key)); return previous; } catch (Throwable t) { throw new CacheException(t); } } @Override public void clear() throws CacheException { logger.debug("从redis中删除所有元素"); try { cache.flushDB(); } catch (Throwable t) { throw new CacheException(t); } } @Override public int size() { try { Long longSize = new Long(cache.dbSize()); return longSize.intValue(); } catch (Throwable t) { throw new CacheException(t); } } @SuppressWarnings("unchecked") @Override public Set keys() { try { Set keys = cache.keys(this.keyPrefix + "*"); if (CollectionUtils.isEmpty(keys)) { return Collections.emptySet(); }else{ Set newKeys = new HashSet(); for(byte[] key:keys){ newKeys.add((K)key); } return newKeys; } } catch (Throwable t) { throw new CacheException(t); } } @Override public Collection values() { try { Set keys = cache.keys(this.keyPrefix + "*"); if (!CollectionUtils.isEmpty(keys)) { List values = new ArrayList(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) { throw new CacheException(t); } } } package com.zkzy.redis; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import org.apache.shiro.cache.Cache; import org.apache.shiro.cache.CacheException; import org.apache.shiro.cache.CacheManager; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class RedisCacheManager implements CacheManager { private static final Logger logger = LoggerFactory .getLogger(RedisCacheManager.class); // fast lookup by name map private final ConcurrentMap caches = new ConcurrentHashMap(); private RedisManager redisManager; /** * The Redis key prefix for caches */ private String keyPrefix = "shiro_redis_cache:"; /** * 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; } @Override public Cache getCache(String name) throws CacheException { logger.debug("获取名称为: " + name + " 的RedisCache实例"); Cache c = caches.get(name); if (c == null) { // initialize the Redis manager instance redisManager.init(); // create a new cache instance c = new RedisCache(redisManager, keyPrefix); // add it to the cache collection caches.put(name, c); } return c; } public RedisManager getRedisManager() { return redisManager; } public void setRedisManager(RedisManager redisManager) { this.redisManager = redisManager; } } package com.zkzy.redis; import java.util.Set; import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPool; import redis.clients.jedis.JedisPoolConfig; public class RedisManager { private String host = "127.0.0.1"; private int port = 6379; // 0 - never expire private int expire = 0; //timeout for jedis try to connect to redis server, not expire time! In milliseconds private int timeout = 0; private String password = "root"; private static JedisPool jedisPool = null; public RedisManager(){ } /** * 初始化方法 */ public void init(){ if(jedisPool == null){ if(password != null && !"".equals(password)){ jedisPool = new JedisPool(new JedisPoolConfig(), host, port, timeout, password); }else if(timeout != 0){ jedisPool = new JedisPool(new JedisPoolConfig(), host, port,timeout); }else{ jedisPool = new JedisPool(new JedisPoolConfig(), host, port); } } } /** * get value from redis * @param key * @return */ public byte[] get(byte[] key){ byte[] value = null; Jedis jedis = jedisPool.getResource(); try{ value = jedis.get(key); }finally{ jedisPool.returnResource(jedis); } return value; } /** * set * @param key * @param value * @return */ public byte[] set(byte[] key,byte[] value){ Jedis jedis = jedisPool.getResource(); try{ jedis.set(key,value); if(this.expire != 0){ jedis.expire(key, this.expire); } }finally{ jedisPool.returnResource(jedis); } return value; } /** * set * @param key * @param value * @param expire * @return */ public byte[] set(byte[] key,byte[] value,int expire){ Jedis jedis = jedisPool.getResource(); try{ jedis.set(key,value); if(expire != 0){ jedis.expire(key, expire); } }finally{ jedisPool.returnResource(jedis); } return value; } /** * del * @param key */ public void del(byte[] key){ Jedis jedis = jedisPool.getResource(); try{ jedis.del(key); }finally{ jedisPool.returnResource(jedis); } } /** * flush */ public void flushDB(){ Jedis jedis = jedisPool.getResource(); try{ jedis.flushD d4d6 B(); }finally{ jedisPool.returnResource(jedis); } } /** * size */ public Long dbSize(){ Long dbSize = 0L; Jedis jedis = jedisPool.getResource(); try{ dbSize = jedis.dbSize(); }finally{ jedisPool.returnResource(jedis); } return dbSize; } /** * keys * @param regex * @return */ public Set keys(String pattern){ Set keys = null; Jedis jedis = jedisPool.getResource(); try{ keys = jedis.keys(pattern.getBytes()); }finally{ jedisPool.returnResource(jedis); } return keys; } public String getHost() { return host; } public void setHost(String host) { this.host = host; } public int getPort() { return port; } public void setPort(int port) { this.port = port; } public int getExpire() { return expire; } public void setExpire(int expire) { this.expire = expire; } public int getTimeout() { return timeout; } public void setTimeout(int timeout) { this.timeout = timeout; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } } package com.zkzy.redis; import java.io.Serializable; import java.util.Collection; import java.util.HashSet; import java.util.Set; import org.apache.shiro.session.Session; import org.apache.shiro.session.UnknownSessionException; import org.apache.shiro.session.mgt.eis.AbstractSessionDAO; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class RedisSessionDAO extends AbstractSessionDAO { private static Logger logger = LoggerFactory.getLogger(RedisSessionDAO.class); /** * shiro-redis的session对象前缀 */ private RedisManager redisManager; /** * The Redis key prefix for the sessions */ private String keyPrefix = "shiro_redis_session:"; @Override public void update(Session session) throws UnknownSessionException { 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; } byte[] key = getByteKey(session.getId()); byte[] value = SerializeUtils.serialize(session); session.setTimeout(redisManager.getExpire()*1000); this.redisManager.set(key, value, redisManager.getExpire()); } @Override public void delete(Session session) { if(session == null || session.getId() == null){ logger.error("session or session id is null"); return; } redisManager.del(this.getByteKey(session.getId())); } @Override public Collection getActiveSessions() { Set sessions = new HashSet(); Set keys = redisManager.keys(this.keyPrefix + "*"); if(keys != null && keys.size()>0){ for(byte[] key:keys){ Session s = (Session)SerializeUtils.deserialize(redisManager.get(key)); sessions.add(s); } } return sessions; } @Override protected Serializable doCreate(Session session) { Serializable sessionId = this.generateSessionId(session); this.assignSessionId(session, sessionId); this.saveSession(session); return sessionId; } @Override protected Session doReadSession(Serializable sessionId) { if(sessionId == null){ logger.error("session id is null"); return null; } Session s = (Session)SerializeUtils.deserialize(redisManager.get(this.getByteKey(sessionId))); return s; } /** * 获得byte[]型的key * @param key * @return */ private byte[] getByteKey(Serializable sessionId){ String preKey = this.keyPrefix + sessionId; return preKey.getBytes(); } public RedisManager getRedisManager() { return redisManager; } public void setRedisManager(RedisManager redisManager) { this.redisManager = redisManager; /** * 初始化redisManager */ this.redisManager.init(); } /** * 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; } } package com.zkzy.redis; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class SerializeUtils { private static Logger logger = LoggerFactory.getLogger(SerializeUtils.class); /** * 反序列化 * @param bytes * @return */ public static Object deserialize(byte[] bytes) { Object result = null; if (isEmpty(bytes)) { return null; } try { ByteArrayInputStream byteStream = new ByteArrayInputStream(bytes); try { ObjectInputStream objectInputStream = new ObjectInputStream(byteStream); try { result = objectInputStream.readObject(); } catch (ClassNotFoundException ex) { throw new Exception("Failed to deserialize object type", ex); } } catch (Throwable ex) { throw new Exception("Failed to deserialize", ex); } } catch (Exception e) { logger.error("Failed to deserialize",e); } return result; } public static boolean isEmpty(byte[] data) { return (data == null || data.length == 0); } /** * 序列化 * @param object * @return */ public static byte[] serialize(Object object) { byte[] result = null; if (object == null) { return new byte[0]; } try { ByteArrayOutputStream byteStream = new ByteArrayOutputStream(128); try { if (!(object instanceof Serializable)) { throw new IllegalArgumentException(SerializeUtils.class.getSimpleName() + " requires a Serializable payload " + "but received an object of type [" + object.getClass().getName() + "]"); } ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteStream); objectOutputStream.writeObject(object); objectOutputStream.flush(); result = byteStream.toByteArray(); } catch (Throwable ex) { throw new Exception("Failed to serialize", ex); } } catch (Exception ex) { logger.error("Failed to serialize",ex); } return result; } }
xml文件配置:
<!-- shiro filter --> <bean id="ShiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"> <property name="securityManager" ref="securityManager"/> <!-- <property name="loginUrl" value="/login.jsp"/> <property name="successUrl" value="/home.jsp"/> <property name="unauthorizedUrl" value="/unauthorized.jsp"/> --> <!-- The 'filters' property is not necessary since any declared javax.servlet.Filter bean --> <!-- defined will be automatically acquired and available via its beanName in chain --> <!-- definitions, but you can perform instance overrides or name aliases here if you like: --> <!-- <property name="filters"> <util:map> <entry key="anAlias" value-ref="someFilter"/> </util:map> </property> --> <property name="filterChainDefinitions"> <value> /login.jsp = anon /user/** = anon /register/** = anon /unauthorized.jsp = anon /css/** = anon /js/** = anon /** = authc </value> </property> </bean> <!-- shiro securityManager --> <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"> <!-- Single realm app. If you have multiple realms, use the 'realms' property instead. --> <!-- sessionManager --> <property name="sessionManager" ref="sessionManager" /> <!-- cacheManager --> <property name="cacheManager" ref="cacheManager" /> <!-- By default the servlet container sessions will be used. Uncomment this line to use shiro's native sessions (see the JavaDoc for more): --> <!-- <property name="sessionMode" value="native"/> --> </bean> <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/> <!-- shiro redisManager --> <bean id="redisManager" class="org.crazycake.shiro.RedisManager"> <property name="host" value="127.0.0.1"/> <property name="port" value="6379"/> <property name="expire" value="1800"/> <!-- optional properties: <property name="timeout" value="10000"/> <property name="password" value="123456"/> --> </bean> <!-- redisSessionDAO --> <bean id="redisSessionDAO" class="org.crazycake.shiro.RedisSessionDAO"> <property name="redisManager" ref="redisManager" /> </bean> <!-- sessionManager --> <bean id="sessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager"> <property name="sessionDAO" ref="redisSessionDAO" /> </bean> <!-- cacheManager --> <bean id="cacheManager" class="org.crazycake.shiro.RedisCacheManager"> <property name="redisManager" ref="redisManager" /> </bean>
相关文章推荐
- SpringBoot学习笔记(5) Spring Boot集成Redis实现自动配置
- 第四章 INI配置——跟我学习springmvc shiro mybatis
- Spring 4 官方文档学习(十一)Web MVC 框架之约定优于配置
- Spring学习记录(2) Spring MVC+Mybatis 注解配置
- shiro+redis+springMvc整合配置及说明
- [置顶] redis3.2 学习记录 springmvc +jredis +redis 整合
- 第四章 INI配置——跟我学习springmvc shiro mybatis
- Spring 4 官方文档学习(十一)Web MVC 框架之配置Spring MVC
- SpringMVC + Spring + Mybatis+ Redis +shiro以及MyBatis学习
- shiro+redis+springMvc整合配置及说明
- shiro+redis+springMvc整合配置及说明
- Spring 4 官方文档学习(⑥)Web MVC 框架之配置Spring MVC
- shiro开发,shiro的环境配置(基于spring+springMVC+redis)
- Spring3.1 MVC注解配置学习
- ***Spring MVC的多视图解析器配置及与Freemarker的集成
- SpringMVC+Apache Shiro+JPA(hibernate)整合配置
- 记录一下学习VC的初步过程.
- maven学习记录2.maven+mybatis+springmvc+sqlserver2008
- 集成springmvc spring hibernate的配置过程
- windows环境下 springMVC+jdbc+redis整合配置