根据项目需要,整合了springboot+shiro+redis单机、集群,有需要的小伙伴参考吧,有什么不懂的可以加群问,本人不喜欢写文字,直接上代码
redis配置文件:application-dev.yml
spring:
redis:
isJq: false #是否开启集群
host: 127.0.0.1
port: 6379
password: hn863@soft
# 连接超时时间(毫秒)
timeout: 15000
clusterNodes: 192.168.3.131:7000,192.168.3.131:7001,192.168.3.131:7002,192.168.3.131:7003,192.168.3.131:7004,192.168.3.131:7005
max-redirects: 3
pool:
# 连接池中的最大空闲连接
max-idle: 300
# 连接池中的最小空闲连接
min-idle: 10
# 连接池最大连接数(使用负值表示没有限制)
max-total: -1 #如果是jedis 2.4以后用该属性(2.4版本以前使用max-active)
# 连接池最大阻塞等待时间(使用负值表示没有限制)
max-wait: -1
#连接的最小空闲时间 默认1800000毫秒(30分钟)
minEvictableIdleTimeMillis: 300000
#每次释放连接的最大数目,默认3
numTestsPerEvictionRun: 1024
#逐出扫描的时间间隔(毫秒) 如果为负数,则不运行逐出线程, 默认-1
timeBetweenEvictionRunsMillis: 30000
#是否在从池中取出连接前进行检验,如果检验失败,则从池中去除连接并尝试取出另一个
testOnBorrow: true
#在空闲时检查有效性, 默认false
testWhileIdle: true
ShiroConfig:
package com.expo.system.config;
import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
import com.expo.common.config.Constant;
import com.expo.common.redis.shiro.RedisSessionDAO;
import com.expo.common.redis.shiro.ShiroRedisCacheManager;
import com.expo.common.utils.RedisUtil;
import com.expo.system.shiro.MyShiroFilterFactoryBean;
import com.expo.system.shiro.UserRealm;
import net.sf.ehcache.CacheManager;
import org.apache.shiro.cache.ehcache.EhCacheManager;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.session.mgt.eis.MemorySessionDAO;
import org.apache.shiro.session.mgt.eis.SessionDAO;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.web.mgt.CookieRememberMeManager;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.servlet.SimpleCookie;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisClusterConfiguration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.RedisNode;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import redis.clients.jedis.JedisPoolConfig;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.Set;
/**
* @author bootdo 1992lcg@163.com
*/
@Configuration
public class ShiroConfig {
@Value("${spring.redis.host}")
private String host;
@Value("${spring.redis.password}")
private String password;
@Value("${spring.redis.port}")
private int port;
@Value("${spring.redis.timeout}")
private int timeout;
@Value("${spring.cache.type}")
private String cacheType;
@Value("${server.session-timeout}")
private int tomcatTimeout;
@Value("${spring.redis.isJq}")
private boolean isJq;
@Value("${spring.redis.clusterNodes}")
private String clusterNodes;
@Value("${spring.redis.pool.max-idle}")
private int maxIdle;
@Value("${spring.redis.pool.min-idle}")
private int minIdle;
@Value("${spring.redis.pool.max-total}")
private int maxTotal;
@Value("${spring.redis.pool.max-wait}")
private int maxWait;
@Value("${spring.redis.pool.minEvictableIdleTimeMillis}")
private long minEvictableIdleTimeMillis;
@Value("${spring.redis.pool.numTestsPerEvictionRun}")
private int numTestsPerEvictionRun;
@Value("${spring.redis.pool.timeBetweenEvictionRunsMillis}")
private long timeBetweenEvictionRunsMillis;
@Value("${spring.redis.pool.testOnBorrow}")
private boolean testOnBorrow;
@Value("${spring.redis.pool.testWhileIdle}")
private boolean testWhileIdle;
@Value("${spring.redis.max-redirects}")
private int maxRedirectsac;
/**
* JedisPoolConfig 连接池
* @return
*/
@Bean
public JedisPoolConfig jedisPoolConfig() {
JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
// 最大空闲数
jedisPoolConfig.setMaxIdle(maxIdle);
// 连接池的最大数据库连接数
jedisPoolConfig.setMaxTotal(maxTotal);
// 最大建立连接等待时间
jedisPoolConfig.setMaxWaitMillis(maxWait);
// 逐出连接的最小空闲时间 默认1800000毫秒(30分钟)
jedisPoolConfig.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
// 每次逐出检查时 逐出的最大数目 如果为负数就是 : 1/abs(n), 默认3
jedisPoolConfig.setNumTestsPerEvictionRun(numTestsPerEvictionRun);
// 逐出扫描的时间间隔(毫秒) 如果为负数,则不运行逐出线程, 默认-1
jedisPoolConfig.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
// 是否在从池中取出连接前进行检验,如果检验失败,则从池中去除连接并尝试取出另一个
jedisPoolConfig.setTestOnBorrow(testOnBorrow);
// 在空闲时检查有效性, 默认false
jedisPoolConfig.setTestWhileIdle(testWhileIdle);
return jedisPoolConfig;
}
@Bean
public RedisClusterConfiguration redisClusterConfiguration(){
RedisClusterConfiguration redisClusterConfiguration = new RedisClusterConfiguration();
//Set<RedisNode> clusterNodes
String[] serverArray = clusterNodes.split(",");
Set<RedisNode> nodes = new HashSet<RedisNode>();
for(String ipPort:serverArray){
String[] ipAndPort = ipPort.split(":");
nodes.add(new RedisNode(ipAndPort[0].trim(),Integer.valueOf(ipAndPort[1])));
}
redisClusterConfiguration.setClusterNodes(nodes);
redisClusterConfiguration.setMaxRedirects(maxRedirectsac);
return redisClusterConfiguration;
}
/**
* 单机版和集群版配置
* @Title: JedisConnectionFactory
* @param @param jedisPoolConfig
* @param @return
* @return JedisConnectionFactory
* @autor lpl
* @date 2018年2月24日
* @throws
*/
@Bean
public JedisConnectionFactory edisConnectionFactory(JedisPoolConfig jedisPoolConfig, RedisClusterConfiguration redisClusterConfiguration){
//是否开启集群模式
if(isJq){
JedisConnectionFactory JedisConnectionFactory = new JedisConnectionFactory(redisClusterConfiguration,jedisPoolConfig);
JedisConnectionFactory.setPassword(password);
return JedisConnectionFactory;
}else{
JedisConnectionFactory JedisConnectionFactory = new JedisConnectionFactory(jedisPoolConfig);
//连接池
JedisConnectionFactory.setPoolConfig(jedisPoolConfig);
//IP地址
JedisConnectionFactory.setHostName(host);
//端口号
JedisConnectionFactory.setPort(port);
//如果Redis设置有密码
JedisConnectionFactory.setPassword(password);
//客户端超时时间单位是毫秒
JedisConnectionFactory.setTimeout(timeout);
return JedisConnectionFactory;
}
}
/**
* 实例化 RedisTemplate 对象
*
* @return
*/
@Bean
public RedisTemplate init(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate redisTemplate = new RedisTemplate();
redisTemplate.setConnectionFactory(redisConnectionFactory);
return redisTemplate;
}
/**
* 注入封装RedisTemplate
* @Title: redisUtil
* @return RedisUtil
* @autor lpl
* @date 2017年12月21日
* @throws
*/
@Bean(name = "redisUtil")
public RedisUtil redisUtil(RedisTemplate redisTemplate) {
RedisUtil redisUtil = new RedisUtil();
redisUtil.setRedisTemplate(redisTemplate);
return redisUtil;
}
@Bean
public SecurityManager securityManager(RedisConnectionFactory redisConnectionFactory) {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
//设置realm.
securityManager.setRealm(userRealm());
// 自定义缓存实现 使用redis
if (Constant.CACHE_TYPE_REDIS.equals(cacheType)) {
securityManager.setCacheManager(cacheManager(redisConnectionFactory));
} else {
securityManager.setCacheManager(ehCacheManager());
}
securityManager.setSessionManager(sessionManager(redisConnectionFactory));
securityManager.setRememberMeManager(rememberMeManager());
return securityManager;
}
@Bean
public DefaultWebSessionManager sessionManager(RedisConnectionFactory redisConnectionFactory){
DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
sessionManager.setGlobalSessionTimeout(tomcatTimeout * 1000);
sessionManager.setSessionDAO(sessionDAO(redisConnectionFactory));
return sessionManager;
}
/**
* ShiroDialect,为了在thymeleaf里使用shiro的标签的bean
*
* @return
*/
@Bean
public ShiroDialect shiroDialect() {
return new ShiroDialect();
}
@Bean
MyShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
MyShiroFilterFactoryBean shiroFilterFactoryBean = new MyShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(securityManager);
shiroFilterFactoryBean.setLoginUrl("/login");
shiroFilterFactoryBean.setSuccessUrl("/index");
shiroFilterFactoryBean.setUnauthorizedUrl("/403");
LinkedHashMap<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
filterChainDefinitionMap.put("/css/**", "anon");
filterChainDefinitionMap.put("/js/**", "anon");
filterChainDefinitionMap.put("/fonts/**", "anon");
filterChainDefinitionMap.put("/img/**", "anon");
filterChainDefinitionMap.put("/favicon.ico", "anon");
filterChainDefinitionMap.put("/docs/**", "anon");
filterChainDefinitionMap.put("/druid/**", "anon");
filterChainDefinitionMap.put("/upload/**", "anon");
filterChainDefinitionMap.put("/files/**", "anon");
filterChainDefinitionMap.put("/front/**", "anon");
filterChainDefinitionMap.put("/expo/expoCodeprint/**", "anon");
filterChainDefinitionMap.put("/expo/zz/**", "anon");
filterChainDefinitionMap.put("/indexFoot/**", "anon");
filterChainDefinitionMap.put("/sys/exhibitor/register/**", "anon");
filterChainDefinitionMap.put("/sys/exhibitor/jump/**", "anon");
filterChainDefinitionMap.put("/logout", "anon");
filterChainDefinitionMap.put("/czsLogin", "anon");
filterChainDefinitionMap.put("/hnfair", "anon");
filterChainDefinitionMap.put("/touqiahui/**", "anon");
filterChainDefinitionMap.put("/7286272117.txt", "anon");
filterChainDefinitionMap.put("/MP_verify_*", "anon");
filterChainDefinitionMap.put("/", "anon");
filterChainDefinitionMap.put("/**", "user");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
return shiroFilterFactoryBean;
}
@Bean
UserRealm userRealm() {
UserRealm userRealm = new UserRealm();
return userRealm;
}
/**
* 开启shiro aop注解支持.
* 使用代理方式;所以需要开启代码支持;
*
* @param securityManager
* @return
*/
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
return authorizationAttributeSourceAdvisor;
}
/**
* cacheManager 缓存 redis实现
* 使用的是shiro-redis开源插件
*
* @return
*/
public ShiroRedisCacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
return new ShiroRedisCacheManager(init(redisConnectionFactory));
}
@Bean
public SessionDAO sessionDAO(RedisConnectionFactory redisConnectionFactory) {
if (Constant.CACHE_TYPE_REDIS.equals(cacheType)) {
RedisSessionDAO redisSessionDAO=new RedisSessionDAO(redisUtil(init(redisConnectionFactory)));
return redisSessionDAO;
// return new EnterpriseCacheSessionDAO();
} else {
return new MemorySessionDAO();
}
}
//@Bean
public EhCacheManager ehCacheManager() {
EhCacheManager em = new EhCacheManager();
em.setCacheManager(CacheManager.create());
return em;
}
@Bean
public SimpleCookie rememberMeCookie(){
//这个参数是cookie的名称,对应前端的checkbox的name = rememberMe
SimpleCookie simpleCookie = new SimpleCookie("rememberMe");
//<!-- 记住我cookie生效时间30天 ,单位秒;-->
simpleCookie.setMaxAge(259200);
return simpleCookie;
}
/**
* cookie管理对象;
* @return
*/
@Bean
public CookieRememberMeManager rememberMeManager(){
CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager();
cookieRememberMeManager.setCookie(rememberMeCookie());
return cookieRememberMeManager;
}
public boolean getIsJq() {
return isJq;
}
}
RedisSessionDAO:
package com.expo.common.redis.shiro;
import com.expo.common.utils.RedisUtil;
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;
import java.io.Serializable;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
/**
* @author bootdo 1992lcg@163.com
* @version V1.0
*/
public class RedisSessionDAO extends AbstractSessionDAO {
private static Logger logger = LoggerFactory.getLogger(RedisSessionDAO.class);
private RedisUtil redisUtil;
/**
* The Redis key prefix for the sessions
*/
private String keyPrefix = "shiro_redis_session:";
public RedisSessionDAO(RedisUtil redisUtil){
this.redisUtil = redisUtil;
}
@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;
}
String key = getStringKey(session.getId());
byte[] value = SerializeUtils.serialize(session);
redisUtil.setString(key,value);
}
@Override
public void delete(Session session) {
if(session == null || session.getId() == null){
logger.error("session or session id is null");
return;
}
redisUtil.delString(getStringKey(session.getId()));
}
@Override
public Collection<Session> getActiveSessions() {
Set<Session> sessions = new HashSet<Session>();
Set<String> keys=redisUtil.keysString(this.keyPrefix + "*");
if(keys != null && keys.size()>0){
for(String key:keys){
Session s = (Session)SerializeUtils.deserialize((byte[])redisUtil.getString(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((byte[])redisUtil.getString(this.getStringKey(sessionId)));
return s;
}
/**
* 获得byte型的key
* @param sessionId
* @return
*/
private byte[] getByteKey(Serializable sessionId){
String preKey = this.keyPrefix + sessionId;
return preKey.getBytes();
}
/**
* 获得String型的key
* @param sessionId
* @return
*/
private String getStringKey(Serializable sessionId){
String preKey = this.keyPrefix + sessionId;
return preKey;
}
}
ShiroRedisCacheManager:
package com.expo.common.redis.shiro;
import org.apache.shiro.cache.AbstractCacheManager;
import org.apache.shiro.cache.Cache;
import org.apache.shiro.cache.CacheException;
import org.springframework.data.redis.core.RedisTemplate;
import java.util.*;
public class ShiroRedisCacheManager extends AbstractCacheManager{
private RedisTemplate redisTemplate;
public ShiroRedisCacheManager(RedisTemplate redisTemplate){
this.redisTemplate = redisTemplate;
}
@Override
protected Cache createCache(String name) throws CacheException {
return new ShiroRedisCache(redisTemplate,name);
}
}
class ShiroRedisCache<K,V> implements Cache<K,V> {
private RedisTemplate redisTemplate;
private String prefix = "random_shiro_redis";
public String getPrefix() {
return prefix+":";
}
public void setPrefix(String prefix) {
this.prefix = prefix;
}
public ShiroRedisCache(RedisTemplate redisTemplate){
this.redisTemplate = redisTemplate;
}
public ShiroRedisCache(RedisTemplate redisTemplate,String prefix){
this(redisTemplate);
this.prefix = prefix;
}
@Override
public V get(K k) throws CacheException {
if (k == null) {
return null;
}
String key = getStringKey(k);
return (V)redisTemplate.opsForValue().get(key);
}
@Override
public V put(K k, V v) throws CacheException {
if (k== null || v == null) {
return null;
}
String key = getStringKey(k);
redisTemplate.opsForValue().set(key, v);
return v;
}
@Override
public V remove(K k) throws CacheException {
if(k==null){
return null;
}
String key =getStringKey(k);
V v = (V)redisTemplate.opsForValue().get(key);
redisTemplate.delete(key);
return v;
}
@Override
public void clear() throws CacheException {
redisTemplate.getConnectionFactory().getConnection().flushDb();
}
@Override
public int size() {
return redisTemplate.getConnectionFactory().getConnection().dbSize().intValue();
}
@Override
public Set<K> keys() {
String keyall = getPrefix()+"*";
Set<String> keys = redisTemplate.keys(keyall);
Set<K> sets = new HashSet<>();
for (String key:keys) {
sets.add((K)key);
}
return sets;
}
@Override
public Collection<V> values() {
Set<K> keys = keys();
List<V> values = new ArrayList<>(keys.size());
for(K k :keys){
values.add(get(k));
}
return values;
}
private byte[] getBytesKey(K key){
if(key instanceof String){
String prekey = this.getPrefix() + key;
return prekey.getBytes();
}else {
return SerializeUtils.serialize(key);
}
}
private String getStringKey(K key) {
String prekey = this.getPrefix() + key;
return prekey;
}