当前位置:文档之家› JAVAWEB缓存技术

JAVAWEB缓存技术

JAVAWEB缓存技术
JAVAWEB缓存技术

JA V AWeb应用缓存技术资料收集与总结

——作者:夏俊时间:2011-1-2 WEB用户行为分析系统上线,在测试某些功能时候,发现部分功能响应时间过长,比如对起点文学的按月的统计数据显示,响应时间超过了3秒,这个不太符合用户的需要,那么接下来就是优化系统,提高系统速度的工作。我们在分析响应速度缓慢的原因,发现还是数据库处理数据这块原因,究其根本还是数据量过大的原因,而且在数据库层面已经速度

这块很难再有提升,因此考虑到w eb的缓存技术,这些响应速度缓慢的功能基本都是按周,按月的统计数据,因此在单位时间内的缓存是完全可以实现,以下就是我收集的java web 缓存的相关技术,有两个技术重点推荐,一个是OSCache,一个是JCS,这两个是缓存技术里应用最为广泛的,也是最为成熟并且是开源的技术。

下面是我推荐这两种技术的原因,如下:

1)都是开源的JA V A程序

2)网上能找到比较丰富的资料

3)都支持分布式的系统

4)操作部署都不太难

5)均符合我们现在系统开发的需要

OSCACHE和JCS区别在哪里了?现在我都只是简单看了下,现在总结还不全面,等具体操作后会加以补充:

1)OSCache我找到的资料,我感觉主要是是页面级的缓存,他的缓存开发代码基本都是

在页面里,用标签定义,应该数据都是缓存在客户端(这点还要细细体味)

2)JCS是服务端的缓存,他基本是将需要缓存的数据先存在服务器的内存或是硬盘里,

在一定时间内用户可以不通过数据库这个线路获取数据,而是从服务器直接获取,但这样会不会服务端负荷过大

从以上区别来说,如果数据能在客户端缓存,我还是更加推荐点,但是客户端如果缓存,用户要是有什么原因经常清理客户端缓存也是个问题。

最后这几种缓存技术和我们现在系统的整合的问题,这个我还要接着找下数据,我们系统

是struts2+jquery(service和DAO层,这个缓存应该不会牵涉到),JCS是服务端缓存,所以数据返回可以在action里封装,对于前台而言影响不大,至于OSCache,如果使用它那么系统该如何改造,这个我要考虑下。

再有就是何时来缓存数据,就是触发缓存的方式,是用户的第一次在适当时间的点击还是通过调度的方式定时缓存了,这点也要考虑下。

写以上内容发现自己刚才对OSCache没有理解太清楚,OSCache缓存是使用标签的,在标签里的内容就会按时间缓存。因此实际操作下是很重要的。

(一) 第一份资料—JCS

Java 缓存系统(Java Caching System,JCS)

a)资料编号NO101

JCS概述:JCS 是一个用Java 语言编写的缓存系统,可以使用它来创建Java 桌面和Web 应用程序。它提供了在缓存器中存储数据、从缓存器中删除数据等方便机制。使用JCS 可以在各种指定的数据区域中存储缓存数据。JCS 定义了 4 种类型的核心区域:内存区域、磁盘区域、外围区域和远程区域。可以结合使用这些核心区域以在如何存储缓存数据、将缓存数据存储在什么地方等方面获得更大的灵活性。您可以指定首次使用哪个区域,以及发生故障时转移到哪个区域。

内存区域:内存区域是一个使用最近最少算法(Least Recently Used,LRU)的纯内存缓存区域。当内存缓存区域满时,LRU 会首先删除最近最少使用的缓存数据。这个数据区域执行良好,大多数JCS 用户将它指定为最先使用的默认缓存区域。

磁盘区域:磁盘区域是在Web 服务器的文件磁盘上缓存数据。为了提高性能,JCS 在文件磁盘上存储实际缓存数据的同时,会在内存中存储缓存数据键。在首先使用内存区域的典型JCS 配置中,任何无法在内存区域中保存的数据都会写入磁盘区域中。

外围区域:外围区域提供一种可配置方式来在多台服务器之间分发缓存数据。缓存数据服务器必须有一个开放的用于侦听的端口,而且必须创建一个套接字连接。这个区域存在一个潜在问题,因为它不能保证各缓存之间的数据的一致性。但如果是按计划使用该区域,则不会出现这个问题。

远程区域:远程区域提供了一个使用远程方法调用(RMI)API 的缓存区域。这个区域使用一台远程服务器处理缓存数据。这台远程缓存服务器可以被多个JCS 客户端应用程序用于存储缓存数据。一些侦听器被定义用于收集来自客户端和服务器的请求。这个缓存区域帮助减少串行化和多个连接点的开销。

(JCS 的可插入控制器:JCS 通过组合缓存器(Composite Cache)让使用多个区域进行缓存存储变得很简单。组合缓存器为缓存区域提供了一个可插入控制器。组合缓存器仔细处理复杂的任务,即确定何时以及如何使用每个缓存区域。JCS 将完成大部分复杂的工作,开发人员只需关心获取和设置缓存。)

夏俊备注:我看了下ibatis缓存机制,内存区域的缓存和磁盘缓存,ibatis也有实现。

JCS 配置:配置JCS 就是简单地创建和填充一个https://www.doczj.com/doc/229289250.html,f 文件。这个文件定义缓存应该使用哪些区域,以及这些区域的属性或选项。根据应用程序的需求配置这个文件是一种快速扩展缓存的简便方式。您可以指定许多适合配置的选项和属性来满足需求。

清单 1 显示的是最基本的https://www.doczj.com/doc/229289250.html,f 文件—一个纯内存缓存配置:

清单 1. JCS 的基本配置

jcs.default=jcs.default.cacheattributes=https://www.doczj.com/doc/229289250.html,positeCacheAttributes

jcs.default.cacheattributes.MaxObjects=1000

jcs.default.cacheattributes.MemoryCacheName=org.apache.jcs.engine.memory.lru.LRUMemoryCache

从清单 1 中可以看出,该配置文件将内存缓存指定为一个LRUMemoryCache。还可以看到,内存中能保存的对象的最大数量被设置为1000。

大多数应用程序的缓存系统配置要比清单 1 中复杂得多。在清单2 的配置中,我在定义自己的区域(OUR_REGION)时使用了一个内存区域和一个磁盘区域:

清单 2. 在 JCS 配置中定义的区域

jcs.default=DISK_REGION

jcs.default.cacheattributes=https://www.doczj.com/doc/229289250.html,positeCacheAttributes

jcs.default.cacheattributes.MaxObjects=1000

jcs.default.cacheattributes.MemoryCacheName=org.apache.jcs.engine.memory.lru.LRUMemoryCache jcs.region.OUR_REGION=DISK_REGION

jcs.region.OUR_REGION.cacheattributes=https://www.doczj.com/doc/229289250.html,positeCacheAttributes

jcs.region.OUR_REGION.cacheattributes.MaxObjects=1000

jcs.region.OUR_REGION.cacheattributes.MemoryCacheName=

org.apache.jcs.engine.memory.lru.LRUMemoryCache

jcs.region.OUR_https://www.doczj.com/doc/229289250.html,eMemoryShrinker=true

jcs.region.OUR_REGION.cacheattributes.MaxMemoryIdleTimeSeconds=3600

jcs.region.OUR_REGION.cacheattributes.ShrinkerIntervalSeconds=60

jcs.region.OUR_REGION.cacheattributes.MaxSpoolPerRun=500

jcs.region.OUR_REGION.elementattributes=org.apache.jcs.engine.ElementAttributes

jcs.region.OUR_REGION.elementattributes.IsEternal=false

jcs.auxiliary.DISK_REGION=org.apache.jcs.auxiliary.disk.indexed.IndexedDiskCacheFactory jcs.auxiliary.DISK_REGION.attributes=

org.apache.jcs.auxiliary.disk.indexed.IndexedDiskCacheAttributes

jcs.auxiliary.DISK_REGION.attributes.DiskPath=c:/jcs/disk_region

jcs.auxiliary.DISK_REGION.attributes.maxKeySize=100000

清单 2 中的第一行表明该配置将默认区域设置为DISK_REGION。DISK_REGION 是IndexedDiskCacheFactory 类型,并且该文件在磁盘上指定为c:\jcs\disk_region。清单 2 中的第二个配置组定义了我自己的区域,我为它添加了一些选项,这种类型的配置(在指定用户定义区域时同时使用内存区域和磁盘区域)是很常见的。清单 2 中的第 3 个配置组定义了一个辅助区域。

JCS 有两个依赖项:concurrent 和commons-logging(JCS 1.2.7.0 之前的版本中,还有两个其他依赖项:commons-collections 和commons-lang)。

