初步学习shiro+redis+springMVC的集成配置,做一下记录文档吧

为了使用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接口,按照提示添加一行
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.flushDB(); }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>


  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
springboot:是一个基于Java开发的框架,简化了Spring应用的初始化配置和部署过程。它提供了一套开发规范和约定,帮助开发人员快速搭建高效稳定的应用程序。 mybatis-plus:是基于MyBatis的增强工具,提供了一些便捷的CRUD操作方法和代码生成功能,简化了数据库操作的开发工作。它能够轻松集成到SpringBoot应用中,提高开发效率。 springmvc:是一种基于MVC设计模式的Web框架,用于构建Web应用程序。它能够从URL中解析请求参数,并将请求分发给对应的Controller进行处理。SpringMVC提供了一套灵活的配置和注解方式,支持RESTful风格的API开发。 shiro:是一种用于身份验证和授权的框架,可以集成到SpringBoot应用中。它提供了一套简单易用的API,可以处理用户认证、角色授权、会话管理等安全相关的功能。Shiro还支持集成其他认证方式,如LDAP、OAuth等。 redis:是一种开源的内存数据库,采用键值对存储数据。Redis具有高性能、高并发和持久化等特点,常用于缓存、消息队列和分布式锁等场景。在企业级报表后台管理系统中,可以使用Redis来进行缓存数据,提高系统的响应速度和性能。 企业级报表后台管理系统:是一种用于统一管理和生成报表的系统。它通常包括用户权限管理、报表设计、报表生成、数据分析等功能。使用SpringBoot、MyBatis-Plus、SpringMVCShiroRedis等技术,可以快速搭建一个可靠、高效的报表管理系统,满足企业对数据分析和决策的需求。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值