




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、javaweb应用缓存技术资料收集与总结 作者:夏俊 时间:2011-1-2web用户行为分析系统上线,在测试某些功能时候,发现部分功能响应时间过长,比如对起点文学的按月的统计数据显示,响应时间超过了3秒,这个不太符合用户的需要,那么接下来就是优化系统,提高系统速度的工作。我们在分析响应速度缓慢的原因,发现还是数据库处理数据这块原因,究其根本还是数据量过大的原因,而且在数据库层面已经速度这块很难再有提升,因此考虑到web的缓存技术,这些响应速度缓慢的功能基本都是按周,按月的统计数据,因此在单位时间内的缓存是完全可以实现,以下就是我收集的java web缓存的相关技术,有两个技术重点推荐,一个是
2、oscache,一个是jcs,这两个是缓存技术里应用最为广泛的,也是最为成熟并且是开源的技术。下面是我推荐这两种技术的原因,如下:1) 都是开源的java程序2) 网上能找到比较丰富的资料3) 都支持分布式的系统4) 操作部署都不太难5) 均符合我们现在系统开发的需要oscache和jcs区别在哪里了?现在我都只是简单看了下,现在总结还不全面,等具体操作后会加以补充:1) oscache我找到的资料,我感觉主要是是页面级的缓存,他的缓存开发代码基本都是在页面里,用标签定义,应该数据都是缓存在客户端(这点还要细细体味)2) jcs是服务端的缓存,他基本是将需要缓存的数据先存在服务器的内存或是硬盘
3、里,在一定时间内用户可以不通过数据库这个线路获取数据,而是从服务器直接获取,但这样会不会服务端负荷过大从以上区别来说,如果数据能在客户端缓存,我还是更加推荐点,但是客户端如果缓存,用户要是有什么原因经常清理客户端缓存也是个问题。最后这几种缓存技术和我们现在系统的整合的问题,这个我还要接着找下数据,我们系统是struts2+jquery(service和dao层,这个缓存应该不会牵涉到),jcs是服务端缓存,所以数据返回可以在action里封装,对于前台而言影响不大,至于oscache,如果使用它那么系统该如何改造,这个我要考虑下。再有就是何时来缓存数据,就是触发缓存的方式,是用户的第一次在适当
4、时间的点击还是通过调度的方式定时缓存了,这点也要考虑下。写以上内容发现自己刚才对oscache没有理解太清楚,oscache缓存是使用标签的,在标签里的内容就会按时间缓存。因此实际操作下是很重要的。(一) 第一份资料jcsjava 缓存系统(java caching system,jcs)a) 资料编号no101jcs概述:jcs 是一个用 java 语言编写的缓存系统,可以使用它来创建 java 桌面和 web 应用程序。它提供了在缓存器中存储数据、从缓存器中删除数据等方便机制。使用 jcs 可以在各种指定的数据区域 中存储缓存数据。jcs 定义了 4 种类型的核心区域:内存区域、磁盘区域、
5、外围区域和远程区域。可以结合使用这些核心区域以在如何存储缓存数据、将缓存数据存储在什么地方等方面获得更大的灵活性。您可以指定首次使用哪个区域,以及发生故障时转移到哪个区域。内存区域:内存区域是一个使用最近最少算法(least recently used,lru)的纯内存缓存区域。当内存缓存区域满时,lru 会首先删除最近最少使用的缓存数据。这个数据区域执行良好,大多数 jcs 用户将它指定为最先使用的默认缓存区域。磁盘区域:磁盘区域是在 web 服务器的文件磁盘上缓存数据。为了提高性能,jcs 在文件磁盘上存储实际缓存数据的同时,会在内存中存储缓存数据键。在首先使用内存区域的典型 jcs 配置
6、中,任何无法在内存区域中保存的数据都会写入磁盘区域中。外围区域:外围区域提供一种可配置方式来在多台服务器之间分发缓存数据。缓存数据服务器必须有一个开放的用于侦听的端口,而且必须创建一个套接字连接。这个区域存在一个潜在问题,因为它不能保证各缓存之间的数据的一致性。但如果是按计划使用该区域,则不会出现这个问题。远程区域:远程区域提供了一个使用远程方法调用(rmi)api 的缓存区域。这个区域使用一台远程服务器处理缓存数据。这台远程缓存服务器可以被多个 jcs 客户端应用程序用于存储缓存数据。一些侦听器被定义用于收集来自客户端和服务器的请求。这个缓存区域帮助减少串行化和多个连接点的开销。(jcs 的
7、可插入控制器:jcs 通过组合缓存器(composite cache)让使用多个区域进行缓存存储变得很简单。组合缓存器为缓存区域提供了一个可插入控制器。组合缓存器仔细处理复杂的任务,即确定何时以及如何使用每个缓存区域。jcs 将完成大部分复杂的工作,开发人员只需关心获取和设置缓存。)夏俊备注:我看了下ibatis缓存机制,内存区域的缓存和磁盘缓存,ibatis也有实现。jcs 配置:配置 jcs 就是简单地创建和填充一个 cache.ccf 文件。这个文件定义缓存应该使用哪些区域,以及这些区域的属性或选项。根据应用程序的需求配置这个文件是一种快速扩展缓存的简便方式。您可以指定许多适合配置的选项
8、和属性来满足需求。清单 1 显示的是最基本的 cache.ccf 文件 一个纯内存缓存配置:清单 1. jcs 的基本配置jcs.default=jcs.default.cacheattributes=org.apache.jcs.engine.compositecacheattributesjcs.default.cacheattributes.maxobjects=1000jcs.default.cacheattributes.memorycachename=org.apache.jcs.engine.memory.lru.lrumemorycache从清单 1 中可以看出,该配置文件将内
9、存缓存指定为一个 lrumemorycache。还可以看到,内存中能保存的对象的最大数量被设置为 1000。大多数应用程序的缓存系统配置要比清单 1 中复杂得多。在清单 2 的配置中,我在定义自己的区域(our_region)时使用了一个内存区域和一个磁盘区域:清单 2. 在 jcs 配置中定义的区域jcs.default=disk_regionjcs.default.cacheattributes=org.apache.jcs.engine.compositecacheattributesjcs.default.cacheattributes.maxobjects=1000jcs.defau
10、lt.cacheattributes.memorycachename=org.apache.jcs.engine.memory.lru.lrumemorycachejcs.region.our_region=disk_regionjcs.region.our_region.cacheattributes=org.apache.jcs.engine.compositecacheattributesjcs.region.our_region.cacheattributes.maxobjects=1000jcs.region.our_region.cacheattributes.memorycach
11、ename= org.apache.jcs.engine.memory.lru.lrumemorycachejcs.region.our_region.cacheattributes.usememoryshrinker=truejcs.region.our_region.cacheattributes.maxmemoryidletimeseconds=3600jcs.region.our_region.cacheattributes.shrinkerintervalseconds=60jcs.region.our_region.cacheattributes.maxspoolperrun=50
12、0jcs.region.our_region.elementattributes=org.apache.jcs.engine.elementattributesjcs.region.our_region.elementattributes.iseternal=falsejcs.auxiliary.disk_region=org.apache.jcs.auxiliary.disk.indexed.indexeddiskcachefactoryjcs.auxiliary.disk_region.attributes= org.apache.jcs.auxiliary.disk.indexed.in
13、dexeddiskcacheattributesjcs.auxiliary.disk_region.attributes.diskpath=c:/jcs/disk_regionjcs.auxiliary.disk_region.attributes.maxkeysize=100000清单 2 中的第一行表明该配置将默认区域设置为 disk_region。disk_region 是 indexeddiskcachefactory 类型,并且该文件在磁盘上指定为 c:jcsdisk_region。清单 2 中的第二个配置组定义了我自己的区域,我为它添加了一些选项,这种类型的配置(在指定用户定义区域
14、时同时使用内存区域和磁盘区域)是很常见的。清单 2 中的第 3 个配置组定义了一个 辅助区域。jcs 有两个依赖项:concurrent 和 commons-logging(jcs 之前的版本中,还有两个其他依赖项:commons-collections 和 commons-lang)。(jcs 辅助插件:除了 4 个核心缓存实现外,jcs 还提供了一些辅助插件,它们是区域可以使用的可选插件。这些辅助插件包括索引磁盘缓存(indexed disk cache)、tcp 外围缓存(tcp lateral cache)和远程缓存服务器(remote cache server)。例如
15、,索引磁盘缓存允许在到达内存阈值时在磁盘上交换项目。这使得每个区域能更灵活地控制其缓存,提供一种类似于大多数操作系统所使用的虚拟内存的存储方法。cache.ccf 配置文件可以让每个辅助区域满足应用程序的需求。 )jcs 的基本用法:学习 jcs 基础知识的一个好方法是查看 api 最常用的方法。最好从初始化区域开始。初始化 jcs 缓存区域对象能使您访问大部分所需的常用方法。清单 3 初始化 jcs 对象并获得一个默认缓存区域实例:清单 3. 检索默认缓存区域/ initialize the jcs object and get an instance of the default cach
16、e regionjcs cache = jcs.getinstance(default);检索 jcs 实例后,可以调用最需要的方法。put 方法将一个新对象放入缓存中。接下来只需一个 key(第一个参数)和一个 value(第二个参数)。清单 4 显示一个基本示例:清单 4. 设置缓存项/ set upstring key = key0;string value = value0;/ place a new object in the cachecache.put(key, value);清单 4 中的示例使用字符串值作为参数,但是您可以使用任何对象。检索缓存对象只不过是使用 jcs 提供的
17、 get 方法。清单 5 显示了一个简单示例。同样,本例使用了一个字符串参数,但您可以使用任何对象。清单 5. 检索缓存项/ retrieve a cached objectstring cacheddata = (string)cache.get(key);测试缓存数据的有效性可能是处理缓存系统时需要使用的另一种方法。在 jcs 中,没有定义只测试缓存项是否存在的测试缓存方法。但是 get 方法的返回值可以帮助您。清单 6 显示了一种获得此必要功能的方式:清单 6. 测试缓存项的有效性/ retrieve a cached objectstring cacheddata = (string)
18、cache.get(key);/ check if the retrieval workedif (cacheddata != null) / the cacheddata is valid and can be used system.out.println(valid cached data: + cacheddata);最后需要几个用于在使用 jcs、缓存项和缓存区域后清除它们的常用缓存实用程序。jcs 提供了一种 clear 方法,用于从调用的缓存区域中删除所有缓存数据。此外,还提供了一个 remove 方法,用于删除指定缓存项。dispose 方法也可以处理初始化的 jcs 区域。清
19、单 7 显示了如何使用这些方法:清单 7. 清除缓存区域/ dispose of a specific cached itemcache.remove(key);/ dispose of all cache datacache.clear();/ dispose of the cache regioncache.dispose();jcs 和 java 对象:jcs 优于其他缓存系统(请参阅 参考资料)的一个地方是它可以很好地使用对象。大多数 web 应用程序是使用面向对象的方法通过 java 技术创建的。例如,与连续从数据库中逐段检索对象相比,缓存对象使应用程序能够更好地执行。 设计一个简单
20、的面向对象的 jcs 站点的第一个步骤是创建需要存储的对象。在本例中,我将开发一个基本 blogging 站点。清单 8 显示了我将使用的 blogobject 类:清单 8. blogobject 类package com.ibm.developerworks.objects;import java.io.serializable;import java.util.date;public class blogobject implements serializable private static final long serialversionuid = 63923761461635100
21、46l; private int blogid; private string author; private date date; private string title; private string content; public blogobject(int blogid, string author, date date, string title, string content) this.blogid = blogid; this.author = author; this.date = date; this.title = title; this.content = cont
22、ent; public int getblogid() return this.blogid; public string getauthor() return this.author; public date getdate() return this.date; public string gettitle() return this.title; public string getcontent() return this.content; 在一个类中表示对象后,接着还需要一个类来管理该对象。管理器处理所有与 blog 对象相关的管理和缓存功能。在本例中,管理器将处理三大任务: 检索 b
23、log 对象 在缓存中设置 blog 对象 从缓存中清除 blog 对象 如清单 9 所示,getblog 方法检索 blog 对象。该方法首先试图从缓存获得 blog 对象。如果该对象不在缓存中,它将根据其他机制获取该对象:清单 9. 通过 blog 管理器检索 blog 对象public blogobject getblog(int id) blogobject blog = null; try blogcache = jcs.getinstance(blogcacheregion); blog = (blogobject)blogcache.get(id); catch (cacheex
24、ception ce) blog = null; if (blog = null) blog = databasemanager.getblog(id); this.setblog( blog.getblogid(), blog.getauthor(), blog.getdate(), blog.gettitle(), blog.getcontent() ); return blog;在清单 9 中,我使用一个数据库作为检索 blog 对象的替代机制。根据另一种机制检索该对象时,应该将该对象设置为缓存,以便下一次检索可以直接从该缓存获取这个对象。如清单 10 所示,setblog 方法将 bl
25、og 对象放在缓存中。这个方法比较简单,因为它只是使用传入的信息创建一个新的 blog 对象,然后将这个对象放在缓存中。清单 10. 通过 blog 管理器将 blog 对象放在缓存中public boolean setblog(int bid, string author, date date, string title, string content) blogobject blog = new blogobject(bid, author, date, title, content); try blogcache = jcs.getinstance(blogcacheregion); b
26、logcache.put(bid, blog); return true; catch (cacheexception ce) return false; 如清单 11 所示,cleanblog 方法要么从缓存中清除一个指定的 blog,要么从缓存中清除掉所有 blog。这个方法使用 jcs 的 remove 和 clear 方法来清除缓存对象。清单 11. 通过 blog 管理器从缓存中删除 blog 对象public boolean cleanblog(int blogid) try blogcache = jcs.getinstance(blogcacheregion); blogcac
27、he.remove(blogid); catch (cacheexception ce) return false; return true;public boolean cleanblog() try blogcache = jcs.getinstance(blogcacheregion); blogcache.clear(); catch (cacheexception ce) return false; return true;前面的几个类展示了使用 jcs 缓存对象是很简单的。拥有对象管理器并使用简单的对象表示之后,您就获得一种在 web 应用程序中处理对象的简单但强大的方法。缓存元数
28、据jcs 提供了更多方法,向应用程序添加缓存所用的方法只是其中的一小部分。例如,它提供了收集缓存对象和缓存区域元数据的实用程序。您可以轻松检索以下内容: 缓存键名称 创建缓存项的时间 缓存可以存在的最长时间 缓存过期时间 清单 12 中的例子显示如何检索缓存项的元数据:清单 12. 检索缓存项的元数据try jcsadminbean admin = new jcsadminbean(); linkedlist linkedlist = admin.buildelementinfo(regionname); listiterator iterator = linkedlist.listitera
29、tor(); while (iterator.hasnext() cacheelementinfo info = (cacheelementinfo)iterator.next(); system.out.println(key: + info.getkey(); system.out.println(creation time: + info.getcreatetime(); system.out.println(maximum life (seconds): + info.getmaxlifeseconds(); system.out.println(expires in (seconds
30、): + info.getexpiresinseconds(); catch (exception e) 清单 13. 检索缓存区域的元数据try jcsadminbean admin = new jcsadminbean(); linkedlist linkedlist = admin.buildcacheinfo(); listiterator iterator = linkedlist.listiterator(); while (iterator.hasnext() cacheregioninfo info = (cacheregioninfo)iterator.next(); com
31、positecache compcache = info.getcache(); system.out.println(cache name: + compcache.getcachename(); system.out.println(cache type: + compcache.getcachetype(); system.out.println(cache misses (not found): + compcache.getmisscountnotfound(); system.out.println(cache misses (expired): + compcache.getmi
32、sscountexpired(); system.out.println(cache hits (memory): + compcache.gethitcountram(); system.out.println(cache updates: + compcache.getupdatecount(); catch (exception e) 收集缓存区域和项的元数据能帮助您分析 web 站点的哪些区域和项目需要优化。元数据也能帮助您管理时间敏感型的缓存数据。例如,您可以使用每个缓存项的最长生命周期和过期时间来为需要更新数据的特定用户刷新缓存数据。结束语:jcs 是为 java 开发人员提供的功
33、能强大但简单易用的缓存系统。它为桌面和类似的 web 应用程序提供数据缓存。类似桌面的 web 应用程序的发展前景是提高速度和敏捷性。缓存数据对这些方面非常有益。本文概述如何配置和使用 jcs。此外,还讨论了基本缓存方法所需要语法,以及如何在常见 web 应用程序中缓存对象和检索缓存元数据。解了 jcs 的基本知识之后,您现在可以利用数据缓存功能来开发下一个 web 站点了。您还可以学习其他几个提供高级功能的 jcs 区域,比如 http servlet 访问、jcs 实用程序、基本 http 验证和其他辅助区域。b) 资料编号no102给web应用加jcs缓存系统: 下载jcs-1.2.6.
34、jar,找了半天也没有找到它的源码和api文档,不知为什么?在这个站点有: using jcs: some basics for the web ,不错,就用它练习。一、创建值对象假设有一book,它在数据库中的表为:table book(book_id_pk ,title ,author,isbn,price,publish_date)创建值对象如下:package com.genericbookstore.data;import java.io.serializable;import java.util.date;public class bookvobj implements seria
35、lizable public int bookid = 0; public string title; public string author; public string isbn; . public string price; public date publishdate; public bookvobj() 二、创建缓存管理器应用中对book数据的访问都通过缓存管理器。package com.genericbookstore.data;import org.apache.jcs.jcs;/ in case we want to set some special behaviorimp
36、ort org.apache.jcs.engine.behavior.ielementattributes;public class bookvobjmanager private static bookvobjmanager instance; private static int checkedout = 0; public static jcs bookcache; private bookvobjmanager()/构造函数 try bookcache = jcs.getinstance(bookcache); catch (exception e) / handle cache re
37、gion initialization failure / do other initialization that may be necessary, such as getting / references to any data access classes we may need to populate / value objects later /* * singleton access point to the manager. */ public static bookvobjmanager getinstance() synchronized (bookvobjmanager.
38、class) if (instance = null) instance = new bookvobjmanager(); synchronized (instance) instance.checkedout+; return instance; /* * retrieves a bookvobj.default to look in the cache. */ public bookvobj getbookvobj(int id) return getbookvobj(id, true); /* * retrieves a bookvobj. second argument decides
39、 whether to look * in the cache. returns a new value object if one cant be . * loaded from the database. database cache synchronization is * handled by removing cache elements upon modification. */ public bookvobj getbookvobj(int id, boolean fromcache) bookvobj vobj = null; / first, if requested, at
40、tempt to load from cache if (fromcache) vobj = (bookvobj) bookcache.get(bookvobj + id); / either fromcache was false or the object was not found, so / call loadbookvobj to create it if (vobj = null) . vobj = loadbookvobj(id); returnvobj; /* * creates a bookvobj based on the id of the book table.data
41、 * access could be direct jdbc, some or mapping tool, or an ejb. */ public bookvobj loadbookvobj(int id) bookvobj vobj = new bookvobj(); vobj.bookid = id; try boolean found = false; / load the data and set the rest of the fields / set found to true if it was foundfound = true; / cache the value obje
42、ct if found if (found) / could use the defaults like this / bookcache.put( bookvobj + id, vobj ); / or specify special characteristics / put to cache bookcache.put(bookvobj + id, vobj); catch (exception e) 。 / handle failure putting object to cache return vobj; /* * stores bookvobjs in database.clea
43、rs old items and caches * new. */ public void storebookvobj(bookvobj vobj) try / since any cached data is no longer valid, we should / remove the item from the cache if it an update. if (vobj.bookid != 0) bookcache.remove(bookvobj + vobj.bookid); / put the new object in the cache bookcache.put(bookv
44、obj + vobj.bookid, vobj); catch (exception e) / handle failure removing object or putting object to cache. 三、配置文件cache.ccf,它定义你配置何种类型的缓存、缓存的大小、过期时间等。#web-inf/classes/cache.ccf(以下内容不要换行)jcs.default=jcs.default.cacheattributes=org.apache.jcs.engine.compositecacheattributesjcs.default.cacheattributes.m
45、axobjects=1000jcs.default.cacheattributes.memorycachename=org.apache.jcs.engine.memory.lru.lrumemorycache jcs.default.cacheattributes.usememoryshrinker=truejcs.default.cacheattributes.maxmemoryidletimeseconds=3600jcs.default.cacheattributes.shrinkerintervalseconds=60jcs.default.cacheattributes.maxsp
46、oolperrun=500jcs.default.elementattributes=org.apache.jcs.engine.elementattributesjcs.default.elementattributes.iseternal=false四、测试的jsp文件 五、测试::8080/jcs/testjcs.jspc) 资料编号no103安装和配置:在web应用中安装和配置jcs是非常简单的事情。从jakarta turbine网站下载压缩文件,解压缩文件到临时目录,并拷贝jsc.jar文件(jcs-1.0-dev.jar)到servlet容器的通用目
47、录(在我的web应用中使用的servlet容器是tomcat,通用目录在windows下就是%tomcat_home%commonlib,在再unix类型的系统下就是$tomcat_home/common/lib)。你可能还需要commons-collections.jar, commons-lang.jar, 和 commons-logging.jar 这些文件存在于web应用的类路径下以便使用jcs。框架的主要原理缓存属性我们将所有的缓存参数配置在名为cache.ccf的属性文件中。这些参数包括缓存信息如:内存中存储的对象的最大数量,缓存时间(过了时间之后缓存的数据九自动从内存中释放),中
48、断时间(elapsed time since last access time), 内存缓存名称(例如:缓存算法如lru或mru)等。在当前版本的jcs中,缓存属性文件是纯文本格式的。spiritcache framework,一种来自spiritsoft的jcache api商业实现,支持xml格式的缓存配置。确认该属性文件存放在类路径中。注意:如果你需要使用其它不同的文件来存放缓存属性的话,jcs 也提供了方法来指定一个配置文件的名称。请参考jcs的 javadocs 学习如何从其它非缺省的属性文件中读取缓存配置信息。下面列出来的是web应用使用缓存功能需要了解的一些java类。这些类存放
49、在本文的示例代码的common.caching包中。这些类的javadocs也包括在源代码压缩包中。 (图2 中的类图显示了这些java类的关系)icachemanager这是客户应用实现所有缓存有关操作(如:存储、访问以及释放缓存中的数据)的主接口(契约)。客户程序可以是jsp、struts action类,或者就是一个pojo对象。创建该接口用于对客户端隐藏所有缓存的实现细节,这样当我们将来需要切换另一种的第三方缓存api的时候无需对客户端代码做任何调整。basecachemanager这是web门户缓存框架的主类。是对icachemanager 接口的最基本实现。创建basecachem
50、anager 用于在一个类中集中所有缓存相关的方法。它被设计为单例模式保证在servlet容器的jvm中有且仅有一个icachemanager 的实例被创建。在多web服务器/servlet容器实例共同处理web请求的集群环境中,每个jvm将会创建独立的icachemanager 实例。如果将来你要转换到不同的缓存api ,这是唯一需要为新的缓存api修改的类。如果你切换到jcache-兼容的缓存实现,对缓存管理器的修改将会是很小的。icacheloader该接口用于在web客户端实现真正的数据访问逻辑。所有需要使用缓存机制的客户端应用必须实现该接口。它包括仅有的一个方法叫做loadcache
51、object() ,有两个输入参数:一个string参数制定缓存区域名称,一个对象参数制定缓存键值。这样,缓存管理器将知道在缓存的对象超过指定的“生存时间”的时候,使用哪个客户端程序(运行loadcacheobject 方法)来重载缓存中的对象 。icachekeyicachekey 接口创建的目的是为了隐藏特定的创建缓存键值的细节。有时候缓存的键值不是一个简单的字符串。它可能像多个对象组合起来一样复杂,从数据源获取这些值需要多个查找方法而不是单一的方法。在这种情况下, icachekey 接口可以被用来定义创建缓存键值的所有复杂的逻辑。这样,缓存键值创建逻辑将会被定义为独立的类。我编写了一个
52、简单的类testcachekey 实现了该接口并实现了getcachekey() 方法来演示使用该接口的方法。cacheregions一个 缓存区域 被定义为一个组织起来的命名空间用于容纳一组缓存对象集合。你需要在配置文件中定义缓存区域来实现在一块单独的内存空间中存储数据,管理缓存数据的有效期限。如果需要的话,对有相似特征的对象(例如:生存时间和业务用途)应该被缓存在相同的缓存区域中,让它们可以在相同的时间失效。我定义了分离的缓存区域来存储静态数据和小变动数据。为了避免同步操作带来的效率影响,我对每个缓存区域使用了单独的cache (jcs) 实例。cacheelementinfo该类用于封装所有的缓存统计信息(例如:命中数、不中数、命中比例等),用来监测在web应用中所有缓存对象的效率。编译, 构建, 和单元测试 我用ant创建了一个构建脚本来编译我的对象缓存框架
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
评论
0/150
提交评论