(JCS 辅助插件:除了4 个核心缓存实现外,JCS 还提供了一些辅助插件,它们是区域可以使用的可选插件。这些辅助插件包括索引磁盘缓存(Indexed Disk Cache)、TCP 外围缓存(TCP Lateral Cache)和远程缓存服务器(Remote Cache Server)。例如,索引磁盘缓存允许在到达内存阈值时在磁盘上交换项目。这使得每个区域能更灵活地控制其缓存,提供一

种类似于大多数操作系统所使用的虚拟内存的存储方法。https://www.doczj.com/doc/229289250.html,f 配置文件可以让每个辅助区域满足应用程序的需求。)

JCS 的基本用法:学习JCS 基础知识的一个好方法是查看API 最常用的方法。最好从初始化区域开始。初始化JCS 缓存区域对象能使您访问大部分所需的常用方法。清单3 初始化JCS 对象并获得一个默认缓存区域实例:

清单 3. 检索默认缓存区域

// Initialize the JCS object and get an instance of the default cache region

JCS cache = JCS.getInstance("default");

检索JCS 实例后,可以调用最需要的方法。put 方法将一个新对象放入缓存中。接下来只需一个key(第一个参数)和一个value(第二个参数)。清单 4 显示一个基本示例:

清单 4. 设置缓存项

// Set up

String key = "key0";

String value = "value0";

// Place a new object in the cache

cache.put(key, value);

清单 4 中的示例使用字符串值作为参数,但是您可以使用任何对象。

检索缓存对象只不过是使用JCS 提供的get 方法。清单5 显示了一个简单示例。同样,本例使用了一个字符串参数,但您可以使用任何对象。

清单 5. 检索缓存项

// Retrieve a cached object

String cachedData = (String)cache.get(key);

测试缓存数据的有效性可能是处理缓存系统时需要使用的另一种方法。在JCS 中,没有定义只测试缓存项是否存在的测试缓存方法。但是get 方法的返回值可以帮助您。清单6 显示了一种获得此必要功能的方式:

清单 6. 测试缓存项的有效性

// Retrieve a cached object

String cachedData = (String)cache.get(key);

// Check if the retrieval worked

if (cachedData != null) {

// The cachedData is valid and can be used

System.out.println("Valid cached Data: " + cachedData);

}

最后需要几个用于在使用JCS、缓存项和缓存区域后清除它们的常用缓存实用程序。JCS 提供了一种clear 方法,用于从调用的缓存区域中删除所有缓存数据。此外,还提供了一个remove 方法,用于删除指定缓存项。dispose 方法也可以处理初始化的JCS 区域。清单7 显示了如何使用这些方法:

清单 7. 清除缓存区域

// Dispose of a specific cached item

cache.remove(key);

// Dispose of all cache data

cache.clear();

// Dispose of the cache region

cache.dispose();

JCS 和 Java 对象:JCS 优于其他缓存系统(请参阅参考资料)的一个地方是它可以很好地使用对象。大多数Web 应用程序是使用面向对象的方法通过Java 技术创建的。例如,与连续从数据库中逐段检索对象相比,缓存对象使应用程序能够更好地执行。

设计一个简单的面向对象的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 = 6392376146163510046L;

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 = content;

}

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 对象相关的管理和缓存功能。在本例中,管理器将处理三大任务:

?检索blog 对象

?在缓存中设置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 (CacheException 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 方法将blog 对象放在缓存中。这个方法比较简单,因为它只是使用传入的信息创建一个新的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);

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

blogCache.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 应用程序中处理对象的简单但强大的方法。

缓存元数据

JCS 提供了更多方法,向应用程序添加缓存所用的方法只是其中的一小部分。例如,它提供了收集缓存对象和缓存区域元数据的实用程序。您可以轻松检索以下内容:

?缓存键名称

?创建缓存项的时间

?缓存可以存在的最长时间

?缓存过期时间

清单12 中的例子显示如何检索缓存项的元数据:

清单 12. 检索缓存项的元数据

try {

JCSAdminBean admin = new JCSAdminBean();

LinkedList linkedList = admin.buildElementInfo(regionName);

ListIterator iterator = linkedList.listIterator();

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): " + 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();

CompositeCache 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.getMissCountExpired());

System.out.println("Cache Hits (memory): " + compCache.getHitCountRam());

System.out.println("Cache Updates: " + compCache.getUpdateCount());

}

} catch (Exception e) {

}

收集缓存区域和项的元数据能帮助您分析Web 站点的哪些区域和项目需要优化。元数据也能帮助您管理时间敏感型的缓存数据。例如,您可以使用每个缓存项的最长生命周期和过期时间来为需要更新数据的特定用户刷新缓存数据。

结束语:JCS 是为Java 开发人员提供的功能强大但简单易用的缓存系统。它为桌面和类似的Web 应用程序提供数据缓存。类似桌面的Web 应用程序的发展前景是提高速度和敏捷性。缓存数据对这些方面非常有益。本文概述如何配置和使用JCS。此外,还讨论了基本缓存方法所需要语法,以及如何在常见Web 应用程序中缓存对象和检索缓存元数据。解了JCS 的基本知识之后,您现在可以利用数据缓存功能来开发下一个Web 站点了。您还可以学习其他几个提供高级功能的JCS 区域,比如HTTP Servlet 访问、JCS 实用程序、基本HTTP 验证和其他辅助区域。

b)资料编号NO102

给WEB应用加JCS缓存系统:

下载jcs-1.2.6.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 Serializable

{

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 behavior

import 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 region 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.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 whether to look * in the cache. Returns a new value object if one can't 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, attempt 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);

}

return vObj;

