Ehcache在工程实践中的应用

为了解决令牌验证问题,采用Ehcache作为缓存方案。通过实例介绍Ehcache的基本使用方法,包括配置文件解析、单例模式获取缓存及结合Spring框架的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

项目背景: 工程需要一个传输数据的接口,为了安全问题,我们加入一个获取令牌的接口,令牌是一个随机码,可设置失效时间,只有拿到令牌之后才可以带着令牌访问数据接口,我们通过比对令牌来确保调用者的合法性。

这是一个很简单的web需求,我们只需要把返回的令牌存在一个地方然后等待再次调用的时候拿出来对比一下就ok,于是我想到了session,因为session可以帮你管理失效时间,其本身的调用又很方便,代码写好之后浏览器测试一下没问题,是我们想要的结果。

                                                         

                                                

但是这里我忽略的一个比较大的问题,我们用网页调用接口的时候,网页是可以帮我们管理sessionid的,sessionid随着每次请求到服务器找到对用的session然后找到对应的值,只有你网页不关,sessionid不会变,但是在实际生产过程中,我们代码却无法管理sessionid,就是说我们获取到token之后下次再调用别的接口的时候服务器无法像之前一样根据sessionid匹配到session,这样我们之前存在session中的值找不到了,也就没法做token验证了

解决思路:

1. 我们使用长链接,把调用接口一和接口二的代码写在一个连接里面,这样就保证了两次调用面对同一个session,token验证就可行了。但是这样的缺点很明显,就是我们每次调用接口的时候都必须两个接口一起调用,耦合度太高,极不灵活

2. 把token存在application里面,application面向全局,也很容易把token存在其中,但是需要我们手工管理时效时间,这样就很繁琐

终极解决方案: 缓存的应用

3.把token放在缓存里面,这个方案倒是可行,提到缓存我首先想到redis,redis是缓存的典型应用,速度快,稳定性好,但是放在这个工程中就有点大材小用,毕竟我们是存储kb级别的token,今天来介绍一下java原生缓存框架Ehcache

Ehcache在本次工程中的应用极其轻便,其原理也很简单,话不多说,先看下Ehcache的存取流程

CacheManager manager = CacheManager.create();
Cache cache = manager.getCache("defaultCache");//对应xml的配置 后面会说
//element就是一个标签,我们的每个键值对对应每个element
Element ele = new Element("name","hello world");
ele.setTimeToLive(12);
//存入缓存
cache.put(ele);
//获取的时候更简单,直接获取.get(key)
Element element = cache.get("name");
//对应的值
Object obj = element.getObjectValue();
System.out.println((String) obj);


<!---------------上个demo看下效果--------------->

首先要有一个配置文件ehcache.xml  (下载jar的时候,jar里面会有一个default.xml  把它拷贝出来改名为ehcache.xml放到工程文件夹里面就行了)

<!-----------------------ehcache.xml --------------------------------->
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../config/ehcache.xsd">
<diskStore path="java.io.tmpdir"/>
    <defaultCache
            maxElementsInMemory="10000"
            eternal="false"
            timeToIdleSeconds="120"
            timeToLiveSeconds="120"
            maxElementsOnDisk="10000000"
            diskExpiryThreadIntervalSeconds="120"
            memoryStoreEvictionPolicy="LRU">
        <persistence strategy="localTempSwap"/>
    </defaultCache>
    <cache name="demo"//demo 对应之前的那个defaultCache
maxElementsInMemory="10000"//大小限制,超出溢写磁盘
eternal="false"//是否永久存储
overflowToDisk="true"//溢出是否写磁盘
timeToIdleSeconds="300"//没有访问的时候多少秒消亡
timeToLiveSeconds="600"//总的存活时间
memoryStoreEvictionPolicy="LFU" />//算法策略 自己百度 
</ehcache>


<!-----------------------单例获取cache --------------------------------->
public class Ehcache {

  private static Cache cache ;

