spring,shiro,redis实现session共享

来源:互联网 发布:python 毫秒数 编辑:程序博客网 时间:2024/05/21 17:33

spring-shiro 整合请看shiro springmvc整合第一步

spring-redis整合请看spring redis整合

用到的redis jar如下

<dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId><version>2.6.2</version></dependency><dependency><groupId>org.springframework.data</groupId><artifactId>spring-data-redis</artifactId><version>1.4.1.RELEASE</version></dependency><dependency><groupId>org.apache.commons</groupId><artifactId>commons-pool2</artifactId><version>2.2</version></dependency>

想要实现使用redis管理session 需要在shiro 的sessionmanager添加sessionDAO属性 如下

<bean id="sessionManager"class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager"><property name="sessionDAO" ref="sessionDao"></property><property name="globalSessionTimeout" value="60000" /><!-- 删除失效session --><property name="sessionValidationSchedulerEnabled" value="true" /><property name="sessionListeners" ref="myShiroSessionListener"></property></bean><bean id="myShiroSessionListener" class="com.zyc.listener.MyShiroSessionListener"></bean><bean id="sessionDao" class="com.zyc.security.SessionDao"><property name="redisUtil" ref="redisUtil"></property></bean>
redis配置如下

<bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig"><property name="maxIdle" value="100" /><property name="maxWaitMillis" value="10000" /><property name="testOnBorrow" value="true" /></bean><!-- redis服务器中心 --><bean id="connectionFactory"class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"><property name="poolConfig" ref="poolConfig" /><property name="port" value="63791" /><property name="hostName" value="127.0.0.1" /><!-- <property name="password" value="${redis.password}" /> --><property name="timeout" value="10000"></property></bean><bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate"><property name="connectionFactory" ref="connectionFactory" /><property name="keySerializer"><beanclass="org.springframework.data.redis.serializer.StringRedisSerializer" /></property><property name="valueSerializer"><beanclass="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer" /></property></bean>

sessionDao需要实现EnterpriseCacheSessionDAO类或者CachingSessionDAO类,咱们这里以EnterpriseCacheSessionDAO类为例如下:

