ehcache_local.xml(/项目/src/main/resources/cache/ehcache_local.xml)
< ?xml version=”1.0” encoding=”UTF-8”?>
< ehcache updateCheck=”false” name=”shirocache”>
< diskStore path=”../cache/ehcache” />
< !– 默认缓存配置. 自动失效:最后一次访问时间间隔300秒失效,若没有访问过自创建时间600秒失效。–>
< !–
< diskStore>==========当内存缓存中对象数量超过maxElementsInMemory时,将缓存对象写到磁盘缓存中(需对象实现序列化接口)
< diskStore path=”“>==用来配置磁盘缓存使用的物理路径,Ehcache磁盘缓存使用的文件后缀名是.data和.index
name=================缓存名称,cache的唯一标识(ehcache会把这个cache放到HashMap里)
maxElementsOnDisk====磁盘缓存中最多可以存放的元素数量,0表示无穷大
maxElementsInMemory==内存缓存中最多可以存放的元素数量,若放入Cache中的元素超过这个数值,则有以下两种情况
1)若overflowToDisk=true,则会将Cache中多出的元素放入磁盘文件中
2)若overflowToDisk=false,则根据memoryStoreEvictionPolicy策略替换Cache中原有的元素
eternal==============缓存中对象是否永久有效,即是否永驻内存,true时将忽略timeToIdleSeconds和timeToLiveSeconds
timeToIdleSeconds====缓存数据在失效前的允许闲置时间(单位:秒),仅当eternal=false时使用,默认值是0表示可闲置时间无穷大,此为可选属性
即访问这个cache中元素的最大间隔时间,若超过这个时间没有访问此Cache中的某个元素,那么此元素将被从Cache中清除
timeToLiveSeconds====缓存数据在失效前的允许存活时间(单位:秒),仅当eternal=false时使用,默认值是0表示可存活时间无穷大
即Cache中的某元素从创建到清楚的生存时间,也就是说从创建开始计时,当超过这个时间时,此元素将从Cache中清除
overflowToDisk=======内存不足时,是否启用磁盘缓存(即内存中对象数量达到maxElementsInMemory时,Ehcache会将对象写到磁盘中)
会根据标签中path值查找对应的属性值,写入磁盘的文件会放在path文件夹下,文件的名称是cache的名称,后缀名是data
diskPersistent=======是否持久化磁盘缓存,当这个属性的值为true时,系统在初始化时会在磁盘中查找文件名为cache名称,后缀名为index的文件
这个文件中存放了已经持久化在磁盘中的cache的index,找到后会把cache加载到内存
要想把cache真正持久化到磁盘,写程序时注意执行net.sf.ehcache.Cache.put(Element element)后要调用flush()方法
diskExpiryThreadIntervalSeconds==磁盘缓存的清理线程运行间隔,默认是120秒
diskSpoolBufferSizeMB============设置DiskStore(磁盘缓存)的缓存区大小,默认是30MB
memoryStoreEvictionPolicy========内存存储与释放策略,即达到maxElementsInMemory限制时,Ehcache会根据指定策略清理内存
共有三种策略,分别为LRU(最近最少使用)、LFU(最常用的)、FIFO(先进先出)
–>
< defaultCachemaxEntriesLocalHeap="1000" eternal="false" timeToIdleSeconds="300" timeToLiveSeconds="600" overflowToDisk="true" statistics="true"/>
< !– 系统缓存 –>
< cache name=”sysCache”
maxEntriesLocalHeap=”1000”
eternal=”true”
overflowToDisk=”true”
statistics=”true”/>< !– 用户考试统计数据缓存 –>
< cache name=”userExamStaticsCashe”
maxEntriesLocalHeap=”10000”
eternal=”false”
timeToIdleSeconds=”3”
timeToLiveSeconds=”0”
overflowToDisk=”false”
statistics=”true” >
< /cache>
< /ehcache>ShiroEhcacheConfig.java(/src/main/java/com/cstar/mt/config/shiro/ShiroEhcacheConfig.java)
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import javax.servlet.Filter;
import org.apache.log4j.Logger;
import org.apache.shiro.cache.ehcache.EhCacheManager;
import org.apache.shiro.session.SessionListener;
import org.apache.shiro.session.mgt.SessionManager;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.servlet.Cookie;
import org.apache.shiro.web.servlet.SimpleCookie;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* Shiro 配置
* Apache Shiro 核心通过 Filter 来实现,就好像SpringMvc 通过DispachServlet 来主控制一样。
* 既然是使用 Filter 一般也就能猜到,是通过URL规则来进行过滤和权限校验,所以我们需要定义一系列关于URL的规则和访问权限。
* Created by sun on 2017-4-2.
*/
@Configuration
public class ShiroEhcacheConfig{
private final Logger logger = Logger.getLogger(ShiroEhcacheConfig.class);
/**
* ShiroFilterFactoryBean 处理拦截资源文件问题。
* 注意:单独一个ShiroFilterFactoryBean配置是或报错的,因为在
* 初始化ShiroFilterFactoryBean的时候需要注入:SecurityManager
*
Filter Chain定义说明
1、一个URL可以配置多个Filter,使用逗号分隔
2、当设置多个过滤器时,全部验证通过,才视为通过
3、部分过滤器可指定参数,如perms,roles
*
*/
@Bean("ehCacheManager")
public EhCacheManager getEhCacheManager(){
EhCacheManager ehcacheManager = new EhCacheManager();
ehcacheManager.setCacheManagerConfigFile("classpath:cache/ehcache_local.xml");
return ehcacheManager;
}
@Bean(name = "mtShiroRealm")
public MtShiroRealm myShiroRealm(EhCacheManager ehCacheManager){
MtShiroRealm realm = new MtShiroRealm();
realm.setCacheManager(ehCacheManager);
return realm;
}
@Bean(name = "lifecycleBeanPostProcessor")
public LifecycleBeanPostProcessor lifecycleBeanPostProcessor(){
return new LifecycleBeanPostProcessor();
}
@Bean
public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator(){
DefaultAdvisorAutoProxyCreator creator = new DefaultAdvisorAutoProxyCreator();
creator.setProxyTargetClass(true);
return creator;
}
@Bean(name = "securityManager")
public DefaultWebSecurityManager defaultWebSecurityManager(MtShiroRealm realm){
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
//设置realm
securityManager.setRealm(realm);
securityManager.setCacheManager(getEhCacheManager());
securityManager.setSessionManager(sessionManager());
return securityManager;
}
@Bean
public SessionManager sessionManager() {
DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
//session Listener
Collection<SessionListener> listeners = new ArrayList<SessionListener>();
listeners.add(new MtSessionListener());
sessionManager.setSessionListeners(listeners);
sessionManager.setGlobalSessionTimeout(30*60*1000);//shiro会话有效时间
sessionManager.setDeleteInvalidSessions(true);//是否清除过期的session
sessionManager.setSessionValidationSchedulerEnabled(true);//是否开启扫描
sessionManager.setSessionValidationInterval(10*60*1000);//shiro扫描间隔时间
//cookie set
Cookie cookie = new SimpleCookie();
cookie.setName("mt.session.id");
sessionManager.setSessionIdCookie(cookie);
sessionManager.setSessionIdCookieEnabled(true);
return sessionManager;
}
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(DefaultWebSecurityManager securityManager){
AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
advisor.setSecurityManager(securityManager);
return advisor;
}
@Bean(name = "shiroFilter")
public ShiroFilterFactoryBean shiroFilterFactoryBean(DefaultWebSecurityManager securityManager){
ShiroFilterFactoryBean factoryBean = new MtShiroFilterFactoryBean();
Map<String, Filter> filters = new HashMap<>();
filters.put("authc",new MtFormAuthenticationFilter());
factoryBean.setFilters(filters);
factoryBean.setSecurityManager(securityManager);
// 如果不设置默认会自动寻找Web工程根目录下的"/login.jsp"页面
factoryBean.setLoginUrl("/");
// 登录成功后要跳转的连接
factoryBean.setSuccessUrl("/welcome");
factoryBean.setUnauthorizedUrl("/403");
loadShiroFilterChain(factoryBean);
logger.info("shiro拦截器工厂类注入成功");
return factoryBean;
}
/**
* 加载ShiroFilter权限控制规则
*/
private void loadShiroFilterChain(ShiroFilterFactoryBean factoryBean) {
/**下面这些规则配置最好配置到配置文件中*/
Map<String, String> filterChainMap = new LinkedHashMap<String, String>();
/** authc:该过滤器下的页面必须验证后才能访问,它是Shiro内置的一个拦截器
* org.apache.shiro.web.filter.authc.FormAuthenticationFilter */
// anon:它对应的过滤器里面是空的,什么都没做,可以理解为不拦截
//authc:所有url都必须认证通过才可以访问; anon:所有url都都可以匿名访问
filterChainMap.put("/error", "anon");
filterChainMap.put("/v1/auth/login", "anon");
filterChainMap.put("/static/**", "anon");
filterChainMap.put("/**", "authc");
//filterChainMap.put("/**", "anon");//开发使用全部放过
factoryBean.setFilterChainDefinitionMap(filterChainMap);
}
/*1.LifecycleBeanPostProcessor,这是个DestructionAwareBeanPostProcessor的子类,负责org.apache.shiro.util.Initializable类型bean的生命周期的,初始化和销毁。主要是AuthorizingRealm类的子类,以及EhCacheManager类。
2.HashedCredentialsMatcher,这个类是为了对密码进行编码的,防止密码在数据库里明码保存,当然在登陆认证的生活,这个类也负责对form里输入的密码进行编码。
3.ShiroRealm,这是个自定义的认证类,继承自AuthorizingRealm,负责用户的认证和权限的处理,可以参考JdbcRealm的实现。
4.EhCacheManager,缓存管理,用户登陆成功后,把用户信息和权限信息缓存起来,然后每次用户请求时,放入用户的session中,如果不设置这个bean,每个请求都会查询一次数据库。
5.SecurityManager,权限管理,这个类组合了登陆,登出,权限,session的处理,是个比较重要的类。
6.ShiroFilterFactoryBean,是个factorybean,为了生成ShiroFilter。它主要保持了三项数据,securityManager,filters,filterChainDefinitionManager。
7.DefaultAdvisorAutoProxyCreator,Spring的一个bean,由Advisor决定对哪些类的方法进行AOP代理。
8.AuthorizationAttributeSourceAdvisor,shiro里实现的Advisor类,内部使用AopAllianceAnnotationsAuthorizingMethodInterceptor来拦截用以下注解的方法。*/
}
- EhcacheUtil.java
import org.apache.shiro.cache.Cache;
import org.apache.shiro.cache.ehcache.EhCacheManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.cstar.common.utils.SpringContextHolder;
public class EhcacheUtil {
private static final Logger logger = LoggerFactory.getLogger(EhcacheUtil.class);
private static EhCacheManager cacheManager = (EhCacheManager) SpringContextHolder.getBean(“ehCacheManager”);
private static final String SYS_CACHE = "sysCache";//自定义缓存名称
private static final String USEREXAMSTATICS_CASHE = "userExamStaticsCashe";
public static void put(String cacheName, String key, Object value) {
Cache cache = cacheManager.getCache(cacheName);
cache.put(key,value);
}
public static void put(String key, Object value) {
put(SYS_CACHE,key,value);
}
public static void putUserExamStatics(String key, Object value) {
put(USEREXAMSTATICS_CASHE, key,value);
}
public static Object get(String cacheName, String key) {
Cache cache = cacheManager.getCache(cacheName);
return cache.get(key);
}
public static Object get(String key){
return get(SYS_CACHE,key);
}
public static void remove(String cacheName, String key) {
Cache cache = cacheManager.getCache(cacheName);
cache.remove(key);
}
public static void remove(String key) {
remove(SYS_CACHE,key);
}
public static void clear(String cacheName) {
logger.debug("清除缓存:"+cacheName);
cacheManager.getCache(cacheName).clear();
}
}
缓存使用
EhcacheUtil.get(Constants.USEREXAMSTATICS_CASHE, reserveId);