Greenbow Town
来源: BlogBus 原始链接: http://novrain.blogbus.com:80/index.html 存档链接: https://web.archive.org/web/20060214190102id_/http://novrain.blogbus.com:80/index.html
Greenbow Town nothing lasts forever, even cold november rain. 天气预报 链接 最新文章 最新评论 存档 2004-10-16 15:59 - [ 2:00 AM ] 你以为你真的对我很重要啊,你不过是条狗 滚回去吧 阅读全文 | 评论(0) | 引用(0) novrain @ 2004-10-16 15:59 | 编辑 2004-10-14 15:46 - [ Tech ] 在IBM的developerWorks上有两篇非常优秀的关于 Java XML API的评测文章: Java 中 XML 文档模型的性能 Java 中 XML 文档模型的用法 对这两篇文章我想说的就是 吐血推荐 Java 的 XML API这几篇文章该讲的都讲到了,我只想补充几点: 一、Crimson和Xerces恩仇录 Crimson来自于Sun捐赠给Apache的ProjectX项目,Xerces来自IBM捐赠给Apache的 XML 4J项目,结果Xerces胜出,成了Apache XML 小组全力开发的 XML API,而Crimon已经早就不做了,如今Xerces名满天下,到处都是在用Xerces DOM和SAX解析器,只有Sun不服气,非要在JDK1.4里面使用过时的Crimson,让人感觉像是在赌气一样,真是让人可怜又可气!不过IBM发行JDK用的 XML 解析器自然是Xerces。 由于JDK的Class Loader的优先级关系,当你采用JAXP编写 XML 程序的时候,即使把Xerces包引入CLASSPATH,JDK还是会顽固的使用Crimson,这一点通过打开JVM的verbose参数可以观察到。不过JDK也允许你采用其它的解析器,因此我们可以通过在JRE\lib\目录下建一个jaxp.properties的文件,来替换解析器,jaxp.properties内容如下: java x. xml .parsers.DocumentBuilderFactory=org.apache.xerces.jaxp.DocumentBuilderFactoryImpl java x. xml .parsers.SAXParserFactory=org.apache.xerces.jaxp.SAXParserFactoryImpl 这样就可以使用Xerces,当然你必须还是要把Xerces包放到CLASSPATH下。 二、JAXP的姗姗来迟 Sun在 XML 领域总是后知后觉,等到Sun重视 XML 的时候, XML 的API早就满天 飞了,尤其是IBM具有非常大的领先优势。不过Sun是规范的制订者,于是参考W3C的标准制订了JAXP规范。JAXP不像Xerces和Crimon那样,它只是一个spec,本身是不做任何事情的,它的作用就是提出一个统一的接口,让其它的 XML API都来遵循JAXP编程,那么用JAXP写出来的程序,底层的API可以任意切换。 具体来说JAXP包括了几个工厂类,这就是JDK1.4里面的 java x. xml .parsers 包,用来寻找符合DOM标准的 XML API实现类的位置;此外JAXP还包括一整套interface,这就是JDK1.4里面的org.w3c.dom那几个包。工厂类负责加载DOM的实现类。那么加载的规则是什么呢? 我是通过阅读JAXP的源代码知道的,工厂类首先会根据 java 命令行传入的参数进行寻找,然后在根据JRE\lib\jaxp.properties中定义的实现类寻找,最后什么都找不到的话,就用Crimson。注意Crimons是由Bootstrap Class Loader来load的,如果你不通过上面两个方法来改变工厂的寻找顺序,那么铁定用Crimson了 :( 三、DOM解析器和DOM API 当你严格采用JAXP编程的时候,是遵循W3C的DOm标准的,那么在JAXP底层你实际上可以任意切换不同的DOM实现,例如Xerces,或者Crimon,再或者其它,切换方法就是配置jaxp.properties。因此JAXP就是一些标准接口而已。 而Xerces和Crimon也不单单是一个DOM实现那么简单,他们本身实际上也包含SAX解析器和DOM解析器。所以一个JAXP程序下面有如下层次: JAXP应用程序 -> JAXP接口 -> Xerces DOM实现 -> Xerces DOM/SAX 解析器 只要你用JAXP编程,那么你就可以切换到Crimson上来 JAXP应用程序 -> JAXP接口 -> Crimson DOM实现 -> Crimson DOM/SAX 解析器 另外你也可以这样来做: JAXP应用程序 -> JAXP接口 -> Crimson DOM实现 -> Xerces DOM/SAX 解析器 不过如果你的程序不安装JAXP来写,那么就没有办法切换不同的DOM实现了。 四、不是标准的dom4j和jdom W3C的DOM标准API难用的让人想撞墙,于是有一帮人开发 Java 专用的 XML API目的是为了便于使用,这就是jdom的由来,开发到一半的时候,另一部分人又分了出来,他们有自己的想法,于是他们就去开发dom4j,形成了今天这样两个API,至于他们之间的性能,功能之比较看看上面我推荐的文章就知道了,jdom全面惨败。 jdom 相当于上面的 JAXP接口 + Xerces DOM实现部分,它本身没有解析器,它可以使用Xerces或者Crimson的解析器,就是这样: jdom应用程序 -> jdom API -> Xerces/Crimson解析器 dom4j 和jdom类似,不过他自己绑定了一个叫做Alfred2的解析器,功能不是很全,但是速度很快,当没有其它的解析器的时候,dom4j将使用Alfred2解析器,如下: dom4j应用程序 -> dom4j API -> Xerces/Crimson解析器 或者 dom4j应用程序 -> dom4j API -> Alfred2解析器 你在SF上下载的dom4j.jar是不含 Alfred2解析器的,而dom4j-full.jar包含了 Alfred2解析器,在这种情况下,实际上你什么也不需要,光是一个dom4j-full.jar就全部都包括了。 因此可以看出采用dom4j/jdom编写的应用程序,已经不具备可移植性了。 五、小插曲 Sun是JAXP标准的制订者,甚至很执著的在JDK1.4里面绑定Crimson DOM实现和解析器,然后可笑的是,Sun自己的JAXM RI竟然不是用JAXP写出来的,而是dom4j,制订标准让大家遵守,自己却监守自盗,这未免太说不过去了吧! BTW: Hibernate也用的是dom4j来读取 XML 配置文件,如今已经越来越多的程序纷纷采用dom4j,如果你不是那么在乎可移植性,我强烈建议你采用dom4j。 阅读全文 | 评论(0) | 引用(0) novrain @ 2004-10-14 15:46 | 编辑 2004-10-13 10:50 - [ Tech ] 帮我下载这些带回来, 有好处!!! 1、 http://www.hibernate.org.cn/download/hibernate-2.1.2.zip 2、 http://www.hibernate.org.cn/download/hibernate-extensions-2.0.2.zip 3、 http://www.apache.org/dist/struts/binaries/jakarta-struts-1.2.4.zip 4、 http://download2.eclipse.org/downloads/drops/R-3.0.1-200409161125/eclipse-SDK-3.0.1-win32.zip 5、 http://download2.eclipse.org/downloads/drops/L-3.0.1_Translations-200409161125/NLpack-eclipse-SDK-3.0.x-win32.zip 阅读全文 | 评论(0) | 引用(0) novrain @ 2004-10-13 10:50 | 编辑 2004-10-13 09:39 - [ Tech ] 板桥里人 http://www.jdon.com 2004/08/25 最近,Spring很热闹,因为实现IoC模式和AOP(见 本站专栏 ),然后又成立公司,吸取上次JBoss的教训,文档不敢收费,结果迎来了一片祝贺声。 Spring真正的精华是它的 Ioc模式 实现的BeanFactory和 AOP ,它自己在这个基础上延伸的功能有些画蛇添足。 其实说白了,大家"惊奇"的是它的IoC模式(使用AOP功能需要了解AOP,比较难),那么,Spring之类的Ioc模式是什么? 就是:你在编制程序时,只要写被调用者的接口代码,具体子类实例可通过配置实现。 Ioc模式是什么 知道的人不多,但是,当他知道生成对象不用再使用new了,只要在配置文件里配置一下,他感到新鲜,其实这就是Ioc模式的实现,PicoContainer是另外一种真正轻量的Ioc模式实现,PicoContainer还是采取代码将对象注射一个小容器中,而Spring采取配置文件。 配置式编码其实有利有弊,编码本来可通过开发工具或编译器检查错误,但是过分依赖配置时,就会经常出现因为粗心导致的小错误,如果调试程序出错经常是因为配置文件中小写字母写成大写字母,不知道你是怎么心情? Spring最近还发表了Spring without EJB的书,这倒是说了实话,Spring和EJB其实是相竞争,如同黑与白,如果硬是将两者搭配使用,显得不协调,更不是一些人所谓优化EJB调用的谣言,原因下面将会分析。既然Spring+EJB有缺陷,那么就直接使用Spring+Hibernate架构,但是又带来了新问题:无集群分布式计算性能,只能在一台机器上运行啊,具体分析见: 可伸缩性和重/轻量,谁是实用系统的架构主选? 下面来分析所谓Spring+EJB的不协调性,正如水和油搅拌在一起使用一样。 目前,Spring+EJB有两种应用方式:
- Spring不介入EJB容器,只做Web与EJB之间的接口,这个位置比较尴尬,Web层直接调用EJB的方法比较直接快捷,为什么要中间加个Spring?可实现Web缓存?使用性能更好的AOP框架 aspectwerkz 啊;实现Web和EJB解耦?这样的工具更多,自己都可以做个小框架实现,就不必打扰背着AOP和IOC双重重担的Spring了吧。
- Spring介入EJB容器,这时,需要在你的ejb-jar.xml中配置beanFactoryPath值指向你为EJB配置的applicationContext.xml,那么你的EJB还需要继承Spring的SimpleRemoteStatelessSessionProxyFactoryBean。 好了,现在你的SLSB(无状态Session Bean)成为下面这个样子: void updateUser(){ myService.updateUser(); //委托给一个POJO的方法,真正业务逻辑封装在这个POJO中 } 这样做有很多“优点”,当然最大“优点”是: 由于真正业务核心在POJO中实现,因此,只要改一下applicationContext.xml配置,这样,调试时,前台就可以直接调用POJO,不必通过EJB,调试起来方便了,这有一个前提:他们认为调试EJB复杂,其实不然,在JBuilder中,结合Junit,测试EJB如同测试POJO一样方便,这是其他分支,不在此讨论。当部署使用时,再改一下applicationContext.xml配置,指引前台调用到EJB。 似乎很巧妙,这里有两个疑问,首先,指引到EJB的改变是什么时候做?持续集成前还是后,在前在后都有问题,这里不仔细分析。 这种表面巧妙的优点带来最大的问题是:粗粒度事务机制 。所谓粗粒度事务机制,最早见于Petstore的WEB调用EJB Command模式,在 这个帖子 中有讨论。 下面以代码描述什么是粗粒度事务机制: ejb方法: public void updateUser(){ service.updateUser(); } service是一个POJO,具体方法可能是更新两个表: public void updateUser(){ updateTabel1();//更新table1 updateTable2(); //更新table2 } 当updateTable2()抛出异常,updateTable1()是不回滚的。这样,table1中就有一条错误的多余的记录,而table2则没有这条记录。 那么,怎么做才能使两个表记录一致,采取事务机制,只有下面这样书写才能实现真正事务: 在EJB方法中写两个方法,因为EJB方法体缺省是一个事务。 public void updateUser(){ updateTabel1();//更新table1 updateTable2(); //更新table2 } 关于EJB自动的事务机制,最近也有一个道友做了测试, 对于JBoss中容器管理的事务的疑惑。 如果你从事关键事务,就是带money相关操作的事务,这种粗粒度机制可能害苦你,那么,似乎有一种办法可弥补事务,不使用EJB容器事务(CMT),在service中使用Spring的事务机制。 如果使用Spring事务机制,业务核心又在POJO中实现,那么我有一个疑问:还要套上EJB干什么?至此,你终于明白,Spring本质是和EJB竞争的,如果硬套上EJB使用,只是相借助其集群分布式功能,而这个正是Spring目前所缺少的。 我太惊异Spring精巧的诡异了,他和EJB关系,正如异型和人的关系一样。 为了避免你每次使用Spring时想到粘糊糊的异型,不如Spring without EJB,这也正是Spring的初衷,也是它的一个畅销书名。 阅读全文 | 评论(0) | 引用(0) novrain @ 2004-10-13 09:39 | 编辑 2004-10-12 08:52 - [ Tech ] StrutsTest: http://strutstestcase.sourceforge.net/ StrutsTestCase: The tool for Struts unit testing: http://sourceforge.net/docman/display_doc.php?docid=19672&group_id=39190 EasyMock使用手册: http://dev.csdn.net/Develop/article/article/28/article/28/article/28/article/28/28583.shtm Struts 是目前在 web 开发中广泛使用的几个框架之一,而 StrutsTest 正是专门负责测试 strut 应用程序的 Mock 测试框架。 使用目的 StrtusTest 是 junit 的扩展,使用它,不需要启动 servlet 容器就可以方便的测试 struts 应用程序(容器外测试)。它也是属于使用 Mock 对象测试,但是与 EasyMock 不同的是, EasyMock 是提供了创建 Mock 对象的 API ,而 StrutsTest 则是专门负责测试 Struts 应用程序的 Mock 对象测试框架。除了容器外测试, StrutsTest 也可以很方便的用容器内的测试。 当前的版本是 StrutsTest2.1.0 ,在这个版本中不支持 Struts1.0 。如果需要测试 struts1.0 的应用程序,对应的版本是 StrutsTest2.0 。可以从 http://sourceforge.net/projects/strutstestcase/ 下载。 用法
基本步骤:
书写 struts action 。
确定需要进行测试的方式: Mock 对象则选用 MockStrutsTestCase 作为基类; Cactus 方式则选用 CactusStrutsTestCase ;这两种方式以下的步骤都是一样的。
使用 setUp 和 tearDown 进行初始化,明确这两个函数的第一句话是调用 super 的方法。
设置要测试的 struts action 的路径,方便 strutstest 能找到 web.xml 和 struts 相关的配置文档。
设置 action 在 strtus-config.xml 中对应的 path 名称。
设置 action 需要使用的各个参数值到 request 对象中,包括 action 所使用的 formbean 的值。
执行 action 。
验证 action 的返回路径是否正确,即 forward 的名字。
验证 action 相关的其余部分。 2. 使用例子(采用 Mock 方式): public class DeparmentDBActionTest extends MockStrutsTestCase { public DeparmentDBActionTest(String arg0) { super(arg0); } public void setUp(){ super.setUp(); // 指明 web 应用的根 File contextFile = new File("D:\Projects\fog\implement\web"); setContextDirectory(contextFile); } protected void tearDown() throws Exception { super.tearDown(); } public void testDoAdd() { // 设置 action 的 path setRequestPathInfo("/dpEdit"); // 准备 action 所需要的 formbean 的参数 addRequestParameter("method", "doAdd"); addRequestParameter("pageId", "1"); addRequestParameter("dpname"," 测试部门 "); addRequestParameter("dptype"," 测试部门 "); addRequestParameter("yn","n"); // 执行 action actionPerform(); // 验证返回的 forward verifyForward("success"); } 3. 主要函数和作用:
setContextDirectory ,设置 web 应用的根
setRequestPathInfo ,设置 request 的请求
addRequestParameter ,将参数和对应的值加入 request 中
actionPerform ,执行这个请求
verifyForward ,验证 forward 的名字是否正确
verifyForwardPath ,验证 forward 的 path 是否正确
verifyNoActionErrors ,验证在 action 执行过程中没有 ActionError 产生
verifyActionErrors ,验证在 action 执行过程中产生的 ActionError 集合的内容 具体详细的内容请参见对应的 javaDoc 。 4. 测试 Tile 。其基本过程与上面类似,不同之处在于验证:使用 verifyTilesForward 和 verifyInputTilesForward 。 5. 测试子模块。其基本过程也和上面一样,不同之处在于需要指定该模块所需要使用的 struts-config.xml 和调用方式:
首先,指定所需要的 struts-config.xml : setConfigFile("mymodule","/WEB-INF/struts-config-mymodule.xml");
其次,指明调用的路径: setRequestPathInfo("/mymodule","/login.do"); 检查表 使用 StrutsTest 需要注意的地方:
在 TestCase 中可以访问 request 、 session 等对象, StrutsTest 为我们提供了访问接口。
junit 的 assert 函数和 fail 函数都可以在 StrutsTest 中使用。
对于文件上载,目前 StrutsTest 并没有什么特别好的方案。具体参见 StrusTest 的 Faq 。 阅读全文 | 评论(0) | 引用(0) novrain @ 2004-10-12 08:52 | 编辑 2004-10-10 17:34 - [ Tech ] ibm WebSphere Portal Server 专题 http://www-900.ibm.com/developerWorks/cn/wsdd/zones/portal/bigpicture.shtml WebSphere Portal 技术文档 www-900.ibm.com/cn/software/websphere/products/ portal / weblogic http://dev2dev.bea.com.cn/bbs/school/guide/wlportal/index.jsp http://dev2dev.bea.com.cn/bbs/school/guide/wlportal/20030513.html http://dev2dev.bea.com.cn/bbs/thread.jspa?forumID=101&threadID=13946&start=0&tstart=0 J道的一个讨论 http://www.jdon.com/jive/thread.jsp?forum=62&thread=10031&start=15&msRange=15 JFoxPortal(JFox门户)开发计划 http://www.huihoo.org/jfox/jfoxportal/jfoxportal_plan.html jsr-168 http://www.jcp.org/en/jsr/overview 阅读全文 | 评论(0) | 引用(0) novrain @ 2004-10-10 17:34 | 编辑 2004-10-10 17:30 - [ Tech ] 1 定义头和根元素 部署描述符文件就像所有XML文件一样,必须以一个XML头开始。这个头声明可以使用的XML版本并给出文件的字符编码。 DOCYTPE声明必须立即出现在此头之后。这个声明告诉服务器适用的servlet规范的版本(如2.2或2.3)并指定管理此文件其余部分内容的语法的DTD(Document Type Definition,文档类型定义)。 所有部署描述符文件的顶层(根)元素为web-app。请注意,XML元素不像HTML,他们是大小写敏感的。因此,web-App和WEB-APP都是不合法的,web-app必须用小写。 2 部署描述符文件内的元素次序 XML元素不仅是大小写敏感的,而且它们还对出现在其他元素中的次序敏感。例如,XML头必须是文件中的第一项,DOCTYPE声明必须是第二项,而web-app元素必须是第三项。在web-app元素内,元素的次序也很重要。服务器不一定强制要求这种次序,但它们允许(实际上有些服务器就是这样做的)完全拒绝执行含有次序不正确的元素的Web应用。这表示使用非标准元素次序的web.xml文件是不可移植的。 下面的列表给出了所有可直接出现在web-app元素内的合法元素所必需的次序。例如,此列表说明servlet元素必须出现在所有servlet-mapping元素之前。请注意,所有这些元素都是可选的。因此,可以省略掉某一元素,但不能把它放于不正确的位置。 l icon icon元素指出IDE和GUI工具用来表示Web应用的一个和两个图像文件的位置。 l display-name display-name元素提供GUI工具可能会用来标记这个特定的Web应用的一个名称。 l description description元素给出与此有关的说明性文本。 l context-param context-param元素声明应用范围内的初始化参数。 l filter 过滤器元素将一个名字与一个实现javax.servlet.Filter接口的类相关联。 l filter-mapping 一旦命名了一个过滤器,就要利用filter-mapping元素把它与一个或多个servlet或JSP页面相关联。 l listener servlet API的版本2.3增加了对事件监听程序的支持,事件监听程序在建立、修改和删除会话或servlet环境时得到通知。Listener元素指出事件监听程序类。 l servlet 在向servlet或JSP页面制定初始化参数或定制URL时,必须首先命名servlet或JSP页面。Servlet元素就是用来完成此项任务的。 l servlet-mapping 服务器一般为servlet提供一个缺省的URL:http://host/webAppPrefix/servlet/ServletName。但是,常常会更改这个URL,以便servlet可以访问初始化参数或更容易地处理相对URL。在更改缺省URL时,使用servlet-mapping元素。 l session-config 如果某个会话在一定时间内未被访问,服务器可以抛弃它以节省内存。可通过使用HttpSession的setMaxInactiveInterval方法明确设置单个会话对象的超时值,或者可利用session-config元素制定缺省超时值。 l mime-mapping 如果Web应用具有想到特殊的文件,希望能保证给他们分配特定的MIME类型,则mime-mapping元素提供这种保证。 l welcom-file-list welcome-file-list元素指示服务器在收到引用一个目录名而不是文件名的URL时,使用哪个文件。 l error-page error-page元素使得在返回特定HTTP状态代码时,或者特定类型的异常被抛出时,能够制定将要显示的页面。 l taglib taglib元素对标记库描述符文件(Tag Libraryu Descriptor file)指定别名。此功能使你能够更改TLD文件的位置,而不用编辑使用这些文件的JSP页面。 l resource-env-ref resource-env-ref元素声明与资源相关的一个管理对象。 l resource-ref resource-ref元素声明一个资源工厂使用的外部资源。 l security-constraint security-constraint元素制定应该保护的URL。它与login-config元素联合使用 l login-config 用login-config元素来指定服务器应该怎样给试图访问受保护页面的用户授权。它与sercurity-constraint元素联合使用。 l security-role security-role元素给出安全角色的一个列表,这些角色将出现在servlet元素内的security-role-ref元素的role-name子元素中。分别地声明角色可使高级IDE处理安全信息更为容易。 l env-entry env-entry元素声明Web应用的环境项。 l ejb-ref ejb-ref元素声明一个EJB的主目录的引用。 l ejb-local-ref ejb-local-ref元素声明一个EJB的本地主目录的应用。 3 分配名称和定制的UL 在web.xml中完成的一个最常见的任务是对servlet或JSP页面给出名称和定制的URL。用servlet元素分配名称,使用servlet-mapping元素将定制的URL与刚分配的名称相关联。 3.1 分配名称 为了提供初始化参数,对servlet或JSP页面定义一个定制URL或分配一个安全角色,必须首先给servlet或JSP页面一个名称。可通过servlet元素分配一个名称。最常见的格式包括servlet-name和servlet-class子元素(在web-app元素内),如下所示: Test moreservlets.TestServlet 这表示位于WEB-INF/classes/moreservlets/TestServlet的servlet已经得到了注册名Test。给servlet一个名称具有两个主要的含义。首先,初始化参数、定制的URL模式以及其他定制通过此注册名而不是类名引用此servlet。其次,可在URL而不是类名中使用此名称。因此,利用刚才给出的定义,URL http://host/webAppPrefix/servlet/Test 可用于 http://host/webAppPrefix/servlet/moreservlets.TestServlet 的场所。 请记住:XML元素不仅是大小写敏感的,而且定义它们的次序也很重要。例如,web-app元素内所有servlet元素必须位于所有servlet-mapping元素(下一小节介绍)之前,而且还要位于5.6节和5.11节讨论的与过滤器或文档相关的元素(如果有的话)之前。类似地,servlet的servlet-name子元素也必须出现在servlet-class之前。5.2节"部署描述符文件内的元素次序"将详细介绍这种必需的次序。 例如,程序清单5-1给出了一个名为TestServlet的简单servlet,它驻留在moreservlets程序包中。因为此servlet是扎根在一个名为deployDemo的目录中的Web应用的组成部分,所以TestServlet.class放在deployDemo/WEB-INF/classes/moreservlets中。程序清单5-2给出将放置在deployDemo/WEB-INF/内的web.xml文件的一部分。此web.xml文件使用servlet-name和servlet-class元素将名称Test与TestServlet.class相关联。图5-1和图5-2分别显示利用缺省URL和注册名调用TestServlet时的结果。 程序清单5-1 TestServlet.java package moreservlets; import java.io.; import javax.servlet.; import javax.servlet.http.*; /** Simple servlet used to illustrate servlet naming
- and custom URLs.
- Taken from More Servlets and JavaServer Pages
- from Prentice Hall and Sun Microsystems Press,
- http://www.moreservlets.com/.
- © 2002 Marty Hall; may be freely used or adapted. */ public class TestServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html"); PrintWriter out = response.getWriter(); String uri = request.getRequestURI(); out.println(ServletUtilities.headWithTitle("Test Servlet") + "<BODY BGCOLOR="#FDF5E6">\n" + "URI: " + uri + "\n" + ""); } } 程序清单5-2 web.xml(说明servlet名称的摘录)