JAVA缓存技术

最近再ITEYE上看到关于讨论JAVA缓存技术的帖子比较多,自己不懂,所以上网大概搜了下,找到一篇,暂作保存,后面如果有用到可以参考。此为转贴,帖子来处:http://cogipard.info/articles/cache-static-files-with-jnotify-and-ehcache

介绍 
JNotify:http://jnotify.sourceforge.net/,通过JNI技术,让Java代码可以实时的监控制定文件夹内文件的变动信息,支持Linux/Windows/MacOS;
EHCache:http://ehcache.org/,一个广泛使用的Java缓存模块,可以做使用内存和文件完成缓存工作。 
在Java Web项目中,为了提高WEB应用的响应速度,可以把常用的静态文件(包括css,js和其他各种图片)提前读入到内存缓存中,这样可以减少很多文件系统的IO操作(这往往也是项目性能的瓶颈之一)。但是这么做往往有一个弊端,那就是当实际的静态文件发生改变的时候,缓存并不能得到及时的刷新,造成了一定的滞后现象。有些项目可能没什么问题,但是对于某些项目而言,必须解决这个问题。办法基本有两种,一种是另外开启一个线程,不断的扫描文件,和缓存的文件做比较,确定该文件时候修改,另外就是使用系统的API,来监控文件的改变。前面一种解决办法缺点很明显,费时费力,后面的办法需要用到JNI,并且编写一些系统的本地库函数,幸运的是,JNoify为我们做好了准备工作,直接拿来用就可以了。

本文会简单给出一个利用JNotify和EHCache实现静态文件缓存的一个小例子。

JNotify的准备 
在使用JNotify之前,你需要“安装”一下JNotify。JNotify使用了JNI技术来调用系统的本地库(Win下的是dll文件,Linux下是so文件),这些库文件都已近包含在下载包中了。但是如果你直接使用JNotify的话,往往会报错:

Java代码  

  1. BASH
  2. java.lang.UnsatisfiedLinkError: no jnotify in java.library.path
  3. at java.lang.ClassLoader.loadLibrary(Unknown Source)
  4. at java.lang.Runtime.loadLibrary0(Unknown Source)
  5. at java.lang.System.loadLibrary(Unknown Source)
  6. at net.contentobjects.jnotify.win32.JNotify_win32.<clinit>(Unknown Source)
  7. at net.contentobjects.jnotify.win32.JNotifyAdapterWin32.<init>(Unknown Source)

[java] view plaincopy

  1. 这是由于jnotify找不到需要的dll或者其他库文件导致的,解决办法是把jnotify压缩包里的库文件放到java.library.path所指向的文件夹中,一般在windows下可以放在[jre安装目录]/bin下即可。
  2. java.library.path的值可以通过System.getProperty("java.library.path")查看,但是你即使在程序中通过System.setProperty("java.library.path", "some/folder/path/contain/dll")来改变java.library.path的值,还是无法加载到对应的dll库文件,原因是JVM只在程序加载之初读取java.library.path,以后再使用java.library.path的时候,用的都是最一开始加载到得那个值。有人认为只是一个bug,并且报告给了SUN(http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4280189)但是好像SUN不认为这是一个BUG。
  3. 除了把dll文件放到[jre安装目录]/bin下,也可以手动指定程序的启动参数:
  4. java -Djava.library.path=some/folder/path/contain/dll的方法来达到目的。
  5. EHCache的基本使用方法
  6. EHCache非常容易使用,首先我们要获得一个CacheManager的实例。CacheManager有两种获得方法,一种是实例模式,一种是单例模式。这里我们用后面一种:

Java代码  

  1. //CacheManager manager = new CacheManager("src/ehcache.xml");实例模式
  2. CacheManager.create();//单例模式,默认读取类路径下的ehcache.xml作为配置文件
  3. Cache cache = CacheManager.getInstance().getCache("staticResourceCache");
  4. //staticResourceCache在ehcache.xml中提前定义了

ehcache.xml的简单例子:

Java代码  

  1. ehcache.xml :
  2. <?xml version="1.0" encoding="UTF-8"?>
  3. <ehcache updateCheck="false" dynamicConfig="false">
  4. <diskStore path="java.io.tmpdir"/>
  5. <cache name="staticResourceCache"
  6. maxElementsInMemory="1000"
  7. timeToIdleSeconds="7200"
  8. timeToLiveSeconds="7200" >
  9. </cache>
  10. </ehcache>

然后就可以使用Cache实例来操纵缓存了,主要的方法是

Java代码  

  1. Cache.get(Object key),Cache.put(new Element(Object key, Object value)),Cache.remove(Object key)。