  public  static synchronized Cache getIntance(){
    if(cache != null){
      return cache;
    }else{
      CacheManager manager = CacheManager.create();
      cache = manager.getCache("demo");
      return cache;
    }
  }
}
<!-----------------------测试类 --------------------------------->
public class Test {
  public static void main(String[] args) throws InterruptedException {//主方法存数据  另起线程取数据
    CacheManager manager = CacheManager.create();
    Cache cache = manager.getCache("demo");
    Element ele = new Element("name","hello world");
    ele.setTimeToLive(12);
    cache.put(ele);
    Element element = cache.get("name");
    Object obj = element.getObjectValue();
    System.out.println((String) obj);
    Thread.sleep(3000);

    ThreadAction action = new ThreadAction();
    action.setCacheName("demo");
    action.setManager(manager);
    action.start();

    System.out.println("----main  thread is return !----");
  }
}
class ThreadAction extends Thread{
  private String cacheName;
  private CacheManager manager;
  @Override
  public void run(){
    while(true){
      try {
        Thread.sleep(3000);
        Cache cache = manager.getCache(cacheName);
        Element element = cache.get("name");
        System.out.println("从缓存中取数据:"+element.getObjectValue().toString());
      } catch (IllegalStateException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      } catch (ClassCastException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      }
    }
  }
}


运行结果:

----main  thread is return !----
从缓存中取数据:hello world
从缓存中取数据:hello world

看下Ehcache结合spring的应用:

    <!----------applicationContext.xml--------->
    <bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">  
        <property name="configLocation" value="classpath:spring/applicationContext-ehcache.xml"></property>  
    </bean> 
    <!----------applicationContext-ehcache.xml--------->
    <?xml version="1.0" encoding="UTF-8"?>
    <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd">
 
    <!-- 指定一个文件目录,当EhCache把数据写到硬盘上时,将把数据写到这个文件目录下 -->
    <diskStore path="java.io.tmpdir"/>
 
    <!-- 设定缓存的默认数据过期策略 -->
    <defaultCache
            maxElementsInMemory="10000"  
            eternal="false" 
            overflowToDisk="true"
            timeToIdleSeconds="10"
            timeToLiveSeconds="20"
            diskPersistent="false"
            diskExpiryThreadIntervalSeconds="120"/>

    <cache name="tokenCache"
        maxElementsInMemory="1000"
        eternal="false"
        overflowToDisk="true"
        timeToIdleSeconds="10"
        timeToLiveSeconds="20"/>
</ehcache>


<!----------controller注入cacheManager--------->

 

      @Autowired
      private CacheManager cacheManager;
      //拿cache
      Cache cache = cacheManager.getCache(ParsePropUtil.getProp(ConfigurtionManager.TOKEN_CACHE_NAME));
      Element ele = cache.get(apiKey);
      ele.setTimeToIdle(invalidTime); //设置最后一次访问后的时效时间
      ele.setTimeToLive(Integer.MAX_VALUE);//设置全过程的时效时间
      cache.put(ele);


然后就可以随心所欲的在缓存中存取数据设置失效时间了,问题解决,本文简单介绍了Ehcache在本次工程中的应用,Ehcache有着很多高级的用法和功能后面我们再深入探讨一起学习把。




工程用于研究如何借助Ehcache缓存框架实现对页面的缓存工程编码方式:UTF-8 本工程开发工具:MyEclipse 说明: 1、ehcache.xml和ehcache.xsd两个文件可以在下在下载下来的名为“ehcache-core-x.x.x-distribution.tar.gz”压缩文件中找到 2、由于要实现Ehcache缓存页面,所以必须要添加“ehcache-web-2.0.4.jar” jar包,该jar包主要用于辅助Ehcache实现页面缓存 注意: 本web工程的发布不要使用Tomcat7,否则会出现如下异常: 2015-3-25 9:53:50 org.apache.catalina.loader.WebappClassLoader loadClass 信息: Illegal access: this web application instance has been stopped already. Could not load net.sf.ehcache.store.disk.DiskStore$KeySet. The eventual following stack trace is caused by an error thrown for debugging purposes as well as to attempt to terminate the thread which caused the illegal access, and has no functional impact. java.lang.IllegalStateException at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1600) at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1559) at net.sf.ehcache.store.disk.DiskStore.keySet(DiskStore.java:560) at net.sf.ehcache.store.disk.DiskStorageFactory$DiskExpiryTask.run(DiskStorageFactory.java:838) at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:441) at java.util.concurrent.FutureTask$Sync.innerRunAndReset(FutureTask.java:317) at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:150) at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$101(ScheduledThreadPoolExecutor.java:98) at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.runPeriodic(ScheduledThreadPoolExecutor.java:181) at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:205) at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908) at java.lang.Thread.run(Thread.java:619) 相关jar包下载地址: Ehcache 对象、数据缓存:http://ehcache.org/downloads/destination?name=ehcache-core-2.5.2-distribution.tar.gz&bucket=tcdistributions&file=ehcache
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值