spring boot 中 Ehcache 缓存应用实例

  1. 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(先进先出)
    –>
    < defaultCache

        maxEntriesLocalHeap="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>

  2. 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来拦截用以下注解的方法。*/

}

  1. 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);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值