缓存静态文件 
首先需要扫描包含静态文件的文件夹,为了方便我们采用Jodd工具包:

Java代码  

  1. import jodd.io.findfile.FilepathScanner;
  2. ...
  3. FilepathScanner fs = new FilepathScanner(){
  4. @Override
  5. protected void onFile(File file) {
  6. cacheStatic(file);//缓存文件的函数,实现见后面
  7. }
  8. };
  9. fs.includeDirs(true).recursive(true).includeFiles(true);
  10. fs.scan(Configurations.THEMES_PATH);//扫描包含静态文件的文件夹

一般来说,如果客户端浏览器接受GZip格式的文件的话,GZip压缩可以让传输的数据大幅度减少,所以考虑对某些缓存的静态文件提前进行GZip压缩。把读取到的静态文件内容缓存到Cache里,如果静态文件时可以用GZip来传输的话,需要把文件内容首先进行压缩。

Java代码  

  1. import java.util.zip.GZIPOutputStream;//JDK自带的GZip压缩工具
  2. import jodd.io.FastByteArrayOutputStream;//GZip输出的是字节流
  3. import jodd.io.StreamUtil;//JODD的工具类
  4. private static void cacheStatic(File file){
  5. if(!isStaticResource(file.getAbsolutePath()))
  6. return;
  7. String uri = toURI(file.getAbsolutePath());//生成一个文件标识
  8. FileInputStream in = null;
  9. StringBuilder builder = new StringBuilder();
  10. try {
  11. in = new FileInputStream(file);
  12. BufferedReader br = new BufferedReader(
  13. new InputStreamReader(in, StringPool.UTF_8));
  14. String strLine;
  15. while ((strLine = br.readLine()) != null)   {
  16. builder.append(strLine);
  17. builder.append("\n");//!important
  18. }
  19. FastByteArrayOutputStream bao = new FastByteArrayOutputStream();
  20. GZIPOutputStream go = new GZIPOutputStream(bao);
  21. go.write(builder.toString().getBytes());
  22. go.flush();
  23. go.close();
  24. cache.put(new Element(uri, bao.toByteArray()));//缓存文件的字节流
  25. } catch (FileNotFoundException e) {
  26. e.printStackTrace();
  27. } catch (UnsupportedEncodingException e) {
  28. e.printStackTrace();
  29. } catch (IOException e) {
  30. e.printStackTrace();
  31. } finally {
  32. StreamUtil.close(in);
  33. }
  34. }

当文件改变的时候,使用JNotify来改变缓存内容

