运行headless Java服务器

对于一个Java服务器来说经常要处理一些图形元素,例如地图的创建或者图形和图表等。这些API基本上总是需要运行一个X-server以便能使用AWT(Abstract Window Toolkit,抽象窗口工具集)。然而,运行一个不必要的X-server并不是一种好的网络管理方式。 这个解决方案依赖于你的Java版本。如果你运行在JDK1.4上,那么你将有机会运行headless服务器。 -Djava.awt.headless=true 对于JDK1.3及更低的版本,有个来自eTeks的PJA工具包(Pure Java AWT Toolkit,纯Java AWT工具集)可以使用。它是一个在配置上与Sun的1.4版非常相似的headlessJava服务器,这种配置方式包含一组-D属性标志。 你需要下载相关的jar,将它们放到你的CLASSPATH中,然后设置下面的标志: Dawt.toolkit=com.eteks.awt.PJAToolkit Djava.awt.graphicsenv=com.eteks.java2d.PJAGraphicsEnvironment 在IBM的JDK下,你能找到下列所需的属性,这里我们将PJA的jar要放到lib/pja下: Djava.awt.fonts=$JAVA_HOME/jre/lib/fonts Djava2d.font.usePlatformFont=false Duser.home=lib/pja 你可以从eTeks网站上下载PJA工具包。 -------------------------------------------------------------------------------- 译者注:在JDK1.4的新特性的AWT中提到 headless支持是指在图形环境下是否支持显示器、鼠标和键盘,详细内容可以参考Sun的网站的headless支持 <淘宝热门商品:
 

0.11 元 

:麒麟电子

★麒麟电子★超高亮的led灯箱专用led白发蓝5mm圆头聚光灯珠

 

50.00 元 

黑头粉刺净 扫光黑头粉刺顽痘 卖疯了


来源:程序员网

小小豆叮

Windows2000下的Apache2与Tomcat4的整合

题目:Windows2000 profession下的Apache2与Tomcat4的整合 作者:robornet 日期:2002-10-30 原由:搞了一段时间的java项目,到分发的时候了,可找不到一份最新的Apache2与Tomcat4的整合配置,遂看了半天的jakarta在线资料,并参照以前网友的文章,写了这篇配置文档,以作参考,欢迎斧正! 原文: http://www.xtong.com.cn/robornet/docs/Apache2_Tomcat4.txt 目录: 一、软件准备 二、软件安装 三、首次配置及测试 四、整合配置 五、全线测试 六、不足 七、感谢 八、说明 九.改进 步骤: 一、软件准备: 假设你有一台能正常运行win2000 professional的硬软软件环境 1.j2sdk1.4.1: 到 http://java.sun.com/j2se/1.4.1/download.html下载!(注意是Windows (all languages, including English)的sdk版) 2.Apache2.0.43: 到 http://www.apache.inetcosmos.org/dist/httpd/binaries/win32/apache_2.0.43-win32-x86-no_ssl.msi 下载! 3.Tomcat4.1.12:到 http://jakarta.apache.org/builds/jakarta-tomcat-4.0/release/v4.1.12/bin/jakarta-tomcat-4.1.12.exe 下载! 4.mod_jk.dll: 到 http://jakarta.apache.org/builds/jakarta-tomcat-connectors/jk/release/v1.2.0/bin/win32/mod_jk-2.0.42.dll下载! (说明,由于mod_jk2-2.0.43.dll与Apache2.0.43配置没成功,现用mod_jk-2.0.42.dll代替) 二、软件安装: (1)安装j2sdk: 1.按照安装向导进行安装(一般安装到C:\j2sdk1.4.1下,方便下面操作) (2)安装apache: 1.按照安装向导进行安装(选择安装目录为C:\,方便下面操作;安装成功后其路径为:C:\Apache2) (3)安装Tomcat: 1.按照安装向导进行安装(更改安装目录为C:\Tomcat4,方便下面操作),其间会要你输入Admin(系统管理员)的口令。 三、首次配置及测试: 对以上安装的软件环境进行首次配置,并测试其环境。 (1)配置--环境变量: 1.新建系统变量JAVA_HOME,其值为:C:\j2sdk1.4.1 //若你没按以上路径安装请更改为正确的路径 2.新建系统变量TOMCAT_HOME,其值为:C:\Tomcat4 //同上 3.新建系统变量CLASSPATH,其值为:%JAVA_HOME%\lib;%TOMCAT_HOME%\lib (2)修改错误: 1.Apache2.0.43有一个小问题,默认安装成功后在Apache2主目录下的htdocs目录中没有index.html文件,你须将该目录下的index.html.en改名为index.html (3)测试默认服务: 请先运行Apache2与Tomcat4. 1.打开浏览器,在地址栏中输入:http://localhost 检验:此时能在浏览器中看到Apache2的欢迎界面.说明Apache2工作正常.(注意,Tomcat默认端口为80, 若有其它程序占用,请更改,下面有说明) 2.打开浏览器,在地址栏中输入:http://localhost:8080 检验:此时能在浏览器中看到Tomcat的欢迎界面.说明Tomcat工作正常.(注意,Tomcat默认端口为 8080,若有其它程序占用,请更改,下面有说明) 小结:若到此步骤没有任何错误,那可继续下面的操作,Let' go! (4)测试你的项目: 现只用Tomcat测试你的项目,为方便此例说明,假设你已有一个项目在E:\Application\OA目录下 (包含index.jsp及其它jsp文件和bean,如WEB-INF\classes\下的servlet、javabean)。 1.设置Tomcat以支持你的项目,打开C:\Tomcat4\conf\server.xml文件,在""之前,""之后添加 并保存。 说明:Context (表示一个web应用程序): docBase定义应用程序的路径;path 表示此web应用程序的url的前缀,这样请求的url为http://localhost:8080/oa; reloadable 这个属性非常重要,如果为true,则tomcat会自动检测应用程序的/WEB-INF/lib 和/WEB-INF/classes目录的变化,自动装载修改或新的bean 及servlet,我们可以在不重起tomcat的情况下看到bean带给jsp的变化。 2.启动你Tomcat4.1.12,在浏览器的地址中输入http://localhost:8080/oa,如你的jsp及bean,servlet没有错误,一般会将你的index.jsp/index.html文件的 内容给执行并显示。 小结:若到此步骤没有任何错误,那可继续下面的操作,Let' go! 四、整合配置: 对Apache与Tomcat做相应的配置,让其共同为你工作。 若Apache2与Tomcat4正运行着,请关闭它们。 (1)配置Apache2: 1.先将下载的mod_jk-2.0.42.dll复制到C:\Apache2\modules下。 2.设置主页文件类型:打开C:\Apache2\conf下的httpd.conf,查找"DirectoryIndex",在index.html的后面添加index.jsp并保存,注意相互之间应有空格。 3.设置虚拟主机,让Apache自动控制html与jsp的解析: 打开C:\Apache2\conf\httpd.conf,在最后加入下面这段代码并保存。 //localhost为本机,你可用本机ip ServerAdmin robornet@robornet.com //你的mail地址 DocumentRoot E:\Application //你的项目组根目录,因为Application下有OA及其它多个项目,因此只能设为E:\Application ServerName localhost //你的服务名,若你的机器有域名,设为域名,但现用本机作测试 ErrorLog logs/robornet_home_log.txt //错误日志,在C:\Apache2\logs下,可用其它任意名字 CustomLog logs/robornet_Custom_log.txt common //访问日志,在C:\Apache2\logs下,可用其它任意名字 4.设置Apache与Tomcat之间的连接,让Apache遇到jsp文件时,在后台将其交由Tomcat去处理:打开C:\Apache2\conf\httpd.conf,在最后加入下面这段代码并保存。 # Using mod_jk2.dll to redirect dynamic calls to Tomcat LoadModule jk_module modules/mod_jk-2.0.42.dll //装载模块,用于处理连接 JkWorkersFile "C:/Tomcat4/conf/workers.properties" //设置模块的工作文件,下面会说明 JkLogFile "C:/Tomcat4/logs/mod_jk2.log" //设置模块工作的日志文件,Tocmat启动时会自建 JkMount /servlet/* ajp13 //让Apache支持对servlet传送,用以Tomcat解析 JkMount /*.jsp ajp13 //让Apache支持对jsp传送,用以Tomcat解析 小结:到此Apache的配置基本完成,不过这时启动Apache还不能正常工作。 (2)配置Tomcat4: 1.在C:\Tomcat4\conf下新建一个文件workers.properties 注意文件后缀,建议用EditPlus或UltraEdit建立,若用记事本,记得改名, 不要成了workers.properties.txt了!其内容如下: workers.tomcat_home=c:\Tomcat4 //让mod_jk模块知道Tomcat workers.java_home=c:\j2sdk1.4.1 //让mod_jk模块知道j2sdk ps=\ worker.list=ajp13 //模块版本,现有ajp14了,不要修改 worker.ajp13.port=8009 //工作端口,若没占用则不用修改 worker.ajp13.host=localhost //本机,若上面的Apache主机不为localhost,作相应修改 worker.ajp13.type=ajp13 //类型 worker.ajp13.lbfactor=1 //代理数,不用修改 2.打开C:\Tomcat4\conf下的server.xml文件:查找到"",将以前的代码: 更改为: 并保存后关闭. 小结: 兄弟一定都累了吧!好了,可以来一杯java,好好享受你的成果吧! 五、全线测试: 1.启动Apache2,Tomcat4 。 2.打开你的浏览器,在地址栏中输入http://localhost:8080/oa ,若与上面的测试相同,则Tomcat重新配置后正常! 3.在地址栏中输入http://localhost/oa ,若与http://localhost:8080/oa的结果相同,那恭喜你,Apache2与Tomcat4整合成功了!!! 六、不足: 1.虽用最新的Apache2.0.43与Tomcat4.1.12,但我是用的jk连接的,刚用jk2配置未成功,所以只好写这份文档了! 2.Tomcat还是采用的Tomcat-Standalone,未采用Tomcat-Apache,不过这个大家可以自己完成,这个应不是个问题! 七、感谢: 1.感谢Apache组织,为我提供了如此之好的服务器,而且还是免费的! 2.感谢www.chinajavaworld论坛,是它给了我们一个平等的交流空间! 3.感谢以前写过Apache1.x与Tomcat3.x/Tomcat4.*配置文档的朋友们,为我今天写这篇文档作了参考! 八、说明: 1.若您觉得满意,想转载或收藏这篇文章,我非常感谢,但请您注明作者robornet及出处: http://www.xtong.com.cn/robornet 。 九===============================================================================||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| 最新改变===================================================== ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| 因我没采用jk2,而现在jk2已很稳定了,建议你用jk2来配置! 附网友一作,以补之不足! 本文介绍的配置方法,用JK2连接Apache和Tomcat,连接使用JNI通道。并且启动Apache时,Apache会通过JNI直接在后台启动Tomcat,无须你再手工启动Tomcat。 我是参考Apache网站的资料,并在自己Win2K上配置成功。配置过程如下,希望对大家有用。 安装版本: Apache 2.0.44 Tomcat 4.1.18 mod_jk2-2.0.43.dll 以上版本都可在WWW.APACHE.ORG下载 整合步骤 首先假定Apache2和Tomcat4已经安装完成,安装目录分别为:[Apache_install_dir]和[Tomcat_install_dir]。并且Apache的服务端口为80,Tomcat服务端口为8080。 一:在Apache2中安装mod_jk2-2.0.43.dll 将mod_jk2-2.0.43.dll拷贝到[Apache_install_dir]/modules目录中 编辑[Apache_install_dir]/conf/httpd.conf配置文件,在文件最后添加如下一行: LoadModule jk2_module modules/mod_jk2-2.0.43.dll 二:配置Apache端 Apache端通过workers2.properties文件使用JK2。 在[Apache_install_dir]/conf目录中新建文件workers2.properties。(注意不要误建成workers2.properties.txt) 编辑该文件,添加如下内容: # Define the comunication channel [channel.jni:jni] info=The jni channel, used if tomcat is started inprocess # Define the parameters for the Java Virtual Machine [vm:] info=Parameters used to load a JVM in the server process OPT=-Djava.class.path=[Tomcat_install_dir]/bin/tomcat-jni.jar;[Tomcat_install_dir]/bin/bootstrap.jar;[Tomcat_install_dir]/bin/commons-daemon.jar OPT=-Dtomcat.home=[Tomcat_install_dir] OPT=-Dcatalina.home=[Tomcat_install_dir] OPT=-Xmx128M # JNI worker startup handler [worker.jni:onStartup] info=Command to be executed by the VM on startup. This one will start tomcat. class=org/apache/jk/apr/TomcatStarter ARG=start stdout=${serverRoot}/logs/stdout.log stderr=${serverRoot}/logs/stderr.log # JNI worker shutdown handler [worker.jni:onShutdown] info=Command to be executed by the VM on shutdown. This one will stop tomcat. class=org/apache/jk/apr/TomcatStarter ARG=stop # Map the Tomcat examples webapp to the Web server uri space [uri:/examples/*] info=Map the whole webapp 注意:其中[Tomcat_install_dir]用你实际安装路径代替,[uri:/examples/*]用于映射Tomcat的examples Webapp,为了后面测试用。 三:配置Tomcat端 Tomcat端通过jk2.properties文件使用JK2。 在[Tomcat_install_dir]/conf目录中已经有jk2.properties文件,用如下内容覆盖原内容: # Set the desired handler list handler.list=apr,request,container,channelJni # Enable jni use channelJni directive apr.jniModeSo=[Apache_install_dir]\modules\mod_jk2-2.0.43.dll # If set to inprocess the mod_jk2 will Register natives itself # This will enable the starting of the Tomcat from mod_jk2 # If you wish to start the Tomcat from inside web server then # you don't need any above directive. Here is shown the default # value for the apr that you can ommit apr.jniModeSo=inprocess 四:测试 以上配置完毕后,整合就成功了。启动Apache。(不必手工启动Tomcat,Apache会自动在后台启动Tomcat,Tomcat的屏幕输出被重新定向到[Apache_install_dir]/logs/stdout.log和stderr.log中。 打开浏览器,访问 http://localhost/examples/ 哈哈!成功了没有? <淘宝热门商品:
 

 

衣品堂

 

4.60 元  

旺智通讯手机配件商城-----诚邀各地商家加盟合作(可代发货)

皇冠推荐 特卖 诺基亚原装二手BL-5C电池 型号BL5C


来源:程序员网

小小豆叮

轻松处理命令行参数

你能够轻松地使用java标准的传递标志的方式获得一个简单且功能强大的命令行应用。事实上,传递进来的标志不仅仅在main方法中有效。 java命令直接将带有-D的标志传递给了System类的Properties对象。这允许通过System.getProperty的方式检出这个标志。 通过java -Dflag=jack运行下面的代码将在屏幕上输出“jack”。 public class ShowFlag { static public void main(String[] args) { String flag = System.getProperty("flag"); System.err.println(flag); } } 如果想查看所有的属性,你可以运行下面的代码: import java.util.Properties; public class ShowAll { static public void main(String[] args) { Properties sysprops = System.getProperties(); sysprops.list(System.err); } } 当传递新的系统属性的时候,通常采用以域名倒序的风格,例如: java -Dcom.generationjava.someproduct.color=green rather than: java -Dcolor=green 这个技巧能能防止你的标记和传递进来的其它系统属性冲突。 这只是一个简单类的例子,对于一个完备的Java命令行应用其实需要使用合适的参数处理器。这个参数处理器能够帮助校验是否允许一个特定的标记,它也允许简单的一个字符的标记和值的自动转换。 <淘宝热门商品:
 

 

:◤╭ Shanghai 秀卡蒂╮╰女性健康購物中心 ╯◥◣瘦身╮減肥╮

 

88.00 元 

双皇冠热卖 日本原装 RAKU系列30倍运动硅胶


来源:程序员网

小小豆叮

使用混淆器,保护你的java程序

