Shiro-Redis-Cache:
Cache:负责完成缓存数据的功能
CacheManager:负责管理Cache核心流程,重点是会创建Cache对象.
一、定义Cache组件
package com.vince.cache;
import lombok.Getter;
import lombok.Setter;
import org.apache.shiro.cache.Cache;
import org.apache.shiro.cache.CacheException;
import org.springframework.data.redis.core.RedisTemplate;
import java.util.Collection;
import java.util.Set;
@Setter
@Getter
public class MyShiroCache implements Cache {
private String name; // 权限缓存的标识
private RedisTemplate<String,Object> template;
public MyShiroCache(){}
public MyShiroCache(String name){ // 需 get/set
this.name=name; // 在 cacheManager 中会调用此方法
}
// cache 主业务
@Override
public Object get(Object o) throws CacheException {
System.out.println("检查缓存权限~");
Object data = template.opsForValue().get(o.toString());
if (data!=null){
System.out.println("权限信息检查 ----命中缓存~");
return data;
}else{
System.out.println("权限信息检查 ----缓存中不存在~");
return null;
}
}
@Override
public Object put(Object o, Object o2) throws CacheException {
template.opsForValue().set(o.toString(), o2);
return null;
}
// 可以移除某个用户的权限信息的缓存,用于 subject.logout();
// o =key=用户凭证 ~= 用户名
@Override
public Object remove(Object o) throws CacheException {
System.out.println(o+"的权限信息被清除");
template.delete(o.toString());
return null;
}
@Override
public void clear() throws CacheException {
}
@Override
public int size() {
return 0;
}
@Override
public Set keys() {
return null;
}
@Override
public Collection values() {
return null;
}
}
二、定义CacheManager
import lombok.Setter;
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;
@Setter
public class MyCacheManager extends AbstractCacheManager {
private RedisTemplate<String,Object> template; // 需要注入RedisTemplate
@Override
protected Cache createCache(String s) throws CacheException {
System.out.println("标识是:--"+s);
MyShiroCache cache = new MyShiroCache(s);
cache.setTemplate(template);
return cache;
三、配置Cache和CacheManager
shiro-spring.xml:j将此文件导入spring工厂
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 整合mybaits,事务控制等 配置不变 -->
<!-- 声明realm -->
<bean id="myRealm" class="com.vince.realm.MyRealm">
<property name="userService" ref="userServiceImpl"/>
<property name="roleService" ref="roleServiceImpl"/>
<property name="permissionService" ref="permissionServiceImpl"/>
<!--密码比对器-->
<property name="credentialsMatcher">
<bean class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
<property name="hashAlgorithmName" value="SHA-256"/>
<!-- true means hex encoded, false means base64 encoded -->
<property name="storedCredentialsHexEncoded" value="false"/>
<property name="hashIterations" value="10000"/>
</bean>
</property>
</bean>
<!-- 声明CacheManager,注意Cache不用声明,会由CacheManager创建 -->
<bean class="com.vince.cache.MyCacheManager" id="cacheManager9">
<property name="template" ref="redisTemplate02"/>
</bean>
<!-- 声明SecurityManager -->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="realm" ref="myRealm"/>
<!--缓存管理器-->
<property name="cacheManager" ref="cacheManager9"></property>
</bean>
<!-- 生产SpringShiroFilter
( 持有shiro的过滤相关规则,可进行请求的过滤校验,校验请求是否合法 )
-->
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<property name="securityManager" ref="securityManager"/>
<!--<property name="loginUrl" value="/user/login/page"/>-->
<!--<property name="unauthorizedUrl" value="/user/error"/>-->
<property name="filterChainDefinitions">
<value>
/user/logout = logout
</value>
</property>
</bean>
<!--引入redis文件-->
<import resource="classpath:application-redis.xml"></import>
</beans>
redis配置文件:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<!-- 连接池配置 -->
<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
<!-- 最多空闲连接数 -->
<property name="maxIdle" value="1" />
<!-- 最多有多少连接 -->
<property name="maxTotal" value="5" />
<property name="minIdle" value="1"></property>
<!-- 连接数用完时,是否阻塞,阻塞超过maxWaitMillis会抛出异常 -->
<property name="blockWhenExhausted" value="true" />
<!-- 检出连接时,最大等待时长 -->
<property name="maxWaitMillis" value="30000" />
<!-- 在检出时是否检测 -->
<property name="testOnBorrow" value="false" />
<!-- 空闲时是否检测连接是否可用 -->
<property name="testWhileIdle" value="false"></property>
<!-- Evict=驱逐 连接至少要空闲多少时间才会成为可以被驱逐线程扫描并移除 -->
<property name="minEvictableIdleTimeMillis" value="60000"></property>
<!-- 驱逐线程 两次驱逐之间要sleep的时间 如果小于0,则不会有驱逐线程,则minEvictableIdleTimeMillis无效-->
<property name="timeBetweenEvictionRunsMillis" value="30000"></property>
<!-- 驱逐线程每次最多扫描几个连接 -->
<property name="numTestsPerEvictionRun" value="3"></property>
<!-- last in first out 检出策略 后入先出 或 先入先出 -->
<property name="lifo" value="true"></property>
</bean>
<!-- 为 redisClusterConfiguration定制参数配置-->
<bean id="propertyPropertySource" class="org.springframework.core.env.PropertiesPropertySource">
<constructor-arg index="0" type="java.lang.String" value="redisParam04"></constructor-arg>
<constructor-arg index="1" type="java.util.Properties">
<props>
<!-- 集群中的所有或部分节点ip:port -->
<prop key="spring.redis.cluster.nodes">192.168.11.128:9001,192.168.11.128:9005,192.168.11.128:9006</prop>
<!--
默认为5,连接不到集群时,重试次数
-->
<prop key="spring.redis.cluster.max-redirects">5</prop>
</props>
</constructor-arg>
</bean>
<!--将 propertyPropertySource 注入-->
<bean id="redisClusterConfiguration" class="org.springframework.data.redis.connection.RedisClusterConfiguration">
<constructor-arg name="propertySource" ref="propertyPropertySource"/>
</bean>
<!-- 连接Factory -->
<bean id="jedisConnectionFactory"
class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
<!-- Redis主机 -->
<!--<property name="hostName" value="192.168.11.128"></property>-->
<!--<property name="port" value="8000"></property>-->
<!--redis集群-->
<constructor-arg name="clusterConfig" ref="redisClusterConfiguration"></constructor-arg>
<!-- 连接池配置信息 -->
<property name="poolConfig" ref="jedisPoolConfig"></property>
</bean>
<!-- 如果没有设置序列化,则默认使用DefaultSerializer。
声明序列化组件
-->
<bean id="ss" class="org.springframework.data.redis.serializer.StringRedisSerializer" />
<bean class="org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer" id="jacks" />
<bean class="com.alibaba.fastjson.support.spring.GenericFastJsonRedisSerializer" id="fast"></bean>
<!-- RedisTemplate:核心组件 -->
<bean id="redisTemplate02" class="org.springframework.data.redis.core.RedisTemplate"
p:connectionFactory-ref="jedisConnectionFactory"
p:keySerializer-ref="ss"
p:hashKeySerializer-ref="ss"
p:hashValueSerializer-ref="fast"
p:stringSerializer-ref="ss"
p:valueSerializer-ref="fast"></bean>
</beans>
如上就可将频繁从数据库中查询改为从缓存中查询数据 ,提高查询效率。