package com.zyc.security;import java.io.ByteArrayInputStream;import java.io.ByteArrayOutputStream;import java.io.IOException;import java.io.ObjectInputStream;import java.io.ObjectOutput;import java.io.ObjectOutputStream;import java.io.Serializable;import org.apache.shiro.session.Session;import org.apache.shiro.session.mgt.SimpleSession;import org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO;public class SessionDao extends EnterpriseCacheSessionDAO {private RedisUtil redisUtil;public RedisUtil getRedisUtil() {return redisUtil;}public void setRedisUtil(RedisUtil redisUtil) {this.redisUtil = redisUtil;}// 创建session,保存到数据库    @Override    protected Serializable doCreate(Session session) {        Serializable sessionId = super.doCreate(session);        redisUtil.set(sessionId.toString(), sessionToByte(session),1*60L);                return sessionId;    }    // 获取session    @Override    protected Session doReadSession(Serializable sessionId) {        // 先从缓存中获取session,如果没有再去数据库中获取        Session session = super.doReadSession(sessionId);         if(session == null){            byte[] bytes = (byte[]) redisUtil.get(sessionId.toString());            if(bytes != null && bytes.length > 0){                session = byteToSession(bytes);                }        }        return session;    }    // 更新session的最后一次访问时间    @Override    protected void doUpdate(Session session) {        super.doUpdate(session);        redisUtil.set(session.getId().toString(), sessionToByte(session),1*60L);    }    // 删除session    @Override    protected void doDelete(Session session) {        super.doDelete(session);        redisUtil.remove(session.getId().toString());    }    // 把session对象转化为byte保存到redis中    public byte[] sessionToByte(Session session){        ByteArrayOutputStream bo = new ByteArrayOutputStream();        byte[] bytes = null;        try {            ObjectOutput oo = new ObjectOutputStream(bo);            oo.writeObject(session);            bytes = bo.toByteArray();        } catch (IOException e) {            e.printStackTrace();        }        return bytes;    }        // 把byte还原为session    public Session byteToSession(byte[] bytes){        ByteArrayInputStream bi = new ByteArrayInputStream(bytes);        ObjectInputStream in;        SimpleSession session = null;        try {            in = new ObjectInputStream(bi);            session = (SimpleSession) in.readObject();        } catch (ClassNotFoundException e) {            e.printStackTrace();        } catch (IOException e) {            e.printStackTrace();        }            return session;    }}
RedisUtil工具类如下:

package com.zyc.security;import java.io.Serializable;import java.util.Set;import java.util.concurrent.TimeUnit;import javax.annotation.Resource;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.data.redis.core.RedisTemplate;import org.springframework.data.redis.core.ValueOperations;import org.springframework.stereotype.Service;/** * @author: zyc * @date:2017年10月24日 上午9:26:55 * @description: * @version : *  */@Service("redisUtil")public class RedisUtil {private Logger logger = LoggerFactory.getLogger(RedisUtil.class);@Resource(name = "redisTemplate")private RedisTemplate<Serializable, Object> redisTemplate;/** * 批量删除对应的value *  * @param keys */public void remove(final String... keys) {for (String key : keys) {remove(key);}}/** * 批量删除key *  * @param pattern */public void removePattern(final String pattern) {Set<Serializable> keys = redisTemplate.keys(pattern);if (keys.size() > 0)redisTemplate.delete(keys);}/** * 删除对应的value *  * @param key */public void remove(final String key) {if (exists(key)) {redisTemplate.delete(key);}}/** * 判断缓存中是否有对应的value *  * @param key * @return */public boolean exists(final String key) {return redisTemplate.hasKey(key);}/** * 获取所有的key *  * @return */public Set<Serializable> keys() {return redisTemplate.keys("*");}/** * 读取缓存 *  * @param key * @return */public Object get(final String key) {Object result = null;ValueOperations<Serializable, Object> operations = redisTemplate.opsForValue();result = operations.get(key);return result;}/** * 写入缓存 *  * @param key * @param value * @return */public boolean set(final String key, Object value) {boolean result = false;try {ValueOperations<Serializable, Object> operations = redisTemplate.opsForValue();operations.set(key, value);result = true;} catch (Exception e) {e.printStackTrace();}return result;}/** * 写入缓存 *  * @param key * @param value * @return */public boolean set(final String key, Object value, Long expireTime) {boolean result = false;try {ValueOperations<Serializable, Object> operations = redisTemplate.opsForValue();operations.set(key, value);redisTemplate.expire(key, expireTime, TimeUnit.SECONDS);result = true;} catch (Exception e) {e.printStackTrace();}return result;}public void setRedisTemplate(RedisTemplate<Serializable, Object> redisTemplate) {this.redisTemplate = redisTemplate;}}

session监听类如下(可写可不写,不写需要在配置中将监听器给去掉):

package com.zyc.listener;import org.apache.shiro.session.Session;import org.apache.shiro.session.SessionListener;import com.zyc.security.RedisUtil;import com.zyc.security.SpringContext;public class MyShiroSessionListener implements SessionListener {@Overridepublic void onStart(Session session) {}@Overridepublic void onStop(Session session) {// TODO Auto-generated method stubSystem.out.println("onStop==="+session.getId());RedisUtil redisUtil=(RedisUtil) SpringContext.getBean("redisUtil");redisUtil.remove(session.getId().toString());}@Overridepublic void onExpiration(Session session) {System.out.println("onExpiration==="+session.getId());RedisUtil redisUtil=(RedisUtil) SpringContext.getBean("redisUtil");redisUtil.remove(session.getId().toString());}}
SpringContext是获取bean的一个工具类:

package com.zyc.security;import org.springframework.beans.BeansException;import org.springframework.context.ApplicationContext;import org.springframework.context.ApplicationContextAware;import org.springframework.stereotype.Component;@Componentpublic class SpringContext implements  ApplicationContextAware{private static ApplicationContext applicationContext;@Overridepublic void setApplicationContext(ApplicationContext arg0)throws BeansException {// TODO Auto-generated method stubapplicationContext=arg0;}public static Object getBean(String name){if(applicationContext!=null){return applicationContext.getBean(name);}return null;}}


原创粉丝点击