/**

* Creates a BookVObj based on the id of the BOOK table. Data * 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 found

found = true;

// cache the value object 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 BookVObj's in database. Clears 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("BookVObj" + vObj.bookId, vObj);

}

catch (Exception e)

{

// Handle failure removing object or putting object to cache.

}

}

}

三、配置文件https://www.doczj.com/doc/229289250.html,f,它定义你配置何种类型的缓存、缓存的大小、过期时间等。

#WEB-INF/classes/https://www.doczj.com/doc/229289250.html,f(以下内容不要换行)

jcs.default=

jcs.default.cacheattributes=https://www.doczj.com/doc/229289250.html,positeCacheAttributes

jcs.default.cacheattributes.MaxObjects=1000

jcs.default.cacheattributes.MemoryCacheName=org.apache.jcs.engine.memory.lru.LRUMemoryCache https://www.doczj.com/doc/229289250.html,eMemoryShrinker=true

jcs.default.cacheattributes.MaxMemoryIdleTimeSeconds=3600

jcs.default.cacheattributes.ShrinkerIntervalSeconds=60

jcs.default.cacheattributes.MaxSpoolPerRun=500

jcs.default.elementattributes=org.apache.jcs.engine.ElementAttributes

jcs.default.elementattributes.IsEternal=false

四、测试的JSP文件

<%@page import="com.genericbookstore.data.*,java.util.*" %>

<%

BookVObjManager cache = BookVObjManager.getInstance();

BookVObj bv1=cache.getBookVObj(8,true);

out.println(bv1.bookId);

%>

五、测试:http://127.0.0.1:8080/jcs/testjcs.jsp

c)资料编号NO103

安装和配置:在web应用中安装和配置JCS是非常简单的事情。从Jakarta Turbine网站下载压缩文件,解压缩文件到临时目录,并拷贝JSC.jar文件(jcs-1.0-dev.jar)到servlet容器

的通用目录(在我的web应用中使用的servlet容器是Tomcat,通用目录在windows下就是%TOMCAT_HOME%\common\lib,在再Unix类型的系统下就是

$TOMCAT_HOME/common/lib)。你可能还需要commons-collections.jar, commons-lang.jar, 和commons-logging.jar 这些文件存在于web应用的类路径下以便使用JCS。

框架的主要原理

缓存属性

我们将所有的缓存参数配置在名为https://www.doczj.com/doc/229289250.html,f的属性文件中。这些参数包括缓存信息如:内存中存储的对象的最大数量,缓存时间(过了时间之后缓存的数据九自动从内存中释放),中断时间(elapsed time since last access time),内存缓存名称(例如:缓存算法如LRU或MRU)等。在当前版本的JCS中,缓存属性文件是纯文本格式的。SpiritCache framework,一种来自SpiritSoft的Jcache API商业实现,支持XML格式的缓存配置。

确认该属性文件存放在类路径中。注意:如果你需要使用其它不同的文件来存放缓存属性的话,JCS 也提供了方法来指定一个配置文件的名称。请参考JCS的Javadocs 学习如何从其它非缺省的属性文件中读取缓存配置信息。

下面列出来的是web应用使用缓存功能需要了解的一些Java类。这些类存放在本文的示例代码的common.caching包中。这些类的Javadocs也包括在源代码压缩包中。(图2 中的类图显示了这些Java类的关系)

ICacheManager

这是客户应用实现所有缓存有关操作(如:存储、访问以及释放缓存中的数据)的主接口(契约)。客户程序可以是JSP、Struts Action类,或者就是一个POJO对象。创建该接口用于对客户端隐藏所有缓存的实现细节,这样当我们将来需要切换另一种的第三方缓存API的时候无需对客户端代码做任何调整。

BaseCacheManager

这是web门户缓存框架的主类。是对ICacheManager 接口的最基本实现。创建BaseCacheManager 用于在一个类中集中所有缓存相关的方法。它被设计为单例模式保证在servlet容器的JVM中有且仅有一个ICacheManager 的实例被创建。在多web服务器/servlet 容器实例共同处理web请求的集群环境中,每个JVM将会创建独立的ICacheManager 实例。如果将来你要转换到不同的缓存API ,这是唯一需要为新的缓存API修改的类。如果你切换到JCache-兼容的缓存实现,对缓存管理器的修改将会是很小的。

ICacheLoader

该接口用于在web客户端实现真正的数据访问逻辑。所有需要使用缓存机制的客户端应用必须实现该接口。它包括仅有的一个方法叫做loadCacheObject() ,有两个输入参数:一个String参数制定缓存区域名称,一个对象参数制定缓存键值。这样,缓存管理器将知道在缓存的对象超过指定的“生存时间”的时候,使用哪个客户端程序(运行loadCacheObject 方法)来重载缓存中的对象。

ICacheKey

ICacheKey 接口创建的目的是为了隐藏特定的创建缓存键值的细节。有时候缓存的键值不是一个简单的字符串。它可能像多个对象组合起来一样复杂,从数据源获取这些值需要多个查找方法而不是单一的方法。在这种情况下,ICacheKey 接口可以被用来定义创建缓存键值的所有复杂的逻辑。这样,缓存键值创建逻辑将会被定义为独立的类。我编写了一个简单的类TestCacheKey 实现了该接口并实现了getCacheKey() 方法来演示使用该接口的方法。

CacheRegions

一个缓存区域被定义为一个组织起来的命名空间用于容纳一组缓存对象集合。你需要

在配置文件中定义缓存区域来实现在一块单独的内存空间中存储数据,管理缓存数据的有效期限。如果需要的话,对有相似特征的对象(例如:生存时间和业务用途)应该被缓存在相同的缓存区域中,让它们可以在相同的时间失效。我定义了分离的缓存区域来存储静态数据和小变动数据。为了避免同步操作带来的效率影响,我对每个缓存区域使用了单独的Cache (JCS) 实例。

CacheElementInfo

该类用于封装所有的缓存统计信息(例如:命中数、不中数、命中比例等),用来监测在web应用中所有缓存对象的效率。

编译, 构建, 和单元测试

我用Ant创建了一个构建脚本来编译我的对象缓存框架的所有代码。Ant的构建脚本build.xml, 放在WEB-INF\classes 目录下。我还编写了Junit测试客户端来测试使用web门户缓存框架的不同缓存场景。测试脚本CachingTestCase, 放在

WEB-INF\classes\common\caching\test 目录下。解压缩示例代码到一个新的web应用目录,如果要验证Junit测试脚本,从命令行运行以下命令:

切换当前目录到%TOMCAT_HOME%/webapps/web-app-name/WEB-INF/classes (在Unix测试环境中,目录应该是$TOMCAT_HOME/webapps/web-app-name/WEB-INF/classes)。

运行以下命令:

ant https://www.doczj.com/doc/229289250.html,pile

编译缓存框架中所有的Java类。

ant common.runjunit

用于运行Junit测试脚本。测试脚本使用Log4J API来显示所有的输出信息。

考虑何时使用对象缓存的指导方针

当你决定要在你的web应用中缓存一些特定类别的数据的时候,请参照这些指导方针。缓存的应用应该经过谨慎地考虑,只有当其它方法,如:数据访问等,已经无法再进一步改进的时候才需要使用缓存。缓存将会带来复杂性,让维护工作变得更加复杂。因此,必须统筹考虑性能和缓存带来的复杂性的平衡关系。

当考虑使用缓存的时候,需要考虑对象的预定执行时间和刷新率或者叫做对象的生存时间。缓存不能容纳所有我们想要存储的数据,因此缓存使用的内存及时得到释放,即可以通过定义合理的生存时间实现,也可以在数据不再需要的时候显式地释放被缓存的对象。可以指定缓存算法如最近被访问算法(LRU)或者最少被使用算法(LFU)以便缓存基于访问频率来释放对象。Jack Shirazi的著作Java 性能调整提供了一个关于缓存主题的非常有趣的讨论,讨论了什么类型的数据应该被缓存,以及何时使用缓存的建议。

注意缓存框架并没有处理在web应用中需要被缓存的对象的创建(例如:从数据源检索数据的数据访问逻辑并没有在缓存类中编写)。这要依赖于客户程序来定义真正的数据访问逻辑。像Java数据对象等技术通常用于在企业级web应用中封装数据访问逻辑。参考

O'Reilly的Java 数据对象来学习更多的关于如何将数据访问层与业务逻辑层分离的知识。

结论

本文提供了对使用Jakarta的Java缓存系统(JCS)来为web门户应用开发对象缓存框架的概要介绍。该框架非常稳定并可以被重用于其它任何web应用,甚至可以用于客户/服务器模式的Java应用程序。本文详细介绍了web门户缓存框架的工作原理,并提供了Junit 测试脚本来对不同场景的缓存框架进行测试。

JCS was built as a system close to JCACHE Java Temporary Caching API (JSR-107), a description of the caching system used in Oracle 9i and other popular caching frameworks. 该规

范可能会在将来的JDK发行版本中作为一种Java扩展框架。我的其中一个目的就是让web

门户缓存框架与JCS保持松散耦合。这样的话,如果我将来需要转换到另一种框架(例如Jcache),我可以在对web门户应用客户程序代码不做大的调整的情况下完成切换。

我现在通过记录缓存监测信息的日志(使用Log4J API)如:命中数、不中数、命中率来衡量缓存的效率。可能将来有其它参数需要被监测来衡量缓存的效率。同样的,用来测量使用或不使用缓存对数据访问的反馈时间,应该使用一些负载测试工具如:Grinder或者Jmeter来测试其伸缩性和性能效果。

在机群环境下保持缓存同步将是一个挑战,因为每个servlet容器将会在自己的JVM中拥有一个缓存管理器实例。解决该问题的方法就是创建消息驱动Bean(MDB)在需要刷新数据的时候通知所有的缓存管理器。

通常的对象查找方法,如:简单的Hashtable、JNDI甚至是EJB,提供了在内存中存放对象并通过键值查找对象的方法。但是任何一种方法都没有提供当对象不需要的时候从内存中移出的机制,或者当访问对象迟于对象存放期限的时候自动创建对象的机制。HttpSession 对象(in the servlet package) 也允许对象被缓存,但是它没有共享、失效、单一对象存放期满、自动装载或者spooling 这些缓存框架需要具备的基础机制。

虽然将缓存功能集成到web应用中需要额外的设计和开发工作,但我认为缓存带来的利益大于额外付出的工作。我已经看到在我实现了缓存框架之后,我的web应用的性能有很大的提高,特别是在访问静态数据和查找结果方面。该web应用模块目前处于测试阶段。在不久的将来,我会提供一些性能方面的测试数据(包括使用与不使用缓存的情况)来比较缓存如何帮助设计更快、更具伸缩性的web应用。

图1

图2

d)资料编号NO104

JCS是Jakarta的项目Turbine的子项目。它是一个复合式的缓冲工具。可以将对象缓冲到内存、硬盘。具有缓冲对象时间过期设定。还可以通过JCS构建具有缓冲的分布式构架,以实现高性能的应用。

对于一些需要频繁访问而每访问一次都非常消耗资源的对象,可以临时存放在缓冲区中,这样可以提高服务的性能。而JCS正是一个很好的缓冲工具。缓冲工具对于读操作远远多于写操作的应用性能提高非常显著。

JCS的详细说明在https://www.doczj.com/doc/229289250.html,/turbine/jcs/

我想使用到它是因为我想实现一个有时效性的对象的东西,当一个对象一段时间不操作,则销毁!

示例代码:

缓存的对象User,一定要实现Serializable接口

package org.c2one.sercenter.entity;

import java.io.Serializable;

import java.util.HashMap;

import java.util.Map;

public class User implements Serializable {

private String name;

private String password;

private Map detailInfoMap = new HashMap();

public Map getDetailInfoMap() {

return detailInfoMap;

}

public void setDetailInfoMap(Map detailInfoMap) {

this.detailInfoMap = detailInfoMap;

}

public String getName() {

return name;

}

public void setName(String name) {

https://www.doczj.com/doc/229289250.html, = name;

}

public String getPassword() {

return password;

}

public void setPassword(String password) {

this.password = password;

}

}

缓存操作类UserManager

package org.c2one.sercenter.cache;

import org.apache.jcs.JCS;

import org.apache.jcs.access.exception.CacheException;

import org.apache.log4j.Logger;

import https://www.doczj.com/doc/229289250.html,er;

import https://www.doczj.com/doc/229289250.html,erServiceImpl;

public class UserManager {

private static final Logger logger = Logger.getLogger(UserManager.class);

private JCS jcs;

private static UserManager userCache;

public static UserManager getInstance() throws CacheException {

if (userCache == null) {

userCache = new UserManager();

//使用default的jcs配置

userCache.jcs = JCS.getInstance("userCache");

}

return userCache;

}

public void regiestUser(String key, User user) throws CacheException {

jcs.put(key, user);

}

public User getUser(String key) {

return (User) jcs.get(key);

}

}

另外需要的就剩下jcs的配置文件https://www.doczj.com/doc/229289250.html,f,放到src的根目录下就行

内存上的LRU缓存机制配置:

# DEFAULT CACHE REGION

# sets the default aux value for any non configured caches

jcs.default=

jcs.default.cacheattributes=https://www.doczj.com/doc/229289250.html,positeCacheAttributes

#存放对象个数

jcs.default.cacheattributes.MaxObjects=1000

jcs.default.cacheattributes.MemoryCacheName=org.apache.jcs.engine.memory.lru.LRUMemoryCach e

jcs.default.elementattributes.IsEternal=false

jcs.default.elementattributes.MaxLifeSeconds=3600

jcs.default.elementattributes.IdleTime=1800

jcs.default.elementattributes.IsSpool=true

jcs.default.elementattributes.IsRemote=true

jcs.default.elementattributes.IsLateral=true

#这里指明对象超过3600秒则过期,每隔60秒检查一次

web cache缓存技术的概述与举例

1.1 宽带用户需求分析 面对主流宽带运营商(电信、联通)的强大资源优势,移动、广电处于不利局面。申请和使用线路会遇到一定麻烦,同时电信与联通的互访速度慢、国内访问国外网站的速度慢,都会造成用户体验下降。 同时使用大量带宽的大学、职业学院、大企业也会面临同样的问题。 通过下面几节分析我们认为,使用基于HTTP协议的CACHE,将显著降低基于HTTP协议的小数据包的应用,有助于明显优化客户体验,节省大量带宽资源。同时,基于HTTP的CACHE 将解决在线web视频的问题,极大地提升了在线视频的客户体验。 同时,采用P2P协议的其它部分视频内容由于大型视频网站如迅雷的采用加密算法,目前没有有效地P2PCACHE解决方案,建议与原服务提供商联系得到其授权的镜像服务器。 以上网络问题可以用web Cache 来解决,即增加用户带宽体验,减少网络带宽流量。 例如:可以通过MARA SYSTEM(迈锐赛腾)的高性能加速加速平台CACHEMARA,解决了处理HTTP小包过程中所面临的问题,一、大量HTTP小包所产生的短连接形成的连接的成本消耗。二、大量HTTP小包的频繁读取对存储介质所产生的巨大压力。而CACHEMARA最高端型号的单台设备的HTTP小包处理能力可支持到1.5Gbps,业界仅有其能实现这一点。(下面我们也将以CACHEMARA来做参考) 更详细的信息,请访问https://www.doczj.com/doc/229289250.html, 或https://www.doczj.com/doc/229289250.html,

1.2 目前网络应用的协议及用户群分析 据统计用户上网的基本应用按照协议分类为:

Web缓存技术概述

Web缓存技术概述 [日期:2006-05-31] 来源:作者:[字体:大中小] 王世克吴集金士尧 摘要WWW是互联网上最受欢迎的应用之一,其快速增长导致网络拥塞和服务器超载,缓存技术被认为是减轻服务器负载、降低网络拥塞,减少客户访问延迟的有效途径之一。本文首先描述了Web缓存系统的基本要素及理想属性,然后介绍目前围绕Web缓存技术已经开展的研究,最后讨论Web缓存技术需要进一步研究的问题。 关键字WWW 缓存技术代理 1 引言 WWW是互联网上最受欢迎的应用之一,其快速增长造成网络拥塞和服务器超载,导致客户访问延迟增大,WWW服务质量问题日益显现出来。缓存技术被认为是减轻服务器负载、降低网络拥塞、增强WWW可扩展性的有效途径之一,其基本思想是利用客户访问的时间局部性(Temporal Locality)原理,将客户访问过的内容在Cache中存放一个副本,当该内容下次被访问时,不必连接到驻留网站,而是由Cache中保留的副本提供。 Web内容可以缓存在客户端、代理服务器以及服务器端。研究表明,缓存技术可以显著地提高WWW性能[1][2],它可以带来以下好处: (1)减少网络流量,从而减轻网络拥塞; (2)降低客户访问延迟,其主要原因有:①缓存在代理服务器中的内容,客户可以直接从代理获取而不是从远程服务器获取,从而减小了传输延迟;②没有被缓存的内容由于网络拥塞及服务器负载的减轻而可以较快地被客户获取; (3)由于客户的部分请求内容可以从代理处获取,从而减轻了远程服务器负载; (4)如果由于远程服务器故障或网络故障造成远程服务器无法响应客户请求,客户可以从代理中获取缓存的内容副本,使得WWW服务的鲁棒性(Robustness)得到了加强。Web缓存系统也会带来以下问题: (1)客户通过代理获取的可能是过时的内容; (2)如果发生缓存失效,客户的访问延迟由于额外的代理处理开销而增加。因此在设计W eb缓存系统时,应力求做到Cache命中率最大化和失效代价最小化; (3)代理可能成为瓶颈。因此应为一个代理设定一个服务客户数量上限及一个服务效率下限,使得一个代理系统的效率至少同客户直接和远程服务器相连的效率一样。

大型WEB网站架构深入分析_缓存

缓存 1介绍 缓存就是利用本地参考原则:当CPU要读取一个数据时,首先从缓存中查找,找到就立即读取并送给CPU处理;没有找到,就用相对慢的速率从内存中读取并送给CPU处理,同时把这个数据所在的数据块调入缓存中,可以使得以后对整块数据的读取都从缓存中进行,不必再调用内存。它们几乎被用在每一个计算层上:硬件、操作系统、Web浏览器、Web应用程序等。一个缓存就相当于是一个临时内存:它有一个有限的空间量,但访问它比访问原始数据速度要快。缓存也可以存在于各个层的架构中,但经常在离前端最近的那个层上发现,在那里可以快速实现并返回数据,无需占用下游层数据。 那么如何利用缓存使数据访问更快呢在这种情况下,有许多地方可以插入缓存。一种是在请求层节点上插入缓存,如图1所示。 图 1 在请求层节点插入缓存 在请求层节点上放置一个缓存,即可响应本地的存储数据。当对服务器发送一个请求时,如果本地存在所请求数据,那么该节点即会快速返回本地缓存数据。如果本地不存在,那么请求节点将会查询磁盘上的数据。请求层节点缓存即可以存在于内存中(这个非常快速)也可以位于该节点的本地磁盘上(比访问网络存储要快)。

图2 多个缓存 ] 当扩展到许多节点的时候,会发生什么呢如图2所示,如果请求层被扩展为多个节点,它仍然有可能访问每个节点所在的主机缓存。然而,如果你的负载均衡器随机分布节点之间的请求,那么请求将会访问各个不同的节点,因此缓存遗漏将会增加。这里有两种方法可以克服这个问题:全局缓存和分布式缓存。 1.1全局缓存 顾名思义,全局缓存是指所有节点都使用同一个缓存空间。这包含添加一台服务器或某种类型的文件存储,所有请求层节点访问该存储要比原始存储快。每个请求节点会以同种方式查询缓存,这种缓存方案可能有点复杂,随着客户机和请求数量的增加,单个缓存(Cache)很容易溢出,但在某些结构中却是非常有效的(特别是那些特定的硬件,专门用来提升全局缓存速度,或者是需要被缓存的特定数据集)。 在图3中描述了全局缓存常见的两种方式。当一个Cache响应在高速缓存中没有发现时,Cache自己会从底层存储中检索缺少的那块数据。如图4所示,请求节点去检索那些在高速缓存中没有发现的数据。

java开发工程师简历

求职意向:java软件工程师 工作经验:2年 到岗时间:一周之内 期望薪资:面议 个人信息 年龄:25岁邮箱: 手机: 现居地:北京通州 专业技能 ?熟悉掌握JavaScript,Ajax,jQuery,JSON等前台技术并能够熟练使用EasyUI,zTree,ECharts等插件 ?熟悉掌握Servlet,Cookie,Session,JDBC,JavaBean,EL表达式,JSTL 等技术,深入了解MVC开发模式 ?熟悉使用Struts2框架,包括拦截器,OGNL表达式,Ajax并熟悉Struts2的工作流程 ?熟悉使用Spring框架,包括IOC和DI,AOP编程,声明式事务处理以及代理模式 ?熟悉使用Hibernate框架,包括一对多,多对多的对象关系映射,HQL,对象状态转换,数据缓存等 ?熟练运用SpringMVC,Mybatis 进行项目开发,掌握shiro 安全框架 ?熟悉使用MySQL和oracle数据库,使用其编写复杂的SQL语句,具有Mysql数据库的优化经验;掌握redis数据缓存技术 ?熟悉使用MyEclipse、HBilder,PLSQLDevelopment等开发工具,熟悉使用maven 项目管理工具,以及SVN 服务器的使用 ?熟悉Tomcat服务器的应用部署和集群配置

工作经历 毗邻智慧软件开发科技有限公司 担任职位:java软件开发师 ●初期主要实现项目的维护和个性化需求的搜集整理 ●完成项目模块的编码和测试工作 项目经验 项目名称:泉翼达商城 框架构建:Spring + SpringMVC + Mybatis + Mysql + zTree +PageHelper+ + EasyUI +CKeditor+Nginx+Redis 项目描述:此系统主要实现的功能是用户网上预订果蔬功能,包括交易系统和后台管理系统、会员系统、积分系统、支付系统、物流系统、单点登录系统 功能模块:商品信息展示、购物车管理、订单管理、用户管理、商品管理、积分管理、支付管理等功能模块 项目职责: ?负责了此系统的商品信息模块和商品管理模块的用户需求分析,完成了文档的设计与编写 ?前台交易系统负责了商品信息模块和购物车管理模块的代码编写,实现了商品基本信息(如商品预览、商品明细、分类检索)的功能,以及购物车管理模块(实现添 加商品、删除列表、数量修改、清空购物车、结算功能) ?后台管理系统负责商品管理(实现商品列表、商品发布、商品删除、商品修改功能)和用户管理模块(实现登入/登出、用户注册、信息修改功能)

缓存服务器介绍

什么是缓存服务器 无论企业有多大,Web缓存都有助于优化性能和节省带宽。而且如果选择了正确的缓存解决方案,它可以随着企业网络的增长而扩大,而无需进行昂贵且耗时的重建。 Web缓存提供了比将访问对象放在Internet Web服务器上更好的方法,它将需要频繁访问的Web页面和对象保存在离用户更近的系统中。当再次访问这些对象的时候加快了速度。 几年以前,理论是超高带宽的Internet连接会使Web缓存毫无用处,但是结果并非如此。即使最快的速率达到30-45Mbps的光纤Internet连接和速度在100 Mbps到1 Gbps速率的局域网相比仍然很慢,所以性能依旧是一个问题。除此之外,缓存提高了可用性,因为即使托管的Web服务器停机或者由于网络问题而不可达时,缓存的对象拷贝仍然可以访问。如果企业根据流量付费,缓存还可以降低Internet连通性的费用。即使是小公司,缓存也会有利,而且好的缓存解决方案将随着企业级别升级。[1] 编辑本段缓存概念 这是两种主要的Web缓存: 直接缓存,将用户频繁访问的来自Internet服务器的Web对象的拷贝保存在企业本地网络中。 反向缓存,企业内部Web服务器的Web对象的拷贝保存在企业网络边缘的代理服务器上以提高外界访问企业站点的性能。 Web缓存可以根据不同等级进行配置: 本地缓存:将Web对象缓存的拷贝保存在本地计算机中。大多数流行的Web浏览器默认情况下保留一个先前访问对象的缓存。例如,Internet Explorer称之为“临时Internet 文件”。本地缓存拷贝只是在用户频繁地从同一台机器访问页面时有用。 代理缓存:代理服务器是为公司内的多个用户/客户计算机缓存Web对象的单独机器。它们是位于客户端和托管的Web服务器之间的计算机,而且它们比本地缓存效率更高,因为在企业本地网络中的任何用户或计算机访问某个Web对象时,缓存拷贝对想访问该对象的任何其他用户/计算机是可用的,无需到Internet服务器上再次下载它。代理缓存可以在网络边缘与防火墙结合使用。 微软的ISA Server和BlueCoat的工具一样,既包括防火墙也包括缓存代理服务器。缓

多层技术架构JAVA

多层技术架构 本系统构建于J2EE平台,采用分层提供服务支持的设计思想,将系统划分为数据库层、中间件层、EMALL基础服务层、业务表现层和系统接口层。系统对每一层定义明确的功能接口,同时在层次内实现组件化的接口实现。层次化、模块组件化的实现,使系统具备了最大程度的灵活度,从而能对业务需求的变化作出快速的反应,使系统具有很好的扩展性。 首先我们来看一个系统技术架构图: 上图可以清晰的了解到整个系统的层次划分,系统从最底部的数据库层开始,一层一层的向上提供接口服务,最终实现用户按业务要求的可见操作界面和其他系统接口。各层次专著于自身功能的接口实现,整个层次保持相对的稳定。系统通过不改变接口,各个层次、各个组件进行优化的策略,能在不影响整个业务的前提下,不断的完善和改进。 一、数据库层 对于平台中的所有应用,都存在着各种各样的配置信息、业务数据、系统运行状态等信息。数据库层对这些数据信息本身进行归档,提供快速查询的底层接口,并保证数据的完整性、可靠性。 在数据库方面,我们采用Oracle或者是MySQL。这两种数据库分别有不同的适用环境。 1、Oracle ◆适合大型的电子商务应用。 ◆能使用所有的网客通平台功能。如访问量排行榜、降价排行榜、销售排行榜、访问量统计等等,就以往的经验来看,这些功能每天要处理的数据都会超过一千万。这种数据量如果使用传统的统计方法,统计一次的时间就可能会以天来计算了。如果使用Oracle,再配合我们专门对Oracle进行优化的高效率的统计程序,那么只需十数秒便可完成。 ◆此外,如果只用一台数据库无法应付日益增长的服务器访问量,可以使用Oracle RAC(真正应用集群),通过增加数据库服务器进行集群。 2、MySQL ◆适合中小型的电子商务应用。 ◆无法使用网客通平台一些高级应用,如排行榜、统计分析、MIS系统对接等。这是由于MySQL设计上强调访问速度,牺牲了一些数据库的高级功能,虽然用程序也可以实现这些功能,但是在性能上无法满足需求。 ◆不支持数据库集群。

爱奇艺的Java缓存之路,你应该知道的缓存进化史!

爱奇艺的Java缓存之路,你应该知道的缓存进化史! 本文是上周去技术沙龙听了一下爱奇艺的Java缓存之路有感写出来的。先简单介绍一下爱奇艺的java缓存道路的发展吧。 可以看见图中分为几个阶段: 第一阶段:数据同步加redis 通过消息队列进行数据同步至redis,然后Java应用直接去取缓存这个阶段优点是:由于是使用的分布式缓存,所以数据更新快。缺点也比较明显:依赖Redis的稳定性,一旦redis 挂了,整个缓存系统不可用,造成缓存雪崩,所有请求打到DB。

第二、三阶段:JavaMap到Guava cache 这个阶段使用进程内缓存作为一级缓存,redis作为二级。优点:不受外部系统影响,其他系统挂了,依然能使用。缺点:进程内缓存无法像分布式缓存那样做到实时更新。由于java内存有限,必定缓存得设置大小,然后有些缓存会被淘汰,就会有命中率的问题。 第四阶段: Guava Cache刷新 为了解决上面的问题,利用Guava Cache可以设置写后刷新时间,进行刷新。解决了一直不更新的问题,但是依然没有解决实时刷新。 第五阶段: 外部缓存异步刷新 这个阶段扩展了Guava Cache,利用redis作为消息队列通知机制,通知其他java应用程序进行刷新。

这里简单介绍一下爱奇艺缓存发展的五个阶段,当然还有一些其他的优化,比如GC调优,缓存穿透,缓存覆盖的一些优化等等。有兴趣的同学可以关注公众号,联系我进行交流。上面说的是爱奇艺的一个进化线路,但是在大家的一般开发过程中,第一步一般都没有redis,而是直接查库。 在流量不大的时候,查数据库或者读取文件是最为方便,也能完全满足我们的业务要求。当我们应用有一定流量之后或者查询数据库特别频繁,这个时候就可以祭出我们的java中自带的HashMap或者ConcurrentHashMap。我们可以在代码中这么写: 但是这样做就有个问题HashMap无法进行数据淘汰,内存会无限制的增长,所以hashMap 很快也被淘汰了。当然并不是说他完全就没用,就像我们古代社会也不是所有的东西都是过时的,比如我们中华名族的传统美德是永不过时的,就像这个hashMap一样的可以在某些

Ehcache是现在最流行纯Java开源缓存框架

Ehcache是现在最流行的纯Java开源缓存框架 2014-12-22 13:28 37723人阅读评论(0) 收藏举报分类: java(405) c:\t _blank Ehcache是现在最流行的纯Java开源缓存框架,配置简单、结构清晰、功能强大,最初知道它,是从hibernate的缓存开始的。网上中文的EhCache材料以简单介绍和配置方法居多,如果你有这方面的问题,请自行google;对于API,官网上介绍已经非常清楚,请参见官网;但是很少见到特性说明和对实现原理的分析,因此在这篇文章里面,我会详细介绍和分析EhCache的特性,加上一些自己的理解和思考,希望对缓存感兴趣的朋友有所收获。 一、特性一览,来自官网,简单翻译一下: 1、快速轻量 过去几年,诸多测试表明Ehcache是最快的Java缓存之一。 Ehcache的线程机制是为大型高并发系统设计的。 大量性能测试用例保证Ehcache在不同版本间性能表现得一致性。 很多用户都不知道他们正在用Ehcache,因为不需要什么特别的配置。 API易于使用,这就很容易部署上线和运行。 很小的jar包,Ehcache 2.2.3才668kb。 最小的依赖:唯一的依赖就是SLF4J了。 2、伸缩性 缓存在内存和磁盘存储可以伸缩到数G,Ehcache为大数据存储做过优化。 大内存的情况下,所有进程可以支持数百G的吞吐。 为高并发和大型多CPU服务器做优化。 线程安全和性能总是一对矛盾,Ehcache的线程机制设计采用了Doug Lea的想法来获得较高的性能。 单台虚拟机上支持多缓存管理器。

通过Terracotta服务器矩阵,可以伸缩到数百个节点。 3、灵活性 Ehcache 1.2具备对象API接口和可序列化API接口。 不能序列化的对象可以使用除磁盘存储外Ehcache的所有功能。 除了元素的返回方法以外,API都是统一的。只有这两个方法不一致:getObjectValue和getKeyValue。这就使得缓存对象、序列化对象来获取新的特性这个过程很简单。 支持基于Cache和基于Element的过期策略,每个Cache的存活时间都是可以设置和控制的。 提供了LRU、LFU和FIFO缓存淘汰算法,Ehcache 1.2引入了最少使用和先进先出缓存淘汰算法,构成了完整的缓存淘汰算法。 提供内存和磁盘存储,Ehcache和大多数缓存解决方案一样,提供高性能的内存和磁盘存储。 动态、运行时缓存配置,存活时间、空闲时间、内存和磁盘存放缓存的最大数目都是可以在运行时修改的。 4、标准支持 Ehcache提供了对JSR107 JCACHE API最完整的实现。因为JCACHE在发布以前,Ehcache的实现(如net.sf.jsr107cache)已经发布了。 实现JCACHE API有利于到未来其他缓存解决方案的可移植性。 Ehcache的维护者Greg Luck,正是JSR107的专家委员会委员。 5、可扩展性 监听器可以插件化。Ehcache 1.2提供了CacheManagerEventListener和CacheEventListener接口,实现可以插件化,并且可以在ehcache.xml里配置。 节点发现,冗余器和监听器都可以插件化。 分布式缓存,从Ehcache 1.2开始引入,包含了一些权衡的选项。Ehcache的团队相信没有什么是万能的配置。 实现者可以使用内建的机制或者完全自己实现,因为有完整的插件开发指南。 缓存的可扩展性可以插件化。创建你自己的缓存扩展,它可以持有一个缓存的引用,并且绑定在缓存的生命周期内。 缓存加载器可以插件化。创建你自己的缓存加载器,可以使用一些异步方法来加载数据到缓存里面。 缓存异常处理器可以插件化。创建一个异常处理器,在异常发生的时候,可以执行某些特定操作。

缓存管理需求说明

缓存管理功能需求说明 缓存管理开发背景 缓存管理功能的开发,意在减少系统对数据库的过多访问,通过减少对数据库的访问次数,改用访问内存的方式,提升系统的性能。直接从内存获取数据,较之从数据库获取数据,效率可以得到显著的提升。 系统由于多次查询数据库,消耗大量系统资源,且查询效率可能因为开发者的个人能力导致查询效率不高,或占用过多资源影响系统性能。使用缓存管理,系统只有第一次查询访问数据库,而后皆通过访问内存取得数据,不需要在计较这次查询的SQL是否过于复杂,是否效率低下,直接取得数据返回即可。 第一部分、缓存管理 缓存管理提供了缓存工具类CacheUtils以供开发者对缓存进行自定义开发。如果开发者需要自己开发某功能需要涉及缓存管理则可以借助使用CacheUtils工具类来完成。本地缓存管理和redis 缓存管理的区分在于redis是否正确连接且启动。注意,是正确连接并且启动redis服务器。 关于开发者需要自行开发某功能的缓存管理需要了解CacheUtils怎么使用可以查看《缓存管理开发说明》 本地缓存管理 本地缓存管理是在redis没有正常启动运行的时候系统提供的缓存管理方式。本地缓存管理暂无任何持久化操作。对于缓存中的所有数据,在应用重启后一律清空,需要重新载入缓存。本地缓存

管理采用的是标准的key-value形式保存,于Java中采用的结构形式为HashMap结构,HashMap 有利于快速的存取,因而采用该结构保存本地缓存。其中key的类型为string,value的类型为object。本地缓存管理对于类型的限制基本没有。Value可以置入任何Java支持的对象。 本地缓存管理中,保存进入缓存只需要使用CacheUtils中的save方法进行保存即可,保存的数据在本地缓存中不做多余的处理,直接置入缓存中。由于采用的是以Object类型的形式保存,并不会对保存的数据进行转换,获取保存的缓存数据时直接使用CacheUtils中的get方法即可取得保存的数据,达到怎么存就怎么取,存什么取什么。无需更多的变换数据结构,更不会导致因为存储导致类型的变换或者数据的丢失。 由于存什么取得的就是什么,因而直接修改取得的数据对象有可能导致缓存数据也被修改。Redis缓存管理 Redis缓存管理需要开启redis服务器并正确配置连接信息,系统会在启动的时候检测redis是否可以正常连接启用,如果没有正常连接启用则使用本地缓存管理。 Redis缓存管理对于类型具有特别的要求,对于不同的数据类型需要使用对应的类型进行保存。且不允许使用复杂的对象类型进行保存,如list-object是不被允许的,需要转换为list-string的类型再进行保存,同理Map类型也不被允许使用Object,但是单个JavaBean是允许进行存取的。即redis 缓存管理不支持三维结构存储,仅支持二维结构存储。 Redis缓存管理的数据会有简易的持久化。即当redis停止后或者系统停止后,再次启动时redis 依然存有数据提供,不需要再次载入缓存。如果缓存设置了失效则可能会被清除。 Redis缓存管理保存、修改 由于redis数据类型的特殊性,所以所有Java中复杂的对象存储都需要进行相应的转换后才可

web缓存服务器介绍

web缓存服务器介绍 对于web缓存服务器的了解,大多数人都不是很了解,只是道听途说,对于其真正的作用,专职优化、域名注册、网站空间、虚拟主机、服务器托管、vps主机、服务器租用的中国信息港就在这里为你详细探讨! 无论企业有多大,Web缓存都有助于优化性能和节省带宽。而且如果选择了正确的缓存解决方案,它可以随着企业网络的增长而扩大,而无需进行昂贵且耗时的重建。 Web缓存提供了比将访问对象放在Internet Web服务器上更好的方法,它将需要频繁访问的Web 页面和对象保存在离用户更近的系统中。当再次访问这些对象的时候加快了速度。 几年以前,理论是超高带宽的Internet连接会使Web缓存毫无用处,但是结果并非如此。即使最快的速率达到30-45Mbps的光纤Internet连接和速度在100 Mbps到1 Gbps速率的局域网相比仍然很慢,所以性能依旧是一个问题。除此之外,缓存提高了可用性,因为即使托管的Web服务器停机或者由于网络问题而不可达时,缓存的对象拷贝仍然可以访问。如果企业根据流量付费,缓存还可以降低Internet连通性的费用。即使是小公司,缓存也会有利,而且好的缓存解决方案将随着企业级别升级。 缓存概念 这是两种主要的Web缓存: 直接缓存,将用户频繁访问的来自Internet服务器的Web对象的拷贝保存在企业本地网络中。 反向缓存,企业内部Web服务器的Web对象的拷贝保存在企业网络边缘的代理服务器上以提高外界访问企业站点的性能。 Web缓存可以根据不同等级进行配置: 本地缓存:将Web对象缓存的拷贝保存在本地计算机中。大多数流行的Web浏览器默认情况下保留一个先前访问对象的缓存。例如,Internet Explorer称之为“临时Internet文件”。本地缓存拷贝只是在用户频繁地从同一台机器访问页面时有用。 代理缓存:代理服务器是为公司内的多个用户/客户计算机缓存Web对象的单独机器。它们是位于客户端和托管的Web服务器之间的计算机,而且它们比本地缓存效率更高,因为在企业本地网络中的任何用户或计算机访问某个Web对象时,缓存拷贝对想访问该对象的任何其他用户/计算机是可用的,无需到Internet服务器上再次下载它。代理缓存可以在网络边缘与防火墙结合使用。 微软的ISA Server和BlueCoat的工具一样,既包括防火墙也包括缓存代理服务器。缓存服务器也可以是单独的机器,运行免费的缓存软件或商业产品,例如: Linux版的Squid免费缓存代理 MOWS基于Java分布式web和缓存服务器 Vicomsoft RapidCache Server for Windows或Macintosh WinProxy for Windows 可升级的缓存解决方案 随着公司的扩大,单一的Web缓存服务器可能无法处理所有的通信或存储足够的Web 对象。在这种情况下,可以扩展缓存解决方案以建立一个缓存阵列——一组共同工作以便在组内分配缓存负载的缓存代理服务器。万一某个缓存服务器停机,还提供缺省的容量。

使用JCS在Web门户应用中实现对象缓存

使用JCS在Web门户应用中实现对象缓存(1) 使用JCS在Web门户应用中实现对象缓存 在我最近的web门户应用开发工作中,我们需要在Servlet容器(Tomcat)的内存中存储一些查找数据(例如:比率更新数据、状态和产品列表),这样我们不需要在每次访问数据的时候进行数据库查找。同时,我们也需要定期地刷新存储在内存中的数据以保证其新鲜和准确。我们也需要一种机制在不同的时间间隔对存储在内存中的不同类型的数据进行刷新。例如,比率更新数据需要每天刷新一次,而查找类型的数据则可以在内存中保留很长一段时间。对象缓存是最方便地达到上述所有目的的完美解决方案。 对象缓存 最恰当的对象缓存的定义可以在Object Caching Service for Java (OCS4J)的功能规范文档中找到,它是这样定义的: 服务器必须将信息和可执行对象分为三种基本类别管理:永远不会改变的对象,每次请求都会发生改变的对象,以及在两者之间的对象。Java对前两种对象的处理提供了很好的支持,但是对第三种类别的支持非常有限。如果对象永远不改变,我们在服务器初始化的时候创建静态对象。如果对每个请求对象都是不同的,我们每次都创建新的对象。对于介于两者之间的对象或信息,它们的状态可能会发生变化,但是又需要提供跨越请求、跨越用户或跨越进程的共享,就要采用“对象缓存服务”了。 基本上,对象缓存就是通过在使用对象后不立即释放,而是存储在内存中并被后来的客户端请求重用,避免重新获得对象的昂贵成本。当数据第一次从数据源被检索出来后,在名为cache的内存缓冲中临时存放。同样的数据再次被访问的时候,对象从缓存中取出来,而不是从数据源重新获取。最后,被缓存的数据在不再需要的时候从内存中释放出来。从Web应用的观点来看,什么时候指定的对象可以从内存中释放出来取决于定义一个对象变成无效的合理的间隔时间。 缓存的益处

缓存设计详解低成本的高性能Web应用解决方案

过去几年中,Web应用程序已经从简单的HTML页面堆积演变成使用各种各样的技术构建高可扩展性和交互式的富应用程序。设计和开发这类应用程序变得越来越复杂,此外,决策者正越来越多地寻求构建更丰富的互动功能到这些应用程序中,同时还要保证可维护性和高性能,但高性能意味着高成本。为了构建提供给最终用户体验的是一个牢固的应用程序,开发人员需要解决潜在的性能瓶颈。 本文侧重于缓存——它是交付高性能Web应用程序急需的——也简要介绍一下压缩功能。有一些公司在生产和销售专门的压缩和性能产品。本文旨在简单介绍在寻求专业产品解决性能问题之前开发人员可以在客户端和服务器端对Web应用程序做的一些性能改进。 性能瓶颈 性能瓶颈主要体现在高延时、拥塞和服务器负载。缓存不能完全解决掉这三个问题,但经过详细的设计考虑,缓存是可以提高性能的。在服务器端和客户端都缓存内容,据调查,平均而言,下载HTML只需要总的用户响应时间的10-20%,剩下的80-90%全部用于下载页面中的其它组成内容,这些组成内容通常包括图像,如公司logo,缓存logo可以有效避免到服务器的多次往返。在前日51CTO上发布的中,Google提到的提升网站速度和性能的低成本技巧中就包括缓存这一条。至于架构设计方面,则可参考51CTO的。

简单地讲,缓存是临时存储。它将数据复制到不同的计算机或不同于原始数据源的位置,有了正确的配置,访问缓存数据的速度比访问原始数据的速度要快得多,使用缓存数据可以减小服务器负载和带宽消耗,从最终用户的角度来看就是性能提高了。 图1显示了Internet如何工作的快速总揽,以及缓存在哪里发生作用。 ? 图 1 Internet上的缓存:这个图显示了常见的请求和检索缓存信息的时机

Java编程提高性能时需注意的地方

Java编程提高性能时需注意的地方 最近的机器内存又爆满了,出了新增机器内存外,还应该好好review一下我们的代码,有很多代码编写过于随意化,这些不好的习惯或对程序语言的不了解是应该好好打压打压了。 下面是参考网络资源和总结一些在java编程中尽可能做到的一些地方 1.尽量在合适的场合使用单例 使用单例可以减轻加载的负担,缩短加载的时间,提高加载的效率,但并不是所有地方都适用于单例,简单来说,单例主要适用于以下三个方面 第一,控制资源的使用,通过线程同步来控制资源的并发访问 第二,控制实例的产生,以达到节约资源的目的 第三,控制数据共享,在不建立直接关联的条件下,让多个不相关的进程或线程之间实现通信 2.尽量避免随意使用静态变量 要知道,当某个对象被定义为stataic变量所引用,那么gc通常是不会回收这个对象所占有的内存,如 1 2 3 public class A{ static B b = new B(); } 此时静态变量b的生命周期与A类同步,如果A类不会卸载,那么b对象会常驻内存, 直到程序终止。 3.尽量避免过多过常的创建java对象 尽量避免在经常调用的方法,循环中new对象,由于系统不仅要花费时间来创建对象,而且还要花时间对这些对象进行垃圾回收和处理,在我们可以控制的范围内,最大限度的重用对象,最好能用基本的数据类型或数组来替代对象。 4.尽量使用final修饰符 带有final修饰符的类是不可派生的。在Java核心API中,有许多应用final的例子,例如https://www.doczj.com/doc/229289250.html,ng.String。为String类指定final防止了使用者覆盖length()方法。另外,如果一个类是final的,则该类所有方法都是final的。java编译器会寻找机会内联(inline)所有的final方法(这和具体的编译器实现有关)。此举能够使性能平均提高50%。 5.尽量使用局部变量 调用方法时传递的参数以及在调用中创建的临时变量都保存在栈(Stack)中,速度较快。其他变量,如静态变量,实例变量等,都在堆(Heap)中创建,速度较慢。 6.尽量处理好包装类型和基本类型两者的使用场所 虽然包装类型和基本类型在使用过程中是可以相互转换,但它们两者所产生的内存区域是完全不同的,基本类型数据产生和处理都在栈中处理,包装类型是对象,是在堆中产生实例。 在集合类对象,有对象方面需要的处理适用包装类型,其他的处理提倡使用基本类型。

8种缓存框架介绍

8种流行的java缓存框架介绍 OSCache OSCache是个一个广泛采用的高性能的J2EE缓存框架,OSCache能用于任何Java应用程序的普通的缓存解决方案。OSCache有以下特点:缓存任何对象,你可以不受限制的缓存部分jsp页面或HTTP请求,任何java对象都可以缓存。拥有全面的API--OSCache API给你全面的程序来控制所有的OSCache特性。永久缓存--缓存能随意的写入硬盘,因此允许昂贵的创建(expensive-to-create)数据来保持缓存,甚至能让应用重启。支持集群--集群缓存数据能被单个的进行参数配置,不需要修改代码。缓存记录的过期--你可以有最大限度的控制缓存对象的过期,包括可插入式的刷新策略(如果默认性能不需要时)。 Java Caching system JSC(Java Caching system)是一个用分布式的缓存系统,是基于服务器的java应用程序。它是通过提供管理各种动态缓存数据来加速动态web应用。JCS和其他缓存系统一样,也是一个用于高速读取,低速写入的应用程序。动态内容和报表系统能够获得更好的性能。如果一个网站,有重复的网站结构,使用间歇性更新方式的数据库(而不是连续不断的更新数据库),被重复搜索出相同结果的,就能够通过执行缓存方式改进其性能和伸缩性。 EHCache EHCache 是一个纯java的在进程中的缓存,它具有以下特性:快速,简单,为Hibernate2.1充当可插入的缓存,最小的依赖性,全面的文档和测试。 JCache JCache是个开源程序,正在努力成为JSR-107开源规范,JSR-107规范已经很多年没改变了。这个版本仍然是构建在最初的功能定义上。 ShiftOne ShiftOne Java Object Cache是一个执行一系列严格的对象缓存策略的Java lib,就像一个轻量级的配置缓存工作状态的框架。 SwarmCache SwarmCache是一个简单且有效的分布式缓存,它使用IP multicast与同一个局域网的其他主机进行通讯,是特别为集群和数据驱动web应用程序而设计的。SwarmCache能够让典型的读操作大大超过写操作的这类应用提供更好的性能支持。SwarmCache使用JavaGroups 来管理从属关系和分布式缓存的通讯。 TreeCache / JBossCache

Java 对文件读写操作

Java 对文件进行读写操作的例子很多,让初学者感到十分困惑,我觉得有必要将各种方法进行 一次分析,归类,理清不同方法之间的异同点。 一.在JDK 1.0 中,通常是用InputStream & OutputStream 这两个基类来进行读写操作的。InputStream 中的FileInputStream 类似一个文件句柄,通过它来对文件进行操作,类似的,在 OutputStream 中我们有FileOutputStream 这个对象。 用FileInputStream 来读取数据的常用方法是: FileInputStream fstream = new FileInputStream(args[0]); DataInputStream in = new DataInputStream(fstream); 用in.readLine() 来得到数据,然后用in.close() 关闭输入流。 完整代码见Example 1。 用FileOutputStream 来写入数据的常用方法是: FileOutputStream out out = new FileOutputStream("myfile.txt"); PrintStream p = new PrintStream( out ); 用p.println() 来写入数据,然后用p.close() 关闭输入。 完整代码见Example 2。 二.在JDK 1.1中,支持两个新的对象Reader & Writer,它们只能用来对文本文件进行操作,而 JDK1.1中的InputStream & OutputStream 可以对文本文件或二进制文件进行操作。 用FileReader 来读取文件的常用方法是: FileReader fr = new FileReader("mydata.txt"); BufferedReader br = new BufferedReader(fr); 用br.readLing() 来读出数据,然后用br.close() 关闭缓存,用fr.close() 关闭文件。 完整代码见Example 3。 用FileWriter 来写入文件的常用方法是: FileWriter fw = new FileWriter("mydata.txt"); PrintWriter out = new PrintWriter(fw); 在用out.print 或out.println 来往文件中写入数据,out.print 和out.println的唯一区别是后者写 入数据或会自动开一新行。写完后要记得用out.close() 关闭输出,用fw.close() 关闭文件。完整代码见Example 4。 -------------------------------------------------------------- following is the source code of examples------------------------------------------------------ Example 1:

java分页原理及实现方式

Java分页原理及常用分页方法 什么是分页技术 分页,是一种将所有数据分段展示给用户的技术.用户每次看到的不是全部数据,而是其中的一部分。如果在其中没有找到自习自己想要的内容,用户可以通过制定页码或是翻页的方式转换可见内容,直到找到自己想要的内容为止.其实这和我们阅读书籍很类似,我们不能把整本书的全部内容写在一页纸上。 为什么要分页? 1、加载少量数据,减少客户的和服务器数据交互,降低服务器压力。 2、增强用户体验,每次加载数据量少,加载速度自然就快,用户体验就好。 常见分页样式: 1、传统分页(分页工具栏),如百度的分页: 2、自动加载:如QQ空间下拉自动加载数据

传统分页与下拉式分页对比 传统分页可以明确数据信息,数量等; 下拉式无法明确数据量等信息,分页后之前从信息还在页面上。 常见分页实现方式 1.Java程序分页的实现主要是用List接口中的subList(intstartIndex,intendIndex)方法, 这种方式也称为程序内存分页。 2.使用数据库的SQL语句实现数据分页。适用于数据量较大,访问频度较低的操作。如 果数据量大,访问频度又高,可以参考大数据分页。 关于内存分页 当数据量较小时推荐使用。使用subList进行分页时,如果数据量比较大是一个非常耗费系统资源的方案。 目前web项目有许多分布式系统,可能有多个系统访问同一个数据库,那么对数据库的开销就比较大了,这时可以考虑对内存分页进行优化,例如利用程序缓存处理机制等。 其实真正的内存分页不是那么简单的事情,要实现一个完整的通用的机制,不是一两个小时就能搞定的。首先有一个数据记录的服务器缓存问题,然后才是数据记录分页问题,这个相对好解决一点,但第一个问题就不太好组织。因为缓存问题涉及到数据的缓存位置,缓存时间,删除时间和利于查询的数据组织问题。 数据库分页:

web常用的常用缓存技术有哪些此贴一网打尽

web常用的常用缓存技术有哪些?此贴一网打尽! 1、Opcode缓存 首先php代码被解析为Tokens,然后再编译为Opcode码,最后执行Opcode码,返回结果;所以,对于相同的php文件,第一次运行时 可以缓存其Opcode码,下次再执行这个页面时,直接会去找到缓存下的opcode码,直接执行最后一步,而不再需要中间的步骤了。2、内存式缓存提到这个,可能大家想到的首先就是Memcached;memcached是高性能的分布式内存缓存服务器。 一般的使用目的是,通过缓存数据库查询结果,减少数据库访问次数,以提高动态Web应用的速度、 提高可扩展性。它就是将需要缓存的信息,缓存到系统内存中,需要获取信息时,直接到内存中取;比较常用的方式就是key–>value方式; <?php $memcachehost = '192.168.6.191'; $memcacheport = 11211;

$memcachelife = 60; $memcache = new Memcache; $memcache->connect($memcachehost,$memcacheport) or die ("Could not connect"); $memcache->set('key','缓存的内容'); $get = $memcache->get($key); //获取信息 ?>复制代码3、php APC缓存扩展Php有一个APC 缓存扩展,windows下面为php_apc.dll,需要先加载这个模块,然后是在php.ini里面进行配置: extension=php_apc.dll apc.rfc1867 = on upload_max_filesize = 100M

javajava概要设计

概要设计 1.引言 1.1编写的目的。 本文档的阅读对象为软件开发组成员。 1.2背景 随着信息检索技术的高速发展,做为信息检索代表的搜索引擎被广泛引用,如google,百度等,在中国Internet高速发展过程中,越来越受关注,特别是google,百度在美国上市后,搜索引擎备受关注。 a.系统的名称 简易搜索引擎 c.该系统同其他系统或其他机构的基本的相互来往关系。 Lucene ,apache 1.3定义 spider (基于一个树型spider改写而成) Index (lucene) Search 实现搜索(JSP , lucene ) Analyzer 实现分词(CJKAnalyzer) Eclipse (JDK开发平台(IDE) ) 1.4参考资料 中文分词https://www.doczj.com/doc/229289250.html,/windshow/category/70837.aspx?PageNumber=3 < lucene in action >(index 和search ) < thinking in java >(JNI)< java核心技术第2卷> (JNI) 正则表达式 https://www.doczj.com/doc/229289250.html,/myweb/disp.asp?idd=312&room=10 https://www.doczj.com/doc/229289250.html,/myweb/disp.asp?idd=314&room=10 https://www.doczj.com/doc/229289250.html,/myweb/disp.asp?idd=315&room=10 https://www.doczj.com/doc/229289250.html,/developer/tech/story/0,2000081602,39077620,00.htm https://www.doczj.com/doc/229289250.html,/develop/Read_Article.asp?Id=8254 https://www.doczj.com/doc/229289250.html,/develop/Read_Article.asp?Id=8255 https://www.doczj.com/doc/229289250.html,/develop/Read_Article.asp?Id=17735 https://www.doczj.com/doc/229289250.html,/develop/Read_Article.asp?Id=17739 https://www.doczj.com/doc/229289250.html,/develop/Read_Article.asp?Id=17781 2.总体设计 2.1需求规定

相关主题
相关文档 最新文档