RetroGuard的使用方法: RetroGuard是一个很不错的Java混淆器,而且在JBuilder7的企业版中也带了这个混淆器。 RetroGuard本身是一个Java程序(一个Jar包),所以要使用的话必须先安装JDK。运行前需要设置一些环境变量,除了要在PATH中包含java的执行路径以外,还要在CLASSPATH中加入D:\retroguard\RetroGuard.jar(假设你的RetroGuard.jar在D:\retroguard下)。如果没有设置CLASSPATH的话也不要紧,只不过每次运行时就要通过 -classpath 加上路径参数。设置好运行环境以后还要准备好你要混淆的.jar文件包,至于如何把编译好的类打包成.jar文件就不在这里多说了。 RetroGuard的执行格式是: java RetroGuard [输入JAR文件 [输出JAR文件 [“保留脚本文件” [日志文件]] 其中“保留脚本文件”描述了那些类、函数、变量名必须保留,不能被混淆;日志文件是执行后生成的记录文件,记录的错误、混淆情况等信息。 对于“保留脚本文件”可以通过一个图形界面RGgui来设置,执行命令是: java RGgui 运行后,可以根据提示选择输入Jar文件,选择要保留的类、函数、变量,完成后会自动生成“保留脚本文件”。其实通常情况下只要保留运行的起始类名称就可以了。 如果你的Jar包用到了第三方的函数库,比如Siemens的API,那么就要在 -classpath 参数中指定。例如: java -classpath c:\siemens\smtk\6688i1_b8\lib\api.jar RetroGuard in.jar out.jar script.txt log.txt 如果RetroGuard混淆失败,可以查看日志文件取得错误信息。 这里我发现一个问题,就是遇到有类似 ...$$1.class 这样的文件,RetroGuard会提示出错,后来我修改了他的源代码,直接跳过了对这种文件的处理。 JBuilder7中RetroGuard的设置和用法: JBuilder7的企业版中带了RetroGuard v1.1,再JBuilder7安装路径下的retroguard-v1.1目录中。在JBuilder7中可以直接调用RetroGuard。设置的方法如下: 点菜单Tools -> Configure Obfuscators配置混淆器,点左下角的New...新建一个混淆器,选择RetroGuard的路径,完成配置。使用起来要通过Archive Builder,点菜单Wizards -> Archive Builder...,Archive type选择MIDlet(这里仅仅介绍针对J2ME应用),然后根据提示一步一步往下设置,到达第9步也就是混淆器设置的时候,选中obfuscate the contents of the archive,Obfuscator选择混淆器,Use the classes specified blow下面添加要保留的类(默认保留起始执行类),结束设置。 这样当每次编译的时候,就会自动生成混淆过的Jar文件包了。 sun的jade 运行java setup.class按装 在F:\jade\lib下 运行java Jade +g 出现图形界面,可以进行混淆了. <淘宝热门商品:
 

 

黑龙江商盟】棋子儿平价美妆店-烟熏彩妆/假睫毛大全/新娘用品

 

198.00 元 

08秋款欧洲正版G-star双排扣夹克外套 超好


来源:程序员网

小小豆叮

怎样在Beblogic中使用BeanShell

有很多网友问为什么在weblogic中beanshell可以执行一般的脚本语句,但是不能引用其他包里面的类的问题.其实这不是beanshell的问题而是weblogic本身已经内置了beanshell类,只不过版本比较老一点. 我们知道系统在引用类的时候是按照在先找到先用的原理调用的,也就是说如果我们在weblogic调用它自己内置的beanshell类之前找到我们设置的beanshell包即可 另外我们在开发web程序的时候需要引用很多的包文件,每次在发布的时候包含这些包文件,程序会变得很大,发布起来很慢.可以按照下面的解决方法解决这类问题,大家如果有更好的方法可以贴出来共同分享. 解决方法如下(以linux为例) 1.建立一个放置常用包的文件夹 比如:/home/web/lib 2.把常用的包放到这个目录中,比如 mail.jar(可以在Jbuilder8_home/lib/下找到) jdom.jar(可以在Jbuilder8_home/lib/下找到) xercesImpl.jar(可以在Jbuilder8_home/lib/下找到 jdom需要使用这个包) xmlParserAPIs.jar(可以在Jbuilder8_home/lib/下找到 jdom需要使用这个包) junit.jar(可以在Jbuilder8_home/thirdparty/junit3.8/找到) rowset.jar(可以到http://developer.java.sun.com/developer/earlyAccess/index.html下载) bsh-1.2b7.jar(可以到http://www.beanshell.org下载) 3.建立一个sh脚本(比如setLib) #!/bin/sh #**************************************************** # defined the extends lib jar #**************************************************** EXT_LIB_JAR="/home/web/lib/mail.jar:/home/web/lib/bsh-1.2b7.jar:home/web/lib/junit.jar:/home/web/lib/jdom.jar:/home/web/lib/exercesImpl.jar:/home/web/lib/xmlParserAPIs.jar:/home/web/lib/rowset.jar" echo ****************************************** echo EXT_LIB_JAR=${EXT_LIB_JAR} echo ****************************************** 4.修改startWeblogic.sh文件 一般最后一行为. "/home/web/bea/weblogic700/server/bin/startWLS.sh" 在这句话之前加入引用setLib.sh文件的命令如下 . "/home/web/lib/setLib.sh" 修改后的内容如下 …… . "/home/web/lib/setLib.sh" . "/home/web/bea/weblogic700/server/bin/startWLS.sh" 5.修改startWLS.sh文件 在home/web/bea/weblogic700/server/bin/startWLS.sh文件中找到 CLASSPATH="${JAVA_HOME}/lib/tools.jar${CLASSPATHSEP}${WL_HOME}/server${CLASSPATHSEP}${WL_HOME}/server/lib/weblogic_sp.jar${CLASSPATHSEP}${WL_HOME}/server/lib/weblogic.jar${CLASSPATHSEP}${CLASSPATH}" 改成 CLASSPATH="${EXT_LIB_JAR}${CLASSPATHSEP}${JAVA_HOME}/lib/tools.jar${CLASSPATHSEP}${WL_HOME}/server${CLASSPATHSEP}${WL_HOME}/server/lib/weblogic_sp.jar${CLASSPATHSEP}${WL_HOME}/server/lib/weblogic.jar${CLASSPATHSEP}${CLASSPATH}" <淘宝热门商品:
 

58.00 元  

淘宝生活 运动鞋专卖/正品ZIPPO热卖//淘宝职业信誉卖家

冲双钻 ADIDAS三叶草08夏季新款特价 漫画小子个性 休闲板鞋

 

3.80 元  

幸福生活 联盟津沽 种子蔬菜种子、花卉种子、园艺用品

【天津商盟】【皇冠信誉】食用草莓种子-观赏草莓种子-花种


来源:程序员网

小小豆叮

使用CVS进行版本管理

翻译:廖斌 #////////////////////////////////////////////////////////////////////// # 使用CVS进行版本管理 # 2000-6-30 # CVS 1.10.7 # # # # Per Cederqvist et al 著 # 廖斌 译 # 感谢黄箐的输入和排版工作 # copyrigh: GPL # #////////////////////////////////////////////////////////////////////// 快捷内容索引 1. 概述.........................................................1 2. 代码仓库.....................................................7 3. 使用CVS开始一个项目..........................................29 4. 主干版本(Revision).........................................33 5. 分支与合并...................................................41 6. Recarsive behavior...........................................49 7. 增加,删除,更名文件和目录...................................51 8. 回顾开发历史.................................................57 9. 放置二进制文件...............................................59 10 多个开发者的同时工作........................................61 11 主干版本管理.............................................71 12 关键字替代................................................73 13 跟踪第三方代码...............................................77 14 你的系统如何同CVS交互........................................81 15 特殊文件.....................................................83 16 附录 1) CVS命令导向..................................................85 2) CVS命令快速参考............................................115 3) 管理文件的参考习册.........................................127 4) 影响CVS的所有环境变量......................................141 5) CVS各版本之间的兼容性......................................143 6) 遇到的问题.................................................145 7) Credits....................................................153 8) 对CVS和这本手册的总是处理..................................155 目录 ...........................................................157 1 概论 这一章为从未用过CVS的人写的,也许以前也从未用过任何版本控制工具。 1.1 什么是CVS? CVS是个版本控制系统,使用它你可以记录你原代码文件的历史。 例如,当软件修改时有时会产生问题(*bugs这里被译为问题),并且你可能在做这 次修改后很长时间不会发现这些问题。使用CVS,你可以容易地回顾老的代码版本去 发现哪一次的修改导致这些问题。有时候这样会非常有帮助。 你可能会保留你每一次的代码版本,这可能会浪费你很多的代码空间。CVS使用一 种聪明的办法保存你的多个版本在一个文件中。它仅仅保留版本间的不同内容。如果 你是一个项目中的一组成员之一,CVS也能够帮助你。除非你特别仔细,你很容易覆盖其 他人的工 作。一些编辑器,例如GNUEmacs,试图去判定一个文件是否被两人同时修改。 不幸的是,如果一个人使用其它的编辑器时,这个安全方式将不再有效。CVS使用让不同 开发者独立工作的方式解决了这个问题。每一个开发者的工作都在他自己的目录内,并且 CVS将 在每个开发者的工作完成后进行合并工作。 CVS是由Dick Grune作为Shell脚本的一个分支而创建的,1986年10月,在它的第6个发行卷 时,它被投递到新闻组comp.soures.unix。然而现在的CVS冲突算法中没有任何代码是从这 些脚本中来的。 在1989年3月,Brian Berlinor设计并编写了CVS的代码。Jett.Polk在以后帮助 Brian 完成了CVS 模型的设计和商业版本支持。 你可以通过不同的方式得到CVS,包括在Internet上自由的下载。如果你想下载CVS和其它CVS 文章以得到更多的信息,请看: http://www.cyxlic.com http://www.loria.fr/~molli/cvs-index.html. 有一个叫 info-cvs 的邮件列表是有关CVS的内容。订阅或取消订阅这个列表请发邮件到 info-cvs-request@gnu.org 如果你更喜欢Usenet新闻组,CVS的讨论组为 Comp.software.confg.mgmt. 在将来也许会建一个 Comp.software.confg.mgmt.cvs 的新闻组, 但也许这会是Comp.software.confg.mgmt在有太多讨论之后的事情吧。 你也许想订阅bug-cvs的邮件列表,这在附录H[BUGS]中有更多的信息。订阅它请发Email到 bug-cvs-reqnest@gnu.org. 1.2 CVS不能做的事 (未译) 2 3 使用CVS开始一个项目 ======================= 因为更改文件名并且把它们移动到另一个目录中不是经常发生的,因此你在开始一个新项 目时要做的第一件事是考虑你的文件组织。更改文件名或移动文件并非不可能,但增加了 理解上潜在的费解,并且CVS在更改名字的目录上特别的敏感。请参见7.4节[移动文件]。 (* 译者注: 在Unix中改名和移动是相同的)。 下一步做的事取决于手中的情况。 3.1 建立文件 第一步是在仓库中建立文件。这可以使用多种不同的方法来完成。 -------------------------------------------------------------------- 3.1.1 建立一个目录树 当你开始使用CVS时,你可能已经有几个项目可以使用CVS进行管理了。在这种情况下, 最容易的方法就是使用: "import"命令。一个例子是最容易解释如何使用它的。假定你现 在有一些你想放到CVS中的文件在"wdir"中,并且你想让它们放在数据仓库中的如下目录: "$CVSROOT/yoyodyne/rdir" 你可以使用如下命令: $cd wdir $cvs inport -m "Inported Sources" yoyodyne/rdir yoyo start 如果你没有使用"-m"参数记录一个日志信息,CVS将调用一个编辑器(*译者注:通常是vi) 并且提示输入信息。"yoyo"字符串是开发者标笺,"start"是发行标笺。他们没有什么特别 的意义,仅仅是因为CVS的需要才放在这里。 请参见第13章[跟踪代码],得到更多的这方面信息。 你现在可以检查一下它是否有效了,然后可以删除你原来的代码目录。 $cd $mv dir dir.orig $cvs checkout yoyodyne/dir $diff -r dir.orig yoyodyne/dir $rm -r dir.orig. 为了避免偶然进入到你原来的目录中去编辑文件,删除原来的代码是个好主意。当然,在 你删除之前保留一份备份到其它地方也是明智之举。 "checkout"命令能使用模块名作为参数(正如前面所有例子)或是一个相对于$CVSROOT的路 径,如同上面的例子。你应当检查CVS目录中的权限情况是否合适,应当使它们属于某一个 特定的组。请参见2.2.2.节[文件权限]。 如果你想"import"的一些文件是二进制代码,你可以使用一些特殊的方法表明这些文件是否 是二进制文件。请参见C.2节[Wrappers]。 ------------------------------------------------------------------------------------ 3.1.2 从其它版本控制系统建立文件 如果你有一个其它版本控制系统维护的项目,例如RCS,你也许希望把这些文件放到CVS中, 并且要保留这些文件的历史。以下是一些讨论。 从RCS: 如果你使用RCS,找到RCS文件??通常一个文件名叫"foo.c"的文件会有"RCS/foo.c,v"的RCS文 件。(但它有可能在其它地方,请看RCS的文档以得到相关信息)。如果文件目录在CVS中不存 在,那在CVS中创建它。然后把这些文件拷贝到CVS的仓库目录中(在仓库中的名字必须是带 ",v"的原文件;这些文件直接放在CVS中的这个目录下,而非"RCS"子目录中)。这是在CVS中 一个为数不多的直接进入CVS仓库直接操作的情况,而没使用CVS命令。然后你就可以把它们 在新的目录下"checkout"了。 当你把RCS文件移动CVS中时,RCS文件应在未被锁定的状态,否则移动操作时CVS 将会出 现一些问题。 从其它版本控制工具 许多版本控制工具都可以输出"RCS"格式的标准文档。如果你的版本控制工具可以做到这一 点,直接输出RCS文件,然后按照上面的例子做就可以了。 如果你的版本工具不能输出RCS文件,那么你必需要写一个脚本文件来,每次取出一个版本 然后把它放到CVS中去。下面提到的"sccsarcs"脚本就是一个很好的例子。 从SCCS: 有一个"sccsarcs"的脚本文件可以做把SCCS的文件转化成RCS文件,这个文件放在CVS原代码 目录的"contrib"目录中。注意: 你必须在一台同时安装了RCS和SCCS的机器上运行它。并且,正如其它在"contrib."目录中的 其它脚本一样。(你的方法也许是变化多端的) (*译者注:我并未查看过CVS的contrib目录:-(,因此不知道这下面都有些什么)。 从PVCS: 在"contrb"中有一个叫"pves-to-rcs"的脚本可以转换PVCS到RCS文件。你必须在一台同时有 PVCS和RCS的机器上运行它。 请看脚本中的注释以得到更多细节。 3.1.3从无到有建立一个目录树 建立一个新的项目,最容易的方法是建立一个空的目录树,如下所示: $mkdir tc $mkdir tc/man $mkdir tc/testing 在这之后,你可以"import"这个(空)目录到仓库中去。 $cd tc $cvs import -m "created directory structure"yoyodyne/dir yoyo start 然后,当新增一个文件时,增加文件(或目录)到仓库中。请检查$CVSROOT中的权限是否正确。 ------------------------------------------------------------------------------------------- 3.2 定义模块 下一步是在"moduyes"文件中定义模块。这不是严格需要的,但模块能把相关的目录和文件容易 关联起来。下面的例子可以充分演示如何定义模块。 1. 得到模块文件的工作拷贝。 $cvs checkout CVSROOT/modules $cd CVSROOT 2. 编辑这个文件并写入定义模块的行。请参见2.4节[管理文件的介绍]。有一个简单介绍,参见C.1节 [模块文件]。有它的详细描述。你可以使用下面的行定义模块"tc": tc yoyodyne/tc 3. 提交你的更改到仓库 $cvs commit -m "Added tc module." modules 4. 发行模块文件 $cd $cvs release -d CVSROOT 4 ======= 5 分支与合并 ================== CVS允许你独立出一个派生的代码到一个分离的开发版本---分支。当你改变一个分支中的文 件时,这些更改不会出现在主开发版本和其它分支版本中。 在这之后你可以使用合并(merging)把这些变更从一个分支移动到另一个分支(或主开发版 本)。合并涉及到使用“cvs update -j”命令,合并这些变更到一个工作目录。你可以确认 (commit)这次版本,并且因此影响到拷贝这些变更到其它的分支。 ----------------------------------------------------------------------------------- 5.1 何时应当创建一个分支 假定tc.c发行版已完成。你正在继续开发tc.c,计划在2个月后发行1.1的版本。在不久以后你的 客户开始抱怨说代码有些问题,你检查了一下1.0的发行版(请参见4.4节[标笺])并且找到了这 个错误(这将会有一个小小的更正)。但是,这个当前的版本是处于一个不稳的状态,并且在下 一个月才能有希望稳定下来。这样就没有办法去发行一个最新的现有版本去更正问题。 这时就可以去创建基于这棵版本树1.0版的分支。你可以修改这棵树的分支而不影响到主干。当 修订完成时,你可以选定是否要把它同主干合并或继续保留在这个分支里。 ----------------------------------------------------------------------------------- 5.2 建立一个分支 你可以使用“tag -b”去建立一个分支。例如,假定你在工作于一个工作拷贝中: $cvs tag -b rel_1_0_patches 这将基于当前的拷贝分离出一个分支,并分配“rel_1_0_patches”的名字。 懂得分支是在CVS仓库中创建,而非在工作拷贝中创建的是非常重要的。正上面的例 子,创建一个基于当前版本的分支不会自动把当前的工作拷贝转到新的分支上。欲知 详情,请看5.3节[进入 一个分支]。你也可以不参考任何工作拷贝而建立一个分支。 你可以使用rtag命令: cvs rtag -b -r rel-1-0 rel-1-0-patches tc. “-r rel-1-0”说明这个分支是基于标志了rel-1-0的版本文件,它不是从最新的版本 开始分支.这对需要从老的版本进行分支很有用(例如:当修订一个过去的稳定版本时) 当使用“tag”标志,这个“-b”标志告诉rtag去创建一个分支(而非是这个版本的符号 连接)。注意标记“rel-1-0”可能对不同的文件有不同的版本数字。因此,这个命令的结果 是为tc模块建立了一个命名为“rel-1-0-patches”的新版本分支,它是基于标记为“rel-1-0” 的版本树。 ----------------------------------------------------------------------------------- 5.3 进入分支 你可以通过两种方式进入分支:重新checkout或是从现存的拷贝进入。重新checkout使用 checkout命令并带上“-r”标识,后面是这个分支的标笺(tag)名。(请看5.2[创建一个分支]): $cvs checkout -r rel-1-0-patches tc. 或者如果你已有了一个拷贝,你可以使用“update -r”命令转到这个分支。 $cvs update -r rel-1-0-patches tc. 或者使用另一个等同的命令: $cd tc $cvs update -r rel-1-0-patches 这对现有拷贝为主干代码或是其它分支都是有效的.上面的命令将把它转到命 名的分支。同“update”命令相类似。“update -r”合并你所做的任何改变,请注 意是否有冲突出现。 一但你的工作拷贝已经转向一个特定的分支。它将一直保持在这个分支内,除非你 又做了其它的操作。这意味着从这个工作拷贝checkin的变更将加到这个分支的新版 本中,而不影响到主干版本和其它分支代码。 想看一个工作拷贝是基于哪一个分支,可以使用“status”命令。在它们输出中查找 一个“sticky tag”的域(请参见4.9节["sticky tag"],第38页).那就是你的当前分支号。 $cvs status -v driver.c backend.c ==================================================================== File: driver.c Status: Up-to-date Version: 1.7 Sat Dec S 18:25:54 1992 RCS version: 1.7 /u/cvsroot/yoyodyne/tc/driver.c,v Sticky Tag: rel-1-0-patches (branch: 1.7.2) Sticky Date: (none) Stick Option: (none) Existing Tag: rel-1-0-patches (branck: 1.7.2) rel-1-0 (revision: 1.7) ==================================================================== File: backend.c status: Up-to-date Version: 1.4 Tue Dec 1 14:39:01 Rcs Version: 1.4 /u/cvsroot/yoyodyne/tc/ Sticky Tag: rel-1-0patches(branch:1.4.2) Sticky Date: (none) Sticky Option: (none) Existing Tag: Rel-1-0-patches (branch: 1.4.2) Rel-1-0 (revision: 1.4) Rel-0-4 (revision: 1.4) 请不要因为每个文件的分支是不同(“1.7.2”和1.4.2")而迷惑。分支的标笺(tag) 是相同的:"rel-1-0-patches",这些相同标笺的文件是相同分支的。在以上的例子中,分支建 立之前,"driver.c" 比 "backend.c"有更多的变更,因此它们的版本编号是不同的。请参见5.4节 [分支和主干版本号]去了解分支如何构建原理的细节。 -------------------------------------------------------------------------------------- 5.4 分支与主干版本 通常,一个文件的主干版本历史是一个增长线(请看4.1[主干版本]页): +-----+ +-----+ +-----+ +-----+ +-----+ ! 1.1 !----! 1.2 !----! 1.3 !----! 1.4 !----! 1.5 ! +-----+ +-----+ +-----+ +-----+ +-----+ 然而,CVS并不局限于线性的开发。主干版本可以分为不同的分支,每一个分支可 以是一个独立的自我维护的开发线。而在一个分支中的变更可以很容易的转移到主干中。 每一个分支均有一个分支号,由一个“.”分离的十进制奇数组成,分支号的编排依 赖于它分离出的主线版本。使用分支号允许从一个特定版本分离出多个分支。 所有的分支版本都依赖于它的原始分离版本号。下面的例子将展示这一点。 +-------------+ 1.2.2.3.2 分支 -> +--! 1.2.2.3.2.1 ! ! +-------------+ ! +---------+ +---------+ +---------+ 1.2.2 分支-> +--! 1.2.2.1 !----! 1.2.2.2 !----! 1.2.2.2 ! ! +---------+ +---------+ +---------+ ! ! +-----+ +-----+ +-----+ +-----+ +-----+ ! 1.1 !----! 1.2 !----! 1.3 !----! 1.4 !----! 1.5 ! <- 主干 +-----+ +-----+ +-----+ +-----+ +-----+ ! ! ! +---------+ +---------+ +---------+ 1.2.4 分支-> +--! 1.2.4.1 !----! 1.2.4.2 !----! 1.2.4.2 ! +---------+ +---------+ +---------+ 你是如何创建具体的分支号的细节通常不是你需要考虑的,但这里谈谈它如何工作。 当CVS建立一个分支号时,它先得到第一个未用的偶数,开始的数字是2,例如你 从6.4的主干版本创建分支时,分支号为6.4.2所有分支号码末位为0的号码用于CVS内 部,(例如6.4.0)。(请参见5.5节[内部分支号]44页)分支1.1.1有特别的含义,请看13章 [跟踪代码]。 ----------------------------------------------------------------------------------- 5.5 内部分支号码 这一节描述CVS的内部分支(magic branches) (* 译者注:magic branch 译为内部分支) 特性。在大多数情况下,你不用考虑内部分支号码,CVS将为你进行管理。然而,在 一些特定条件下,它将显现出来,因此理解它如何工作将是有用的。一般的,分支号 码将由奇数个 "."分隔的十进制整数组成。请看4.1节[版本号码]。然而那并非完全是这 样的,由于效率的原因,CVS有时插入一个额外的“0”在右末的第二个位置(1.2.4 变为1.2.0.4,8.9.10.11.12变为8.9.10.11.0.12等)。 CVS将会很好的将这些变换隐蔽在背后进行,但在一些地方,这种隐蔽并不完全: * 内部分支编号会出现在CVS的日志(log)文件中。 * 你不能够对 "cvs admin" 使用符号分支名。 你可以使用admin命令去为一个分支重新分配一个RCS希望的那样的符号名。如果 R4patches是一个分配给分支1.4.2(内部分支编号为1.4.0.2)的一个文件"numbers.c"的 命名,你可以使用如下命令: $cvs admin -NR4patches:1.4.2 numbers.c 它将只在至少一个版本已经提交到这个分支时才会有效。请非常小心不要把一个标 笺(tag)分配给了一个错误标识号(现在没有看到昨天的一个标笺是如何分配的)。 ---------------------------------------------------------------------------------- 5.6 合并一个整个分支 你可以合并一个分支到你的工作目录在“update”命令中“-j 分支号”的标识。使 用“-j 分支号”将合并这个派生分支点与原版本的最新版之间的变更到你的工作目录 “-j”的意思是“join”。 我们现在来考察下面这棵树: +-----+ +-----+ +-----+ +-----+ ! 1.1 !----! 1.2 !----! 1.3 !----! 1.4 ! <- 主干 +-----+ +-----+ +-----+ +-----+ ! ! ! +---------+ +---------+ R1fix 分支-> +--! 1.2.2.1 !----! 1.2.2.2 ! +---------+ +---------+ 分支1.2.2分配了一个Rifix的名字.下面的例子假定模块"mod"只包含一个文件"m.c" $cvs checkout mod # 得到最新的1.4版 $cvs update -j R1fix m.c # 合并所有在分支中的改变,即:1.2与1.2.2.2 # 之间的变化到这个文件的工作目 录. $cvs commit -m "Included R1fix # 建立1.5版 在合并时可能会发生冲突,如果这种情况发生,你可以在提交新版本之前解决它。请 参见10.3节[冲突的例子]。 如果你的原文件中包含关键字(请看第12章[关键字替代])。你可能会得到比严格意义 上的冲突更多的冲突信息。请参见5.10节[合并和关键字],去了解如何避免这个问题。 "checkout"命令也支持使用"-j"参数。下面的例子同上面所用的例子有相的效果。 $cvs checkout -j R1fix mod. $cvs commit -m "Included R1fix" --------------------------------------------------------------------------------- 5.7 从一个分支多次合并。 继续我们上面的例子。现在这棵树看起来是这样的: +-----+ +-----+ +-----+ +-----+ +-----+ ! 1.1 !----! 1.2 !----! 1.3 !----! 1.4 !----! 1.5 ! <- 主干 +-----+ +-----+ +-----+ +-----+ +-----+ ! * ! * ! +---------+ +---------+ R1fix 分支-> +--! 1.2.2.1 !----! 1.2.2.2 ! +---------+ +---------+ 正如上面所讨论的,分支1.2.2.2所引导的“*”号表示从Rifix分支到主干的合并。 现在我们继续开发Rifix分支: +-----+ +-----+ +-----+ +-----+ +-----+ ! 1.1 !----! 1.2 !----! 1.3 !----! 1.4 !----! 1.5 ! <- 主干 +-----+ +-----+ +-----+ +-----+ +-----+ ! * ! * ! +---------+ +---------+ +---------+ R1fix 分支-> +--! 1.2.2.1 !----! 1.2.2.2 !----! 1.2.2.3 ! +---------+ +---------+ +---------+ 然后你可能会希望合并新的变更到主干中去。如果你仍使用“cvs update -j Fifix m.c" cvs将试图合并你已经合并过的东西,这可能写导致一些不希望发生的东西。 因此,你必须表达清楚你希望只合并未被合并的内容的意思。这样需要使用两个 “-j“参数。CVS合并从第一个“-j”的版本到第二个“-j”版本的变化。例如,在我们上面 的例子中: cvs update -j 1.2.2.2 -j R1fix m.c 如果出现的问题是你需要手工指定1.2.2.2的版本号,一个更好的方法是使用: cvs update -j R1fix:yesterday -j R1fix m.c 然而,更好的方式是在每一次合并后重新放一个标笺给Rifix分支,然后使用标 笺做后的合并: cvs update -j merged_from_Rifix_to_trunk -j R1fix m.c ---------------------------------------------------------------------------------- 5.8 合并两个任意版本之间的不同 使用两个“-j”标志,这个update(和checkout)命令能合并两个任意不同的版本 到你的工作目录。 $cvs update -j 1.3 backend.c 将把1.5版本恢复到1.3版本,所以一定要注意版本的顺序。 如果你在操作多个文件时使用这个选择项,你必须了解在不同的文件之间,版本的 数字可能是完全不同的。你必须使用标笺(tag)而不是使用版本号来完成多个文件 的操作。使用两个“-j”操作也能会恢复增加或删除的文件。例如,假定你有一个 叫“file1”的文件在在于1.1版本中,然后你在1.2版本中删除了它,下面是如何操作的例子: $cvs update -j 1.2 -j 1.1 file1 file1 $cvs commit -m test checking in file1; /tmp/cvs-sanity/cvsroot/first-dir/file1 file1,v new revision:1.3; previous revision:1.2 done $ ------------------------------------------------------------------------------------ 5.9 合并能添加和删除文件 如果你在合并时的改变涉及到添加或删除一些文件,“update -j”将反映这些变化。 例如: cvs update -A touch a b c cvs add a b c ; cvs ci -m "added" a b c cvs tag -b branchtag cvs update -r branchtag touch d ; cvs add d rm a ; cvs rm a cvs ci -m "added d , removed a" cvs update -A cvs update -j branchtag 在这些命令之后(注意要commit),文件'a'将被删除,而文件'd'将被加入到主干。 ------------------------------------------------------------------------------------- 5.10 合并和关键词 如果你合并的文件包含关键词(参见第12章[关键词替代],73页),你通常将会在 合并时得到 无数个冲突报告,因为在不同版本中非常不同。 因此,你常需要在合并时使用“-kk”(参见12.4节[替代模式],75页)选择项。使用 关键字名字,而非去扩展关键字的值的方法,这个功能选择项确保你合并的版本之间互相相 同,而避免了冲突。 例如:假设你有一个文件如下: +---------+ br1 -> +--! 1.1.2.1 ! ! +---------+ ! ! +-----+ +-----+ ! 1.1 !----! 1.2 ! +-----+ +-----+ 并且你的当前工作目录拷贝为主干(1.2版本)。那么对于以下的合并将会产生一个 冲突的结果。请看例子: $cat file1 Key $Revision: 1.3 $ ... $cvs update -j br1 U file1 RCS file: /cvsroot/first-dir/file1,v retrieving revision 1.1 retrieving revision 1.1.2.1 Meging differences between 1.1 and 1.1.2.1 into file1 rscmerge: warning: conflicts during merge $ cat file1 $<<<<<<< file1 Key $Revision: 1.3 $ ======= Key $Rerision: 1.1.2.1 $ $>>>>>>> 1.1.2.1 ... 冲突发生在试图将1.1和1.1.2.1合并到你的工作目录中去的时候。因此,当这个 关键词从“Revision:1.1"到"Revision:1.1.2.1"时,CVS将试图合并这个变化到 你工作目录, 这就同你的目录中的变更“Revision:1.2"发生了冲突。 以下是使用了:“-kk”后的例子: $cat file1 key $Revision: 1.3 $ ... $cvs update -kk -j br1 V file1 RCS file: /cvsroot/first-dir/file1,v retrieving revision 1.1 retrieving revision 1.1.2.1 Merging differences between 1.1 and 1.1.2.1 into file1 $ cat file1 key $Revision: 1.3 $ ... 在这里版本“1.1”和“1.1.2.1"都扩展为单纯的 "Revision",因此,合并时就不会 发生冲突了。 然而,使用 "-kk" 参数还一个主要的问题。即,它使用了CVS通常使用的关 键字扩展模式。在特殊情况下,如果模式使用针对二进制文件的 "-kb" 参数。这将会产生问题。因此,如果你的数据库中包括有二进制文件,你将 必须手工处理这些问题,而不能使用 "-kk"。 10 多个开发者同时工作 --------------------- 当多个开发者同时参与一个项目时,常常会发生冲突。一般经常发生的情况是两个人想 同时编辑一个文件的时候。它的解决方法之一是文件锁定或是使用保留式的checkout,这种 方法允许一个文件一次只允许一个人编辑。这是一些版本控制系统的唯一解决方式,包括 RCS和SCCS。现在在CVS通常使用保留式checkout的方法是使用"CVS admin-1"命令(参见A-6-1AB [admin选择项])。在下面将解释这不是一种好的智能的解决方式,当它是许多人喜欢使用的 一种方式。下面也将讲述可以使用适当的方法来避免两个人同时编辑一个文件,而非使用软件 的方式强迫达到这一点。 在CVS中默认的方法是"unreserved checkout"--非保留式的导出。在这种方法下,开发者 可以同时在他们的工作拷贝中编辑一个文件。第一个提交工作的没有一种自动的方法可以知道 另一个人在编辑文件。另一个人可能会在试图提交时得到一个错误信息。他们必须使用CVS命令 使他们的工作拷贝同仓库的内容保持更新。这个操作是自动的。 CVS可以支持facilitate多种不同的通信机制,而不会强迫去遵守某种规则,如"resered checkouts"那样。以下的部分描述这些不同的方式是如何工作的,和选择多种方式之间涉及到 的一些问题。 10.1 文件状态 基于你对导出的文件使用过的操作,和这些文件在仓库中的版本使用过的操作,我们可以 把一个文件分为几个状态。这个状态可以由"status"命令得到,它们是: up-to-date: 对于正在使用的这个分支,文件同仓库中的最后版本保持一致。 Locally Modified: 你修改过文件,但没有"commit"。 Locally added: 使用了"add"命令增加文件,但没有"commit" Locally Removed: 你使用了"remove"命令,但没有"commit" Needs checkout: 其他人提交了一个更新的版本。这个状态的名字有些误导,你应当使用"update"而非 "checkout"来更新新的版本。 Needs Patch: 象"Needs checkout"一样,但CVS服务将只给出Patch(补丁)文件,而非整个文件。而 给出Patch和给出整个文件的效果是相同的。 Needs Merge: 一些人提交了一个更新版本,而你却修改过这些文件。 File had conflicts on merge: 这同"Locally Modified"相象,只是"update"命令给出了一个冲突信息。如果你还没有 解决冲突,那么你需要解这个问题,解决冲突的方法参见10.3节[冲突的例子]. Unkown: CVS不知道关于这个文件的情况.例如,你创建了一个新文件,而没有使用"add"命令 为了帮助弄清楚文件的状态,"status"也报告工作版本(working vevision),这是这个文件是从哪个版本来的,另外还报告"仓库版本"(Repository vevision)。这是这个文件在仓库中的这个版本分支的最后版本。 "status"命令的选择项例在附录B[invoking cvs]。有关"sticky tag"和"sticky date"输出内容的信息,参见4.9节[sticky tags]。有关"sticky options"输出内容参见"-k"选择项, A.16.1节[update选择项]。 你应当把"update"和"status"命令放在一起来认识。你使用"update"使你的文件更新到最 新状态,你使用"status"命令来得到"update"命令将会做何种操作。(当然,仓库中的状态将可 能会在你运行update之前变化)。事实上,如果你想使用一个命令得到比使用"status"正式的状 态信息,你可以使用: $cvs -n -q -update 这里"-n"选择项表示不真正执行update,而只显示状态;"-q"选择项表示不打印每个目录的 名字。有关更多的关于"update"命令的住处参见附录B[使用CVS]。 10.2 使一个文件更新到最版本 当你想更新或是合并一个,使用update命令。对于一个不是最新版本的文件,这个命令大略等 同于"checkout"命令:最新版本从仓库中提出并放到工作目录中。 当你使用"update"命令时,你修改过的文件在任何情况下不会受到损害。如果在仓库中没有更 新的版本,"update"时你的代码没有任何影响。当你编辑过一个文件,并且仓库中有更新版本,那 么"update"将合并所有的变更到你的工作目录。 例如,想象一个你导出了一个1.4版的文件并且开始编辑它,在某一时候其他人提交了1.5版,然 后又提交了1.6版,如果你运行update命令,CVS将把1.4版到1.6版之间的变更放到你的文件中。 如果在1.4版和1.6版之间的改变太靠近于的你一些变更的话,那么一个"覆盖"("overlop")冲突 就发生了。在这种情况下将输出一个警告信息,然后结果保留的文件中包含了有冲突代码的两个版 本,由特别的符号所分隔开。请参见A.16节[更新],可以得到关于"update"命令的一个完全的描述。 <淘宝热门商品:
 

 

徽商联盟】皇冠信誉店 联盟化妆品の屋

 

4.00 元  

5钻【成都商盟】竹纤维内裤袜子毛巾超市~~收藏本店就有礼物送哦

特价 100%竹纤维毛巾 京杭丽人儿童毛巾27*48 50克/随机颜色


来源:程序员网

小小豆叮

寻求南京地区投资以及技术合作伙伴

寻求南京地区投资以及技术合作伙伴! 现在公司已经找到具备游戏开发以及运营执照的公司挂靠,具备三块牌照资格的公司,但是必须自己投资,投资用途:开发办公场地、设备,企业运营资金,20万左右。 项目:一、自行开发游戏,在国内大型sms社区的基础上,做二次开发(wap,Kjava)。这部分拥有开发费用的收益,以及新版游戏机江苏地区的运营权以及全国市场新版游戏的收益分成。 二、外包游戏开发:1、台湾手机厂商的游戏(50款彩屏游戏) 2、日本i-mode商业运用的订单。 3、欧洲市场(等企业运营三个月后订单产生) 希望能投资的合作伙伴共同创业 联系方式:QQ:11759940 MSN:mawei1981@hotmail.com <淘宝热门商品:
 

55.00 元 

年底冲钻免邮费!热销包包 !韩版单肩包!销量过千

 

86.00 元  

艾尔微品牌店//九阳豆浆机//女士精品-三钻100%真人拍摄

Disney Mickey 迪斯尼米奇多色手动机芯机械中性手表


来源:程序员网

小小豆叮

用PMD自动执行Java代码静态分析

 一、基础知识   PMD是一种分析Java代码错误的工具。与其他分析工具不同的是,PMD通过静态分析获知代码错误。也就是说,在不运行Java程序的情况下报告错误。PMD附带了许多可以直接使用的规则,利用这些规则可以找出Java源程序的许多问题,例如没有用到的变量、多余的变量创建操作、空的catch块,等等。此外,用户还可以自己定义规则,检查Java代码是否符合某些特定的编码规范。例如,你可以编写一个规则,要求PMD找出所有创建Thread和Socket对象的操作。   最初,PMD是为了支持Cougaar项目而开发的。Cougaar是美国国防高级研究计划局(Defense Advanced Research Projects Agency,DARPA)的一个项目。DARPA开放了PMD的源代码,所以PMD被发布到了SourceForge网站上。不久前,PMD的下载次数就超过了14000次,页面浏览次数超过了130000次。更重要的是,在源代码开放作者的努力下,越来越多的PMD规则和IDE插件被开发出来,然后加入到了PMD的核心项目之中。   你可以从PMD的网站下载PMD的二进制版本,或下载带源代码的版本,下载得到的都是ZIP文件。假设你下载了二进制版本,先把它解压缩到任意一个目录。接下来怎么做,就要看你准备怎么用它——最简单的,如果要在一个Java源代码目录中运行PMD,只需直接在命令行上运行下面的命令: C:\data\pmd\pmd>java -jar lib\pmd-1.02.jar c:\j2sdk1.4.1_01\src\java\util text rulesets/unusedcode.xml   输出结果类如: c:\j2sdk1.4.1_01\src\java\util\AbstractMap.java 650 Avoid unused local variables such as 'v' c:\j2sdk1.4.1_01\src\java\util\Date.java 438 Avoid unused local variables such as 'millis'   除了直接在命令行上运行PMD之外,还可以通过Ant、Maven或者各种集成开发环境(IDE)运行PMD,例如jEdit、Netbeans、Eclipse、Emacs、IDEAJ和JBuilder等。   二、内建规则   PMD本身就附带了许多规则。下面是几个例子。 没有用到的代码显然是应该被清除的。 public class Foo { // 下面这个实例变量没有用到 private List bar = new ArrayList(500); } 如果用一个接口也能达到同样的目标,为什么要返回一个具体的类?例如,下例可以改用List接口。 public ArrayList getList() { return new ArrayList(); } 当if的条件为真时,if代码块其实不做任何事情。下面这段代码其实可以写得更加简洁一些。 public void doSomething(int y) { if (y >= 2) { } else { System.out.println("Less than two"); } } 为什么要创建一个新的String对象?只要改用String x="x"就可以了。 String x = new String("x");   PMD还包含其他许多内建规则,但从上面几个例子已经可以看出PMD的基本工作方式。只要定义适当的静态规则,PMD就可以象一个富有经验的程序员那样,帮你指出代码存在的问题。   三、工作原理   PMD的核心是JavaCC解析器生成器。PMD结合运用JavaCC和EBNF(扩展巴科斯-诺尔范式,Extended Backus-Naur Formal)语法,再加上JJTree,把Java源代码解析成抽象语法树(AST,Abstract Syntax Tree)。显然,这句话不那么好懂,且看下文具体说明。   从根本上看,Java源代码只是一些普通的文本。不过,为了让解析器承认这些普通的文本是合法的Java代码,它们必须符合某种特定的结构要求。这种结构可以用一种称为EBNF的句法元语言表示,通常称为“语法”(Grammar)。JavaCC根据语法要求生成解析器,这个解析器就可以用于解析用Java编程语言编写的程序。   不过实际运行中的PMD还要经过JJTree的一次转换。JJTree是一个JavaCC的插件,通过AST扩充JavaCC生成的解析器。AST是一个Java符号流之上的语义层。有了JJTree,语法分析的结果不再是“System, ., out, ., . println”之类的符号序列,而是一个由对象构成的树型层次结构。例如,下面是一段简单的Java代码以及与之对应的AST。 Java源代码: public class Foo { public void bar() { System.out.println("hello world"); } } 对应的抽象语法树 CompilationUnit TypeDeclaration ClassDeclaration UnmodifiedClassDeclaration ClassBody ClassBodyDeclaration MethodDeclaration ResultType MethodDeclarator FormalParameters Block BlockStatement Statement StatementExpression PrimaryExpression PrimaryPrefix Name PrimarySuffix Arguments ArgumentList Expression PrimaryExpression PrimaryPrefix Literal   四、编写规则   前面我们看到了Java源代码以及与之对应的对象层次结构。下面我们就要利用这些对象编写PMD规则检查代码存在的问题。   一般地,一个PMD规则可以看成一个Visitor,它遍历AST,寻找多个对象之间的一种特定模式,这种模式表示代码存在的问题。问题模式可能简单也可能复杂,简单的如查找代码中是否包含new Thread关键词,复杂的如确定一个类是否正确覆盖了equals和hashcode。   下面是一个寻找空if语句的简单PMD规则。 //扩展AbstractRule,以启用Visitor模式 public class EmptyIfStmtRule extends AbstractRule implements Rule { //当源代码中出现一个Block,下面的方法被调用 public Object visit(ASTBlock node, Object data){ //如果父节点是一个if语句且代码块里面没有任何内容 if ((node.jjtGetParent().jjtGetParent() instanceof ASTIfStatement) && node.jjtGetNumChildren()==0) { //肯定代码存在问题。把一个RuleViolation加入到Report。 RuleContext ctx = (RuleContext)data; ctx.getReport().addRuleViolation(createRuleViolation(ctx, node.getBeginLine())); } //继续检查树的下一个节点 return super.visit(node, data); } }   也许你不能一下子掌握这段代码,其实它的思路还是比较简单的:   #扩展AbstractRule基类。   #声明一个“钩子”,一旦我们感兴趣的节点出现,它就会被调用(称为“回调”)。在上面的例子中,我们要求在每一个ASTBlock出现时得到通知,所以声明visit(ASTBlock node, Object data)。   #在回调函数中,判断是否出现了我们正在检查的问题。本例我们检查是否存在空的if块,所以先判断当前是否在ASTIfStatement之内,然后判断它是否有子节点。   当然,我们还可以按照另一种方法进行检查:声明一个要求检查ASTIfStatement的回调函数,然后在回调函数中检查是否存在子节点。   五、配置规则   写好自定义规则之后,接下来要把它加入到某个PMD规则集。所谓PMD规则集,就是由一组PMD规则构成的集合。每个PMD规则集由一个XML文件定义,下面是一个PMD规则的配置信息的例子: <rule name="EmptyIfStmt" message="避免使用空的if语句" class="net.sourceforge.pmd.rules.EmptyIfStmtRule"> <description> 找到空的if语句:if检查了条件,但if块里面没有任何内容。 </description> <priority>3</priority> <example> <![CDATA[ if (absValue < 1) { // not good } </XMLCDATA> </example> </rule>   可以看出,规则配置文件包含了许多有用的信息。要运行新添加的规则,只需把规则集XML文件和Java源代码文件放入CLASSPATH,然后运行PMD。   结束语:本文介绍了PMD如何在不编译代码的情况下分析和寻找代码存在的问题,通过几个简单的例子了解了EBNF语法、JavaCC和AST,以及如何用PMD检查代码存在的问题、如何编写和运用定制PMD规则等。愿PMD能够助你一臂之力! <淘宝热门商品:
 

¥:50.00 

【北京同仁堂国药】

 

3.20 元  

Lily's 园艺-万元赠品大派送!种球“买就送”!朱顶红已到货!

Lily's-现货!PT-01葡萄风信子album-荷兰进口种球/球根-皇冠


来源:程序员网

小小豆叮

在Java中轻松打印文档

有关在Java中实现文档打印的典型说法描述了一个复杂的过程,它要求对字体进行测定、对文本进行解析并将结果绘制到一个Graphics对象中。这个过程似乎执行起来相当困难,并且它和用于文档视频显示的高级编程方法不一致。如果你想要花费大量的精力来完成这个过程,那么你就不会首先想到要在Java中编程。 你一定不想自己完成测定、解析和绘制过程,而是希望通过简单地将文档发送到一个能为你处理所有事情的对象中来完成这个任务。本文就将介绍这样一个对象――DocumentRenderer,它将一个文档作为方法中的一个参数并处理指定任务来完成打印。比如,用这个类来显示一个HTML文档需要两个步骤:构造一个DocumentRenderer类的实例并将HTML文档作为参数发送到print(HTMLDocument)方法中。DocumentRenderer类用于处理打印该文档所必需的开销,包括显示一个打印对话框以及格式化文本。下载用于该类的源代码(DocumentRenderer.java)。 我们设计了这个DocumentRenderer类以便利用这个已经在Java中可用的高级文本性能。 根据可重用和可扩展类的原则,我们使用了一些现有的对象(Java Swing Text Package用它来对显示结果进行格式化)使打印结果能够显示在纸上。用这种方法设计DocumentRenderer使我们能够用比前面讨论过的方法少写近200行的代码来建立这个类。 除了能少写代码之外,使用DocumentRenderer 实现中的现有对象还提供了一些额外的功能使得该类更加通用。在最初设计这个类的时候,我们只是打算将HTML文档打印出来。而添加一些功能来打印其他类型的文档则是后来的想法。当我们发现只需在用于HTML 打印类的代码中加上约6行的额外代码就可以打印一个Rich Text Format文档时,便在这个项目的后期添加了这个功能。 显示文档 DocumentRenderer能够用来打印几类包含在JEditorPane中的文档。我们用三种类型的文档(JEditorPane能够缺省识别的)测试了这个printer类:HTMLDocuments、PlainDocuments和Rich Text Format文档。只需要做一些很小的改动,这个类就应该可以将包含在JEditorPane中的其他类型文档打印出来了。 DocumentRenderer类将一个文档的打印形式从其视频显示中区分出来了。这就使你能够针对特定的打印结果进行文本格式化,而会不影响其屏幕显示。DocumentRenderer采用所有打印页面的实际大小来显示文本并计算出行间距(line break)。当文档的宽度不足以显示在打印页面上时,该类会允许使用缩放(scaling)。 DocumentRenderer相当智能。分页符(page breaks)不会将一行单一语句分放到两个页面上。字符也不会被切成两半,不会象浏览器在处理一般打印时会在这一页末尾显示一句话的上半部分而在下一页的顶部显示这句话的下半部分。这个类能够处理大量字体、颜色和小图标。分栏文本(columnar text)的显示也没有问题。对于每一个JEditorPane能够显示的文本特性,通常DocumentRenderer都可以将这种性能呈现到纸上。 你只需使用两行代码便可以将DocumentRenderer结合到你的程序中去了。用一个不带参数的构造器创建这个类的实例,再调用一个合适的打印方法来处理其他事情。比如,以下代码将打印这个htmlDocument,它是HTMLDocument类的一个有效实例:DocumentRenderer DocumentRenderer = new DocumentRenderer(); DocumentRenderer.print(htmlDocument); 它给用户显示一个打印对话框,允许用户选择打印机、打印数量等,同时还有一个取消打印的选项。 PlainDocuments使用了print(PlainDocument)方法,采用和HTMLDocuments相同的方式执行打印。由于在Java中不能直接访问Rich Text Format文档,所以你必须将这种类型的文档发送到DocumentRenderer中(通过将它封装到一个JEditorPane里),就象这样:DocumentRenderer.print(jeditorPane); 这里的jeditorPane是JEditorPane的一个有效实例,其中包含一个Rich Text Format文档。 为了给用户提供方便,你可以调用DocumentRenderer的pageDialog方法来显示一个打印对话框以便用户可以调整页面大小、页边设置和纸的打印方向(orientation)。DocumentRenderer还提供了一种方法使开发人员可以选择是否对那些无法在打印宽度内完全显示的文档进行按比例缩放。我们认为能够进行缩放通常是比较好的选择,因为它能够防止文本在正确的页边处被分开,但它似乎比较适合让用户去选择。这种名为setScaleWidthToFit(boolean)的方法提供了按比例缩放的选项。你必须确定在调用打印方法之前调用这个scaling和pageDialog方法。 了解DocumentRenderer DocumentRenderer用于执行显示一个打印对话框并通过使用在Java Swing Printing API中可用的标准化工具开始打印操作。由于在使用这个DocumentRenderer类时无需完全了解这个API,而且该API已经在很多地方被详细描述过(见资源),因此这里我们就不再介绍它了。这个用于DocumentRenderer类的源代码中还包括了这个打印逻辑的完整文档。 然而我们或许应该解释一下DocumentRenderer用来在单独打印页面中定位文本的过程,以便你了解这个类所提供的改进功能,这会帮你回顾这个Java打印过程通常遵循的显示文档的逻辑。 文档通常是以一种简单的方式进行打印的。首先,文档会被放入JEditorPane。你可以将打印过程想象为在JEditorPane 的上面放置一个矩形框(其大小和页面打印区的大小相等),并对其中的内容进行打印而无需关心外面的部分。 这个矩形的上沿与JEditorPane 顶部齐平,矩形框内部的区域会被绘制(paint)。如果矩形的下沿穿过文本,不用去管它;字符会在打印页面的底部被分开。打印第二页时,矩形的上沿被向下移至前面被下沿所占据的那一行,该过程被重复执行。由于第二页正好在第一页结束的地方开始,因此在第一页底部被分开的字符会出现在第二页的顶部。后面几页也是一样。 为了避免从行中断开,DocumentRenderer会仔细检侧文档以测定是否一个单独文本和页面完整契合。这样会比只是在JEditorPane中放一个矩形框并打印其中内容的效果更佳。 绘制视图(View) 如果将JEditorPane看作仅包含了一个文档的方法,你就不能测定所有文本的位置或大小了。一个文档对于这个任务来说太大了,文档或许会契合于一个单一页面,或许不会。为了使文档能够完整契合于打印纸,你必须将它分成一些小的部分以便对每个部分的位置进行检测。 幸运的是,Java Swing Text Package提供了一个View类,它能使你将文档分成单一的、适于绘制的部分。你可以将JEditorPane想象成是由几个视图部分组成的;现在你就可以完全基于这些小部分的大小和位置来打印文档了。 View类的子类用于处理可视性组件(visual component)中的显示和打印文本的任务。然而,处理打印文本的许多程序员没有意识到的是视图可以在显示到纸上时提供这些相同的功能。尽管对视图问题进行详细讨论是本文以外的话题,但在讨论文档打印时对它有一个大致的了解还是很有必要的。 在Swing中,视图被当作处理文本显示的容器。在树型目录中一个根视图可以有多个视图分支。在这些分支的端部会显示代表真实文本的叶视图(leaf view)。 将这个视图的树型结构当作一个由单一的、大的、包含整个文本的视图来考虑。这个文档视图被分成几个段落视图,它被依次分成几个单独的行。尽管真实工作中的视图情况要比这个简单的描述复杂的多,但该例子中显示了如何通过视图来将一个文档分成契合于打印纸的小的部分。通过查看每一行,你可以测定它是否完全契合于打印纸而不会在底部被分开。如果行数契合,就执行打印,如果不契合,则将它记录下来以便在下一页中执行打印。 包含在JEditorPane中的视图采取了一种和在JPanel中的组件行为相类似的操作。一个主要区别在于视图不要求布局管理器(layout managers)来进行位置处理;它们会自己参与布局。这样一来,在JEditorPane中的视图就会象一个真实的组件和布局管理器一样进行操作。视图知道如何查看、如何绘制自己以及在哪里显示其子文档。 视图并不是被直接建立的。更确切地说,它们是由ViewFactory子类的工厂(factory)来生成的。一个ViewFactory生成一个文档并将它们分成根视图以及所需的分支视图和叶视图。工厂会按照这种方式来处理这些乏味的解析文档和计算布局的工作。 你很少能够直接和这些工厂打交道。对很多部分来说,它们是被自动调用的。在JEditorPane中设置文档并调用JEditorPane.validate()方法来将文档发送的适合的工厂中,该工厂则会返回所需的视图。然后这些视图会被用在组件的布局上。 打印视图 DocumentRenderer类能够将需要打印的文档放入jeditorPane中,它是JEditorPane的一个实例。jeditorPane的宽度决定了打印页面的大小而且它会调用一个验证方法来执行布局。DocumentRenderer不会显示这个JEditorPane,因此屏幕显示不会生效。需要被打印的根视图是通过一个有点复杂的jeditorPane用户界面调用来获得的:View rootView = jeditorPane.getUI().getRootView(jeditorPane); 这个rootView及其子视图可能会对所需信息进行查询以便对打印文档进行布局。这些视图在每部分文本的绘制环境(graphical context)中提供了坐标和大小。通过这些信息你就能够测定这部分文本是否和打印页面相契合。如果契合,则DocumentRenderer将执行打印;如果不契合,该类将对这个用来打印这部分文本而不将其分开的分页符进行测定。 由于视图知道如何自行绘制,因此你无需自己设置字体或颜色。DocumentRenderer以多种字体和颜色通过调用一个简单视图的paint方法来处理式样文本(styled text)。 然而这个视图的树型结构也存在一个问题。你不能确定在一个代表打印文本的叶视图结束之前分支视图从根视图中被分出了几次。你可以通过使用DocumentRenderer 类中的一个简单的循环方法来解决这个问题。 printView方法循环经过视图的分支结构来查找可打印的叶视图。这种方法将一个视图作为其中一个参数。它从根视图开始对每个视图进行检查以测定它是否有相关的子视图。如果有,则printView会依次调用每个子视图将其作为其视图参数。这样一来,这个方法最终会运行至整个树型结构。当该方法发现一个不带子视图的叶视图时,它会在用于打印的绘制环境中检测它的位置。这个方法只用于绘制那些完全契合于该环境的可打印部分的叶视图。当一个叶视图分跨(straddle)页面的底部时,这个方法就会记录该页面上沿的位置以便使下一页从这个位置开始。因此分页符就不会从文本的行当中断开了。 如果你想要更深入地了解打印视图的用法,你可以查找DocumentRenderer类的源代码。我们对它进行了注释讲解。由于它只有不到200行的代码,因此我们有充足的时间来给它加上注释。 该类的局限 我们在Java SDK 1.3和1.4版本中对DocumentRenderer进行过测试,尽管它应该是适用于实现Swing的所有Java版本的。DocumentRenderer是通过标准的Java技术来运行的,因此它不能实现比Java本身更好或更糟的文本绘制。在JEditorPane中不能显示的字符也将无法显示在纸上。 Java在Windows环境下对文本进行测定时有一个小问题。由于文本没有被精确地测定,一些位置可能有些偏离。由于这些错误很小所以通常不是什么大问题,但它会在对文本右对齐(right-justified )时变得很麻烦。因此,要尽量避免使用右对齐方式。DocumentRenderer类不会产生这个问题,它似乎也不会出现在Linux环境中。 最后要说的是,大图标是不能被打印出来的。在Java中不能将它们显示在页面中,但小图标是没有问题的。 在Java中执行打印不再会是一个复杂的问题了。只需简单地写两行代码并通过DocumentRenderer类来将高级的文本打印功能添加到你的程序中可以了。 关于作者: Kei G. Gauthier(CPA成员)是位于Mass州Springfield市American International College的一名会计学教授。Stephen E. Sugermeyer(CPA成员)是位于Mass州Springfield市Western New England College的一名会计学教授。 <淘宝热门商品:
 

145.00 元 

八心八箭瑞士钻石六爪旁镶钻经典钻戒指

 

100.00 元 

韩国手表正品intercrew品牌手表LED手表


来源:程序员网

小小豆叮

局域网电脑远程监控程序

局域网电脑远程监控程序 包括服务器端和客户端 在一台机器运行服务器程序 客户端运行客户端程序 可以动态监视服务器的屏幕 能将鼠标和键盘事件传过去,能进行一般的操作 运行环境:jdk1.4.1(能处理鼠标滚轮的事件) 我在三台机器分别是 win2000 ad server winxp profession redhat linux 8.0 上进行了测试,都可以运行服务器端和客户端,并能工作 支持一台服务器多台客户端,大家一起操纵,呵呵 服务器端源代码: //package com.zms.remotecontrol; import java.awt.BorderLayout; import java.awt.Dimension; import java.awt.Rectangle; import java.awt.Robot; import java.awt.Toolkit; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.awt.image.BufferedImage; import java.io.ByteArrayOutputStream; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.SocketAddress; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.UIManager; import com.sun.image.codec.jpeg.JPEGCodec; import com.sun.image.codec.jpeg.JPEGEncodeParam; import com.sun.image.codec.jpeg.JPEGImageEncoder; public class ServerTest extends Thread { private DatagramSocket socket; public static final int PORT=5000; public static final int MAX=102400; public boolean end; private Robot robot; private Toolkit toolkit; public ServerTest() throws Exception { robot=new Robot(); toolkit=Toolkit.getDefaultToolkit(); this.socket=new DatagramSocket(PORT); socket.setSendBufferSize(MAX); end=false; } private void sendScreen(SocketAddress address) { try { BufferedImage image=robot.createScreenCapture(new Rectangle(toolkit.getScreenSize())); ByteArrayOutputStream output=new ByteArrayOutputStream(); JPEGEncodeParam param=JPEGCodec.getDefaultJPEGEncodeParam(image); param.setQuality(0.1f,false); JPEGImageEncoder encoder=JPEGCodec.createJPEGEncoder(output,param); encoder.encode(image); encoder.getOutputStream().close(); DatagramPacket packet=new DatagramPacket(output.toByteArray(),output.size (),address); this.socket.send(packet); } catch (Exception e) { e.printStackTrace(); } } public void run() { byte[] bytes=new byte[1020]; while(!end) { try { DatagramPacket packet=new DatagramPacket(bytes,bytes.length); this.socket.receive(packet); String command=new String(packet.getData(),packet.getOffset(),20).trim(); if(command.equalsIgnoreCase('REFRESH')) { sendScreen(packet.getSocketAddress()); } else { byte[] the=packet.getData(); int n=packet.getOffset(); int x=Integer.parseInt(new String(the,n+20,10).trim()); int y=Integer.parseInt(new String(the,n+30,10).trim()); int button=Integer.parseInt(new String(the,n+40,10).trim()); if(command.equalsIgnoreCase('MousePressed')) { robot.mousePress(button); } else if(command.equalsIgnoreCase('MouseReleased')) { robot.mouseRelease(button); } else if(command.equalsIgnoreCase('MouseMoved')) { robot.mouseMove(x,y); } else if(command.equalsIgnoreCase('MouseWheel')) { robot.mouseWheel(button); } else if(command.equalsIgnoreCase('KeyPressed')) { robot.keyPress(x); } else if(command.equalsIgnoreCase('KeyReleased')) { robot.keyRelease(x); } } } catch (Exception e) { try { Thread.sleep(100); } catch (Exception ex) { } } } } public void close() { end=true; this.socket.close(); } public static void main(String[] args) { ServerTest one=null; try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); JFrame frame=new JFrame('Remote Control Server'); frame.getContentPane().setLayout(new BorderLayout()); frame.setSize(240,80); JButton exit=new JButton('Exit'); frame.getContentPane().add(exit,BorderLayout.CENTER); Dimension screen=Toolkit.getDefaultToolkit().getScreenSize(); Dimension a=frame.getSize(); frame.setLocation((screen.width-a.width)/2,(screen.height-a.height)/2); one=new ServerTest(); one.start(); final ServerTest the=one; exit.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { the.close(); System.exit(0); } }); frame.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { the.close(); System.exit(0); } }); frame.setVisible(true); } catch (Exception e) { e.printStackTrace(); if(one!=null) { one.close(); } System.exit(0); } } } 客户端源程序已经编写了,正在完善中。欢迎大家来信咨询,在我的主页已经公开源代码了! //客户端源代码: /* * Created on 2003-3-25 * * To change this generated comment go to * Window>Preferences>Java>Code Generation>Code and Comments 使用方法: 先在服务器运行服务器端程序 再在客户端运行客户端程序(不要运行在一台机器上,你会发现鼠标很奇怪) 在客户端右击中间区域,单击那个菜单项,输入服务器的地址 ok 让我继续来完善 */ - 作者简介: 22岁,大学计算机系专业,现正致力于JAVA开发,对JAVA的桌面应用系统开发和WEB相关技术有一定研究,曾开发jant,jzip,小型游戏,JDBC..etc,对J2EE/J2ME充满信心。 你可以通过网站:http://www.fls-cts.com/kkjvk/、OICQ:29578635,878229,email:kkjvk12@yeah.net和vincent联系。 <淘宝热门商品:
 

35.00 元  

〓朩玲〓网游点卡专卖店『无分店无小号!无手机充值卡!』

【五钻自动发货】跑跑卡丁车40元400点专用卡【充值看商品说明】

 

88.00 元 

【魅力先生】推存!Dior韩国立体裁剪修身小直筒


来源:程序员网

小小豆叮

面向服务架构(SOA)的原则

Web service已经不再是新婚的娘子。众多企业都已经创建各种实验性Web Services 项目,事实证明,这项新兴的分布式计算技术确实能够降低集成和开发的成本。另外,一些关键的Web Services标准纷纷制定,强安全(robust security)和管理方面的产品也陆续问世。对于志向远大的企业来说,他们已经在考虑下一步了。 对大多数公司来说,下一步要考虑的不再是点对点的应用,而是Web services在企业间以及业务伙伴间更为宽广的应用。这种技术的变迁需要更松散耦合、面向基于标准的服务的架构。这样一个架构要求对IT在组织中的角色有新的观点和认识,而不仅仅是一种实现方法。通过对业务的敏捷反应,企业可以得到实实在在的回报,而要达到这一点,面向服务架构设计师的角色非常关键。除此之外,潜在的回报更是不可胜数-分布计算技术能够保证对业务需求足够灵活的反应,而这种业务上的敏捷正是各公司梦寐以求而目前还遥不可及的。 分布式计算将网络上分布的软件资源看作是各种服务。面向服务架构是一种不错的解决方案。但这种架构不是什么新思想;CORBA和DCOM就很类似,但是,这些过去的面向服务架构都受到一些难题的困扰:首先,它们是紧密耦合的,这就意味着如分布计算连接的两端都必须遵循同样API的约束。打比方说,如果一个COM对象的代码有了更改,那么访问该对象的代码也必须作出相应更改。其二,这些面向服务架构受到厂商的约束。Microsoft控制DCOM自不必说,CORBA也只是一个伪装的标准化努力,事实上,实现一个CORBA架构,经常都是在某个厂商对规范的实现上进行工作。 Web services是在改进DCOM和CORBA缺点上的努力。今天应用Web services的面向服务架构与过去不同的特点就在于它们是基于标准以及松散耦合的。广泛接受的标准(如XML和SOAP)提供了在各不同厂商解决方案之间的交互性。而松散耦合将分布计算中的参与者隔离开来,交互两边某一方的改动并不会影响到另一方。这两者的结合意味着公司可以实现某些Web services而不用对使用这些Web services的客户端的知识有任何了解。我们将这种基于标准的、松散耦合的面向服务的架构简称为SOA。 SOA的强大和灵活性将给企业带来巨大的好处。如果某组织将其IT架构抽象出来,将其功能以粗粒度的服务形式表示出来,每种服务都清晰地表示其业务价值,那么,这些服务的顾客(可能在公司内部,也可能是公司的某个业务伙伴)就可以得到这些服务,而不必考虑其后台实现的具体技术。更进一步,如果顾客能够发现并绑定可用的服务,那么在这些服务背后的IT系统能够提供更大的灵活性。 但是,要得到种强大和灵活性,需要有一种实现架构的新方法,这是一项艰巨的任务。企业架构设计师必须要变成“面向服务的架构设计师”,不仅要理解SOA,还要理解SOA的实践。在架构实践和最后得到的架构结果之间的区别非常微妙,也非常关键。本文将讨论SOA的实践,即:面向架构的设计师在构建SOA时必须要做的事情。 SOA的原则 SOA是一种企业架构,因此,它是从企业的需求开始的。但是,SOA和其它企业架构方法的不同之处在于SOA提供的业务敏捷性。业务敏捷性是指企业对变更快速和有效地进行响应、并且利用变更来得到竞争优势的能力。对架构设计师来说,创建一个业务敏捷的架构意味着创建这样一个IT架构,它可以满足当前还未知的业务需求。 要满足这种业务敏捷性,SOA的实践必须遵循以下原则: * 业务驱动服务,服务驱动技术 从本质上说,在抽象层次上,服务位于业务和技术中间。面向服务的架构设计师一方面必须理解在业务需求和可以提供的服务之间的动态关系,另一方面,同样要理解服务与提供这些服务的底层技术之间的关系。 * 业务敏捷是基本的业务需求 SOA考虑的是下一个抽象层次:提供响应变化需求的能力是新的“元需求”,而不是处理一些业务上的固定不变的需求。从硬件系统而上的整个架构都必须满足业务敏捷的需求,因为,在SOA中任何的瓶颈都会影响到整个IT环境的灵活性。 * 一个成功的SOA总在变化之中 SOA工作的场景,更象是一个活的生物体,而不是象传统所说的“盖一栋房子”。IT环境唯一不变的就是变化,因此面向服务架构设计师的工作永远不会结束。对于习惯于盖房子的设计师来说,要转向设计一个活的生物体要求崭新的思维方式。如下文所写的,SOA的基础还是一些类似的架构准则。 SOA基础 在IT行业有两个越来越普遍的发展方向,一个是架构方面的,一个是方法学方面的,面向服务的架构设计师可以从中有所收获。第一个就是MDA(模型驱动架构),由提出CORBA的OMG模型提出。MDA认为架构设计师首先要对待创建的系统有一个形式化的UML(也是由OMG提出)的模型。MDA首先给出一个平台无关的模型来表示系统的功能需求和use cases,根据系统搭建的平台,架构设计师可以由这个平台无关的模型得到平台相关的模型,这些平台相关模型足够详细,以至于可以用来直接生成需要的代码。 MDA的核心就在于在设计阶段系统就已经完全描述,这样,在创建系统的时候,几乎就没有错误解释的可能,模型也就可以直接生成代码。但MDA有一些局限性:首先,MDA假设在创建模型之前,业务需求已经全部描述,而这一点,在当前典型的动态业务环境中几乎是不可能的。第二,MDA没有一个反馈机制。如果开发人员对模型有需要改动的地方,并没有提供给他们这么一个途径。 SOA的另一个基础是敏捷方法(AM),其中非常有名的方法是极限编程(XP)。象XP这样的AM提供了在需求未知或者多变的环境中创建软件系统的过程。XP要求在开发团队中要有一个用户代表,他帮助书写测试来指导开发人员的日常工作。开发团队中的所有成员都参与到设计之中,并且设计要尽量小并且非形式化。AM的目标是仅仅创建用户想要的,而不是在一些形式化模型上耗费工作量。AM的核心思想就在于其敏捷性-处理需求变更的敏捷性。AM的主要弱点是其规模上的限制,例如,XP在一个小团队和中型项目中效果不错,但是当项目规模增大时,如果没有一个一致的清晰的计划,项目成员很难把握项目中的方方面面。 从表面看来,MDA和AM似乎是相对立的-MDA假定需求是固定的,而AM恰恰相反。MDA的中心是形式化的模型,而AM恰恰要避开它们。但是,我们还是决定冒险把这些不同方法中的一些元素提取出来,放入到一个一致的架构实践中。 在SOA中有三个抽象层次,按照SOA的第一条准则:业务驱动服务、服务驱动技术。AM将业务模型直接和实践连接起来,表现在平台相关的模型之中。MDA并没有把业务模型和平台无关模型分开来,而是把平台无关模型做为起点。SOA必须连接这些模型,或者说抽象层次,得到单一的架构方法。我们将从五个视图的架构实现方法来实现这个连接。 SOA的五视图实现方法 企业架构设计师发现他们的职业非常有竞争力并且值得骄傲,因为他们要从很多方面来通盘考虑IT系统。Kruchten(RUP的开发负责人)将这些方面提取出来,在应用到SOA时,我们称为五视图实现方法(five-view approach)。 四个方框表示对一个架构的不同审视方法,分别代表不同的涉众(stakeholder)。弟五个视图,use-case视图涵盖了其它视图,在架构中扮演的是一个特殊的角色。部署视图将软件映射到底层平台和相关硬件上,是系统部署人员对架构的视图;实现视图描述了软件代码的组织,是从开发人员角度出发的视图;业务分析人员则利用过程视图进行工作,它描述的是软件系统的运行时特性。最后,逻辑视图表示的是用户的功能需求。在SOA中,面向服务的架构必须能够以use-case视图中的用例将用户连接到服务,将服务连接到底层的技术。 为了表示面向对象的架构是如何工作在这些视图之上,让我们将他们置于SOA元模型的上下文之中。SOA中两个领域存在重叠:由业务模型和服务模型表示的业务领域和由服务模型及平台相关模型表示的技术领域(两个领域共享服务模型)。业务用户通过逻辑视图和过程视图处理粗粒度的业务服务,根据变化的业务需求,按照需要将它们安排在过程之中。另一方面,技术专家的工作是创建并维护服务和地层技术之间的抽象层。表示这些服务的中间模型,起到的是轴心的作用,业务以它为中心进行。 SOA元模型从MDA中继承平台无关模型和平台相关模型,但是添加了AM和用户交互以及敏捷的反馈这两部分,后者通过椭圆之间的双向箭头来表现。类似地,元模型通过引入由中心的服务模型提供的中间层抽象解决了AM在伸缩性方面的问题。这样,服务模型中的任何需求的变化,都会反映到用户每天的业务处理中。同样,由于底层技术是模型驱动的,技术专家也可以根据这些变化的需求迅速而有效地作出应变。 SOA实践和过去解决企业架构传统方式的不同之处就在于其对敏捷性的支持。如前所说,SOA的第三条原则就在于它总在变化之中。这种恒在的变化性环境是SOA实践的基石。如图所示,涉众(stakeholders,译者注:RUP中也有这个词,表示软件开发中涉及到的各种角色如:用户、设计人员、开发人员乃至测试人员等等。)在一个必需的基础上影响到整个架构的变化。在当技术专家在每天的日常工作中不断对变化的业务需求作出响应的这种情况下,设计阶段和运行阶段之间的界限变得模糊起来,很难清晰地分离这两个阶段。 剩下的部分 我们已经为面向服务的架构提供了一个高层次的框架,其中MDA和AM的元素帮助工具的使用者来创建和维护SOA。但是,SOA中还缺少一些内容-那就是软件开发商和专业的服务组织必需提供的。理想情况下,开发商必需提供面向服务的业务流程、工作流以及服务的协调工具和服务;另外,能够以一种敏捷的、平台无关的方式充分反映业务服务的建模工具也是必须的;技术专家必须配备可以从模型中自动生成代码,并在代码变化时更新模型的工具,最后,开发商必须提供支持SOA的软件,帮助面向服务的架构设计师以一种可信并且可伸缩的方式创建位于服务和底层技术之间的抽象层次。幸运的是,这方面的产品即将上市。 另外,最重要的就是贯穿本文的自顶而下的SOA实现方法了。今天关于Web services的大部分思考都是自底而上的:“这是如何创建Web services的方法,现在,我们来使用它们集成吧”,对Web services技术的这种方法是伟大的第一步,因为它可以惊人地降低集成的开销,这是现在的技术管理人员最乐意见到的了。但当经济进一步发展,IT走出低谷,企业会寻求IT的帮助来提高组织战略意义上的核心价值。使用面向服务的架构,IT可以提供给企业实现业务敏捷性的这样一个框架。 <淘宝热门商品:
 

 

专做VIVI昕薇瑞丽韩日女装~

 

0.90 元  

:①般般dē我 开【不】①般般的店

『四钻信誉』官方QB正规秒冲Q币,按元直充0.9元/QQ币


来源:程序员网

小小豆叮

开源组织发布J2EE网上书店示例应用

近日,致力于开发“J2EE极限开发框架”BS Framework的Bright Side Factory组织发布了一个网上书店(BookStore)的电子商务应用程序演示。这个演示程序正是用他们的开源J2EE框架BS Framework开发的。 和Sun的Petstore以及其他的Xpetstore演示项目相似,BookStore的用途也是展示如何使用这个开放源码的框架快速地构造J2EE应用程序。与此同时,BookStore还向人们展示如何借助Webstart和HTTP通信层轻松地在外部网上实现功能丰富的Swing客户端。 BookStore项目是100%开放源码的。在实现BookStore项目时需要使用JBoss、mySQL和其他一些开源框架,例如Castor、Log4J、foxtrot等,当然还包括BS Framework。 您可以在http://www.bs-factory.org网站了解更多相关信息。 TheServerSide.com的网友评价道: “在电子商务应用程序使用rich client,这是件很有趣的事情,尤其是使用Swing这样颇受非议的库。” 原文请看: http://www.theserverside.com/home/thread.jsp?thread_id=18454&article_count=3 <淘宝热门商品:
 

 

柠檬绿茶 淘宝第一(唯一)100万双金冠信誉! 网络白领女性超市!

 

99.00 元  

DOROTHY去印平坑明星!第二代积雪草细胞再生霜-填平坑


来源:程序员网

小小豆叮

j2ee的13种核心技术

英文原版:http://www.javaworld.com/javaworld/jw-12-2000/jw-1201-weblogic_p.html   内容简介   STEVEN GOULD在文中介绍了JAVA2平台企业版(J2EE)的13种核心技术:JDBC, JNDI, EJBS, RMI, JSP, JAVA SERVLETS, XML, JMS, JAVA IDL, JTS, JTA, JAVAMAIL 和 JAF。为了联系实际,GOULD基于WEBLOGIC应用服务器—来自BEA SYSTEMS公司的一种广为应用的产品—环境来介绍J2EE的这些技术。   JAVA最初是在浏览器和客户端机器中粉墨登场的。当时,很多人质疑它是否适合做服务器端的开发。现在,随着对JAVA2平台企业版(J2EE)第三方支持的增多,JAVA被广泛接纳为开发企业级服务器端解决方案的首选平台之一。   J2EE平台由一整套服务(SERVICES)、应用程序接口(APIS)和协议构成,它对开发基于WEB的多层应用提供了功能支持。   在本文中我将解释支撑J2EE的13种核心技术:JDBC, JNDI, EJBS, RMI, JSP, JAVA SERVLETS, XML, JMS, JAVA IDL, JTS, JTA, JAVAMAIL 和 JAF,同时还将描述在何时、何处需要使用这些技术。当然,我还要介绍这些不同的技术之间是如何交互的。   此外,为了让您更好地感受J2EE的真实应用,我将在WEBLOGIC应用服务器—来自BEA SYSTEMS公司的一种广为应用的产品—环境下来介绍这些技术。不论对于WEBLOGIC应用服务器和J2EE的新手,还是那些想了解J2EE能带来什么好处的项目管理者和系统分析员,相信本文一定很有参考价值。   宏观印象: 分布式结构和J2EE   过去,二层化应用 -- 通常被称为CLIENT/SERVER应用 -- 是大家谈论的最多的。图1刻画了典型的二层化结构。在很多情况下,服务器提供的唯一服务就是数据库服务。在这种解决方案中,客户端程序负责数据访问、实现业务逻辑、用合适的样式显示结果、弹出预设的用户界面、接受用户输入等。CLIENT/SERVER结构通常在第一次部署的时候比较容易,但难于升级或改进,而且经常基于某种专有的协议—通常是某种数据库协议。它使得重用业务逻辑和界面逻辑非常困难。更重要的是,在WEB时代,二层化应用通常不能体现出很好的伸缩性,因而很难适应INTERNET的要求。   图1. 二层化应用结构   SUN设计J2EE的部分起因就是想解决二层化结构的缺陷。于是,J2EE定义了一套标准来简化N层企业级应用的开发。它定义了一套标准化的组件,并为这些组件提供了完整的服务。J2EE还自动为应用程序处理了很多实现细节,如安全、多线程等。   用J2EE开发N层应用包括将二层化结构中的不同层面切分成许多层。一个N层化应用A能够为以下的每种服务提供一个分开的层:   显示:在一个典型的WEB应用中,客户端机器上运行的浏览器负责实现用户界面。   动态生成显示: 尽管浏览器可以完成某些动态内容显示,但为了兼容不同的浏览器,这些动态生成工作应该放在WEB服务器端进行,使用JSP、SERVLETS,或者XML(可扩展标记语言)和(可扩展样式表语言)。   业务逻辑:业务逻辑适合用SESSION EJBS(后面将介绍)来实现。   数据访问:数据访问适合用ENTITY EJBS(后面将介绍)和JDBC来实现。   后台系统集成: 同后台系统的集成可能需要用到许多不同的技术,至于何种最佳需要根据后台系统的特征而定。   您可能开始诧异:为什么有这么多的层?事实上,多层方式可以使企业级应用具有很强的伸缩性,它允许每层专注于特定的角色。例如,让WEB服务器负责提供页面,应用服务器处理应用逻辑,而数据库服务器提供数据库服务。   由于J2EE建立在JAVA2平台标准版(J2SE)的基础上,所以具备了J2SE的所有优点和功能。包括“编写一次,到处可用”的可移植性、通过JDBC访问数据库、同原有企业资源进行交互的CORBA技术,以及一个经过验证的安全模型。在这些基础上,J2EE又增加了对EJB(企业级JAVA组件)、JAVA SERVLETS、JAVA服务器页面(JSPS)和XML技术的支持。   分布式结构与WEBLOGIC应用服务器   J2EE提供了一个框架--一套标准API--用于开发分布式结构的应用,这个框架的实际实现留给了第三方厂商。部分厂商只是专注于整个J2EE架构中的的特定组件,例如APACHE的TOMCAT提供了对JSP和SERVLETS的支持,BEA系统公司则通过其WEBLOGIC应用服务器产品为整个J2EE规范提供了一个较为完整的实现。   WEBLOGIC服务器已使建立和部署伸缩性较好的分布式应用的过程大为简化。WEBLOGIC和J2EE代你处理了大量常规的编程任务,包括提供事务服务、安全领域、可靠的消息、名字和目录服务、数据库访问和连接池、线程池、负载平衡和容错处理等。   通过以一种标准、易用的方式提供这些公共服务,象WEBLOGIC服务器这样的产品造就了具有更好伸缩性和可维护性的应用系统,使其为大量的用户提供了增长的可用性。   J2EE技术   在接下来的部分里,我们将描述构成J2EE的各种技术,并且了解WEBLOGIC服务器是如何在一个分布式应用中对它们进行支持的。最常用的J2EE技术应该是JDBC、JNDI、EJB、JSP和SERVLETS,对这些我们将作更仔细的考察。   图2表示了在一个分布式应用中,J2EE技术的各个方面通常在何处发挥作用。   图2. 一个N层应用结构的例子   JAVA DATABASE CONNECTIVITY (JDBC)   JDBC API以一种统一的方式来对各种各样的数据库进行存取。和ODBC一样,JDBC为开发人员隐藏了不同数据库的不同特性。另外,由于JDBC建立在JAVA的基础上,因此还提供了数据库存取的平台独立性。   JDBC定义了4种不同的驱动程序,现分述如下:   类型 1: JDBC-ODBC BRIDGE   在JDBC出现的初期,JDBC-ODBC桥显然是非常有实用意义的,通过JDBC-ODBC桥,开发人员可以使用JDBC来存取ODBC数据源。不足的是,他需要在客户端安装ODBC驱动程序,换句话说,必须安装MICROSOFT WINDOWS的某个版本。使用这一类型你需要牺牲JDBC的平台独立性。另外,ODBC驱动程序还需要具有客户端的控制权限。   类型 2: JDBC-NATIVE DRIVER BRIDGE   JDBC本地驱动程序桥提供了一种JDBC接口,它建立在本地数据库驱动程序的顶层,而不需要使用ODBC。 JDBC驱动程序将对数据库的API从标准的JDBC调用转换为本地调用。使用此类型需要牺牲JDBC的平台独立性,还要求在客户端安装一些本地代码。   类型 3: JDBC-NETWORK BRIDGE   JDBC网络桥驱动程序不再需要客户端数据库驱动程序。它使用网络上的中间服务器来存取数据库。这种应用使得以下技术的实现有了可能,这些技术包括负载均衡、连接缓冲池和数据缓存等。由于第3种类型往往只需要相对更少的下载时间,具有平台独立性,而且不需要在客户端安装并取得控制权,所以很适合于INTERNET上的应用。   类型 4: PURE JAVA DRIVER   第4种类型通过使用一个纯JAVA数据库驱动程序来执行数据库的直接访问。此类型实际上在客户端实现了2层结构。要在N-层结构中应用,一个更好的做法是编写一个EJB,让它包含存取代码并提供一个对客户端具有数据库独立性的服务。   WEBLOGIC服务器为一些通常的数据库提供了JDBC驱动程序,包括ORACLE, SYBASE, MICROSOFT SQL SERVER以及INFORMIX。它也带有一种JDBC驱动程序用于CLOUDSCAPE,这是一种纯JAVA的DBMS,WEBLOGIC服务器中带有该数据库的评估版本。   以下让我们看一个实例。   JDBC实例   在这个例子中我们假定你已经在CLOUDSCAPE中建立了一个PHONEBOOK数据库,并且包含一个表,名为 CONTACT_TABLE ,它带有2个字段:NAME 和 PHONE。 开始的时候先装载CLOUDSCAPE JDBC DRIVER,并请求 DRIVER MANAGER得到一个对PHONEBOOK CLOUDSCAPE数据库的连接。通过这一连接,我们可以构造一个 STATEMENT 对象并用它来执行一个简单的SQL查询。最后,用循环来遍历结果集的所有数据,并用标准输出将NAME和PHONE字段的内容进行输出。 IMPORT JAVA.SQL.*; PUBLIC CLASS JDBCEXAMPLE { PUBLIC STATIC VOID MAIN( STRING ARGS[] ) { TRY { CLASS.FORNAME("COM.CLOUDSCAPE.CORE.JDBCDRIVER"); CONNECTION CONN = DRIVERMANAGER.GETCONNECTION("JDBC:CLOUDSCAPE:PHONEBOOK"); STATEMENT STMT = CONN.CREATESTATEMENT(); STRING SQL = "SELECT NAME, PHONE FROM CONTACT_TABLE ORDER BY NAME"; RESULTSET RESULTSET = STMT.EXECUTEQUERY( SQL ); STRING NAME; STRING PHONE; WHILE ( RESULTSET.NEXT() ) { NAME = RESULTSET.GETSTRING(1).TRIM(); PHONE = RESULTSET.GETSTRING(2).TRIM(); SYSTEM.OUT.PRINTLN( NAME + ", " + PHONE ); } } CATCH ( EXCEPTION E ) { // HANDLE EXCEPTION HERE E.PRINTSTACKTRACE(); } } }   OK。接着我们来看一看JDBC是如何在企业应用中的进行使用。   JDBC在企业级应用中的应用   以上实例其实是很基本的,可能有些微不足道。它假定了一个2层结构。在一个多层的企业级应用中,更大的可能是在客户端和一个EJB进行通信,该EJB将建立数据库连接。为了实现和改进可伸缩性和系统性能, WEBLOGIC服务器提供了对连接缓冲池CONNECTION POOL的支持。   CONNECTION POOL减少了建立和释放数据库连接的消耗。在系统启动以后即可建立这样的缓冲池,此后如故再有对数据库的请求,WEBLOGIC服务器可以很简单地从缓冲池中取出数据。数据缓冲池可以在WEBLOGIC服务器的 WEBLOGIC.PROPERTIES 文件中进行定义。(可参考 WEBLOGIC.PROPERTIES 文件中的例子,WEBLOGIC服务器的文档中还有更详细的参考信息)   在企业级应用的另一个常见的数据库特性是事务处理。事务是一组申明STATEMENT,它们必须做为同一个STATEMENT来处理以保证数据完整性。缺省情况下JDBC使用 AUTO-COMMIT 事务模式。这可以通过使用CONNECTION类的 SETAUTOCOMMIT() 方法来实现。   现在我们已经对JDBC有了一些认识,下面该转向JNDI了。   JAVA NAMING AND DIRECTORY INTERFACE (JNDI)   JNDI API被用于执行名字和目录服务。它提供了一致的模型来存取和操作企业级的资源如DNS和LDAP,本地文件系统,后者在应用服务器中的对象。   在JNDI中,在目录结构中的每一个结点称为CONTEXT。每一个JNDI名字都是相对于CONTEXT的。这里没有绝对名字的概念存在。对一个应用来说,它可以通过使用 INITIALCONTEXT 类来得到其第一个CONTEXT:   CONTEXT CTX = NEW INITIALCONTEXT();   应用可以通过这个初始化的CONTEXT经有这个目录树来定位它所需要的资源或对象。例如,假设你在WEBLOGIC服务器中展开了一个EJB并将HOME接口绑定到名字 MYAPP.MYEJB ,那么该EJB的某个客户在取得一个初始化CONTEXT以后,可以通过以下语句定位HOME接口:   MYEJBHOME HOME = CTX.LOOKUP( "MYAPP.MYEJB" );   在这个例子中,一旦你有了对被请求对象的参考,EJB的HOME接口就可以在它上面调用方法。我们将在下面的"ENTERPRISE JAVA BEANS"章节中做更多的介绍。   以上关于JNDI的讨论只是冰山之一角而已。如果要更进一步地在CONTEXT中查找对象,JNDI也提供了一些方法来进行以下操作:    将一个对象插入或绑定到CONTEXT。这在你展开一个EJB的时候是很有效的。   从CONTEXT中移去对象。   列出CONTEXT中的所有对象。   创建或删除子一级的CONTEXT。   接下来,我们要开始关注EJB了。   ENTERPRISE JAVA BEANS (EJB)   J2EE技术之所以赢得某体广泛重视的原因之一就是EJB。它们提供了一个框架来开发和实施分布式商务逻辑,由此很显著地简化了具有可伸缩性和高度复杂的企业级应用的开发。EJB规范定义了EJB组件在何时如何与它们的容器进行交互作用。容器负责提供公用的服务,例如目录服务、事务管理、安全性、资源缓冲池以及容错性。   EJB规范定义了3中基本的BEAN类型:   STATELESS SESSION BEANS: 提供某种单一的服务,不维持任何状态,在服务器故障发生时无法继续存在,生命期相对较短。例如,一个STATELESS SESSION BEAN可能被用于执行温度转换计算。   STATEFUL SESSION BEAN: T提供了与客户端的会话交互,可以存储状态从而代表一个客户。典型例子是购物车。STATEFUL SESSION BEAN在服务器故障时无法继续生存,生命气相对较短。每一个实例只用于一个单个的线程。   ENTITY BEANS: 提供了一致性数据的表示-- 通常存放在数据库中 -- 在服务器故障发生后能继续存在。多用户情况下可以使用EJB来表示相同的数据。ENTITY EJB的一个典型例子是客户的帐号信息。   尽管有以上的区别,所有的EJB还是有许多的共同之处。它们都处理HOME INTERFACE。它定义了一个客户端是如何创建与消亡EJB的。可以在BEAN中对定义了客户端方法的远程接口进行调用;BEAN类则执行了主要的商务逻辑。   描述EJB的开发已经超出了本文的范围。但是,如果一个EJB已经被开发了或者从第三方进行了购买,它就必须在应用服务器中进行发布。WEBLOGIC SERVER 5.1带有一个EJB DEPLOYER TOOL来协助处理EJB的发布。当你使用EJB DEPLOYER TOOL的时候,你要定义客户端所用的JNDI名字来定位EJB。DEPLOYER TOOL将生成WRAPPER类来处理和容器的通信以及在一个JAR文件中把被请求的JAVA类绑定在一起。   一旦EJB被发布,客户端就可以使用它的JNDI名字来定位EJB。首先,它必须得到一个到HOME接口的REFERENCE。然后,客户端可以使用该接口,调用一个 CREATE() 方法来得到服务器上运行的某个BEAN实例的句柄;最后,客户端可以使用该句柄在BEAN中调用方法。   了解 EJB后,让我们再来看JSP。   JAVASERVER PAGES (JSPS)   我们中间可能已经有许多人已经熟悉MICROSOFT的ACTIVE SERVER PAGES (ASP)技术了。JSP和ASP相对应的,但更具有平台对立性。他们被设计用以帮助WEB内容开发人员创建动态网页,并且只需要相对较少的代码。 即使WEB设计师不懂得如何编程也可以使用JSP,因为JSP应用是很方便的。 JSP页面由HTML代码和嵌入其中的JAVA代码所组成。服务器在页面被客户端所请求以后对这些JAVA代码进行处理,然后将生成的HTML页面返回给客户端的浏览器。   下面我们来看一个JSP的简单实例。它只显示了服务器的当前日期和时间。虽然,对语法的具体解释已经超出了本文的范围,但我们还是可以很直观地看到,JAVA代码被放在<%和%>的中间,而JAVA的表达式则放在<%=和%>之间。 Sample JSP Page

Date JSP sample

<% response.setHeader("Refresh", 5); %> The current date is <%= new Date() %>.

  您可能有时候听说过JHTML。这是JSP以前的一种较老的标准。WEBLOGIC服务器既可支持JSP,又可支持JHTML。请注意,在缺省状况下,JSP在WEBLOGIC服务器中并没有处于有效状态。要使之有效,你可以编辑WEBLOGIC.PROPERTIES文件。如果WEB服务器还没有处于有效状态,则要先使之有效。SERVLET的情况和JSP是一样的。   下面是: JAVA SERVLETS   JAVA SERVLETS   SERVLET提供的功能大多与JSP类似,不过实现的方式不同。JSP通常是大多数HTML代码中嵌入少量的JAVA代码,而SERVLETS全部由JAVA写成并且生成HTML。   SERVLET是一种小型的JAVA程序,它扩展了WEB服务器的功能。作为一种服务器端的应用,当被请求时开始执行,这和CGI PERL脚本很相似。SERVLETS和CGI脚本的一个很大的区别是:每一个CGI在开始的时候都要求开始一个新的进程 -- 而SERVLETS是在SERVLET引擎中以分离的线程来运行的。因此SERVLETS在可伸缩性上提供了很好的改进。   在开发SERVLETS的时候,您常常需要扩展JAVAX.SERVLET.HTTP.HTTPSERVLET 类,并且OVERRIDE一些它的方法,其中包括:   SERVICE(): 作为DISPATCHER来实现命令-定义方法   DOGET(): 处理客户端的HTTP GET请求。   DOPOST(): 进行HTTP POST操作   其它的方法还包括处理不同类型的HTTP请求 -- 可以参考HTTPSERVLET API文档。   以上描述的是标准J2EE SERVLET API的各种方法。WEBLOGIC服务器提供了一个该API完整的实现途径。一旦你开发了一个SERVLET,你就可以在WEBLOGIC.PROPERTIES 中加以注册并由此可以在WEBLOGIC服务器中对它进行配置。   通过JAVA SERVLETS,我们已经到达了J2EE主要技术的末尾了。但J2EE所提供的并不止于这些。下面的段落中我们将简要地看一下现存的一些技术,包括RMI, JAVA IDL和CORBA, JTA, 以及XML,等等。   REMOTE METHOD INVOCATION (RMI)   正如其名字所表示的那样,RMI协议是在远程对象上调用一些方法。它使用了连续序列方式在客户端和服务器端传递数据。RMI是一种被EJB使用的更下层的协议。   JAVA IDL/CORBA   在JAVA IDL的支持下,开发人员可以将JAVA和CORBA集成在一起。 他们可以创建JAVA对象并使之可在CORBA ORB中展开, 或者他们还可以创建JAVA类并作为和其它ORB一起展开的CORBA对象的客户。后一种方法提供了另外一种途径,通过它JAVA可以被用于将你的新的应用和LEGACY系统相集成。   JAVA TRANSACTION ARCHITECTURE (JTA)/JAVA TRANSACTION SERVICE (JTS)   JTA定义了一种标准的API,应用系统由此可以存取各种事务监控。   JTS是CORBA OTS事务监控的基本的实现。JTS规定了事务管理器的实现方式。该事务管理器是在高层支持JAVA TRANSACTION API (JTA)规范,并且在较底层实现OMG OTS SPECIFICATION的JAVA映像。JTS事务管理器为应用服务器、资源管理器、独立的应用以及通信资源管理器提供了事务服务。   JAVAMAIL AND JAVABEANS ACTIVATION FRAMEWORK   JAVAMAIL是用于存取邮件服务器的API,它提供了一套邮件服务器的抽象类。不仅支持SMTP服务器,也支持IMAP服务器。   JAVAMAIL利用JAVABEANS ACTIVATION FRAMEWORK (JAF)来处理MIME-编码的邮件附件。MIME的字节流可以被转换成JAVA对象,或者转换自JAVA对象。由此大多数应用都可以不需要直接使用JAF。   JAVA MESSAGING SERVICE (JMS)   JMS是用于和面向消息的中间件相互通信的应用程序接口(API)。它既支持点对点的域,有支持发布/订阅(PUBLISH/SUBSCRIBE)类型的域,并且提供对下列类型的支持:经认可的消息传递,事务型消息的传递,一致性消息和具有持久性的订阅者支持。JMS还提供了另一种方式来对您的应用与LEGACY BACKEND系统相集成。   EXTENSIBLE MARKUP LANGUAGE (XML)   XML是一种可以用来定义其它标记语言的语言。它被用来在不同的商务过程中共享数据。XML的发展和JAVA是相互独立的,但是,它和JAVA具有的相同目标正是平台独立性。通过将JAVA和XML的组合,您可以得到一个完美的具有平台独立性的解决方案。目前正有许多不同的公司在为JAVA和XML的组合而努力。如果要了解更多的这方面的信息,可以访问SUN的JAVA-XML页面,或者IBM DEVELOPERWORKS的XML ZONE。   总结   在本文中,我们介绍了建立在J2EE上的分布式应用结构,并且描述了WEBLOGIC服务器对J2EE的各种支持。 然而,我们所揭示的仅仅是冰山之一角而已,要以一篇数千字的文章来展示J2EE潜在的对您的企业级应用的影响可是很不公平的。   我们已经关注了在您开始用J2EE进行工作时最有可能遇到的各类技术:JDBC, JNDI, EJB, JSP和SERVLET。我们也为您提供了一些尚未常见的J2EE技术的背景知识。不管您是一名开发人员,商务应用分析师,或者项目经理,都应该对J2EE和WEBLOGIC服务器所能提供给我们,给我们的企业以及我们的企业级应用所带来的意义有一个更好的认识。 <淘宝热门商品:
 

188.00 元  

地球都踩在脚下

T-MAC8麦迪8代 麦8 08-09赛季麦迪篮球鞋 白黑红 阿迪达斯adidas

 

6.80 元  

北欧橱窗

三冠 三角形强力吸墙角架/置物架/杂物架 承重3公斤 不伤墙面0.14


来源:程序员网

小小豆叮

j2ee的未来!移动客户端的未来,垄断否?control by yourself

J2EE作为企业级的应用,在移动设备发展日益广泛的日子中,将会将移动设备 端的应用整合到其中,企业级应用会在更大程度上依赖移动设备去采集信息, 去反馈信息,而取代现在的大部分终端,因此,就产生了一些应用的方案, 一:j2me的开发应用,二:浏览器的解决方案。 采用j2me解决,可以很好的依赖j2ee的应用中已经存在的java 采用浏览器,可以应用于多个企业及应用中,微软的新款smartPhone 就类似于一款pda,内部拥有msn等一些我们平常使用的软件,但是由于 他切入市场的时机和他平时的一贯名声,使得占领移动市场的步伐缓慢 下来,如果nokia等其他手机厂家不能尽快的将移动设备的软件上一个档次, 这将会是本世纪最影响人们生活的事件产生的一年,。如果smartphone占领 市场,我想又是一场噩梦。 我们可以做自己的,应用open的java.我们中国人能做什么呢?我们可以 有自己的东西,希望有钱的出钱,有力的出力,我们把我们的市场镇守住! 如果有相同志向的,能出力的,和我联系,msn:1981@hotmail.com <淘宝热门商品:
 

46.00 元 

千姿百袋 淘宝第一热销包包!特价疯抢日韩时尚通勤手提包14色

 

96.00 元 

奥地利进口 专柜礼盒 天然水晶 施家经典STARS


来源:程序员网

小小豆叮

一个参考Junit的设计模式ppt

前几天给别人做设计模式的课程培训,希望找个复杂的项目进行剖析,看设计模式的应用。当然想到junit,他的开发者就是大名鼎鼎的Erich Gamma(GOF之一)和Kent Beck。看看牛人是怎样使用设计模式的。然后自己写了一篇ppt,给学员讲解。现在就把他发给你。junit的代码很少,一天左右就看完了。里面的代码写的很美,让人佩服。 希望中国的程序员,都能抽出一天的时间来学习他的源码!!!! 由于时间很紧,内容也没有韵色,copy了不少junit的doc. 下载地址 http://www.cn-java.com/download/book/junit.ppt <淘宝热门商品:
 

运动鞋 

X-2品牌时尚鞋城【郭氏鞋坊旗下】[销售出口多余产品

 

¥:4.00 

蓉蓉de美女加工厂 打造淘宝最低价


来源:程序员网

小小豆叮

高通妥协赌注“双模芯片”中国联通紧急上马JAVA

与中国联通的脚踩两只船相似,高通公司也想出了两全之计———在自己的CDMA芯片中直接嵌入SUN公司的JAVA技术。   不过,“双模芯片”是否能受到青睐?最终将由用户说了算。   在BREW大鸣大放的烟雾掩护下,中国联通悄然摆开了JAVA防御阵线。   中国联通公司增值业务部总经理王颖沛透露,联通公司总部也将在4月份对外招标JAVA平台,随之准备在6、7月份全面启动JAVA业务试运营。目前,招标工作正在紧张筹划过程中。   据悉,5月1日,广东和上海联通将率先在当地正式推出JAVA应用。   向联通妥协   一个月前,中国联通与高通成立合资公司联通博路无线技术有限公司,采用后者的BREW技术发展数据业务。   此前有消息称,双方在签署协议时曾达成一个君子协定:“合资公司成立一年之内,中国联通不正式推广JAVA”。JAVA是美国公司SUN的技术,中国移动采用其建设数据业务平台。   联通博路成立后,联通总部大张旗鼓地做了主攻BREW的总动员,也陆续有了一些推广工作,但反应冷淡。   某联通应用开发商认为,原因有二。一方面,由于推广期工作高举高打,重技术宣传而轻业务介绍,致使普通用户对BREW知之甚少,直接影响了市场接受度的提升;另一方面,由于BREW推广存在相当的投资风险,而JAVA则较有保障,地方联通公司大都忙于后者的测试,对前者多少应付了事。   现在,联通总部违约,准备进行JAVA平台的招标,有业内人士认为,这意味着联通对高通BREW的信心不够。   王颖沛和高通(中国)公司总裁孟普(音)否认联通和高通有一年之内不上JAVA的约定。   王颖沛称,在数据业务开发方面,联通许多地方公司一直以来就在做JAVA的测试,推广JAVA业务也是中国联通日程表上的既定步骤。   而孟普(音)也似乎在帮着打“圆场”:“高通公司在中国的任务在于帮助中国联通,推广CDMA业务,如果中国联通认为这样做有利于公司发展,我们当然表示支持。”   高通(中国)公司另一高层表示,中国联通发展JAVA上与BREW业务并不矛盾,“中国联通一直以来就主张由市场选择技术标准”。   不过,中国联通并没有放弃对BREW的努力。   日前,一封来自于广东联通增值业务部的战前动员檄文分发到了中国联通公司各BREW应用开发商的邮箱中,该函件称:中国联通有限公司广东分公司将在今年4月8日正式开通BREW业务,届时会举办相应的市场推广活动,推出30款BREW应用,以及2-3款BREW手机。   广东联通计划从各BREW服务提供商的BREW应用中选出30款精品业务,在开通当日推向市场。   此次,广东联通将正式推广BREW无线数据业务的时间定在了2003年4月8日。而这一天,也正是中国移动在全国范围内推出基于JAVA的数据业务之日。   和SUN议和   与中国联通的脚踩两只船相似,高通公司也想出了两全之计。   3月13日,高通公司宣布已经与SUN签署一项协议,获准共同开发后者的J2ME虚拟机技术(JAVA的微缩版本)。   全球大约有18%手机使用高通公司的CDMA芯片。但SprintPCS等美国CDMA运营商却选择使用JAVA技术发展数据业务,而不是BREW。   高通公司此举显然是为了留住它们的CDMA客户。   虽然从技术角度而言,BREW可以反向兼容JAVA,但一直以来,高通自己生产的手机芯片只支持BREW应用。去年秋天,高通公司曾宣布公司已经开发出了一套完整的J2ME开发环境,作为其BREW平台的延伸和补充。现在它们又和SUN签订技术授权协议。通过该项协议,高通公司将在自己的CDMA芯片中直接嵌入J2ME虚拟机技术,从而为手机开发商提供同时支持两个应用平台的芯片。   SUN公司中国区市场高级经理邵正强认为,此举表明高通公司在对JAVA的态度上有了一个很大的转变,邵正强称这是一个很正确的选择。   爱立信(中国)公司首席技术官张垦指出,技术发展的最终方向应该是开放,高通公司作为一个封闭的技术提供商,对JAVA技术的“包容”应属明智之举。因为在高通BREW发展的路途中,不得不遭遇用户群和开发商两个“瓶颈”,而这种缺陷又恰恰可以通过向JAVA的兼容绕过,“从某种程度上来看,高通自己承认了自己技术的局限性”。   张垦认为,由于可以给用户带来更多的应用选择,从而给运营商带来更具潜力的消费市场,高通公司的这种妥协当拍手称快。   事实上,虽然高通公司在CDMA领域具有教父级地位,但仍有20%的江山被德州仪器等芯片厂商分瓜。要在CDMA手机实现JAVA应用共享,手机开发商完全可以采用德州仪器等GSM手机公司的芯片,然后在手机软件上加入JAVA软件,也可殊途同归。   由于一台手机同时支持两个平台,对内存、电池等的要求比较高,手机的成本将增加,从而将抬高手机的价格。而且BREW和JAVA应用大同小异,用户愿不愿意尝试“双模手机”也是终端制造商担心的问题。   不过,“双模芯片”是否能受到青睐?王颖沛称,要不要用肯定最终由用户说了算。   据悉,高通公司已经陆续收到过一些手机开发商对类似芯片的订货信息。 <淘宝热门商品:
 

52.00 元  

【卡盟在线】

皇冠在线充|QQ黑钻腾讯黑钻地下城与勇士(DNF)黑钻3月

 

55.00 元 

年底冲钻免邮费!热销包包 !韩版单肩包!销量过千


来源:程序员网

小小豆叮

Java Thread in JVM

本文从JVM的角度探讨Java Thread的语法和编译结果。如果需要获得第一手资料,请直接访问以下的资源——Java语言规范,Java虚拟机规范中有关线程的定义说明。 本文旨在介绍这些比较重要的线程相关的规范,基本上不另作发挥。(除了提到微软的“公共语言基础构造”。:-) Java Language Specification http://java.sun.com/docs/books/jls/second_edition/html/classes.doc.html#30531 JVM Specification http://java.sun.com/docs/books/vmspec/2nd-edition/html/Compiling.doc.html#6530 http://java.sun.com/docs/books/vmspec/2nd-edition/html/Instructions2.doc9.html http://java.sun.com/docs/books/vmspec/2nd-edition/html/Threads.doc.html Microsoft CLI -- Common Language Infrastructure (sorry, off the topic :-) http://msdn.microsoft.com/net/ecma/ 1.synchronized method 的java语言规范 详见http://java.sun.com/docs/books/jls/second_edition/html/classes.doc.html#30531。 用synchronized关键字修饰的方法,分为两种情况:(static)静态方法,和实例方法。 (static)静态方法的“锁”是这个拥有这个方法的对象的Class对象;实例方法的“锁”是this,拥有这个方法的当前对象实例。 怎么理解这段话,看一看下面的例子就明白了。 下面两段代码的效果完全相同。代码1 ==代码2。 代码1: class Test { int count; synchronized void bump() { count++; } static int classCount; static synchronized void classBump() { classCount++; } } 代码2: class BumpTest { int count; void bump() { synchronized (this) { count++; } } static int classCount; static void classBump() { try { synchronized (Class.forName("BumpTest")) { classCount++; } } catch (ClassNotFoundException e) { ... } } } 2.synchronized关键字的编译结果 这一节,我们来看一看synchronized关键字编译之后的java虚拟机指令是什么。 如果需要第一手资料,请参见java虚拟机规范相关的部分 http://java.sun.com/docs/books/vmspec/2nd-edition/html/Compiling.doc.html#6530 这段规范里面讲到,java虚拟机规范提供两条指令,monitorenter和monitorexit,来支持线程。但是对于上一节讲到的,用synchronized修饰的方法来说,并不使用这两个方法,而只是简单地用ACC_SYNCHRONIZED标志修饰。虚拟机调用方法的时候会检查这个标志,进行同步。 synchronized语句的编译结果对应monitorenter和monitorexit两条指令。 比如,下面的代码: void onlyMe(Foo f) { synchronized(f) { doSomething(); } } 的编译结果是 Method void onlyMe(Foo) 0 aload_1 // Push f 1 astore_2 // Store it in local variable 2 2 aload_2 // Push local variable 2 (f) 3 monitorenter // Enter the monitor associated with f 4 aload_0 // Holding the monitor, pass this and... 5 invokevirtual #5 // ...call Example.doSomething()V 8 aload_2 // Push local variable 2 (f) 9 monitorexit // Exit the monitor associated with f 10 return // Return normally 11 aload_2 // In case of any throw, end up here 12 monitorexit // Be sure to exit monitor... 13 athrow // ...then rethrow the value to the invoker 3.monitorenter和monitorexit 详见http://java.sun.com/docs/books/vmspec/2nd-edition/html/Instructions2.doc9.html monitorenter定义的一段节录: Operation : Enter monitor for object Operand Stack : ..., objectref ... Description : The objectref must be of type reference. Each object has a monitor associated with it. The thread that executes monitorenter gains ownership of the monitor associated with objectref. If another thread already owns the monitor associated with objectref, the current thread waits until the object is unlocked, then tries again to gain ownership. If the current thread already owns the monitor associated with objectref, it increments a counter in the monitor indicating the number of times this thread has entered the monitor. If the monitor associated with objectref is not owned by any thread, the current thread becomes the owner of the monitor, setting the entry count of this monitor to 1. 这段话的意思是说,monitorenter操作的目标一定要是一个对象,类型是reference。Reference实际就是堆里的一个存放对象的地址。每个对象(reference)都有一个monitor对应,如果有其它的线程获取了这个对象的monitor,当前的线程就要一直等待,直到获得monitor的线程放弃monitor,当前的线程才有机会获得monitor。 如果monitor没有被任何线程获取,那么当前线程获取这个monitor,把monitor的entry count设置为1。表示这个monitor被1个线程占用了。 当前线程获取了monitor之后,会增加这个monitor的时间计数,来记录当前线程占用了monitor多长时间。 我们看到,monitor这个词在java虚拟机规范规定出现,但是在java语言和API文档里面并没有出现。monitor是藏在线程同步后面的原理和概念。 4.Threads and Locks 详见http://java.sun.com/docs/books/vmspec/2nd-edition/html/Threads.doc.html。 这段规范详细地介绍了thread和lock的原理。下面给出这段规范的highlight。 8.4 Nonatomic Treatment of double and long Variables (double和long类型的非原子操作。) 8.7 Rules for volatile Variables 8.10 Example: Possible Swap 8.11 Example: Out-of-Order Writes 如果对列出的这些highlight感兴趣,请访问相应的java虚拟机规范网址。 5.Why specification? 本文主要讨论java相关规范的内容。规范文档非常重要,尤其对于java,C#这种生成中间代码的语言来说。 上面说的是java的相关规范。这里顺便提一下微软.Net的相关规范。 微软的“公共语言基础构造”规范: Microsoft CLI -- Common Language Infrastructure (sorry, off the topic :-) http://msdn.microsoft.com/net/ecma/ 这个网址上有C#语言规范,CLI规范的下载。 Enjoy it. :-) <淘宝热门商品:
 

35.00 元 

【天使名妆】100%纯棉休闲瑜珈裤

 

运动鞋 

X-2品牌时尚鞋城【郭氏鞋坊旗下】[销售出口多余产品


来源:程序员网

小小豆叮

微软IBM等讨论Web服务标准方案 Sun被拒之门外

微软、IBM和BEA三家公司正在筹备举行一次新的Web服务盛会,Sun微系统再一次被拒之门外。 8月9日,Sun公司官员称,Sun微系统公司作为主要网络系统供应商和Java程序设计语言的创建者,并没得到邀请参加由微软、IBM和BEA三家公司近期提出的Web服务标准方案的讨论。 这是今年微软、IBM和BEA三公司第二次讨论标准方案问题,也是第二次将Sun公司拒之门外。今年2月份,上述三公司组建了Web服务互操作性组织(WS-I),以提高网络服务的互操作性。 Sun公司XML部门负责人Struble说,就最近这次规格讨论来讲,Sun公司应该了解那些用于提高标准化的技术工作和技术支持。但该公司并没有得到关于举行BPEL4WS讨论的通知。 BPEL4WS是从前两种对立标准的联姻,即IBM的Web服务流程语言(WSFL)和微软的Xlang语言。作为一种可执行语言,BPEL4WS设计目的是确保Web服务环境中的不同业务流程能够互相支持。 9日微软、IBM和BEA公司公布的计划还包括Web服务协调和Web服务处理两种标准提案。Web服务协调是确保系统之间同时正确执行处理指令的标准方法;Web服务处理则用于监控业务流程。 Struble说,BPEL4WS看上去同Sun公司的“WSCI”Web服务协调语言相似。WSCI用于“描述”在计算机、应用程序以及服务之间所进行的信息交换情况。国际网络标准联盟已经确认了WSCI提交的报告,但还没有作为一个正式标准预予采纳。BEA公司曾参与了WSCI报告的提交。 Struble说,BPEL4WS和WSCI有可能融合在一起,“我们对此非常欢迎。它们确实需要融合在一起,我们不需要分离和独立的Web服务标准。” BEA公司的一名官员没有直接回答Sun公司为什么没有参与这次活动的问题。 <淘宝热门商品:
 

3C数码配件 

:麒麟光电

 

 

极限特攻-新奇产品仓库   金秋时节好礼送不停


来源:程序员网

小小豆叮

Java程序的加密和反加密

neek2000@SMTH neek@sina.com ========================================================================= 写在前面的话:写这篇文档的目的是让大家能更深入的了解Java技术,而不是教你怎么去破解Java程序;武器没有罪过,要看是好人用它还是坏人用它。 首先我们来看看Java程序的反加密,也就是通常所说的Crack过程,只有明白了这个过程,我们才能有效的对我们的程序进行加密。 通常我们得到的Java程序的Crack包有两种,一种属于KeyGen(注册码生成器)、一种属于替换修改; 我们先看第一种,当我们找到一个应用程序的KeyGen的时候我们总是很佩服那个做出KeyGen的人,觉得他很厉害,但是你仔细分析一下,为什么他能做出KeyGen呢?只有 他对这个Java程序的加密算法了解的非常清楚;这种人有哪些呢?一个是那个公司里面的人,那不可能,除非内讧,还又呢,就是猜想,反推,这个可能吗?呵呵,更不可能,那这个算法从哪里来呢?呵呵,往往泄漏秘密的就是秘密本身……回过头来想想,Java应用程序怎么知道你输入的注册码是否正确呢?呵呵,那你就该从应用程序入手…… 得到的它的加密算法,自然KeyGen就不在话下了……(但是这也有列外,如果它是用的公钥秘钥对加密的,就没有办法喽,只能用第二种方法。) 这种办法只适合对付只要一个注册号,别的什么都不要的情况,经典代表Borland JBuilder & Optimizeit Suite 再看第二种,为什么要用替换修改?我们是修改了那部分呢?不用想,肯定是License验证的部分,为什么我们不像上面的方法那样找加密算法呢?原因有两种:(1)使用上面的办法搞不定;(2)Java程序不仅要Key,还有其他的License配置;遇到这种情况,我们只要找到用于License验证的类,进行修改替换就行了。 这种办法使用于任何情况,经典代表BEA WebLogic 经过上面的分析,我们的问题就集中了,关键就是怎么找到用于License验证的部分或加密算法的部分,我们需要3个工具:一个是Sun公司提供的标准JVM:),一个是你 的耐心和细心:),一个是Jad(经典Java反编译工具)。 第一步是定位,这也是最关键的一步,我们这里以Together For JBuilder Edition为例,启动Together,先看看长什么样子?喔,上来就问我要License;Ok, 每关系,退出;找到Together的启动Bat文件,找到它的启动命令:java .....,OK,在Java启动的时候给一个参数:“ -Xrunhprof:cpu=times”,保存,在启动,还是要 License,退出,这个时候,我们可以发现,在这个目录下多了一个“java.hprof.txt”文件,打开一看,就是我要的JVM的Dump文件,好多内容啊,没关系,慢慢看来。 我们可以看见这个文件里面有好多熟悉的东西啊:java.*/com.sun.*/javax.*等等,但这个不是我们关心的,我们要的是com.togethersoft.*或者是一些没有包名的zd.d等等。(这里插一句,几乎所有的Java应用程序都会混淆的,其实混淆的原理也很简单,我们后面再说。)先找找有没有License有关的,Serach一下,嘿嘿,果然,474行:com.togethersoft.together.impl.ide.license.LicenseSetup.execute([DashoPro-V2-050200]:Unknown line),Ok上那堆classpath中的Jar包里面找一下吧(推荐用WinRAR),找到了之后用Jad反编译,一看,这个没有混淆,但是用了一个zae的类,这个看名字就知道混淆过了,先不理它,再看看下面一句IdeLicenseAccess.setLicense(zae1),Ok接着找到IdeLicenseAccess,哈哈,就这点名堂,所有的License验证都是走的这个类,面向对象的思想不错,呵呵:) 定位定完了,接下来的事情就是按猜想的方法修改这两个类,屏蔽掉LicenseSetup里面execute方法的实际内容,修改IdeLicenseAccess,让多有的验证都返回true,然后编译,替换;不要高兴太早,这还没有完呢,要有责任心!!启动Together,果然,这下不要License了,有启动画面,进去了,但是一片灰色,怎么回事,一看控制台,一堆错,没关系,就怕不出错,查找根源,还有一个IdeLicenseUtil类出了问题,再反编译,修改,替换;这下搞定了。再启动,测试一下,OK。 就这样,一个Java应用程序搞定了。看看其实也很简单。 再来说说混淆,大家可能都知道没有经过混淆的Java的Class反编译回来连方法和变量的名字都不会变,这是什么原因呢?这就要追述到Class文件的结构了,简单来说,Class文件种包含又一个常数池(constant pool)这个里面就存放了变量和方法的名称等一下和Class相关的东西,我们通常所说的混淆就是用一种工具把这个常数池里面的东东弄的胡涂一点,这样就能骗过反编译器和你,呵呵:)这就是为什么有时候反编译回来的东西编译不过去的原因。 再回过头来说说Java程序的加密;从上面的两种方法来看,Java程序似乎是没有什么完美的办法进行加密的,其实不然,我们必须遵循一些原则,才能有效的保护你的产品。 原则一,尽量使用公钥和秘钥对进行加密; 原则二,不要在加密验证的部分使用面向对象思想:)把验证的方法写在程序的各个角落,并标注为private final void,让编译器替你处理成内联方法; 原则三,尽可能的大幅度混淆:)找个好点的混淆器; 就这些吧,要是有谁对产品的加密有问题,我可以提供咨询,呵呵:) <淘宝热门商品:
 

 

靓之彩数码影像:柯达数码冲印 刷照片冲印 水晶版画相册 冲洗彩扩

 

鲜花速递/蛋糕配送/园艺花艺 

瑞锦记锦缎喜糖袋〓婚礼特制●上等材质●流行韩


来源:程序员网

小小豆叮