Java代码  

    1. //监控Configurations.THEMES_PATH指向的文件夹
    2. JNotify.addWatch(Configurations.THEMES_PATH,
    3. JNotify.FILE_CREATED  |
    4. JNotify.FILE_DELETED  |
    5. JNotify.FILE_MODIFIED |
    6. JNotify.FILE_RENAMED,
    7. true,  new JNotifyListener(){
    8. @Override
    9. public void fileCreated(int wd,
    10. String rootPath, String name) {
    11. cacheStatic(new File(rootPath+name));//更新缓存
    12. }
    13. @Override
    14. public void fileDeleted(int wd,
    15. String rootPath, String name) {
    16. cache.remove(toURI(rootPath)+name);//删除缓存条目
    17. }
    18. @Override
    19. public void fileModified(int wd,
    20. String rootPath, String name) {
    21. cacheStatic(new File(rootPath+name));
    22. }
    23. @Override
    24. public void fileRenamed(int wd,
    25. String rootPath, String oldName,
    26. String newName) {
    27. cache.remove(toURI(rootPath)+oldName);
    28. cacheStatic(new File(rootPath+newName));
    29. }
时间: 2024-08-05 23:30:38

JAVA缓存技术的相关文章

(转)java缓存技术,记录

http://blog.csdn.net/madun/article/details/8569860 最近再ITEYE上看到关于讨论JAVA缓存技术的帖子比较多,自己不懂,所以上网大概搜了下,找到一篇,暂作保存,后面如果有用到可以参考.此为转贴,帖子来处:http://cogipard.info/articles/cache-static-files-with-jnotify-and-ehcache 介绍 JNotify:http://jnotify.sourceforge.net/,通过JNI

Java 缓存技术

以下仅是对map对方式讨论.没有对点阵图阵讨论.作缓存要做以下2点:  1:清理及更新缓存时机的处理: . 虚拟机内存不足,清理缓存 .. 缓存时间超时,或访问次数超出, 启动线程更新 2:类和方法的反射 (线程嵌套调用) reflect.invoke的使用. JAVA缓存有两种: 一.文件缓存,是指把数据存储在磁盘上,可以XML格式,也可以序列化文件DAT格式还是其它文件格式. 二.内存缓存,也就是实现一个类中静态Map,对这个Map进行常规的增删查. 代码如下:内存中的缓存 package

java缓存技术的介绍(转载)

一.什么是缓存1.Cache是高速缓冲存储器 一种特殊的存储器子系统,其中复制了频繁使用的数据以利于快速访问2.凡是位于速度相差较大的两种硬件/软件之间的,用于协调两者数据传输速度差异的结构,均可称之为 Cache 二.缓存的分类1.基于web应用的系统架构图 2.在系统架构的不同层级之间,为了加快访问速度,都可以存在缓存 操作系统磁盘缓存->减少磁盘机械操作 数据库缓存->减少文件系统I/O 应用程序缓存->减少对数据库的查询 Web服务器缓存->减少应用服务器请求 客户端浏览器

Java 缓存技术之 ehcache

1. EHCache 的特点,是一个纯Java ,过程中(也可以理解成插入式)缓存实现,单独安装Ehcache ,需把ehcache-X.X.jar 和相关类库方到classpath中.如项目已安装了Hibernate ,则不需要做什么..直接可以使用Ehcache Cache 存储方式 :内存或磁盘 2. 单独使用 EHCache 所以大概步骤为: 第一步:生成CacheManager对象 第二步:生成Cache对象 第三步:向Cache对象里添加由key,value组成的键值对的Elemen

分布式缓存技术redis学习系列(三)——redis高级应用(主从、事务与锁、持久化)

上文<详细讲解redis数据结构(内存模型)以及常用命令>介绍了redis的数据类型以及常用命令,本文我们来学习下redis的一些高级特性. 回到顶部 安全性设置 设置客户端操作秘密 redis安装好后,默认情况下登陆客户端和使用命令操作时不需要密码的.某些情况下,为了安全起见,我们可以设置在客户端连接后进行任何操作之前都要进行密码验证.修改redis.conf进行配置. [[email protected] ~]# vi /usr/local/redis/etc/redis.conf ###

如何正确使用缓存技术

缓存技术是用来提升程序运行性能的常见手段,如你所见, 阿里巴巴.新浪微博.美团网等互联网龙头企业都是用缓存技术来提升自己家网站的性能.然而,任何事物都有两面性, 缓存技术使用得当带来的好处自然不言而喻, 但是如果使用不当, 产生的副作用也够让人喝一壶的. 我们写服务器程序时,使用缓存的目的无非就是减少数据库访问次数降低数据库的压力和提升程序的响应时间, 然而根据具体的使用场景又可以派生出无数种情况, 比如说 程序频繁读取数据库, 但是查询获得的结果却总是相同的,这部分相同的结果是不是可以放入缓存

硬盘缓存技术DiskLruCache技术&lt;笔记&gt;

防止多图OOM的核心解决思路就是使用LruCache技术,但LruCache只是管理了内存中图片的存储与释放,如果图片从内存中被移除的话,那么又需要从网络上重新加载一次,这显然非常耗时.因此Google又提供了一套硬盘缓存的解决方案:DiskLruCache(非Google官方编写,但获得官方认证).一般来说新闻类App从网络获取到数据后都会存入到本地缓存中,因此即使手机在没有网络的情况下依然能够加载出以前浏览过的新闻.使用的缓存技术自然是DiskLruCache.以网易新闻为例,它的Andro

强大的Spring缓存技术(上)

缓存是实际工作中非常常用的一种提高性能的方法, 我们会在许多场景下来使用缓存. 本文通过一个简单的例子进行展开,通过对比我们原来的自定义缓存和 spring 的基于注释的 cache 配置方法,展现了 spring cache 的强大之处,然后介绍了其基本的原理,扩展点和使用场景的限制.通过阅读本文,你应该可以短时间内掌握 spring 带来的强大缓存技术,在很少的配置下即可给既有代码提供缓存能力. 概述 Spring 3.1 引入了激动人心的基于注释(annotation)的缓存(cache)

Java分布式应用技术架构介绍

分布式架构的演进 系统架构演化历程-初始阶段架构 初始阶段 的小型系统 应用程序.数据库.文件等所有的资源都在一台服务器上通俗称为LAMP 特征: 应用程序.数据库.文件等所有的资源都在一台服务器上. 描述: 通常服务器操作系统使用linux,应用程序使用PHP开发,然后部署在Apache上,数据库使用Mysql,汇集各种免费开源软件以及一台廉价服务器就可以开始系统的发展之路了. 系统架构演化历程-应用服务和数据服务分离 好景不长,发现随着系统访问量的再度增加,webserver机器的压力在高峰