??xml version="1.0" encoding="utf-8" standalone="yes"?> 插gQplug-inQ也UCؓ bundleQ是 Eclipse 的功能块。在 Eclipse 中,所有的一切都有其相应的插Ӟq包括: 事实上,整个 Eclipse IDE 是被构Zؓ一个大的插仉合。其他基?Eclipse 的品,例如 IBM Rational] Software ArchitectQ通过d新插件增Z基本?Eclipse?/p> 一l相关的插gl成Ҏ?/i>。特性和它们的插件存在于 Eclipse E序目录中(在这个例子中QEclipse 被安装在 /opt/eclipse 目录中)。下面是目录布局的一个示例: Eclipse 可以有许多相同的插gQ针Ҏ个不同的版本有一个这L插g。它知道如何解决插g依赖性、避免版本冲H,因此您永q不必担心同时安装两?Subclipse 插g?/p> 在长期?Eclipse 的过E中Q您L会通过下蝲W三Ҏ件或是创建您自己的插件来增加新的功能。跨不同?Eclipse 版本理q些插g可能是个ȝ。因为插件存在于 Eclipse E序目录中,所以如果您安装 Eclipse 的新版本Q它们就会丢失。这意味着如果您有多个 Eclipse 安装Q就必须保存大量插g的多个副本;甚至Q在每次惌升 Eclipse Ӟ您只能很ȝ地全部重新安装?/p> 如果插件存储于 Eclipse E序目录以外的独立位|,当升U到 Eclipse 的新版本Ӟ׃需要重新安装它们,而且Q可以跨多个 Eclipse 版本׃n插g?/p> 有三U方法对插g实施控制。第一U方法是手动创徏一个可以保存插件的目录Q称之ؓ产品扩展Q,插件移到该目录Q然后告?Eclipse 在这里寻扄性和插g?/p> 在我们的例子中,我们会创Z个名?/opt/eclipse-plugins 的位|用来存储插件。ؓ了让 Eclipse 在这里存储插Ӟ您必首先创建如下的目录l构和文Ӟ 注意Q除了创些目录以外,您还必须?eclipse 目录Q在我们的例子中Q是?/opt/eclipse-plugins/eclipseQ中创徏一个名?.eclipseextension 的文件。这个文件让 Eclipse 知道在这里可以找到扩展。它应该有如下内容: .eclipseextension 文g中的 注意Q如果您使用的是 Windows]Q则无法通过 Explorer shell 创徏 .eclipseextension 文g。通过打开 NotePadQ输入文件的内容Qƈ其保存?.eclipseextensionQ确保文件类型选中?“所有文件”,否则 Notepad 会在文件名后添?.txtQ,可以创徏q样的文件?/p> 下一件事是将q个插g位置告诉 EclipseQ以便它知道以后在这里寻找插件。选择 Help > Software Updates > Manager Configuration 得到 Product Configuration ManagerQ在q里完成q项工作?/p> 使用 Product Configuration ManagerQ您可以d新的 Eclipse 扩展。ؓ了启用上面创建的扩展Q?opt/eclipse-pluginsQ,我们需要将它作Z个扩展位|添加。每一个h都已l有一个扩展位|,那就?Eclipse 安装中的插g文g夏V在 Eclipse Platform 上右击,选择 Add > Extension Location 可以添加另一个扩展?/p> 一旦您已经选中了插件所在的目录Q插件就会显C在产品扩展的列表中。在q里Q您可以验插件是否已扑ֈ?/p> Product Configuration 屏幕好的斚w是,您可以很Ҏ地禁用整个插件位|?—?q在q行插g开发和试不同配置时很有用?/p> 实施控制Q方?2 —?通过 Configuration Manager d产品扩展 不必在文件系l中创徏文g夹和 .eclipseextension 文gQ您可以?Eclipse 为您创徏产品扩展?/p> 您可以在 Update ManagerQ?b>Help > Software Updates > Find and InstallQ中创徏新的产品扩展。在安装新的插gӞEclipse 最l会提示您所要安装的位置。在q里Q您可以单击 Change Location 以选择一个品扩展?/p> 选择 Add Location。当您选定一个目录时QEclipse 在那里为您创徏一个品扩展?/p> 当您以后安装插gӞ保它们是被安装到您所惌的插件扩展地点(参见?3 中的 Install Location 区域Q?/p> 实施控制Q方?3 —?创徏理产品扩展?links 文g?/span> 如果在您的文件系l中已经有了产品扩展Q例如我们在 Ҏ 1 中创建的那个Q那么您可以?Eclipse E序目录中创Z些简单的文gQ告?Eclipse 需要检查这些目录以L插g?/p> 首先Q在 Eclipse 安装文g夹(例如 /opt/eclipseQ中创徏一个名?links 的目录。在q个目录中,您可以创?*.link 文gQ例?emfPlugins.linkQ。每一个链接文件指向一个品扩展位|。Eclipse 会在启动时扫描这?links 文g夹,q在每个链接文g中所指向的品扩展中L插g。下面是一个?links 文g夹的 Eclipse 安装布局的例子: 链接文g的内容看上去应该像下面这P /opt/plugins/emf/ 有一?Eclipse 产品扩展的目录结构,?清单 1 所C?/p> q个Ҏ的优势在于,所有的插g位置被作Z个文件夹中的文本文g来存储。这意味着您可以通过单地?links 文g夹复制到新的 Eclipse 安装中,来升U?Eclipse q其指向您的品扩展文件夹。您也可以通过从每?Eclipse 安装建立一个到 links 文g夹的W号链接Q获得一个针Ҏ?Eclipse 安装的公?links 文g夹(如果您的文gpȝ支持W号链接Q?/p> ?Eclipse 中,工作区的概念被简单地描述成可以通过插g讉K的资源的容器。工作区是终端用户和 Eclipse q_之间交互的枢U。终端用戯够在工作Z创徏目q处理其中的内容。工作区本n作ؓ一个目录存在于文gpȝ中,q且只局限于每个 Eclipse 实例使用一个。工作区q包含一?.metadata 目录Q用来持久存储诸如插件状态这LU有信息?/p> 单的{案是ؓ了性能。工作区中的目多Q达到开发系l所能处理项目的临界点的Zp大。ؓ了解册个问题,您可以通过 您也可以通过?Eclipse 中选择 File > Switch Workspace 切换工作区,而不必重新启?Eclipse?/p> q有一U可能的情况是,您有一?“研I?工作区。在q个工作ZQ您需要?Open TypeQ?b>Ctrl+Shift+TQ等?Eclipse 对蝲入的大代码库的代码仔l搜M遍。如果您试图学习一些例子,或者您曄想知道一个开放源码项目是如何处理特定问题的,那么q种Ҏ是极其有用的?/p> 有多个工作区的不利方面在于需要在它们之间׃n开发首选项。因为首选项被持久存储在 Eclipse 中的一个工作区中,所以您必须导出工作区的首选项q将它们导入您所要求的工作区中(File > Export > PreferencesQ?/p> 如果您用多个基?Eclipse 的品,必焉要多?Eclipse 安装。例如,如果您用基本的 Eclipse V3.1 来完成日常的 Java?语言~程Qƈ使用带有 WebTool ?Eclipse 来编?IBM WebSphere] 应用E序Q那么您有两个完全独立?Eclipse 安装。在q些Z Eclipse 的品之间共享插件和工作区可以节U时_q免一些升U带来的ȝ?/p> 您在开?Eclipse 的插件时也需要多?Eclipse 安装。当有了多个 Eclipse 安装Ӟ您可以跨不同?Eclipse 版本试您的插g的功能。您也可以将一l不同的插g对应不同?Eclipse 安装Q以便跨多个环境配置试您的插g?/p> 注意Q通过?Eclipse 中选择 Help > Software Updates > Manage ConfigurationQ来考察 Eclipse IDEQ它启用和禁用属于这些特性的插gQ中的特性,可以理哪些插g?Eclipse 使用。在开发自q插gӞ您也可以通过 Run Configuration Manager 来管理运?Eclipse 试实例时哪些插件被启用。我们通常的经验是Q用多?Eclipse 安装是管理多?Eclipse 版本和配|最方便且最便于重用的方法,对于试目的其如此?/p> Eclipse 安装独立存在于它们自q文g夹中。要使得多个安装q存Q只要下载您所要的 Eclipse 产品和版本ƈ其解压到它们自q目录中即可。下面是一个用来跨不同 Eclipse 版本试插g的示例布局Q?/p> 对于节约所有当前安装的插g安装旉和避免工作区重复Q尽可能地跨 Eclipse 安装q行׃n是一个好L。正如我们前面所讲述的,您可以共享以下内容: 注意Q跨 Eclipse 安装׃n工作区和首选项可能会有问题Q尤其是?Eclipse 版本的主~号不同Ӟ例如 3.1 ?3.2Q?/p> 我们的目的有两个Q初步介l?Eclipse 的基本工作要素,比如插g、项目和工作区;告诉您管理多?Eclipse 环境的好处以及一些不利方面。我们希望您能够接受q些知识q将其应用到您的实践中以节约 Eclipse l护的时间?br /> ҎҎQ?Xms256m -Xmx256m -XX:MaxNewSize=256m -XX:MaxPermSize=256m 我将? 本文展示了一个通用?
计划单次d
惛_一个煮蛋计时器Q在数分钟之后(q时蛋煮好了Q它会发出声x醒您。清?1 中的代码构成了一个简单的煮蛋计时器的基本l构Q它?Java 语言~写Q?/p>
清单 1. EggTimer c?/b>
注意q段代码与煮蛋计时器应用E序非常怼?code>Scheduler Q而不?
实现计划框架
清单 6 昄? 像煮蛋计时器, cM?
取消d
W三U方式是通过调用?
扩展 cron 实用E序
不过Q计划框架比
有许多计划是 因ؓ 对于 对于创徏大量对象的大型应用程序,JVM 花在垃圾攉QGCQ上的时间会非常多。默认情况下Q进?GC Ӟ整个应用E序都必ȝ待它完成Q这可能要有几秒钟甚x长的旉Q?code>-verbose:gc
我被计划C么时候?
下蝲本文中用的 源代?/u>?br /> 什么是DOM? DOM 可以让你以分层次对象模型来访问储存在XML文档中的信息。DOM生成一节Ҏ(以XML文档的结构和信息为基)你可以通过q棵树来讉K你的信息。在XML文档中的文本信息转变成一l树的节炏V?br />
不管你的XML文档中的信息的类型?不管是表格数?或是一列items,或者只是文?, DOM在你创徏一个XML文档的文档对象时创徏一节?
树。 DOM你用树状模?像 Swing TreeModel)去访问你的XML文档中的信息。这U模式确实不错因为XML原本是分层ơ的?
q也是DOMZ么可以把你的信息攑ֈ一|中的原因(即信息是表格式的或者简单的列表????q里不知道该怎么d文是Q?
even if the information is actually tabular or a simple list??????)?/p>
因ؓ在DOM?每一个元素节点实际上都有一pd的其他节点作为它的孩子。这些孩子节点可以包含文本值或者是其他元素节点。乍看v来,通过遍历讉K一个元
素的所有孩子节Ҏ讉Kq个节点的值是没有必要?举例来说:节点 "<name> Nazmul </name>",
Nazmul是?。如果每个元素只有值的话,q确实是没有必要的。但是,元素可能含有文本数据或者其他元?q是你要在DOM中做额外的工作来获取?
素节点值的原因。 通常当你的文档中只有U数据时,把所有的数据压成一个“块“放到字串中q让DOM把那个字串当成某个特定元素节点的D回是适当的。这
U方式ƈ不适合如果在你的XML文档中的数据是个文档Q比如像WORD文档或者FRAMEMAKER文档Q 在文档中,元素的顺序是非常重要的。对于纯?
?像一个数据库?元素的顺序是不要紧的。 之所以DOM保持从XML文档中读出的元素的顺序,因ؓ它把所有的事物都当成文档来处理。 文档对像模型的
叫法由此而来?/p>
如果你计划用DOM做ؓJAVA对象模型用于你存储在XML文档中的信息Q那么你不需要考虑SAX。可是如果你发现DOM不是一个可以用于处理XML文档
信息的好的对象模式,那么你可能想看看SAX了。在一些必M用自定义对象模型的案例中使用SAX是非常普遍的。说一句让事情看来有些p涂的话Q你也可?
在DOM的基之上创徏自己的对象模式。面向对象真是个好东东?/p> 什么是SAX? SAX让你讉K储存在XML文档中的信息Q不是通过节点树,而是一pd的事件。你会问Q这有什么益处?回答是,SAX选择不在XML文档上创建JAVA对象模型(像DOM做的那样)。 这样得SAX更快, 同时使下面所q成为必? 创立你自q自定义对像模?br /> 创徏一个监听SAX事g的类同时创徏你自q对象模型
在用DOM的情况下,解析器做了绝大多C? dXML文档, 在这基础之上创徏JAVA对象模型Q然后给你一个对q个对象的引?一?
Document对象)Q因而你可以操作使用它。SAX被叫做Simple API for XML不是没有原因? 她真的很单。 SAX没有期待
解析器去做这么多工作Q所有SAX 要求的是解析器应该读入XML文档,同时Ҏ所遇到的XML文档的标{֏Zpd事g。你要自己写一个XML文档处理
器类QXML document handler classQ来处理q些事g,q意味着使所有标{事件有意义q有用你自己的对象模型创建对象。所以你?
完成: 控制所有XML文档信息的自定义对象模型Q或者源文档在这里的写法从来没有见过Q或者怀疑源文档在这里有排版错误Q先q么MQ?br /> 一个监听SAX事g(事g由SAX解析器读取你的XML文档时?的文档处理器Q还有解释这些事件创Z自定义对象模型中的对?br /> 如果你的对象模型单的话那么SAX在运行时会非常快。在q种情况下,它会比DOM?因ؓ它忽略了Z的信息创Z个树形对象模型的q程。从另一斚w来说Q你必须写一个SAX 文档处理器来解释所有的SAX事g(q会是一件很J重的工??/p>
什么类型的SAX事g被SAX解析器抛Z? q些事g实际上是非常单的。SAX会对每一个开始标{抛Z?Ҏ一个结束标{也是如此。它?
#PCDATA和 CDATA 部分同样抛出事g。你的文档处理器 (对这些事件的监听?要解释这些事件同时还要在他们基础之上创徏你自定义的对象模
型。 你的文档处理器必须对这些事件做释,同时q些事g发生的顺序是非常重要的。SAX同时也对processing instructions,
DTDs, comments, 抛出事g. 但是它们在概念上是一L, 你的解析器要解释q些事g(q有q些事g的发生顺?以及使他们有意义?/p> 什么时候用DOM
如果你的XML文档包含文档数据(例如, Framemaker documents stored in XML format), 那么DOM是?
的解x案的最自然选择。如果你要创Z些类g文档信息理的系l,那么你不得不处理大量的文档数据。Datachannel RIO 产品是q么一
个例?它可以烦引和l织各种cd文档资源中的信息(例如Word和Excel 文g)。在q种情况下,DOM是非常合适程序去讉K存贮在这些文档中的信
息的?/p> 然?如果你主要处理的是结构化的数?在XML中的序列化的JAVA对象the equivalent of serialized Java objects in XML)QDOM不是最好的选择。那是SAX会比较合适的地方?/p> 什么时候用SAX 如果在你XML文档中的信息是机器易ȝ(和机器生成的)数据Q那么SAX是让你可以访问这些信息的合适的API。机器易d生成的数据类型包含像下面q些东东: 存成XML格式的Java对象属?br /> 用一些以文本为基的查询语?SQL, XQL, OQL)表示的查?br /> 由查询生成的l果?q也许包含关pd数据库表中的数据~码成XML).
当你的数据是q种样式Q你要创Z自己的数据结构和c(对象模型Q来理操作以及持箋保存q些数据。SAX容许你快速创Z个可以生成你的对象模型实例的
处理器类。一个实例是Q一个SAX文档处理器。它完成的工作有d包含我的地址薄信息的XML文档Q创Z个可以访问到q些信息的AddressBook
cRSAX指南告诉你该怎么做到q些。这个地址薄XML文档包含person元素Qperson元素中有name和email元素。我?
AddressBook对象模型包括下面的类Q?/p> AddressBook c?Person对象的容?br /> Person c?String 型的name和email的容?br /> q样我的“SAX 地址文档处理器”可以把person元素转变成Person对象了,然后把它们都存入AddressBook对象。这个文档处理器name和email元素转变为String对象?/p> --------------------------------------------------------------------------------
1、从一个xml文g中蝲入一个Dom到内存:
FileInputStream in = new FileInputStream(new File(fileName));
SAXReader reader = new SAXReader();
doc = reader.read(in);
2、把Dom中的数据写入到xml文g?br /> 使用Dom4jQ要把一个Dom中的数据写入到文仉常简单,API如下Q?br /> public void write(Writer writer) throws IOExceptionQ?br /> 因此Q假如我们要把一个Document写入到c:\test.xml文g中,可以单的使用下面的代码即可:
java.io.Writer wr= new java.io.FileWrite(filename);
doc.write(wr);
wr.close();//注意Q必要执行close()ҎQ才会实现真正的写入
q种用法也是Dom4j所推荐我们使用的非常简单的Ҏ。然而,当我们的dom中包含有中文字符数据的时候,q种Ҏ写入的xml文档却无法直觉打开。会提示cM如下的错误:
org.dom4j.DocumentException: invalid byte 1 of 1-byte UTF-8 sequence (0xb2) Nested exception: invalid byte 1 of 1-byte UTF-8 sequence (0xb2)
at org.dom4j.io.SAXReader.read(SAXReader.java:484)
at org.dom4j.io.SAXReader.read(SAXReader.java:343)
at
我们可以看生成的xml文g~码Q内Ҏutf-8的,但文件格式确是ANSI的,如下图所C:
原因分析Q?br /> ׃FileWriter默认的输出编码是ANSI~码Q而Dom4j中的wirteҎ提供的内容实际是以UTF-8保存的,因此造成了包括中文字W的XML文g无法正常阅读?br />
解决ҎQ?br /> 不能使用单的FileWriterQ而应该是使用一个能指定具体输出~码的WriterQ在JDK的io包中Q OutputStreamWriter可以指定输出~码?br /> 正确的代码如下:
java.io.OutputStream out=new java.io.FileOutputStream(fileName);
java.io.Writer wr=new java.io.OutputStreamWriter(out,"UTF-8");
doc.write(wr);
wr.close();
out.close();
化一下可以写成下面的样式Q?br /> java.io.Writer wr=new java.io.OutputStreamWriter(new java.io.FileOutputStream(fileName),"UTF-8");
doc.write(wr);
wr.close();
结Q?br /> ׃大多CU的基性开源项目都是老外开发,他们不大可能在中文^Cq行试Q用例数据也很少会用中文^収ͼ因此Q我们即使按照这些开源项目的通用说明文档及用h南去操作Q也会出现很多不可预知的错误。这也是Z么本参与l徏开源团队EasyJFQ提倡搞国开源,q开发一些基性的开源框架如EasyJWeb、EasyDBO的一个初街?br /> 当然Q这里提出的中文问题Q算是一个还“没来得及商量”以及要通过一些罕见的处理才能正确q行的中文问题。因此,同样归ƈC“中文问题没商量”系列中?br />
http://blog.lupaworld.com/blog/htm/do_showone/tid_2261.html
]]>
清单 1. Eclipse Ҏ和插g目录l构
/opt/eclipse/
features/
org.eclipse.jdt_3.1.1/
feature.xml
...
plugins/
org.eclipse.jdt.ui_3.1.1.jar
...
清单 2. Eclipse 产品扩展目录l构
/opt/eclipse-plugins/
eclipse/
.eclipseextension
features/
plugins/
id=org.eclipse.platform name=Eclipse Platform
version=3.1.1
version
属性应该设|ؓ使用q个产品扩展?Eclipse 的版本。该属性可以是特定的(3.1.1Q、比较一般的Q?.0.0Q或者非怸般的Q?.0.0Q。在撰写本文Ӟ版本号似乎对产品扩展的功能ƈ没有M影响?/p>
?1. d扩展位置
?2. 查看一个扩展位|中的插?/b>
?3. 选择插g的安装位|?/b>
?4. 通过 Update Manager 创徏一个新的品扩?/b>
清单 3. 使用 links 文g夹的 Eclipse 安装布局
/opt/eclipse/
links/
emfPlugins.link
webtools.link
updateManager.link
...
...
path=/opt/plugins/emf/
Windows
在本文中Q我们着重介l?Eclipse ?Linux] 安装。所有提供的CZ清单对于 Windows 都是有效的。您仅仅需要将路径替换为相应的 windows 路径。另外请注意Q在 Windows 中,路径中需要用双反斜杠(例如 path=c:\\plugins\\emfQ?回页?/b> -data
参数划分 Eclipse 工作区,q个参数被传递给 Eclipse 可执行文Ӟ例如 /opt/eclipse/eclipseQ:
清单 4. 指定不同的工作区
/opt/eclipse-3.1/eclipse -data /opt/workspaces/web
/opt/eclipse-3.2M2/eclipse -data /opt/workspaces/web
/opt/eclipse-3.2M2/eclipse -data /opt/workspaces/dev -vmargs -Xmx512m
工作区提C?/b>
您可以通过?Eclipse 可执行文件传?-showlocation
参数来显C工作区位置。此外,您还可以通过 -vmargs -Xms
?Xmx
参数Z同的工作区指定不同的性能特征?回页?/b>
/opt/eclipse-3.0
/opt/eclipse-3.1
/opt/eclipse-3.2-m1
回页?/b>
转自Q?a >http://www-128.ibm.com/developerworks/cn/opensource/os-ecl-manage/
]]>
W一ơP代:掌握字符集方面的基本概念?/b>
有些朋友可能会认是多此一举,但实际上正是׃对相兛_本概忉|握不清,才导致了诸多问题和疑问?br />首先是字W集的概c?br />我们知道Q电子计机最初是用来q行U学计算的(所以叫做“计机”)Q但随着技术的发展Q还需要计机q行其它斚w的应用处理。这p求计机不仅能处理数|q能处理诸如文字、特D符L其它信息Q而计机本n能直接处理的只有数g息,所以就要求对这些文字、符号信息进行数值编码,最初的字符集是我们都非常熟悉的ASCIIQ它是用7个二q制位来表示128个字W,而后来随着不同国家、组l的需要,出现了许许多多的字符集,如表CƧ字W的 ISO8859pd的字W集Q表C汉字的GB2312-80、GBK{字W集?br />字符?/b>的实质就是对一l特定的W号Q分别赋予不同的数值编码,以便于计机的处理?br />字符集之间的转换?/b>字符集多了,׃带来一个问题,比如一个字W,在某一字符集中被编码ؓ一个数|而在另一个字W集中被~码为另一个数|比如我来创造两个字W集demo_charset1与demo_charset2Q在demo_charset1中,我规定了三个W号的编码ؓQA Q?001Q,BQ?010Q,Q(1111Q;而在demo_charset2中,我也规定了三个符L~码为:AQ?001Q,CQ?011Q,Q(1111Q,q时我接C个Q务,要编写一个程序,负责在demo_charset1与demo_charset2之间q行转换。由于知道两个字W集的编码规则,对于demo_charset1中的0001Q在转换为demo_charset2Ӟ要将其编码改?001Q对?demo_charset1中的1111Q{换ؓdemo_charset2Ӟ其数g变;而对于demo_charset1中的0010Q其对应的字WؓBQ但在demo_charset2没有对应的字W,所以从理论上无法{换,对于所有这cL法{换的情况Q我们可以将它们l一转换为目标字W集中的一个特D字W(UCؓ“替换字W”)Q比如在q里我们可以?作ؓ替换字符Q所以Bp{换ؓ了?Q出C信息的丢失;同样道理Q将demo_charset2 的C字符转换到demo_charset1Ӟ也会出现信息丢失?br />所以说Q在字符集{换过E中Q如果源字符集中的某个字W在目标字符集中没有定义Q将会出C息丢失?br />数据库字W集的选择?/b>
我们在创建数据库Ӟ需要考虑的一个问题就是选择什么字W集与国家字W集Q通过create database中的CHARACTER SET与NATIONAL CHARACTER SET子句指定Q。考虑q个问题Q我们必要清楚数据库中都需要存储什么数据,如果只需要存储英文信息,那么选择US7ASCII作ؓ字符集就可以Q但是如果要存储中文Q那么我们就需要选择能够支持中文的字W集Q如ZHS16GBKQ;如果需要存储多国语a文字Q那p选择UTF8了?br />数据库字W集的确定,实际上说明这个数据库所能处理的字符的集合及其编码方式,׃字符集选定后再q行更改会有诸多的限Ӟ所以在数据库创建时一定要考虑清楚后再选择?br />而我们许多朋友在创徏数据库时Q不考虑清楚Q往往选择一个默认的字符集,如WE8ISO8859P1或US7ASCIIQ而这两个字符集都没有汉字~码Q所?b>用这U字W集存储汉字信息从原则上说就是错误的?/b>虽然在有些时候选用q种字符集好象也能正怋用,但它会给数据库的使用与维护带来一pd的麻烦,在后面的q代q程中我们将深入分析?br />客户端的字符集?/b>
有过一些Oracle使用l验的朋友,大多会知道通过NLS_LANG来设|客L的情况,NLS_LANG׃下部分组成:NLS_LANG=< Language>_<Territory>.<Clients Characterset>Q其中第三部?lt;Clients Characterset>的本意就是用来指明客L操作pȝ~省使用的字W集。所以按正规的用法,NLS_LANG应该按照客户端机器的实际情况q行配置Q尤其对于字W集一Ҏ是如此,q样Oraclep够在最大程度上实现数据库字W集与客L字符集的自动转换Q当然是如果需要{换的话)?br />ȝ一下第一ơP代的重点Q?/b>
字符集:特定的W号集编码ؓ计算够处理的数|
字符集间的{换:对于在源字符集与目标字符集都存在的符P理论上{换将不会产生信息丢失Q而对于在源字W集中存在而在目标字符集中不存在的W号Q理Z转换会产生信息丢失Q?br />数据库字W集Q?/b>选择能够包含所有将要存储的信息W号的字W集Q?br />客户端字W集讄Q?/b>指明客户端操作系l缺省用的字符集?br />
具体看:http://www.itpub.net/276524,1.html
]]>
1、原因分?/strong>
通过对用户反映情늚分析Q发现字W集的设|不当是影响ORACLE数据库汉字显C的关键问题。那么字W集是怎么一会事呢?字符集是ORACLE 为适应不同语言文字昄而设定的。用于汉字显C的字符集主要有ZHS16CGB231280QUS7ASCIIQWE8ISO8859P1{。字W集不仅需在服务器端存在,而且客户端也必须有字W集注册。服务器端,字符集是在安装ORACLE时指定的Q字W集登记信息存储在ORACLE数据库字典的V$ NLS_PARAMETERS表中Q客LQ字W集分两U情况,一U情冉|sql*net 2.0以下版本Q字W集是在windows的系l目录下的oracle.ini文g中登记的Q另一U情冉|sql*net 2.0以上Q即32位)版本Q字W集是在windows的系l注册表中登记的。要在客L正确昄ORACLE 数据库汉字信息,首先必须使服务器端的字符集与客户端的字符集一_其次是加载到ORACLE数据库的数据字符集必M服务器指定字W集一致。因此,把用户存在的问题归纳分类Q生汉字显C异常的原因大致有以下几U:
1. 1服务器指定字W集与客户字W集不同Q而与加蝲数据字符集一致?
q种情况是最常见的,只要把客L的字W集讄正确卛_Q解军_法见2.1?
1. 2服务器指定字W集与客户字W集相同,与加载数据字W集不一致?
q类问题一般发生在ORACLE版本升或重新安装系l时选择了与原来服务器端不同的字W集Q而恢复加载的备䆾数据仍是按原字符集卸出的场合,以及加蝲从其它用不同字W集的ORACLE数据库卸出的数据的情c这两种情况中,不管服务器端和客L字符集是否一致都无法昄汉字。解军_法见2.2?
1.3服务器指定字W集与客户字W集不同,与输入数据字W集不一致?
q种情况是在客户端与服务器端字符集不一致时Q从客户端输入了汉字信息。输入的q些信息即便是把客户端字W集更改正确Q也无法昄汉字。解军_法见2.3?
2Q解军_?/strong>
下面分别对上述三种情况l出解决办法。ؓ了叙q方便,假设客户端用WINDOWS95/98环境Qƈ已成功地配置了TCP/IP协议Q安装了ORACLE的sql*netQsql*pluse产品?
2.1 讄客户端字W集与服务器端字W集一?
假设当前服务器端使用US7ASCII字符集?
Q?Q查看服务器端字W集
通过客户端或服务器端的sql*plusdORACLE的一个合法用P执行下列SQL语句Q?
SQL > select * from V$NLS_PARAMETERS
parameter value
NLS_LANGUAGE AMERICAN
NLS_TERRITORY AMERICA
? ?
NLS_CHARACTERSET US7ASCII
NLS_SORT BINARY
NLS_NCHAR_CHARACTERSET US7ASCII
从上q列表信息中可看出服务器端ORACLE数据库的字符集ؓ'US7ASCII'?
Q?Q按照服务器端字W集对客Lq行配置
配置Ҏ有两U:
安装ORACLE的客L软g时指?
在安装ORACLE的客L产品软gӞ选择与ORACLE服务端一致的字符集(本例为US7ASCIIQ即可?
修改注册信息的方?
ҎORACLE 客户端所选sql*net 的版本分Z列两U情况:
a. 客户端ؓ sql*net 2.0 以下版本
q入Windows的系l目录,~辑oracle.ini文gQ用US7ASCII替换原字W集Q重新启动计机Q设|生效?
b. 客户端ؓ sql*net 2.0 以上版本
在WIN98 ?q?行REGEDIT,W一步选HKEY_LOCAL_MACHINE,W二步选择SOFTWAREQ?W三步选择 ORACLEQ?W四步选择 NLS_LANGQ???与服 ???????W?集(本例为:AMERICAN_AMERICAN.US7ASCIIQ?
2.2 强制加蝲数据字符集与服务器端字符集一?
假设要加载数据从原ORACLE数据库卸出时的字W集为US7ASCIIQ当前ORACLE服务器字W集为WE8ISO8859P1。?br />
有过一些Oracle使用l验的朋友,大多会知道通过NLS_LANG来设|客L的情况,NLS_LANG׃下部分组成:NLS_LANG=< Language>_<Territory>.<Clients Characterset>Q其中第三部?lt;Clients Characterset>的本意就是用来指明客L操作pȝ~省使用的字W集。所以按正规的用法,NLS_LANG应该按照客户端机器的实际情况q行配置Q尤其对于字W集一Ҏ是如此,q样Oraclep够在最大程度上实现数据库字W集与客L字符集的自动转换Q当然是如果需要{换的话)?/font>
下面提供三种解决ҎQ?
Q?Q?服务器端重新安装ORACLE
在重新安装ORACLE 旉择与原卸出数据一致的字符集(本例为US7ASCIIQ?
加蝲原卸出的数据?
q种情况仅仅使用于空库和h同一U字W集的数据?
Q?Q强行修Ҏ务器端ORACLE当前字符?
在用imp命o加蝲数据前,先在客户端用sql*plusdsystem DBA用户Q执行下列SQL语句q行当前ORACLE数据库字W集修改Q?
SQL > create database character set US7ASCII
* create database character set US7ASCII
ERROR at line 1:
ORA-01031: insufficient privileges
你会发现语句执行q程中,出现上述错误提示信息Q此时不用理会,实际上ORACLE数据库的字符集已被强行修改ؓUS7ASCIIQ接着用imp命o装蝲数据。等数据装蝲完成以后Qshutdown 数据库,再startup 数据库,用合法用L录ORACLE数据库,在sql>命o提示W下Q运行select * from V$NLS_PARAMETERSQ可以看到ORACLE数据库字W集已复原,q时再查看有汉字字符数据的表Ӟ汉字已能被正显C?
Q?Q利用数据格式{储,避开字符集限?
q种Ҏ主要用于加蝲外来ORACLE数据库的不同字符集数据。其Ҏ如下Q?
先将数据加蝲到具有相同字W集的服务器上,然后用{换工具卸Zؓfoxbase 格式或access格式数据库,再用转换工具转入C同字W集的ORACLE数据库中Q这样就避免了ORACLE字符集的困扰。目前数据库格式转换的工具很?象power builder5.0以上版本提供的pipelineQMicrosoft Access数据库提供的数据导入/导出功能{。{换方法参见有兌料说明?
2.3匚w字符集替换汉?
对于1.3提到的情况,没有很好的办法,只能先把客户端与服务器端字符集匹配一致后Q根据原输入汉字的特征码替换汉字字符部分?/font>
]]>
看看占用0.0.0:80端口的PID是多?br />
然后在“Q务管理器”中查到与该PID对应的程序?br />
如果d理器的q程中看不到PID栏,则在d理器的菜单〖查看〗〖选择列〗中选择一?br />-----------------------------------------------------------------------------------------------------
好东西呀。。。?br />netstat q个命o太有用了?img src ="http://www.aygfsteel.com/Duffblog/aggbug/75703.html" width = "1" height = "1" />
]]>
我已l试q了Qok?/p>
以下论坛排名不分先后Q还有许多业界知名的论坛Q主要有点偏门,q个不做概述Q呵c?
IT技术开发综合类
http://community.csdn.net/
适合人群Q只适合软g开发?
技术开发最全面的论坛,里面可以遇到很多牛hQ版面也很全Q什么J2EEQ?NET啊,该有的全上,在这里基本上可以提出M问题Qh气也是最旺的Q不q一般提出的意见都有正方两面的,所以最l解决问题,q是靠自己?
评hQ专业,很牛|是速度慢?
www.itpub.net
适合人群Q数据库开发h?
数据库方面是非常著名的,牛h不少Q不q,现在比较杂,什么都做,|络Q操作系l,行业应用Q到体育贴图Q当然有些也不错Qh气非帔RQ特别是灌水斚wQ^_*.
评hQ强Q速度一般;
http://bbs.chinaunix.net/forum/
适合人员Q系l工E师
q里的特色就是操作系l方面在业界是最著名的,牛h不少Q目前,在数据库Q网l方面也颇有建树Q当然灌水方面也不赖Q呵呵,属于温柔?
评hQ强Q速度q可?
bbs.chinajavaworld.com/
适合人员QJAVA开?
JAVA斚w非常l合的论坛了Q牛Z很多Q是一个难得的JAVA论坛Q涉及你惌的关于JAVA目前M技术?
评论Q强Q速度q可以?
http://www.huihoo.com/forum/
适合人员Q中间g开发?
人气不错Q版面风格独特,在开源,中间Ӟ工作方面非怸错,问题讨论都非常深刅R也很专业?
评hQ很好,速度一般;
IT售前技术顾问综合类
http://www.sysvs.com/bbs
适合人员QIT售前及技术顾?
业界知名的售前技术顾问论坛,比较新异的知识点Q各个IT行业版快划分也比较好Q也非常专业Q绝Ҏ我稀饭(喜欢Q的风格Q网站风g内罕见,也有很多专业文章Q没有地方灌_厉害?
评hQ很好,速度比较?
|络工程c?
www.1000bbs.com
适合人员Q布U?|络工程?
人气很旺Q特色是版面比较紧凑Q综合布U这一块很权威Q很H很专,旉非常久了Q颜色比较明快,是太低端了Q?
评hQ不错,速度一?
http://www.sharecenter.net/
适合人员Q网l工E师
之所以我喜欢是这个网站很多做CISCO工程都知道,也是别h介绍我去的,旉非常久了Q颜色比较暗谈,属于忧郁型?
评hQ不错,速度也还可以
IT营销理c?
http://www.topren.net/forum/index.php
适合人员Q企业策划,CIO
业界知名的知识站点“唐人社区”,信息化管理顾问可以去看看Qh也很多,可惜Q都是下载,实质性内定w要改观,我记得是非常专业的网站?
评hQ不错,速度也还可以?
IT理l合c?
http://club.amteam.org/
适合人群Q大多数Q?
评论cL较多Q基本上在其他媒体上看到的评论,q里都会有,要想了解IT发展的情况,来q里看看?
评hQ很好,休闲工作都可以看?
http://dev.csdn.net/article/72/72374.shtm
]]>所有类型的 Java 应用E序一般都需要计划重复执行的d。企业应用程序需要计划每日的日志或者晚间批处理q程。一?J2SE 或?J2ME 日历应用E序需要根据用LU定计划闚w旉。不q,标准的调度类
TimerTask
没有_的灵zL,无法支持通常需要的计划dcd。在本文中,Java 开发h?Tom White 向您展示了如何构Z个简单通用的计划框Ӟ以用于执行Q意复杂的计划d?/blockquote>
java.util.TimerTask
l称?Java 计时器框?/i>Q它们ɽE序员可以很Ҏ地计划简单的dQ注意这些类也可用于 J2ME 中)。在 Java 2 SDK, Standard Edition, Version 1.3 中引入这个框架之前,开发h员必ȝ写自q调度E序Q这需要花费很大精力来处理U程和复杂的 Timer
来计划,因ؓ在夏令时开始和l束时会出现旉跌?TimerTask
计划框架Q从而允许更灉|的计划Q务。这个框枉常简?—?它包括两个类和一个接?—?q且Ҏ掌握。如果您习惯于?Java 定时器框Ӟ那么您应该可以很快地掌握q个计划框架?/p>
计划框架建立?Java 定时器框架类的基之上。因此,在解释如何用计划框架以及如何实现它之前Q我们将首先看看如何用这些类q行计划?/p>
package org.tiling.scheduling.examples;
import java.util.Timer;
import java.util.TimerTask;
public class EggTimer {
private final Timer timer = new Timer();
private final int minutes;
public EggTimer(int minutes) {
this.minutes = minutes;
}
public void start() {
timer.schedule(new TimerTask() {
public void run() {
playSound();
timer.cancel();
}
private void playSound() {
System.out.println("Your egg is ready!");
// Start a new thread to play a sound...
}
}, minutes * 60 * 1000);
}
public static void main(String[] args) {
EggTimer eggTimer = new EggTimer(2);
eggTimer.start();
}
}
Timer
实例Q用于提供必要的计划。用 TimerTask
Q在指定的分钟数之后执行。时间到了,TimerTask
?
计划重复执行的Q?/span>
实现Q?/p>
清单 2. AlarmClock c?/b>
通过指定一个固定的执行频率或者固定的执行旉间隔Q?code>AlarmClock
package org.tiling.scheduling.examples;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.tiling.scheduling.Scheduler;
import org.tiling.scheduling.SchedulerTask;
import org.tiling.scheduling.examples.iterators.DailyIterator;
public class AlarmClock {
private final Scheduler scheduler = new Scheduler();
private final SimpleDateFormat dateFormat =
new SimpleDateFormat("dd MMM yyyy HH:mm:ss.SSS");
private final int hourOfDay, minute, second;
public AlarmClock(int hourOfDay, int minute, int second) {
this.hourOfDay = hourOfDay;
this.minute = minute;
this.second = second;
}
public void start() {
scheduler.schedule(new SchedulerTask() {
public void run() {
soundAlarm();
}
private void soundAlarm() {
System.out.println("Wake up! " +
"It's " + dateFormat.format(new Date()));
// Start a new thread to sound an alarm...
}
}, new DailyIterator(hourOfDay, minute, second));
}
public static void main(String[] args) {
AlarmClock alarmClock = new AlarmClock(7, 0, 0);
alarmClock.start();
}
}
SchedulerTask
Q而不?DailyIterator
cLq其计划。在q里Q它只是计划d在每天上?7:00 执行。下面是一个正常运行情况下的输出:
Wake up! It's 24 Aug 2003 07:00:00.023
Wake up! It's 25 Aug 2003 07:00:00.001
Wake up! It's 26 Aug 2003 07:00:00.058
Wake up! It's 27 Aug 2003 07:00:00.015
Wake up! It's 28 Aug 2003 07:00:00.002
...
ScheduleIterator
Q这是一个将java.util.Date
对象的接口。然?Date
对象。返回?ScheduleIterator
接口Q?/p>
清单 3. ScheduleIterator 接口
package org.tiling.scheduling;
import java.util.Date;
public interface ScheduleIterator {
public Date next();
}
next()
Ҏq回表示每天同一旉Q上?7:00Q的 next()
c调?next()
会返回后一天的 7:00 AMQ如此重复。ؓ了实现这U行为,java.util.Calendar
实例。构造函C在日历中加上一天,Ҏ历的q种讄使得W一ơ调?Date
。注意代码没有明地提到夏o时修正,因ؓ GregorianCalendar
Q负责对此进行处理,所以不需要这样做?/p>
清单 4. DailyIterator c?/b>
package org.tiling.scheduling.examples.iterators;
import org.tiling.scheduling.ScheduleIterator;
import java.util.Calendar;
import java.util.Date;
/**
* A DailyIterator class returns a sequence of dates on subsequent days
* representing the same time each day.
*/
public class DailyIterator implements ScheduleIterator {
private final int hourOfDay, minute, second;
private final Calendar calendar = Calendar.getInstance();
public DailyIterator(int hourOfDay, int minute, int second) {
this(hourOfDay, minute, second, new Date());
}
public DailyIterator(int hourOfDay, int minute, int second, Date date) {
this.hourOfDay = hourOfDay;
this.minute = minute;
this.second = second;
calendar.setTime(date);
calendar.set(Calendar.HOUR_OF_DAY, hourOfDay);
calendar.set(Calendar.MINUTE, minute);
calendar.set(Calendar.SECOND, second);
calendar.set(Calendar.MILLISECOND, 0);
if (!calendar.getTime().before(date)) {
calendar.add(Calendar.DATE, -1);
}
}
public Date next() {
calendar.add(Calendar.DATE, 1);
return calendar.getTime();
}
}
在上一节,我们学习了如何用计划框Ӟq将它与 Java 定时器框架进行了比较。下面,我将向您展示如何实现q个框架。除?清单 3 中展C的 Scheduler
?Timer
?
清单 5. Scheduler
导致向控制台报告每一?GC 事gQ。要这些由 GC 引v的暂停(q可能会影响快速Q务的执行Q降x,应该应用程序创建的对象的数目降x低。同P在单独的 JVM 中运行计划代码是有帮助的。同Ӟ可以试用几个微调选项以尽可能地减?GC 暂停。例如,增量 GC 会尽量将L集的代h分散到几个小的收集上。当然这会降?GC 的效率,但是q可能是旉计划的一个可接受的代仗?/p>
package org.tiling.scheduling;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
public class Scheduler {
class SchedulerTimerTask extends TimerTask {
private SchedulerTask schedulerTask;
private ScheduleIterator iterator;
public SchedulerTimerTask(SchedulerTask schedulerTask,
ScheduleIterator iterator) {
this.schedulerTask = schedulerTask;
this.iterator = iterator;
}
public void run() {
schedulerTask.run();
reschedule(schedulerTask, iterator);
}
}
private final Timer timer = new Timer();
public Scheduler() {
}
public void cancel() {
timer.cancel();
}
public void schedule(SchedulerTask schedulerTask,
ScheduleIterator iterator) {
Date time = iterator.next();
if (time == null) {
schedulerTask.cancel();
} else {
synchronized(schedulerTask.lock) {
if (schedulerTask.state != SchedulerTask.VIRGIN) {
throw new IllegalStateException("Task already
scheduled " + "or cancelled");
}
schedulerTask.state = SchedulerTask.SCHEDULED;
schedulerTask.timerTask =
new SchedulerTimerTask(schedulerTask, iterator);
timer.schedule(schedulerTask.timerTask, time);
}
}
}
private void reschedule(SchedulerTask schedulerTask,
ScheduleIterator iterator) {
Date time = iterator.next();
if (time == null) {
schedulerTask.cancel();
} else {
synchronized(schedulerTask.lock) {
if (schedulerTask.state != SchedulerTask.CANCELLED) {
schedulerTask.timerTask =
new SchedulerTimerTask(schedulerTask, iterator);
timer.schedule(schedulerTask.timerTask, time);
}
}
}
}
}
清单 6. SchedulerTask
指定的各个时间执?
package org.tiling.scheduling;
import java.util.TimerTask;
public abstract class SchedulerTask implements Runnable {
final Object lock = new Object();
int state = VIRGIN;
static final int VIRGIN = 0;
static final int SCHEDULED = 1;
static final int CANCELLED = 2;
TimerTask timerTask;
protected SchedulerTask() {
}
public abstract void run();
public boolean cancel() {
synchronized(lock) {
if (timerTask != null) {
timerTask.cancel();
}
boolean result = (state == SCHEDULED);
state = CANCELLED;
return result;
}
}
public long scheduledExecutionTime() {
synchronized(lock) {
return timerTask == null ? 0 : timerTask.scheduledExecutionTime();
}
}
}
Timer
的一个实例,用于提供底层计划?code>ScheduleIteratorScheduler
上的 public ScheduleIterator
接口?SchedulerTask
的时间。然后通过调用底层 schedule()
ҎQ启动计划在q一时刻执行。ؓ单次执行提供?SchedulerTimerTask
cȝ一个实例,它包装了d和P代器QiteratorQ。在指定的时_调用嵌入cȝ reschedule()
Ҏ?SchedulerTask
状态检查。重新计划过E反复重复,为每ơ计划执行构造一个新的嵌入类实例Q直CQ务或者调度程序被取消Q或?JVM 关闭Q?/p>
SchedulerTask
在其生命周期中要l历一pd的状态。创建后Q它处于 SCHEDULED
状态,再用下面描述的方法之一取消d后,它就变ؓ VIRGIN
状态的dq行两次计划 —?增加?SchedulerTask
cȝ复杂性。在q行可能改变d状态的操作Ӟ代码必须同步d的锁对象?/p>
取消计划d有三U方式。第一U是调用 cancel()
Ҏ。这很像调用 cancel()
ҎQQ务再也不会运行了Q不q已l运行的d仍会q行完成?cancel()
的话Q计划的d是否q会q行。更准确地说Q如果Q务在调用 SCHEDULED
状态,那么它就q回 Scheduler
׃抛出一?ScheduleIterator
q回 Scheduler
c调?cancel()
Ҏ。如果您想用q代器而不是Q务来控制计划停止旉Ӟq得上q种取消d的方式了?/p>
Scheduler
。这会取消调试程序的所有Q务,q它不能再计划Md?/p>
可以计划框架比?UNIX ?AlarmClock
实现中用的 cron
作业的计划相同,都是׃ crontab
Ҏ定的Q这些字D分别指定分钟、小时、日、月和星期)?/p>
HeatingController
应用E序。我xC它“在每个工作日上?8:00 打开热水Q在周未上午 9:00 打开热水”。?crontab
( 0 9 * * 6,7
Q。而?
清单 7. 用复合定义单一q代?/b>
U程在分配的旉后唤醒时Q它实际执行其Q务的旉取决?JVM 的线E计划策略,以及有多其他线E竞争处理器旉。因此,要减~Q务的延迟执行Q应该将应用E序中可q行的线E数降至最。ؓ了做到这一点,可以考虑在一个单独的 JVM 中运行调度程序?/p>
int[] weekdays = new int[] {
Calendar.MONDAY,
Calendar.TUESDAY,
Calendar.WEDNESDAY,
Calendar.THURSDAY,
Calendar.FRIDAY
};
int[] weekend = new int[] {
Calendar.SATURDAY,
Calendar.SUNDAY
};
ScheduleIterator i = new CompositeIterator(
new ScheduleIterator[] {
new RestrictedDailyIterator(8, 0, 0, weekdays),
new RestrictedDailyIterator(9, 0, 0, weekend)
}
);
DailyIterator
Q只不过它限制ؓ只在一周的特定日子里运行,而一?ScheduleIterator
sQƈ日期正排列到单个计划中?/p>
ScheduleIterator
实现却可以。例如,“每个月的最后一天”描q的计划可以用标?Java 日历法来实玎ͼ?cron
则无法表辑֮。应用程序甚x需使用
实时保证
Ҏ计划d。当前线E要{待直到唤醒它,唤醒可能Z以下原因之一Q?/p>
在编写用计划的应用E序Ӟ一定要了解框架在时间方面有什么保证。我的Q务是提前q是延迟执行Q如果有提前或者gq,偏差最大值是多少Q不q的是,对这些问题没有简单的{案。不q在实际中,它的行ؓ对于很多应用E序已经_了。下面的讨论假设pȝ旉是正的Q有关网l时间协?Network Time Protocol)的信息)?/p>
Timer
c,Timer
的一栗?code>Object.wait(long)
notifyAll()
Ҏ?wait()
的对象是U有的。即便如此,Object.wait(long)
的文档注释声明,它会在规定的旉“前后”苏醒,所以线E有可能提前唤醒。在本例中,wait()
执行Q?code>Timer
如果d本n能监视ƈ记录所有gq执行的实例Q那么对于确定Q务是否能按时q行会很有帮助?code> TimerTaskQ有一?run()
Ҏ开始时Q对表达?
l束?/span>
在本文中Q我介绍?Java 定时器框架的一个简单增强,它得灵zȝ计划{略成ؓ可能。新的框架实质上是更通用?cron
实现Z?cron
Q这是非常有用的。虽然没有提供严格的实时保证Q但是许多需要计划定期Q务的通用 Java 应用E序都可以用这一框架?/p>
http://www.dingl.com/view.shtml?xh=362
]]>
虚拟机的优化
1995q第一代的Java出台之时Q其虚拟机执行是依靠“字节码解释器(Byte Code InterceptorQ”的Q也是说每条指令都p拟机来当释执行,q造成速度令h抓狂地缓慢。更有甚者有人开始ȝ许多的“速度优化l验”,比如_“尽量把所有的代码都放在较大的Ҏ中执行”与“少用接口”等{,q完全与Java语言的设计目的背道而驰Q现在看h是多么可W的奇谈怪论Q当时却是很多程序员z|乐道的经验之谈。无他,Java本n执行太慢了。Java生命的前十分之三是如此~慢地渡q的?br />于是QSun的工E师开始拼命想着提高执行速度。JIT静态编译器的出现是?996q十月,Sun攑և了第一个编译器。JIT~译器在每段代码执行前进行编译,~译的结果ؓ本地静态机器码Q执行速度有了质的提高。Symantec公司当时凭借其傲h的JIT~译器,在整个Java界受到热烈的q捧。在其后?998q_Java 1.2发布的时候,附带了JIT~译器,从此Java的用者终于可以抛开上面说的那些奇怪的“速度优化l验”了?br />JIT静态编译器虽然可以解决一些问题,但是性能仍然和C/C++有很大的差距。对一D늨序而言Q一名优U的程序员是如何来改进q行速度的呢Q首先,他不会傻到把所有的代码都来优化Q他会观察、思考到底哪D代码对整体性能影响最大?然后集中_֊来优化这一D代码。按照经验,整个E序 10%-20%的代码,会占?80%-90%的运行时间。用q种ҎQ在同样的时间、付出同L度的努力后,q名优秀的程序员使整个程序的性能得到了很大程度的优化。HotSpot引擎Q就是模仿h工的q种Ҏq行优化的。在E序q行的开始,Java代码仍然解释执行Q但HotSpot引擎开始进行采?Profiling)。根据采Ll果Q决定某D늨序是占用较多q行旉的,p为它是“HotSpot”,它也是目前E序的瓶颈, 引擎开始启动一个单独的U程q行优化。因Z象原始的 JIT~译器那h差别的编译所有代码,HotSpot引擎可以集中_֊来对HotSpot代码q行深度优化Q这栯部分代码执行h更加q捷。之前的静态编译器只能按照预定的策略进行编译优化,而HotSpot引擎的优化是Z采样的结果的Q因此这U方法对所有的应用E序都有效?999q??7日,Sun攑և了第一个HotSpot引擎。在随后?000q?月的JDK 1.3中,包含了HotSopt引擎Q这也1.3成了一个具有里E碑意义的发行版本。到q里QJava的十q生命,已经q去了一半?br />HotSpot代表的是一U动态编译的技术。对Javaq种大量使用委派、组合等面向对象Ҏ的E序来说Q动态编译比起静态编译来有显著的优势。比如Method Inlining。方法的调用是一个很耗时的操作,假若可以把方法调用直接内嵌到调用者的代码中,可以节省大量的旉Q?q被UCؓ“Method Inlining”。因为涉及到cȝ重蝲Q静态优化很隄切知道哪些属性、方法被重蝲Q因此很隑֯methodq行合ƈQ只好在Ҏ内部q行静态编译,假若每个Ҏ都很,静态优化能起到的作用也比较小。而动态编译因为可以完全随时掌握类的重载情况,可以把相关的方法合q进行深度优化。现代的JavaE序Q特别是在设计模式教育得到普及之后,大量使用cȝl承、委z,形成了很多短的ҎQ动态编译的优势更加明显?br />自从出现了HotSpot之后Q整个Java界ؓ之一振?br />最q的五年Q就是l优化的五年。l进行优化的Ҏ有几条\Q一是研I新的采L法。因为采样关pd不同的优化策略,会对整体性能有比较大的媄响。二是研I深度优化的Ҏ。三是研I垃圾收集的法。垃圾收集会带来E序短暂的停,q会带来负面的用户体验。于是,如何提高垃圾攉的效率,减少延迟Q出C五花八门的算法,比如渐进式收集、火车算法等。在多处理器的时候,如何利用多处理器q行q行攉也是研究的一个热炏V这斚wQBEA的JRocket走在了前面?br />
现实生活中的虚拟?br />最后,让我们来盘点一下目前市面上可见的各个虚拟机?br />首先要提到的Q毫无疑问是Sun的虚拟机。作为大众心目中的“官方实现”,Sun拥有最大的用户,q且拥有“兼容基准”的CQ其他虚拟机都必要考虑和Sun虚拟机的兼容性问题。比?JRocket׃在某些特D情况下表现出和Sun不同的特性,可能对程序运行有影响。不qSun也的没有让q大用户失望Q虽然在早期性能比不上Symantec,后来?.2 的时候性能又被IBM越Q但Sun一直在努力革新Q特别是 1.4.2之后Q性能有了长的进步。虽然JDK 1.5的虚拟机在性能上没有什么提高,但是增强了稳定性,据说修改?000处bugQ真是让人汗不止。原来我们在1.4.2下面一直在享受q么多bug啊?br />其次是老牌劲旅IBM。IBM的JDK?.3的时代创下了最好的性能记录Q从此树立了高端形象。特别是在其WebSphere产品中得C很好的评仗其JDK也是最早支?4bit的JDK之一。到了现在,IBM JDK在高端仍然是和BEA可以一拼的?br />然后是后起之UQBEA的JRocket。说到BEAH然在JVM领域一夜之间异军突P多少让h有些瞠目Q不q它采取的战略特别简单:自己没有Q烦性花׃了在此领域深有研I的JRocketQ在前面加上BEA的标志就可以了。JRocket瞄准高端服务器市场,在多处理器环境下有不俗的表现?br />除此之外Q还有几个开放源代码的JVM值得一提。首先就是大名鼎鼎的JikesRVM。说起其大名Q大多数人都知道Jikes~译器是 IBM开发的Q效率比同等的javac~译器高得多Q很多开发者都使用Jikes~译器来取代javac。而JikesRVM则是IBM开源出来的一整套虚拟机技术,包含了JITQGC的完整实玎ͼ在其|站上也有众多的论文Q实在是惌深入研究JVM者的l佳资源([url]http://jikesrvm.sourceforge.net)[/url]?br />Kaffe是一个老牌的JVM,不过现在已经很少听到了。作者撰写此文时Q[url]www.kaffe.org[/url]|站已经没有响应Q也不知道现在的情况如何了?br />GNU则有两个计划QGCJ和GNU classpath。GNU classpath是一个底层实玎ͼ而GCJ是支持java的预~译器?br />
l束?br />时光{Q蘪轰烈烈的Java虚拟机性能争论仿佛q在而回响Q现在新的争论却已经是“Java的性能是否已经越C/C++”。Joakim Dahlstedt ?JRockit 的主要架构设计师之一Q他坚持认ؓQJaval不是一U速度慢,效率低的语言QJVM 是一个关键的lgQ确保了pȝ的部|与q行和开发一样快速、轻松。特别是在目前开发趋势是采用大量预制的框架时Q动态编译有可能比C/C++q样的静态优化获得更好的性能?br />
J2EE五年: 从v源到目的
?刘天?br />
L
在“J2EE”这个羃略语被第一ơ介l给世h的时刻,也许没有几个人可以预料出它在日后的奇特历E。那是在1999q?月的JavaOneq会上,时QSun公司Java企业开发部门主的Mala Chandra兴奋地预告了Java世界的这位新成员。那些不熟悉背景的听众们Q揣摩着Ҏ说中出现的一串串全新术语Q表情大概又是惊喜、又是迷?一个完整的“多层企业开发架构”、以“容器”和“组件”的形式提供服务、一套“厂商中立的开放技术规范”、对开发者隐藏了不同q_和“中间g”的技术细节、实C企业U应用间的“无~集成”等{。在今天的开发者看来,q些g都已l是老生常谈Q但在当时的场景下,闪动在灯片上的每一个口P都意味着听众们事后又要经历一D困隄学习q程?br />q怺Chandra有一副了不v的口才;q位本科念徏{学的印度裔高层ȝQ谈赯Y件架构来也有特强的空间想象力。她清晰地说明了设计J2EE架构的两个初P首先Q对于厂商,J2EE意味着一套开放标准,加入q个标准Q他们的产品可以运行在各种不同的操作系l和工作环境下,成ؓ一个成熟的企业q算体系中可替换的部Ӟ其次Q对于开发者,J2EE是一套现成的解决ҎQ采用这个方案,企业应用开发中的很多技术难题(包括跨^台移植、事务处理、安全性等{)׃q刃而解Q“信息像一条不间断的河,l过各种各样的^台和讑֤Q从企业应用pȝ的这一端流向那一端”?br />要想理解q段话在当时的实际效应,我们仍然要把旉指针拨回1999q。除了预备迎接千q虫之外Q?9q你做了什么?Z回答q个犀利的问题Q我d6q前的工作记录,发现了自己那时参与的一个项目的规格说明书,它正好能提供一q“Java企业开发”在1999q的标准照。这是一家日本知名IT厂商的企业信息管理系l,q行在NetScape 3.0 Gold览器中的Java Applet界面Q通过一个专用的中间层系l与Oracle 8数据库连接。这个中间层已经相当现成、完善,能够提供q程对象调用、事务处理等一pd的底层服务;留给我们的Q务只是完成服务器端业务对象代码,以及相应的客L交互开发?br />除了Applet客户端有些特别之外,上述pȝ与今天常见的J2EE架构很接q;其是业务对象编码也由homecRPKQ主键)cRentitycȝ部分构成Q很多机刉与EJB如出一辙——只不过q些cdƈ没有l承javax.ejb包的接口Q而是采用了专用的API。它与EJB之间的相g像是偶然的,设计者肯定参照了Sun?997q底推出的EJB 1.0技术规范?br />换言之,在J2EE诞生伊始的语境中Q市面上已经存在着很多E度不一的“准J2EE中间件”了。它们主要用于解决三大类问题Q事务处理、分布式对象理和Webh处理。首先,事务处理理器(Transaction Processing MonitorQ一直是高端企业计算领域的热门品,著名的应用服务器厂商BEAQ正是通过收购事务处理软gTuxedoq入中间件市场的。另一斚wQ从90q代初开始,来多的h把“N层分布式对象架构?当成传统的客L/服务器架构的替代Ҏ。那时刚刚兴LCORBA技术是推动q一势的重要力量(比如_前面提到的那个由日本厂商自行开发的专用中间层,采用了CORBA作ؓ基础架构Q。最后,Java技术在Web领域中的应用也是当时初露头角的热炏V?997q?月,Sun在发布一䏀Java Web Server”的同时W一ơ公布了Servlet APIQ没惛_q项技术副产品Q连?998q问世的JSPQ正好迎合了厂商的战略需要。对于上面提到的N层架构来_HTTP服务是一个非常理想的前端Q所以基于Java的Web引擎Q也在此时成了企业Java解决Ҏ的一个必不可的部分?br />Java、Web、事务、分布式对象Q这几股开发潮汇合在一处,形成了当时最热门的品“应用服务器QApplication ServerQ”或“中间gQMiddlewareQ”。ؓ了给定语“最热门”作个注释,我们可以参照一下BEA公司?998q收购Web应用服务器厂商Weblogic的成交hQ?.92亿美元。而这q不是一桩孤立的收购QNetScape和Sun也以相近的hg下了另外两家企业Kiva和NetDynamics。而这也正是J2EE规范出台的背景:几乎所有要厂商都推Z、或是正在赶制自q应用服务器品,但这个“应用服务器”究竟应该是什么东西,竞争者们又各有表q、莫衷一是?br />说到q里Q我们才梳理ZJ2EE技术规范的W一个版本在1999q?2月问世的实际意义。首先,它ؓJava企业开发提供了一q清晰的全景Q各分支技术在q个领域中的C和作用得C客观、准的定义。至此大家才对一个Java企业解决Ҏ的构成要素有了基本共识。其ơ,它用“容器”和“组件”等概念描绘了Java企业pȝ的一般架构,明确地划分了中间件厂商和应用开发者的职责所在。最后(但绝非最不重要地Q,J2EE通过一套公开标准规定了应用服务器产品的具体行为,在执行此标准的厂商品之间实C一定程度的可替换性和互操作性。当时的媒体用“B2B开发的默认标准”之cȝ说法Ƣ呼q项里程式的成——那些撰Eh哪里知道Q在J2EE与那个被UCؓ“B2B?的短命新贵之_其实q不会有太多故事发生Q同P他们也不会想刎ͼJ2EE要想成ؓ一U真正成熟的开发范式,前方q有一D远辛的旅程?br />
C的Ş?br />记得Kruglinski在名著《Inside Visual C++》的某个版本中给Z一个Web览器的代码例子Q在q一节的开头他说到Q如果你几年前开发了一个Web览器,那肯定会l你带来上千万的收益Q但如果你现在才惛_开发这个东襎쀔—那也就是个C++语言的练习Ş了。在今天的程序员gQ应用服务器g也成了hg廉(如果不是全然免费Q的日用消费品。所以,惌理解它们在那几年的大行其道,非得借助Kruglinskiq样的智慧不可。在1999q底Q市面上可以扑ֈ30U以上自U“Java应用服务器”的产品Q可见当时这cY件是|络风险投资的宠ѝ但是此时出台的J2EE规范像是一阵席h个业的劲风Q在一夜之_所有h都有了判断什么是一个“应用服务器”的权威途径?br />Z获得一张J2EE竞技场的入场券,各家厂商面两项考验Q首先,要具有能够覆盖J2EE中所有主要技术的产品Uѝ这在当时是一w常苛ȝ要求Q在没有开源品可供参照的情况下,短时间内推出包括EJB容器、Web引擎和JMS中间件的整体解决ҎQ这决不是随便哪家创业公叔R能办到的。完成了若干ơ成功的q购之后QBEA在这一点上抢占了先机,完整的品线使它成了Z心目中的首选J2EEq_提供商。其ơ,要让产品通过Sun的J2EE兼容性测试。要做到q一点同样不易:pIBM的WebSphere也一时还没达到百分之癄EJB支持。到2000q底为止Q共?5家厂商能够提供完整的J2EE解决ҎQ其?Ӟ包括Sun本nQ实C“J2EE兼容”,他们中间包括了日后这个领域的主要竞争者。毫无疑问,q是一ơ非常残L行业z牌Q但留在场内的厂商也相应地Ş成了推动J2EE发展的主体力量?br />上面说过Q在它的孵化阶段QSun的J2EE团队ȝ是女ZhMala ChandraQ她本h虽不是工E师nQ但Ҏ术有着很强的感知能力和惌力;J2EE一出台p够ؓZ提供一q完整、直观而不失深邃的图景Q此中当然有Chandra本h的大量A献。在她直接领g工作的几位工E师Q也都是Sun内部非常杰出的h才。无论是制定了JDBC、JMS{规范的Mark Hapner、JavaMail的设计者Bill ShannonQ还是EJB的主要设计者Vlada MatenaQ后来都是业界一a九鼎的技术领袖。这个班子的合作旉q不太长Q?000q左右的那个时期正是IT界创业的黄金q月QChandra很快和Sun公司Java部门的总裁Q也是创造Java的功臣之一QAlan Baratz一PC家刚h的Email中间件公司Zaplet淘金MQ捷克裔的开发天才Matena也离开Sun开办了自己的公司。留下的两个人Hapner和Shannon先后担Q了J2EE技术的首席设计师?br />多年以后QHapner回忆起J2EE初创的那个时期,深感如今Sun对Java的左双力已l大不如前:“现在,Java事实上属于整个技术社区,它的发展有赖全体参与者的推动。”的,如今Sun已经不太可能重演当年的开拓性功l,很难再ؓ一个已l成形的领域重绘版图。但正如上文所_即是在1999q_J2EE设计者们面对的也不是一张从未着墨的白纸。他们的设计始终要以各大厂商的现有品ؓ出发点,q也是天才的设计师们做出的设计却q非完美的原因之一Q与从头设计一门全新的~程语言不同QJ2EE规范从一开始就是各方博弈和妥协的物?br />很容易注意到QJ2EE与JavaC的决{机制JCPQJava Community ProcessQ是几乎同步产生的。J2EE下属的各U技术规范,包括1.4版之后的J2EE本nQ都作ؓ待决规范议案QJSRQJava Specification RequestQ被U_了JCP的议E。这些议案的审议q程很少是一帆风的Q几乎每一个都要经?8个月以上的拉锯战。在多项技术规范的审议q程中,我们都见Cq样的现象:最初列名审议委员会的某家主要厂商,没能{到该规范通过已l被收购或倒闭了。与微Y?NETq_上的乑ֈ独断相比QJ2EE发展中的q个“牛步”特征虽说是审慎和民ȝ表现Q但l归不符合Y件演化应有的速度?br />J2EEC中的另一股重要力量,当然是种cLZ富的开放源代码目?002q以来,在J2EE领域的各个层面上Q几乎所有主品都有来自开源项目的替代ҎQ在其中很多位置上,开源品反而是胜过商业产品的首选。但请别误解Q这里的“开源”ƈ不意味着完全的自动自发,J2EE世界中的开源项目也与Linux或PHP世界颇ؓ不同。在很多非常成功的J2EE开源项目背后,我们都能发现商业机构的推动作用:Apache的JakartaC是IBM扶植的结果;实现了开源应用服务器JOnAS的ObjectWebQ则是许多法国IT厂商Q包括若q政府部门)合资支持的一个联盟组l……这些有商业背景的开源项目资金雄厚,人员齐整Q更重要的是Q从投资者到开发者,参与q些目的很多h都体C软g工业中难得的非功利心态,因而最l推出的产品质量甚至高于同类型的商业软g。在L厂商之外Q它们是支撑J2EE大厦存在的一l基矟?br />另一斚wQ不开发者也间接地通过自己的开源品获得了可观的盈利。这些h大多以免费的开源品ؓ依托Q以收费方式提供附加的咨询、方案实施以及技术支持服务。Marc FleuryQ开源应用服务器的JBoss创始人,不无矛盾地把自己倡导的这U商业模式称为“职业开源开发”?br />无论叫它什么,高端产品的开源化/免费化运动注定要在J2EE产业的发展过E中刉显著的后果。“JBoss的行径恶化了J2EE的商业环境,”这是McNealy先生2002q的著名论断。他的推理过E如下:只有做好商业推广QJ2EE产品才能最l击溃邪恶的.NETq_Q但开源服务器会降低主厂商的销售利润;销售利润越低,用于商业推广的预就少Q因此,整个J2EE阵营都将受损于JBoss?br />但在狂热的开源运动支持者看来,以上的大前提是可疑的。“难道只有会做广告的软g才是好YӞMySQL有过多少q告预算”争论的双方都认为对手误解了软g商业模型的实质。究竟谁才掌握了q里的真理呢Q也许只有根据J2EE的未来——也是它的目标和终点(TelosQ——才能做出最l的裁决?br />
技术的d?br />考察事物的演化,通常有两U对立的Ҏ。考古学家QArchaeologistQ探I肇始和hQ目的论者(TeleologistQ则揭示目的和终炏V对于前者,“开端(希腊语ArcheQ”从Ҏ上决定了此后的发展,参天大树的繁茂都包含在种子最初的萌芽中;而对于后者,“目的(TelosQ”才是事物的Ҏ和旨归:谁没见过h完善的树,谁也没法弄懂种子到底是怎么回事?br />在J2EE五年之后Qh们只能交替地用这两种目光审视它的演化历程。它的v源与它的目的、“它从何处来”与“它往何处厠Z?的问题紧密地交织在一P谁拾起了其中的一个,谁也pq同另一个一起回{?br />今天的J2EE在多大程度上W合它的初衷Q回{这个问题ƈ不涉及对J2EE技术成败的评判Q而只是要考察一下:它是否还q行在最初开辟的那个I间之中。在事务处理、对象分布化和Webh处理q三个方面中Q也许J2EE对事务和Web保持了一贯的忠诚。我们记得Fleury喜欢重复的一个信?“He who owns the transactional Web owns the WebQ谁掌握了带事务处理的WebQ谁掌握了WebQ”Web接口是今天大部分J2EE应用暴露的唯一接口Q而虽然事务处理的常用Ҏ已经有了很大改变Q借助AOP机制Q很多非EJB架构的系l也自如地实C声明式的事务处理Q,但对事务的重视当然仍是J2EE开发中的要素之一?br />换言之,?q的演化中,J2EE发生的最大变化可能就在于它放弃了对“分布式对象模型”的。EJB2.0引入的本地接口得Web层与EJB层可以运行在同一个Java虚拟ZQ从而Web容器与EJB容器的物理分部|变成一U昂늚冗余QJ2EE 1.4以后版本支持的Web Services兼容性,使得客户端可以通过_粒度的Web接口调用q程服务——这两次变化事实上都是在“分布式对象架构”的无用性。h们发玎ͼ同一pȝ的各个分层最好采用细_度接口调用Qƈ且运行在同一个进E中Q之所以划分不同的层次Q与其说是ؓ了实现物理上的可扩展性,不如说是设计学上的考虑。而对于异质系l之间的调用Q则应该量选用异步的、粗_度的服务接口(所以Web Services成ؓ了非常理想的选择Q。换句话_传统上的“分布式对象架构”,现在看来g只适合于银行远E支付等要求极ؓ苛刻的应用场景,而绝不是所有J2EE应用都该考虑的标准方案?br />前面描述的离心现象毕竟还遵@了J2EE发展的内在逻辑Q说到底QEJB的革新和Web Services的引入更多地是主厂商倡导的结果。但在近q来Q还有一股更强劲的离心潮在深刻地媄响着J2EE的演q,它肇始于上文提到的开源Y件运动。最初它只在Rickard Oberg的动态代理RMI设计与JBoss服务器的微内核架构中Nq邪恶的一角,但是两三q来Q经q多个项目、各U技术杂?论坛/Blog的折和攑֤Q它已经形成了一个名为“轻量容器架构”的完整解决ҎQƈ暴露出完全取代传lEJB架构的终极野心。按照这一q动信徒们的说法QJ2EE的发展史上只出现q一个错误——不q的是,q个错误名叫EJB。与EJB提供的重量架构不同Q借助AOP和IoC机制Q轻量容器能够最大程度地降低代码对于专用接口的依赖性,以简短、轻ѝ专注、可UL的方式实C务对象。从“轻量容器架构”这个词被发明出来的那一刻vQh们对J2EEq景的考虑发生了Ҏ性的分裂QSun和大部分L厂商更多地关注于“Web Services”和“快速开发工具”这些利润增长点Q而一部分ȝ叛道的独立专家和开发者则认ؓQ如果不把轻量容器U_规划QJ2EE的发展蓝囑ְ注定无U道。其实,双方争执的关键是传统意义上的“应用服务器”的存亡——如果所有企业服务都可以通过AOP机制提供l普通Java对象Q如果管理业务对象生命周期的可以是一个最微不道的“微内核”,那么q重铠的应用服务器q有什么存在理由?而如果失M应用服务器的q个产品cdQ那些靠q项销售v家的厂商又将何以自处Q?br />正是在这里,两个阵营之间存在着最深刻的利益分歧;而这Z执的l局当然也将军_J2EEQ乃至Java企业开发)的最l走向。或怸q之后,我们从U争中胜利者一方的角度重述J2EE的整部历叜y—或怸q之后的J2EE本n也将随着U争的解册成为历双Ӏ但让我们换个乐观的口吻Q问世五q_J2EE的历史仍在持l的创生之中Q此时善待这树种的hQ也必在今后的树荫下获得它的福?br />
Java十年有成
——谈J2ME的发展历?br />?王森
Java本来是Z嵌入式系l而生
1990q?2月,Sun内部由James Gosling、Patrick Naughton以及Mike Sheridan成立了一个叫做Green Team的小l。Green Team组的主要目标,是要发展一U新架构Q而这U架构必能够在消费性电子品作业^Cq行Q现在我们普遍认识的PDA、手机或是信息家?IA)Q都是属于这U架构的目标q_。接着QGreen Team?992q的9?P发表了一ƄJava 技术之?James Gosling所领军研发Q名叫Star Seven(*7)的机器,研发Z部交互式的掌上型家用׃装置Q可透过使用动画触碰式屏q的使用者接口来控制其它电子讑֤?br />l过?3q的旉Q现在我们检视J2ME的发展历Ԍ我们可以发现Q虽然在1999q_Java被切割成J2SE、J2ME、J2EEQ所以有了J2MEq个名词的出现。但是Javaq1999q开始才开始发展嵌入式pȝ上的应用。其实,Java本来是Z嵌入式系l而发展的一U架构。即使目前大家多半将Java的应用聚焦于企业上的J2EE应用。但是严格来_J2ME才是Java真正“回归本心”的领域?br />
半\杀出的Personal Java
Personal Java是正规Java版本的一个分支,其目的在于能够让PDA或高阶手机执行JavaE序Q目前在Windows Mobile或Symbian OS(仅限采用UIQ或Nokia Series 80的行动电?q_上都可以开发Personal Java应用E序?br />虽然从Java 1.0发表之后QJavapq泛C用在桌上型应用程序以及Applet的开发上Q但是,从Java 1.1开始,Java又回C它一开始的老\-也就是嵌入式pȝ斚w的应用,在当时Sun Microsystems发表了Embedded Java与Personal JavaQ也有hUCؓPJavaQ这两项规格。Personal Java的规格是从Java 1.1之中所分支出来Q因此Personal Java的规格是ҎJava 1.1的规D制定的Q但是ƈ非Java 1.1的全部规格都包含q来Q所以Personal Java只能是Java 1.1q_的子集合?br />Personal Java特别适合用在h丰富囑Ş昄能力的消Ҏ电子品上面,于是我们可以发现Sun Microsystems|站上对于Personal Java的参考实作是建立在Windows Mobile产品(q去叫做Pocket PC)上头的?br />?999q_一般PDA或手机的能力Q离Personal Java所需要的g条g仍有很大的一D差距,因此Personal Javaq不是一个很成功的品。因此Sun Microsystems在此时将Java区分成J2SE、J2EE、J2MEq三块,希望可以重新塑造整个架构,其是J2MEQ希望Java可以在嵌入式pȝ的领域有所发展?br />
J2ME从何而来?
谈到J2MEQ大家就会联惛_KVMq个名词Q?KVM的设计者Antero TaivalsaariQ最早在Sun Microsystems参与Spotless ProjectQ这个项目才是J2ME的最早v源。由于Antero Taivalsaari曄在世界知名电信设备制造商工作Q所以他有了在手Z开发JVM的概念,后来得到公司支持Q就有了各位所知的KVM(K Virtual Machine)?br />最早应用KVM的品,是一个可以在Palm OS上执行的KJava。KJavaq不是一个正式品,只能是一个概忉|试品。开发h员会开发名为Spotlet的应用程序,透过工具和KVM的辅助,应用E序可以在PDA上执行。虽然KJava早已成ؓq去式,但是仍有电信厂商使用q个名词Q作为手ZJavaq_的名Uͼ不过Q已l不是真正的KJava了。有了KJava的发展经验,Sun着手设计J2ME的架构,让J2ME可以应付未来嵌入式系l的发展?br />
J2ME整体架构
J2ME最基本的规范制定在JSR-68(Java规格~号W?8?Q在此规格里头定义了J2ME的技术架构。根据此规范QJ2ME׃U类型的规范堆栈而成Q分别是Configuration、Profile以及Optional Packages。这三种cd的规范定义由其它的规范所定义?br />在最底层的Configuration规范Q定义了g所必须具备的能力,比方说硬件至具备多ROM、RAMQCPU的频率最应该是多少Q连接网l时频宽臛_要多快。Configuration规格之中定义了一l低阶的APIQ这代表Java臛_必须提供的低阶功能,q组低阶的API是核心cd函数库的子集合?br />在Configuration之上的规范称为Profile。Profile针对各种不同机器的特性定义了高阶的APIQ这些高阶的API通常都是与其它^C相关的扩充类别函数库。这些高阶API军_了该U机器上JavaE序的撰写方法。比方说行动通讯装置(手机、PDA{?q类型装|上JavaE序的撰写方式,以及能够调用的APIQ都定义在MIDP(Mobile Information Device Profile)之中?br />q是同cd的装|,有些功能也不一定具?有些厂商的机器可能有Q有些厂商的机器可能没有Q例如手Z的照相机、和弦铃声等)Q这些功能就定义在“厂商选择性实现套?Optional Package)”之中,比方_有的厂商会提供简单的数据库管理系l?DBMS)在该装置上,那么他们׃实现JDBC Optional Package。不提供数据库管理系l的厂商׃需要实现JDBC Optional Package。所以称作厂商选择性实现套件?br />所谓的厂商选择性实现套Ӟ意思是_q是一l和其它规格(或API)没有M怾性的cd函数库,如果厂商愿意提供q样的功能给E序设计?通常是因为硬件具有充分的能力可以完成规格之中所制定的功?Q就会将q组cd函数库实现出来,E序设计师也可以利用q些功能开发出功能更多的应用程序?br />
MIDP工业标准
虽然J2ME架构完整Q但是目前的发展Q除了Personal Profile之外Q最大的应用在于架构在CLDC之上的MIDP。目前所有标C可以支持Java的手机,所支持的都是MIDPQ几乎所有的无线通讯厂商皆采用MIDP作ؓ其开发程序的标准?br />在MIDP 1.0的时代,׃规格上本w的功能不Q得许多厂商不得不加入自己专属的APIQ例如震动、背光、声音等扩充功能(例如:Nokia UI API)Q以弥补MIDPq_的不?br />CMIDP 2.0Q增加了许多众所期盼的功能,但是Q即使规格更清楚了,即很多新功能都已经由JCP制定成标准的Optional PackagesQ这些问题依然无解。市面上的MIDPq_仍然处于混ؕ状态。开发者必d执行时期侦测各种专属API和Optional Package的存在,q会增加多余的程序代码。^台的混ؕ会造成在某个装|上可以利安装及执行,而到了其它装|时Q有可能无法执行Q甚x可能q安装都有问题,所以开发者通常要开发好几种版本的MIDP应用E序供各U厂牌、各U型L装置使用?br />Z解决上述问题Q进一步提高MIDP应用E序的可UL性,Sun Microsystems以MIDP 2.0规格为核心,设计了JTWI规格。未来的无线通讯q_Q将不会只有W合MIDP 2.0规格Q而是必须要符合JTWI规格。这是J2ME软g在可UL性上的一大突破。JTWI(Java Technology for Wireless Industry)是一个统合性的规格Q其目的是ؓ了确保MIDP软g的可UL性。所以JTWI规格除了规范无线通讯q_(特别是手?所必须支持的J2ME标准之外Q也Ҏ有规g模糊不清的地方与以加强。所以新Ƅ手机Z加强UL性,都会支持JTWI标准。JTWI只是一个统合性的规范Qƈ没有制定M新功能,目的只是要统一当前q_混ؕ的现象,让J2ME应用E序更具可移植性。JTWI主要分成几个部分:
1 .规定q_必须支持的API?br />2 .l一的应用程序执行环境?br />3 .既有规格的理清与加强?br />在规定^台必L持的API的部分,JTWI规定臛_必须支持CLDC 1.0、MIDP 2.0以及WMA 1.1:
所以,只要厂商宣称支持JTWIq_Q那么代表一定支持CLDC 1.0、MIDP 2.0以及WMA 1.1规格之中的所有功能。另外,厂商可以Ҏ装置本n的能力,CLDC 1.0提升成CLDC 1.1Q可以加入MMAPI 1.1。因此实际上JTWIq_会有一下几U组合方?
其中QCLDC 1.1 + MIDP 2.0 + WMA 1.1 + MMAPI 1.1是最完整、功能最强^台?br />在统一应用E序执行环境斚wQ过去让J2ME应用E序开发者最为头大的问题有以下几?
?应用E序的大可以多?
?执行时期的内存有多少可以使用?
?有多内存空间可以作为永久储存之?
׃规范中对于J2ME应用E序本n的大和执行环境没有很详l地规范Q得每家厂商都有自q规范Q比方说Nokia限制应用E序最大只?0 KBQMotorola则可以支?0 KB以上的应用程序。这些规范都严重地困扰着开发h员。这些问题在JTWI之中都获得改善?br />JTWI定义了应用程序的标准大小(Standard-size Application)。JTWI规定Q可以执行J2ME应用E序的行动通讯装置Q至可以容许大ؓ64 KB以上的程序主?JAR文g)? KB以上的应用程序描q文?JAD文g)、以?0 KB以上的永l储存空间、执行时期的内存(Heap Memory)?56 KB。上q大只是底U,厂商可以视装|的实际能力支持更大的内存空间。标准应用程序大?Standard-size Application)成Z个计用的单位,举例来说Q厂商会说这个装|可以安?0个标准应用程序,开发者所撰写的程序可以说q个E序需要占?个标准应用程序的I间?br />至于Ҏ有规格的理清与加强的部分Q我们将在往后章节一一说明。最重要的一ҎQJTWI规定Q该装置所支持的Q何媒体格?例如囄、声韟뀁媄像等)都应该能够用HTTP 1.1获取Q也是_存取q些媒体时所使用的URL都必能够接受http作ؓ存取的通讯协议?br />
Java开发环境的
q去、现在和来
?EclipseCN
1995q??3日,San Jose Mercury Newsd一题为“Why Sun thinks Hot Java will give you a lift”的文章Q在那篇文章里预aJava技术将是下一个重大事Ӟq个预言现在看来q不仅仅是商家的宣传伎俩Q虽然文章是当时Sun的公关经?Lisa Poulson安排撰写的。从世h知道Java那一刻v到现在,v来已l过L整十q_回顾q去的十q值得ȝ的东西有许多Q但在这里笔者只惛_Java 开发环境谈些个人的x与朋友们交流一下?br />现在的Y件开发h员在整个软g的开发生命周期里Q也怼Ҏ需要用各式各L开发工h完成相对复杂的开发Q务,而在几十q以前,Zq只是用文本编辑器、编译器和Debuggerq行开发,对于q个阶段的开发环境h们称之ؓCLEs(Command Line Environments)?而当Z发现如果那些单独分开的开发工具集成v来就可以有效的提高开发效率时QIDEs(Integrated Development Environments)出C。Java的出现尽只有十q_但其开发环境也大至l历了从CLEs到IDEs再到XDEsq三个阶D,现在卛_q入CDEs阶段。在上述Java开发环境发展过E中Q有许多值得我们大家x的地斏V?br />
Java开发环境的历史回顾
U观q去十年Java开发环境的发展Q大致可以粗略的划分为如下几个阶D?
● ?995Q命令行开发环境CLEs
● ?996-2000Q集成开发环境IDEs
● ?001-2004Q扩展开发环境XDEs
● ?005至今Q协同开发环境CDEs
1995q_不^凡的一q_q一qJava 获得了成功。可令h尬的是?995qƈ没有一个o人满意的Java开发环境,开发h员在q行Java~程Ӟ大多使用文本~辑器编辑源E序Q然后再使用命o行的方式q行~译处理。那时的Java开发环境还处于CLEs时代Q开发效率非怽Q这预示着在Java开发工具上会有一番激烈的竞争?br />有hU?996qؓ互联|年Q有人却UC为Javaq_q有人称之ؓWeb开发年Q但不论如何U呼1996q_它都反映了一个事实:Bill JoyJava与互联网相结合的{略取得了成功。这一q的9月Sun推出了其Java开发环?Java WorkShopQ这是一Ƒ֟于浏览器的Java开发工P但由于当?Java在许多方面还不成熟,所以实际上Java WorkShopq不成功Q同q发布的Symantec Visual Cafe׃q是采用C/C++语言q行开发,所以性能与成熟度上就比WorkShop好得多。提到Visual Cafe׃能不提Eugene WangQ因为Eugene Wang常常是与计算机间谍这个词同时出现的h物,有h甚至讲当时Symantec的老板Gordon Eubanks与Eugene Wang{Ӟ也同时签下了监狱里的一个单元。Visual Cafe是由Eugene Wangq行主要{划的,它是在同一q发布的Java开发环境中Q唯一解决了与数据库连接问题的开发环境,带有一套可以与数据库相q接的组Ӟ无需太多~程使用拖拽的方式就可完成大部分工作Q这一优点使得Visual Cafe受到了Java开发h员的Ƣ迎。这一qIBM收购了OTI公司Q从而得CDave Thomas的弟子John Duimovich、Dave Thomson、Mike Wilson{一大批软g_英Q这之中q包括“生zd技术刀锋上的开发者”Brian Barry?br />1997q_׃微Y垄断案,使得微Y在Java开发环境上的努力受C限制QVisual Cafe׃界面直观易用Q可以很Ҏ地连接各U数据源{功能再ơ受到开发h员的Ƣ迎。这一qIBM发布VisualAge for Java。VisualAge for Java是面向代码库的开发环境,它提供代码库和项目管理以便于开发团队在 C/S环境下进行项目开发。但׃大多数Java开发h员比较熟悉面向文件的开发环境,q不太习惯面向代码库的开发,再加上VisalAge for Java对系l资源的要求比较高等因素Q得VisualAge for Java一开始未被Java开发h员所认可?br />1998q至2000q比较成功的Java开发环境是JBuilderQ这是由于Borland较好的把握住 J2SE、J2EE和J2ME发布后,Java技术升U的时机Q全面支持Java1.1和Java1.2开发^収ͼ它还提供了多U工h便用户从旧的q_q移到新的Javaq_。JBuilder本n80%是基于JDK1.2q行开发的Q它支持JavaBeans, Enterprise JavaBeans, JDBC{方面的应用开发,可以q接多种关系数据库。ؓ支持分布式应用开发,JBuilderq集成了 VisiBroker ORB、JSP server、数据库和EJB AppServerQƈ提供Open Tools API便于W三方工具集成。上q种U的优点使得JBuilder一举超Visual CafeQ成为当时最受欢q的Java开发环境。在众多Java开发环境中Q?999qIBM发布的VisualAge for Java Micro Edition是比较有特色的开发环境,它是由Erich Gamma和与Erich Gamma有“焦不离孟、孟不离焦”之U的John Wiegand共同q行设计的,采用了Java 扩展机制Qƈ集成了JUnit试框架Q其当时所采用的架构深深地影响了后来Eclipse1.0所采用的架构。同Ӟ通过VisualAge for Java Micro Edition的开发,那些来自“未来世界?Smalltalk们总认Z们来自计机的未来世?的Y件精׃Q全面彻底地对Java技术进行了评估Q得Z许多l论性的东西Q这之中包括现在闹得沸沸扬扬的Swing和SWTҎ。此外,Sun其收购的NetBeans变成了开源的Java IDE也是一件不大不的事情?br />U观1996q至2000q这五年旉里,随着Java及其相关开发应用的发展QJava开发环境也不断的完善,从CLEsq入到IDEs阶段。ؓ了提高Java开发h员的开发效率,Java开发环境主要从两个斚wq行改进与提高。一斚w是提高集成在Java IDEs当中开发工L性能和易用性,另一斚w是将Java开发环境尽可能的覆盖到整个软g的开发生命周期。随着ZWEBQ采用N-层结构的应用开发成为Java开发h员主要从事的开发Q务,Java开发环境需要支持越来越多的技术,比如:XML、JSP、EJB和CORBA{,q就造成了Java IDEs的规模变得越来越大,许多Java开发环境都集成了数据库、JSP Server和AppServerQY件的研究人员上qIDEs不断膨胀的现象称为“IDEs大爆炸”?br />“IDEs大爆炸”现象发生以后,有关Java开发环境是走少而精的发展方向,q是走大而全的发展方向就成了q大Java开发h员关注的问题?001qJava开发h员达C200万,成ؓ每个软g供应商都无法忽视的力量,q一qJetBrains推出了Java开发环境少而精的代表: IntelliJ IDEA?IntelliJ IDEA明确的表C只做最好的Java代码~辑器,不做什么文仉可以~写的编辑器。它xJava开发h员的工作实际q将q些工作q行了优化。由于减掉了一些可有可无的工具Q所以hg相对合理公道。当qIntelliJ IDEA击|JBuilder成ؓ最受Java开发h员欢q的Java开发环境,不过2002q随着JBuilder大而全的功力再提升一步,UML建模工具、JUnit试框架以及Apache Struts{开发工具集成进来,大而全的发展方向又一ơ受到Java开发h员追捧。最全还是最好似乎Java开发h员在选择Java开发环境时处于两难状况Q但实际上当Eclipse 1.0发布Ӟq个问题已经得到了初步的解决Q最好和最全是可以兼顾的?br />Eclipse的出C是从天上掉下来的Q也不是某个天才拍脑袋想出来的,它是一Y件精׃集体智慧的结果。早?998qIBM打开发新一代的工具q_以便它现有的各U开发工L一hQƈ减少开发各U工h重复的劳动,同时希望在新的^C建立新的Java开发环境。经q一D|间的准备Q?IBM开始徏立v一个开发团队,人员构成主要来自VisualAge for Java Micro Edition和VisualAge for Java两个目的开发h员,选择的标准是q去10q至开发过5?个IDE。此外,IBMq联合了9家公司共同成立了一个开源组lEclipse基金会,Eclipse提供l开发h员用,q在开源社区的帮助下进一步完善Eclipse本n。Eclipse在最初设计时Q插件模型是静态的Q不能实现插件的x即用功能Q即便是大受Ƣ迎的Eclipse 2.1也还是静态的。所以到2004q发布Eclipse 3.0ӞEclipseq行了重大改q,采用OSGi的插件模型,初步实现了插件的x即用功能Q至此一个完的、可扩展的开发环境展现在Java开发者面前,q时Java开发h员已l达?00万?br />
Java开发环境的现状
2004qEclipse 3.0的发布极大刺Ȁ了Eclipse用户的增长,l过一q以后,Java开发h员现在用Java开发环境的状况是如何的呢?看了下面的表格里的数据也许可以了解一个大致的状况?br />首先需要指明的是上q的数据q不是当前Java用户使用Java开发环境的准确反映Q但我们可以从中了解一个大致的状况。现在的Java环境可以分ؓ三个集团Q第一集团是Eclispe它大U占?/3的䆾额,W二集团?IntelliJ IDEA、NetBeans 和JBuilder占据另外1/3的䆾额,怺之间旗鼓相当Q第三集团是以JDeveloper和WSADZ表的十几UJava开发环境占据剩下的 1/3份额Q但每种开发环境占M额的比重不超q?%。我们考察Eclipse、intelliJ IDEA、NetBeans 和JBuilderq些L开发环境,可以发觉它们有一个共同的特点那就是可扩展Q尽在实现手段上各有不同。这是Z么称现在的Java开发环境ؓXDEs(eXtended Development Environments)的原因,IDEs已经M?q_专业的开发h员需要了解这个事实,因ؓXDEs也快M?br />׃市场的压力,一个Y件企业不仅要提高开发h员个体的工作效率Q还要提高整个开发团队以及整个企业的开发效率,但在现有的Java开发环境XDEs下无法完全做到这些,所以新一代开发环境CDEs (Collaborative Development Environments)׃生。Grady Booch和Alan W. Brown的研I表明一个程序员一天工作时间的分配是这LQ分析占16%(?%?0%不等)Q?设计?4%(?%?0%不等)Q编E占16%(?%?0%不等)Q测试占10%Q打电话?%Q阅d7%(电子邮gQ文档,月刊和杂?Q参加开发会议占10%Q无关的会议?% 。从q些数据可以发现Q开发h员用于交的旉U占工作旉?/3Q开发h员的怺交流非常重要。可是现有的LJava开发环境一般仅分析、设计、编E和试{工具集成进来,却未包括用于交流的工Pq显然不合理。因此,所谓CDEs是用于h与h、h与团队以及团对于团队q行交流的工具集成进来的开发环境,比如QCDEs常具有发送电子邮件、进行及旉讯和屏q分享等功能Q通过实现无损耗过E的交流提高开发团队的开发效率?br />现在已经商业化的CDEs是CodeBeamer Collaborative Development Platform和CodePro AnalytiXQ上qCƾY仉提供Eclipse的插Ӟ可以与Eclipse集成在一P使Eclipse升成ؓ一个CDEs。大家肯定知道Borland已经宣布开发基于Eclipse的新版JBuilder-“Peloton”,Peloton是一个CDEs(Collaborative Development Environments)Q当它明q上半年发布Ӟ意味着Java开发环境进入CDEs时代Q现在Java开发环境还处于XDEs与CDEs交替的阶Dc?
Java开发环境的未来
在可以看得见的将来,Java的开发环境还会是以CDEs的Ş式存在。开源组l或开发工具供应商会努力Y件的开发创Z个绝对光滑的q面 (Frictionless Surface)Q实现无损耗的开发过E,以提高开发效率。ؓ了实现无损耗的开发过E,Java的开发环境将会关注以下几个方?
● v步阶D|?
● 协作开发方?
● 维护开发团队有效沟通方?
● 多个Q务的旉协调斚w
● 相互协商方?
● 资料有效性方?
但这里必L认未来Java开发环境是如何具体d现无损耗的开发,q需要时间给与答案,因ؓ现在所能采用的Ҏ未必是最好的Q比如,使用面向文g?CVSq行协同开发就有需要改q的地方?br />
ȝ
|里|唆一大堆Q归Uv来不q就?一个目的、三U手D以及一条规律?br />一个目?十年Java开发环境的演变Q其目的是Z提高开发效率?br />三种手段:
● 提高集成在Java开发环境中开发工L性能和易用?
● 将Java开发环境尽可能的覆盖到整个软g的开发生命周?
● 集成h与h、h与团队以及团对于团队q行交流的工?
一条规?软g开发环境的发展q程是从CLEs到IDEs再到XDEs最后进入CDEsQ这是由Grady Boochȝ出来的,套在Java开发环境上也适用?
参考文?br />?Grady Booch and Alan W. Brown, "Collaborative Development Environments", Advances in Computers 59, Aug. 2003.
?Li-Te Cheng,Cleidson R. B. de Souza,Susanne Hupfer,John Patterson, Steven Ross, "Building Collaboration into IDEs", ACM Queue vol. 1, no. 9 - December/January 2003-2004
?J. des Rivie` res,J. Wiegand, "Eclipse: A platform for integrating development tools", IBM System Journal,Volume 43, Number 2, 2004
?The Java Extension Mechanism.
?Grady Booch, "History of Development Environments", January 29, 20
J2SE发展演变?br />?Matirx JavaC 杨洪波 王志?br />
J2SE:怀?br />Java的历史可以追溯到1991q?月,Sun公司的James Gosling领导的绿色计?Green Project)开始着力发展一U分布式pȝl构Q其能够在各种消费性电子品上q行Q他们用了C/C++/Oak语言。由于多U原因,l色计划逐渐陷于停滞状态?br />直至 1994q下半年Q由于Internet的迅猛发展和环球信息|的快速增长,W一个全球信息网l浏览器Mosaic诞生了;此时Q工业界寚w合在网l异构环境下使用的语a有一U非常急迫的需?Games Gosling军_改变l色计划的发展方向,他们对Oakq行了小规模的改造,pPJava?995q的3?3日诞生了QJava的诞生标志着互联|时代的开始,它能够被应用在全球信息网l的q_上编写互动性及强的AppletE序Q?995q的Applet无疑能给Z无穷的视觉和脑力震荡?br />但没有相应的开发库而只靠Java语言来进行开发肯定是困难重重Q所以Sun公司?996q的1?3日发布了JDK 1.0来帮助开发h员的开发。JDK包括两大部分:q行环境和开发工兗紧跟着QSun公司?997q??8日发布了JDK 1.1。JDK1.1相对于旧版本最大的改进Q是推出了JIT(Just-In-Time)~译器,另外一个改q是AWT 1.1?br />在JDK 1.1时代QJavaq_分ؓPersonalJava与EmbeddedJavaQ前者比较适用于运资源和内存丰富的设备,而资源有限者适用于后者。这L分类明显不符合时代发展的潮流Q所以,Javaq_处处蕴藏着新的d覆地的革命…?br />
J2SE1.2:诞生
JDK 1.2?998q?2?日的隆重发布Q标志着Java2q_的诞生。Java 2的J2SE 1.2时代是一个大变革时代Q它q行了如下的三大革命:
?市场推广革命
Sun公司在Java 1.2版以后将JDK 1.2改名为J2SDKQ将Java改名为Java 2。在1999qSun公司q将Java 2q_分ؓ三大?J2SEQJ2EEQJ2ME。这ơ市场推qK命顺应了|络急速发展的潮流Q对Java 2q_的发展vC很好的催化剂的作用?br />
?API供应标准革命
而随着供应商的不同QJava的API分ؓ三大c?
Java Core API:由Sun公司制定的基本的APIQ所有的Javaq_都应该提供?br />Java Optional API:由Sun公司制定的扩充APIQJavaq_可以有选择地提供?br />ҎAPI:qD厂商或者组l提供的API?br />
?API制定q程的革?br />如果你有需求不能通过遵@标准的API来实?可以向JCP提出制定新的API的请?l过审核,你的h可能被通过或者驳?如果是被通过,则开始进入制定该API的程序?br />J2SE 1.2时代q行的这些革命Ş成的制度一直沿用到现在,对Java技术的发展形成了深q的影响?br />除了上述的三大革命,Java 2q支持ƈ新增了许多新Ҏ,最受追捧的当属Swing库。Swing是轻量的APIQ它不但有各式各样先q的lgQ而且q组仉格都可抽换。Swing出现之后Q大家很快地׃太用AWT了。Java 2q废弃了一些APIQ最重要的莫q于ThreadcM对suspend(),resume()和stop(){方法的废弃。由于JDK 1.1的集合类库中的VectorcdHashTablec都考虑了同步,在^常的使用中媄响效率,所以Java 2专门d了对应的非同步类Qƈ完善了集合类库?br />
J2SE1.3:拓广
Java 2q_推出后,得到了市场的强烈反响Q所以,?000q??日推出的J2SE 1.3对J2SE 1.2的改q,主要是对各种已有API的加强和ҎAPI的拓展?br />数字q算:加入了java.lang.StrictMath,方便我们的一般的数字q算?br />新的Timer API:怿大家对其中的java.util.Timer和java.util.TimerTask一定不陌生?br />Collections?加入了一些新的APIQ方便我们的使用?br />虚拟机停止钩?J2SE 1.3q加入了一个强大的功能Q那是虚拟机停止钩?Virtual Machine Shutdown Hooks)Q这个功能得我们能够在虚拟机停止时完成我们自己的操作,比如关闭|络q接或者保存会话状态或者清除时文件等{?br />DNS服务:在JNDI接口斚wQ加入了一个DNS服务的实现?br />Jini实现:J2SE 1.3包含了一个Jini实现Q这使得我们可以方便地把诸如打印机、摄像机和磁盘驱动设备插入现有网l中Qƈ且能自动搜烦已在|上的设备可以提供的服务qn用这些服务?br />XML支持Q由于计机|络和XML技术的快速发展, J2SE 1.3在Optional API中引入了Java API for XML包?br />HotSpot虚拟?J2SE 1.3引入了HotSpot虚拟机。在Solaris版的JDK 1.3中,已经不支持传l的虚拟机,而Windows版的JDK 1.3同时支持传统虚拟机和HotSpot虚拟机?br />从上面的分析可以看出QJ2SE 1.3主要是对J2SE 1.2查漏补缺和拓展新的API。从应用领域斚w考虑QJ2SE 1.3已经늛了数据库、WEB、多媒体、网l、电话、媄像、加解密、图形等{大部分的信息技术领域?br />在这个时期Java 2q有一个重要活动就是推出SCSL(SunC源代码许?许可协议。Sun公司开放源代码目的“女1号”Danese Cooper?999q加入公司,负责SunQ包括JavaQ和开放源代码C之间的协调工作。Sun一直尽可能在赢利和开放源代码之间L更好的^衡?br />Java的大行其道引起了Microsoft的警惕ƈ直接D?Net的生,q同时也宣布了Java作ؓ独一无二的Internetq_C的结束。这两个Ҏ在较量中怺学习Q现在在技术架构上的目标上已趋相同?br />
J2SE 1.4:快?br />J2SE 1.4q_的推出发生在2002q??3日,׃此前在Javaq_?NETq_间发生了规模大的孰优孰劣的论战Q而论战中QJavaq_最大的~点是性能问题Q所以J2SE 1.4q_把性能的改善放在了最重要的位|?br />HotSpot虚拟?HotSpot虚拟够很大程度上提高性能Q所以J2SE 1.4已经不支持传l的虚拟机。现在,启动应用E序应该通过-client或?server选项来启动?
锁机?׃旧版的HotSpot虚拟机的锁机制会导制严重的性能和功能问题,J2SE 1.4已经改写了该锁机制?br />安全API:JCE、JSSE和JAASq三大安全API从optional APIUd了core API中。这PJ2SE 1.4的安全域(SecureRandom)实现可以利用操作pȝ提供的安全机Ӟ以便~短应用E序的启动时间?br />RandomAccess标记接口:加入了RandomAccess标记接口Q如果一个List实现了该接口Q则表示它支持快速的随机讉KQ这样可以提高List讉K的速度?br />LinkedHashMap:加入了LinkedHashMapQ这是一个插入排序的Map实现Q但它的q行速度和HashMap一样快?br />反射:很多产品中都要用反?Reflection)机制Q但大家知道Q反是相当耗时的,所以,J2SE 1.4中重写了java.lang.reflect.Field、java.lang.reflect.Method.invoke()、java.lang.reflect.Constructor.newInstance()和Class.newInstance(){方法,使得我们利用反射也能写出高性能的应用程序?br />64位计?J2SE 1.4支持64位计?br />新的I/O API:J2SE 1.4在API层面最大的变动Q就是它更新了原有的java.io包,以及加入了一l更有效率更多功能的New I/O API?br />断言和日志处?J2SE 1.4版本在Java语言层面上加入了断言Qassert关键字)Q在API层面上加入日志处理APIQ这些ؓE序的调试提供了强有力的支持?br />从上面的分析可以看出QJava 2q_在经q数q的发展后,已经比较成熟E_QJ2SE 1.4主要是对q_的性能q行较多的考虑和修攏V在分布式程序方面,1.4版比1.3版的q行效率提高了一半以上;而在客户端程序方面,1.4版比1.3版的效率提高?/3?br />J2SE 1.4版是J2SEW一个参与了 Java共同体过E?JCP)的J2SE版本?像Borland、Compaq、Fujitsu?SAS?Symbian?IBMq样的公司,和Sun一起定义ƈ发展了J2SE 1.4规范。在开放、良好的文档~撰与管理的q程中,形成了一个高质量的、代表了Java共同体的多样性的规范?br />
J2SE5.0:易用
?004q十月J2SE 5.0发布的时候,Sun公司q样解释q次版本名称不是J2SE 1.5而是J2SE 5.0的原因:“从Java诞生至今已有9q时_而从有J2SEv也有5个年头了Q在q样的背境下Q将该版本号?.5改ؓ5.0可以更好的反映出新版的J2SE的成熟度、稳定性、可伸羃性、安全性。?br />J2SE的这ơ变更之重大和意义之pQ的也值得我们Z把版本号变换到J2SE 5.0。我们再看看Sun公司|站对J2SE 5.0的features描述:“通过增强Javaq_的力量,允许开发者更ҎC用,Java~程语言的这些改q将吸引大量各种Java开发者”,q是“Java技术发展历E的一个重要里E碑?。从q个描述我们可以看出QJ2SE 5.0最大的目标是通过提供易用性而吸引各U开发?当然包括以前的C/C++开发? Q而它对以前版本的修改q不仅仅是API的升U,而且包括对Java语言层面的改q,被誉为是”自Java问世以来的最大一ơ语a标准变化”?br />讉K环境变量:最初的Java语言有一个访问环境变量的ҎSystem.getenv()Q但因ؓJava宣称的”Write Once,Run AnyWhere”特性,所以在JDK 1.0中去掉了q个能够讉Kq_专有信息的方法。在J2SE 5.0中,它又来了Qƈ有所扩充。由此可见J2SE 5.0对编E方便性的重视E度?br />泛型:J2SE 5.0提供了强大的泛型机制Q让E序员可以减代码重复,q个变化应该可以吸引部分的C#开发h员吧?br />增强的for循环:Z克服普通for循环的代码臃肿特点,J2SE 5.0提供了增强的for循环Q我们现在可以这样写一个for循环:
public void printAll(Collection coll)
{
for(String str : coll)
{
System.out.println(str);
}
}
怎么P是不是简单了很多Q?br />自动的装?拆箱:
可变参数数目J2SE 5.0开始支持Varargs(不固定自变量个数)QJ2SE 5.0中还加入了以前抛弃的枚D和C风格的格式化输出Q这应该是ؓ了吸引以前的C开发者吧。毕?在C开发中枚D和格式化输出用的是太多了?br />q发 J2SE 5.0中加入了java.util.concurrent包,q向集合框架中加入了Queue接口QJ2SE 5.0qؓ各种集合提供了ƈ发情况下的实现?br />Propertiescd?׃XML的普及性应用,J2SE 5.0为java.util.Propertiescd入了从XML文g中装载属性和把属性值存储到XML文g中的Ҏ?br />Annotation功能J2SE 5.0提供了注?annotation)/元数据(metadataQ功能,怿以后的大部分应用产品都将充分利用它的注解而实C品的各种Ҏ?br />其它J2SE 5.0q在多线E(q发机制Q、安全、国际化、UI{方面进行了大规模的变更Q得我们能够更方便地进行Java开发?br />其实Q上面的q些变更Qƈ不是我们E序员非要不可的内容。我们完全可以通过自己的办法来辑ֈq些变更实现的功能。但J2SE 5.0的目标就是让我们E序员能够更加方便地q行开发,所以,我们在基于J2SE 5.0开发时Q应该能够明昄体会到它的易用性?br />
展望
时至今日QJ2SE已经发展Z个覆盖面qѝ效率高、易用性强的技术^?见如下的J2SE API体系l构?Q但Javaq没有停止前q的脚步。Mustang版本的J2SE正在紧锣密鼓的开发当中,按以前的惯例Q每两年会发布一个全新的J2SE版本Q所以Mustang开发版对应的J2SE 6.0发布版将?006q完成?br />2005q??3日是Java技术十周年庆典日,在这十年的发展中QJavaq_吸引了四百万开发者,在网l计遍及全球的今天Q更是有17.5亿台讑֤使用了Java技术。作为Java技术的基础QJ2SE的功l不可掩没,我们期望J2SE伴随Javaq_一路走好!
MATRIXC介绍:
MatrixQ面向Java爱好者的非赢利性组l。成立以来,Matrix一直不遗余力地为推动中国Java技术和开源Y件的q步和发展而努力,发布了Jasmin反编译器QJmatrix全站pȝ{开源品。加入MatrixQ与JavapQ[url]www.matrix.org.cn[/url]Q?br />
中国企业走近JCP
?黄v?br />
对Java开发h员,JCPQJava Community ProcessQ这个名词ƈ不陌生。但对国内大部分Java开发h员来_JCP更多的是一个符P一个国际Java开发社区的象征。而对JCPq个l织的来源、组成、运作模式以及JCP对中国Y件业,甚至是我们自w工作事业的影响可能不甚了了。由于历史原因、文化语a的差异,国内Java厂商一直未能对JCP引v_重视Q从而导致国内的软g厂商无法参与到JCP的行业标准的制定q程中去Q结果就使我们只能跟随制定好的标准,而不能媄响标准向着有利于国内Y件业的方向发展?br />
跟随的劣势是很明昄Q以万众期待的下一代Java持久化标准EJB 3Z。EJB 3规范目前仍在早期规范阶段Q预计要刎ͼQ0Q年中期才能完成最l版本,但EJB 3专家l中的Java厂商都已l根据讨论的初步意见开始了产品开发,有些甚至开始发布预览版本。而国内的J2EE厂商却可能要{到EJB 3的最l版才可以着手进行研I和开发(Ҏ早期规范不可靠,变动通常很大Q,差距自然巨大。在其他诸如如商业智能、工作流、数据挖掘等领域都存在类似情c?br />
可喜的是国内软g业的Java行业l织和管理部门都已经认识刎ͼl箋徘徊在JCP的门外不利于国内Java产业的生存和发展Q也和国内庞大的软g市场不相W合。在许许多多有志之士Q很多是W者的前辈Q他们ؓ国内软g业发展默默努力,实在让h钦佩Q的共同努力下,JCP的中国分支也卛_成立。而作为第一个尝试,中国的Java应用体验认证实验室在国家应用软g产品质量监督验中心、Sun计算机系l(中国Q有限公司、中国Y件行业协会中间g分会、北京Y件与信息服务业促q中心四单位共同努力下在北京成立Qؓ中国的Java软g厂商在国内进行Y件的JCP认证和兼Ҏ试?br />http://www.souzz.net/bbs/archiver/?tid-49.html
]]>
]]>
注意q些步骤对DOM而言是不必要的,因ؓDOM已经Z创徏了一个对象模?你的信息用一节Ҏ表示)?/p>
q么看来机器生成的数据是你一般要在java中生成数据结构和cȝ信息。一个简单的例子是包含个Z息的地址,在上图所C。这个地址xml文g不像字处理器文档Q它是一个包含已l被~码成文本的U数据的XML文档?/p>
l论
]]>
2.SysTray for Java ( http://systray.sourceforge.net/ )
q两个都是开源的...可以Ҏ上面的下?
相对来说,我更喜欢SysTray for Java,原因很简?SysTray for Java实现了我所要的功能而且相对来说比Windows Tray Icon 要简?
使用SysTray是很单的.下蝲下来的文件有个例子Example.java,照着q个实现你所需要的功能应该不算困难.
主要是菜单和按钮的操?和操作一般的JFrame一?
下面是一个例子程?
package qiya.systray;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import snoozesoft.systray4j.SysTrayMenu;
import snoozesoft.systray4j.SysTrayMenuEvent;
import snoozesoft.systray4j.SysTrayMenuIcon;
import snoozesoft.systray4j.SysTrayMenuItem;
import snoozesoft.systray4j.SysTrayMenuListener;
public class MainFrame extends JFrame implements ActionListener,
SysTrayMenuListener {
static final int INIT_WIDTH = 400;// 默认H口宽度
static final int INIT_HEIGHT = 244;// 默认H口高度
private static final String toolTip = "宽带计费接口";// 提示文字
static final SysTrayMenuIcon icon = new SysTrayMenuIcon("rocket.gif");// 囄信息
SysTrayMenu menu;// 菜单
private JButton launchButton = new JButton();// 启动按钮
private JButton exitButton = new JButton();// 退出按?
private JLabel statusLabel = new JLabel();// q行状?
public static void main(String[] args) {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (UnsupportedLookAndFeelException e) {
e.printStackTrace();
}
new MainFrame();
}
public MainFrame() {
super("宽带计费接口");// 标题
setIconImage(new ImageIcon(getClass().getResource("rocket.gif"))
.getImage());// 图标
this.setLayout(null);
this.setSize(new Dimension(INIT_WIDTH, INIT_HEIGHT));
Dimension dimScreen = Toolkit.getDefaultToolkit().getScreenSize();
int xPos = (dimScreen.width - INIT_WIDTH) / 2;
int yPos = (dimScreen.height - INIT_HEIGHT) / 2;
statusLabel.setText("pȝ状态监?);
statusLabel.setBounds(new Rectangle(45, 35, 280, 40));
statusLabel.setToolTipText("当前pȝ的运行状?);
statusLabel.setFont(new Font("宋体", 0, 14));
launchButton.setText("启动");
launchButton.setBounds(new Rectangle(80, 180, 80, 23));
exitButton.setText("退?);
exitButton.setBounds(new Rectangle(230, 180, 80, 23));
this.getContentPane().add(statusLabel, null);
this.getContentPane().add(launchButton, null);
this.getContentPane().add(exitButton, null);
launchButton.addActionListener(this);
exitButton.addActionListener(this);
this.setBounds(xPos, yPos, INIT_WIDTH, INIT_HEIGHT);
icon.addSysTrayMenuListener(this);
this.createMenu();
this.setVisible(true);
}
/**
* 创徏菜单
*
*/
private void createMenu() {
SysTrayMenuItem subItem1 = new SysTrayMenuItem("退?, "退?);
subItem1.addSysTrayMenuListener(this);
SysTrayMenuItem subItem2 = new SysTrayMenuItem("关于", "关于");
subItem2.addSysTrayMenuListener(this);
SysTrayMenuItem subItem3 = new SysTrayMenuItem("帮助", "帮助");
subItem3.addSysTrayMenuListener(this);
menu = new SysTrayMenu(icon, toolTip);// 生成菜单
menu.addItem(subItem1);
menu.addSeparator();
menu.addItem(subItem2);
menu.addItem(subItem3);
}
/**
* 点击按钮事g
*/
public void actionPerformed(ActionEvent e) {
if (e.getActionCommand().equalsIgnoreCase("退?)) {
System.exit(0);
} else if (e.getActionCommand().equalsIgnoreCase("启动")) {
// 启动计费E序
}
}
/**
* 菜单选择事g
*/
public void menuItemSelected(SysTrayMenuEvent e) {
if (e.getActionCommand().equalsIgnoreCase("退?)) {
System.exit(0);
} else if (e.getActionCommand().equalsIgnoreCase("关于")) {
JOptionPane.showMessageDialog(this, "宽带计费接口" + "完成?005-3-27");
} else if (e.getActionCommand().equalsIgnoreCase("帮助")) {
JOptionPane.showMessageDialog(this, "宽带计费接口" + "帮助文g待写...");
}
}
/**
* 左键单击事g
*/
public void iconLeftClicked(SysTrayMenuEvent e) {
if (this.isVisible()) {// 如果可见,最化
this.setVisible(false);
} else {// 如果不可见显C出?br /> this.setVisible(true);
}
}
/**
* 左键双击事g
*/
public void iconLeftDoubleClicked(SysTrayMenuEvent e) {
if (this.isVisible()) {// 如果可见,最化
this.setVisible(false);
} else {// 如果不可见显C出?br /> this.setVisible(true);
}
}
}
转自Qhttp://www.xjtublog.com/user1/1034/archives/2006/64310.shtml
]]> // 取得pȝ托盘对象
2final Tray tray = shell.getDisplay().getSystemTray();
3
4if (tray != null) {
5 // 生成托盘对象
6 final TrayItem item = new TrayItem(tray, SWT.NONE);
7 // 为托盘对象添加鼠标停留时的文?/span>
8 item.setToolTipText(“六月天?;
9 // 为托盘添加事?/span>
10 item.addListener(SWT.Show, new Listener() {
11 public void handleEvent(Event event) {
12 System.out.println("show");
13 }
14 });
15 item.addListener(SWT.Hide, new Listener() {
16 public void handleEvent(Event event) {
17 System.out.println("hide");
18 }
19 });
20 item.addListener(SWT.Selection, new Listener() {
21 public void handleEvent(Event event) {
22 System.out.println("selection");
23 }
24 });
25 item.addListener(SWT.DefaultSelection, new Listener() {
26 public void handleEvent(Event event) {
27 System.out.println("default selection");
28 }
29 });
30 // 为托盘对象添加显C用的图?/span>
31 item.setImage(image);
32 // 生成菜单?/span>
33 final Menu menu = new Menu(shell, SWT.POP_UP);
34 MenuItem miShow = new MenuItem(menu, SWT.PUSH);
35 miShow.setText("S&how");
36
37 miShow.addSelectionListener(new SelectionListener() {
38 public void widgetSelected(SelectionEvent arg0) {
39 shell.setVisible(true);
40 shell.setMaximized(true);
41 }
42
43 public void widgetDefaultSelected(SelectionEvent arg0) {
44 }
45 });
46
47 MenuItem miExit = new MenuItem(menu, SWT.PUSH);
48 miExit.setText("E&xit");
49
50 miExit.addSelectionListener(new SelectionListener() {
51 public void widgetSelected(SelectionEvent arg0) {
52 exitAction.run();
53 }
54
55 public void widgetDefaultSelected(SelectionEvent arg0) {
56 }
57 });
58
59 // 为托盘对象添加事Ӟ当右键点d标时Q显C?/span>
60 item.addListener(SWT.MenuDetect, new Listener() {
61 public void handleEvent(Event event) {
62 menu.setVisible(true);
63 }
64 });
65}
ȝQswt/jface为javaE序员提供了快速反映的界面Q由于swt/jface本n也是利用JNI来调用系l的界面Q所以在实现界面的同时也为程序员提供了一些与操作pȝ交互的方法。利用这些方法,可以很方便快捷地完成我们的功能?br />
Eclipse的Forms也非怸错,提供了华丽的界面Q写出来的程序就如同|页一P当然要有一定的审美眼光Q有兴趣的朋友不仿研I研I?br />
转自Qhttp://www.aygfsteel.com/hiswing/archive/2006/08/09/62593.html
]]>
S:select abs(-1) value
O:select abs(-1) value from dual
2.取整(?
S:select ceiling(-1.001) value
O:select ceil(-1.001) value from dual
3.取整Q小Q?
S:select floor(-1.001) value
O:select floor(-1.001) value from dual
4.取整Q截取)
S:select cast(-1.002 as int) value
O:select trunc(-1.002) value from dual
5.四舍五入
S:select round(1.23456,4) value 1.23460
O:select round(1.23456,4) value from dual 1.2346
6.e为底的幂
S:select Exp(1) value 2.7182818284590451
O:select Exp(1) value from dual 2.71828182
7.取e为底的对?br /> S:select log(2.7182818284590451) value 1
O:select ln(2.7182818284590451) value from dual; 1
8.?0为底Ҏ
S:select log10(10) value 1
O:select log(10,10) value from dual; 1
9.取^?br /> S:select SQUARE(4) value 16
O:select power(4,2) value from dual 16
10.取^Ҏ
S:select SQRT(4) value 2
O:select SQRT(4) value from dual 2
11.求Q意数为底的幂
S:select power(3,4) value 81
O:select power(3,4) value from dual 81
12.取随机数
S:select rand() value
O:select sys.dbms_random.value(0,1) value from dual;
13.取符?br /> S:select sign(-8) value -1
O:select sign(-8) value from dual -1
----------数学函数
14.圆周?br /> S:SELECT PI() value 3.1415926535897931
O:不知?/p>
15.sin,cos,tan 参数都以弧度为单?br /> 例如Qselect sin(PI()/2) value 得到1QSQLServerQ?/p>
16.Asin,Acos,Atan,Atan2 q回弧度
17.弧度角度互换(SQLServerQOracle不知?
DEGREESQ弧?〉角?br /> RADIANSQ角?〉弧?/p>
---------数值间比较
18. 求集合最大?br /> S:select max(value) value from
(select 1 value
union
select -2 value
union
select 4 value
union
select 3 value)a
O:select greatest(1,-2,4,3) value from dual
19. 求集合最?br /> S:select min(value) value from
(select 1 value
union
select -2 value
union
select 4 value
union
select 3 value)a
O:select least(1,-2,4,3) value from dual
20.如何处理null?F2中的null?0代替)
S:select F1,IsNull(F2,10) value from Tbl
O:select F1,nvl(F2,10) value from Tbl
--------数值间比较
21.求字W序?br /> S:select ascii('a') value
O:select ascii('a') value from dual
22.从序h字符
S:select char(97) value
O:select chr(97) value from dual
23.q接
S:select '11'+'22'+'33' value
O:select CONCAT('11','22')||33 value from dual
23.子串位置 --q回3
S:select CHARINDEX('s','sdsq',2) value
O:select INSTR('sdsq','s',2) value from dual
23.模糊子串的位|?--q回2,参数L中间%则返?
S:select patindex('%d%q%','sdsfasdqe') value
O:oracle没发玎ͼ但是instr可以通过W四N刂瞥鱿执问?BR> select INSTR('sdsfasdqe','sd',1,2) value from dual q回6
24.求子?br /> S:select substring('abcd',2,2) value
O:select substr('abcd',2,2) value from dual
25.子串代替 q回aijklmnef
S:SELECT STUFF('abcdef', 2, 3, 'ijklmn') value
O:SELECT Replace('abcdef', 'bcd', 'ijklmn') value from dual
26.子串全部替换
S:没发?br /> O:select Translate('fasdbfasegas','fa','? ) value from dual
27.长度
S:len,datalength
O:length
28.大小写{?lower,upper
29.单词首字母大?br /> S:没发?br /> O:select INITCAP('abcd dsaf df') value from dual
30.左补I格QLPAD的第一个参CؓI格则同space函数Q?br /> S:select space(10)+'abcd' value
O:select LPAD('abcd',14) value from dual
31.双I格QRPAD的第一个参CؓI格则同space函数Q?br /> S:select 'abcd'+space(10) value
O:select RPAD('abcd',14) value from dual
32.删除I格
S:ltrim,rtrim
O:ltrim,rtrim,trim
33. 重复字符?br /> S:select REPLICATE('abcd',2) value
O:没发?/p>
34.发音怼性比?q两个单词返回gP发音相同)
S:SELECT SOUNDEX ('Smith'), SOUNDEX ('Smythe')
O:SELECT SOUNDEX ('Smith'), SOUNDEX ('Smythe') from dual
SQLServer中用SELECT DIFFERENCE('Smithers', 'Smythers') 比较soundex的差
q回0-4Q?为同韻I1最?/p>
--------------日期函数
35.pȝ旉
S:select getdate() value
O:select sysdate value from dual
36.前后几日
直接与整数相加减
37.求日?br /> S:select convert(char(10),getdate(),20) value
O:select trunc(sysdate) value from dual
select to_char(sysdate,'yyyy-mm-dd') value from dual
38.求时?br /> S:select convert(char(8),getdate(),108) value
O:select to_char(sysdate,'hh24:mm:ss') value from dual
39.取日期时间的其他部分
S:DATEPART ?DATENAME 函数 Q第一个参数决定)
O:to_char函数 W二个参数决?/p>
参数---------------------------------下表需要补?br /> year yy, yyyy
quarter qq, q (季度)
month mm, m (m O无效)
dayofyear dy, y (O表星?
day dd, d (d O无效)
week wk, ww (wk O无效)
weekday dw (O不清?
Hour hh,hh12,hh24 (hh12,hh24 S无效)
minute mi, n (n O无效)
second ss, s (s O无效)
millisecond ms (O无效)
----------------------------------------------
40.当月最后一?br /> S:不知?br /> O:select LAST_DAY(sysdate) value from dual
41.本星期的某一天(比如星期日)
S:不知?br /> O:SELECT Next_day(sysdate,7) vaule FROM DUAL;
42.字符串{旉
S:可以直接转或者select cast('2004-09-08'as datetime) value
O:SELECT To_date('2004-01-05 22:09:38','yyyy-mm-dd hh24-mi-ss') vaule FROM DUAL;
43.求两日期某一部分的差Q比如秒Q?br /> S:select datediff(ss,getdate(),getdate()+12.3) value
O:直接用两个日期相减(比如d1-d2=12.3Q?br /> SELECT (d1-d2)*24*60*60 vaule FROM DUAL;
44.Ҏ差值求新的日期Q比如分钟)
S:select dateadd(mi,8,getdate()) value
O:SELECT sysdate+8/60/24 vaule FROM DUAL;
45.求不同时区时?br /> S:不知?br /> O:SELECT New_time(sysdate,'ydt','gmt' ) vaule FROM DUAL;
-----时区参数,北京在东8区应该是Ydt-------
AST ADT 大西z标准时?br /> BST BDT 白oh准时?br /> CST CDT 中部标准旉
EST EDT 东部标准旉
GMT 格林治标准旉
HST HDT 阿拉斯加—夏威夷标准旉
MST MDT 山区标准旉
NST U芬兰标准时?br /> PST PDT 太^z标准时?br /> YST YDT YUKON标准旉
---------------------------------------
n
释出?/span>
(Latest Release builds)
E.g.,3.1.2
Releases are builds that have been declared major releases by the development team - for example "R1.0". Releases are the right builds for people who want to be on a stable, tested release, and don't need the latest greatest features and improvements. Release builds always have an "R" at the beginning of the name i.e. R1.0, R2.0 etc. Non-release builds are named according to the date of the build - for example 20011027 is the build from Oct 27, 2001.
?span lang="EN-US">Eclipse开发团队所宣称的主要稳定版本?span lang="EN-US">Release buildsl过完整试Qƈh一致性、定义清楚的功?能。它的定位就跟上市的商业软g一栗?/font>
n
E_?/span>
(Stream Stable builds)
E.g., 3.2RC7
Stable builds are integration builds that have been found to be stable enough for most people to use. They are promoted from integration build to stable build by the architecture team after they have been used for a few days and deemed reasonably stable. The latest stable build is the right build for people who want to stay up to date with what is going on in the latest development stream, and don't mind putting up with a few problems n in order to get the latest greatest features and bug fixes. The latest stable build is the one the development team likes people to be using, because of the valuable and timely feedback.
?span lang="EN-US">Release buildCU的版本Q经?span lang="EN-US">Eclipse开发团队测试,q认定它相当E_。新功能通常会在此过渡版本出现。它的定位就跟商业Y件的beta版一栗?/font>
n
整合?/span>
(Stream Integration builds)
E.g., I20060614-0843
Periodically, component teams version off their work in what they believe is a stable, consistent state, and they update the build configuration to indicate that the next integration build should take this version of the component. Integration builds are built from these stable component versions that have been specified by each component team as the best version available. Integration builds may be promoted to stable builds after a few days of testing. Integration builds are built whenever new stable component versions are released into the build.
此版本的各个独立的组件已l过Eclipse开发团队认定具有稳定度Q但不保证集成在一h问题。若集成在一?够稳定,它就有可能晋升成Stable build?/font>
n
当日最新版Q?/span>
Stream Nightly
builds)
E.g., N20060617-0010
Nightly builds are produced every night from whatever has been released into the HEAD stream of the CVS repository. They are completely untested and will almost always have major problems. Many will not work at all. These drops are normally only useful to developers actually working on the Eclipse Project.
此版本显然是从最新的原始码生出来的。可惌知Q此版本当然不保证它跑v来没问题Q搞不好q有严重?span lang="EN-US">bug?/font>
n
l护?/span>
(Stream Maintenance Build) E.g.,. R2_1_maintenance
Q?/span>
R2.1 or R
Maintenance builds are produced periodically to incorporate fixes into an existing release. They are typically built from tagged plug-in and feature pojects in a maintenance stream of the CVS repository (i.e. R2_1_maintenance). Maintenance builds are promoted to a minor or service release (i.e. R2.1 or R
命oQ?font color="#0000ff">ping 192.168.0.8 Qt Q参敎ͼt是等待用户去中断试
友情提示Q这个是最基本Q最常用的网l命?/p>
2.查看DNS、IP、Mac{信?/b>
A.Win98Q?font color="#0000ff">winipcfg
B.Win2000以上Q?font color="#0000ff">Ipconfig/all
3.|络信
命oQ?font color="#0000ff">Net send 计算机名/IP * (q播) 传送内容,注意不能跨网D?/p>
命oQ?font color="#0000ff">net stop messenger 停止信服务Q也可以在面板-服务修改
命oQ?font color="#0000ff">net start messenger 开始信使服?/p>
4.探测Ҏ计算机名Q所在的l、域及当前用户名 Q追捕的工作原理Q?/font>
命oQ?font color="#0000ff">ping Qa IP Qt Q只昄NetBios?/p>
命oQ?font color="#0000ff">nbtstat -aIP 比较全的
5.netstat -a 昄Z的计机当前所开攄所有端?/font>
命oQ?font color="#0000ff">netstat -s -e
比较详细的显CZ的网l资料,包括TCP、UDP、ICMP ?IP的统计等
6.探测arpl定Q动态和静态)列表Q显C所有连接了我的计算机,昄ҎIP和MAC地址
命oQ?font color="#ff0000">arp -a
7.在代理服务器?/font>
捆绑IP和MAC地址Q解军_域网内盗用IPQ:
命oQ?font color="#0000ff">ARP Qs 192.168.10.59 00 Q?0QffQ?cQ?8Q?5
解除|卡的IP与MAC地址的绑定:
命oQ?font color="#0000ff">arp -d |卡IP
8.在网l邻居上隐藏你的计算?/font>
命oQ?font color="#0000ff">net config server /hidden:yes
命oQ?font color="#0000ff">net config server /hidden:no 则ؓ开?/p>
9.net命o
A.昄当前工作l服务器列表 net viewQ当不带选项使用本命令时Q它׃昄当前域或|络上的计算Z的列表?/p>
比如Q查看这个IP上的׃n资源Q就可以
C:\>net view 192.168.10.8
?192.168.10.8 的共享资?/p>
资源׃n?cd 用?注释
|站服务 Disk
命o成功完成?/p>
B.查看计算Z的用户帐号列?net user
C.查看|络链接 net use
例如Qnet use z: \192.168.10.8\movie 这个IP的movie׃n目录映射为本地的Z?/p>
D.记录链接 net session
例如: C:\>net session
计算?用户?客户cd 打开I闲旉
\192.168.10.110 ROME Windows 2000 2195 0 00:03:12
\192.168.10.51 ROME Windows 2000 2195 0 00:00:39
命o成功完成?br />
10.路由跟踪命o
A.tracert software.pchome.net
B.pathping software.pchome.net 除了昄路由外,q提?25S的分析,计算丢失包的Q?/p>
11.关于׃n安全的几个命?/b>
A.查看你机器的׃n资源 net share
B.手工删除׃nQ可以编个bat文gQ开q行Q把׃n都删了!Q?/p>
命oQnet share c$ /d
命oQnet share d$ /d
命oQnet share ipc$ /d
命oQnet share admin$ /d
注意$后有I格?/p>
C.增加一个共享:
c:\net share mymovie=e:\downloads\movie /users:1
mymovie ׃n成功?/p>
同时限制链接用户Cؓ1人?/p>
12.在DOS行下讄静态IP
A.讄静态IP
CMD
netsh
netsh>int
interface>ip
interface ip>set add "本地链接" static IP地址 mask gateway
B.查看IP讄
interface ip>show address
Arp
昄和修改“地址解析协议 (ARP)”缓存中的项目。ARP ~存中包含一个或多个表,它们用于存储 IP 地址及其l过解析的以太网或o牌环物理地址。计机上安装的每一个以太网或o牌环|络适配器都有自己单独的表。如果在没有参数的情况下使用Q则 arp 命o显C帮助信息?/p>
觉得有用,记得Ҏ藏哦~~
AOP没有出现以前Q该领域l典的设计模式是DecoratorQ像Java IO Stream的设计就是如?不过Q如果ؓ每个DAO, 每个Ҏ的写Decorator函数会写Mh的,所以用上cglib的好处是一ơ过拦截所有方法。?br />
另外Qcglib除了Enhancer之外Q还有BulkBean和TransformQ都是Hibernate持久化的基础Q但文档贫乏Q一时还没去看怎么用?br />
1.AOP里讲了一N阿一N的log aspect在cglib是这样做?