posts - 48,  comments - 14,  trackbacks - 0
 

Sparx Systems Enterprise Architect 是一款全功能的、基于UML的Visual CASE工具,主要用于设计、编写、构建并管理以目标为导向的软件系统。它支持用户案例、商务流程模式以及动态的图表、分类、界面、协作、结构以及物理模型。

此外,它还支持C++、Java、Visual Basic、Delphi、C#以及VB.Net。

Enterprise Architect
是一个全面的UML分析和设计工具,覆盖从采集需求到分析过程、设计模块、测试和维护的软件开发。EA是一个多用户的基于Windows的图形工具,专为帮助您建立健壮的和可维护的软件而设计。它特征灵活和高质量的文档输出。用户手册可在线提供。

统一模型语言提供有效的好处,它用适当的行为帮助建立严格的、可追踪的软件系统模块。Enterprise Architect用一个易用、快速和灵活的环境支持这个处理。

关键特征

  • UML设计和构建;

  • Use Case、Logical、Dynamic和Physical models;

  • 为处理建模等自定义扩展;

  • 高质量的MS Word兼容文档;

  • 低的许可费用;

  • 数据建模,从ODBC正向数据库工程到DLL和反向数据库工程;

  • 支持Java, C#, C++, VB.Net, Delphi, Visual Basic和PHP;

  • XML导入/导出工具;

  • 拼写检验;

  • 等...;

 

Sam Mancarella--"使用Enterprise Architect的UML2.0建模"讲座

时间:北京时间2006年7月5日(周三)晚上19:00-21:00

演讲人
Sam Mancarella,Sparx Systems公司CTO。Sparx Systems就是著名UML/MDA工具Enterprise Architect的开发商。

幻灯下载
Applying UML 2 to the SDLC with Enterprise Architect>>


软件下载:
Sparx Systems Enterprise Architect v6.5.804 破解版
下载地址:http://3ddown.com/soft/22721.htm

网上搜了半天,就是没有找到这个软件的中文教程,郁闷。。。。。。

posted @ 2007-03-08 10:21 逍遥草 阅读(4776) | 评论 (13)编辑 收藏
 以下五种水在某种程度下会形成亚硝酸盐及其他有毒有害物质,会对人体产生一定的危害。

  老化水:俗称“死水”,也就是长时间贮存不动的水。常饮用这种水,对未成年人会使细胞新陈代谢明显减慢,影响身体发育;中老年人则会加速衰老;许多地方食道癌、胃癌发病率日益增高,可能与长期饮用老化水有关。老化水中的有毒物质也随着水贮存时间增加而增加。

 千滚水:千滚水就是在炉上沸腾了一夜或很长时间的水,还有电热水器中反复煮沸的水。这种水因煮过久,水中不挥发性物质,如钙、镁等重金属成分和亚硝酸盐含量很高。久饮这种水,会干扰人的胃肠功能,出现暂时腹泻、腹胀;有毒的亚硝酸盐还会造成机体缺氧,严重者会昏迷惊厥,甚至死亡。

  蒸锅水:蒸锅水就是蒸馒头等剩锅水,多次反复使用的蒸锅水亚硝酸盐浓度很高。常饮这种水,或用这种水熬稀饭,会引起亚硝酸盐中毒;水垢经常随水进入人体,还会引起消化、神经、泌尿和造血系统病变,甚至引起早衰。

  不开的水:人们饮用的自来水,都是经氯化消毒灭菌处理过的。氯处理过的水中可分离出13种有害物质,其中卤化烃、氯仿还具有致癌、致畸作用。当水温达到90℃时,卤代烃含量由原来的每公斤53微克上升到177微克,超过国家饮用水卫生标准的2倍。专家指出,饮用未煮沸的水,患膀胱癌、直肠癌的可能性增加21%-38%。当水温达到100℃,这两种有害物质会随蒸气蒸发而大大减少,如继续沸腾3分钟,则饮用安全。

  重新煮开的水:有人习惯把热水瓶中的剩余温开水重新烧开再饮,目的是节水、节煤(气)、节时。但这种“节约”不足取。因为水烧了又烧,使水分再次蒸发,亚硝酸盐会升高,常喝这种水,亚硝酸盐会在体内积。

原文地址:http://health.enorth.com.cn/system/2006/10/23/001441393.shtml

posted @ 2006-10-25 09:05 逍遥草 阅读(527) | 评论 (0)编辑 收藏

      天下所有夫妻,都希望得到一个健康聪明的小宝贝。然而,生命的孕育历程并不那么平坦,时有风风雨雨相伴。怀孕,并不是女人一个人的事情!健康宝宝来源与一个健康的精子和卵子的结合!所以不能忽视另一半的精子健康!

  ·年龄

  名中医男科专家、中国中医研究院广安门医院泌尿外科男科主任医师贾金铭教授说:“人的最佳生育年龄应是24--30岁。虽然男子18岁就已发育完全,女子“十四天癸至”即月经初潮,可以有子嗣,但这并不是最合适的生育年龄。另一方面,男子在40岁以后,身体素质已逐渐走下坡路,同时因饮食受到各种污染而在体内堆积增多,因此,在这种情况下生育出的下一代,患病几率将明显增加。”

  ·情调

  “精、气、神”乃人体“三宝”,三者互相联系,相辅相成。“神”是人身体状况的外在体现,人的精神状态如何,将直接影响到生育。因此,中医认为要健康生育,重在“调情致”,做到心境豁达开朗,学会排解各种不健康的情绪,这是优育非常重要又往往被忽视的一个方面。

  ·运动

  在打算生育的一段时间,男性要经常保持一定的运动量,工作要劳逸结合。运动时间可根据个人身体状况灵活制定,一般以每周3次以上、每次半小时以上为宜。另外,生活中要多见阳光、多呼吸新鲜空气,这有益于男性内分泌协调。

  ·饮食 

  贾教授强调,其实除了因患疾病而需要忌口外,要做到不偏食、什么都吃,这就是最佳饮食调养。与西方“以肉为主”的饮食相比,东方人尤其是中国人“以谷物和豆类为主”的传统饮食结构则更为健康。注意多吃花生、芝麻、鳝鱼、泥鳅、鸽子、牡蛎、麻雀、韭菜等食物,其中富含促进生育的锌元素,并多吃猪肝、瘦肉等富含氨基酸的食物。这些食物可补精壮阳,有助于形成优良精子。

  大鱼大肉对人体没有太多好处,吃多了还容易诱发前列腺炎等疾病。贾教授介绍,西方科学家曾做过一个实验,他们解剖了多名年龄在40岁以上死者的前列腺,结果发现几乎都存在癌细胞。对于生育能力差、少精的患者,则可以适当多吃瘦肉和蔬菜,因为瘦肉和蔬菜中富含的Vc、Va、Ve对精子很有好处。

  ·守规律

  在生育打算时的前半年内就应该做到戒烟、戒酒,或其他不良生活嗜好。另外,对于性生活要“顺其自然”,没有不行,太过也不行。尤其不要为了追求所谓“持久、高质”的性生活而乱服鞭和补药。而对于有些性功能确实低下的患者,也应该在有经验中医医师的指导下服药进补。

  精子容易受伤害

  从精子生物学特性来看,精子是雄性生殖细胞系发育的终端产物。在精子发生、形成和变形的过程中,由于细胞质脱逸,胞浆中DNA修复酶丢失,使得DNA损伤与修复系统机能随之丢失。因此它不能像体细胞和卵细胞那样能够自行修复90%以上的原发性遗传物质的损伤。在人体各种细胞中,只有精子具有这样的特性。另外,与其他各种细胞相比,精子对有毒物质更为敏感。生精细胞始终处于快速分裂状态,而男性从胚胎中后期一直到老年,会连续不断地生成精子。在快速的生精过程中,各种有害因素产生的危害作用在蓄积和累加之后明显增大。随着近年来对基因的研究和认识的深入,人们更加明确,相对于X染色体而言,Y染色体所携带的基因更容易发生突变。

  小心15大精子杀手

  除遗传及部分器官器质性病变外,男性不育与生活习惯密切相关。如能在日常生活中了解或克服这些不良习惯,至少可减少或避免男性不育症的发生,那么,哪些因素可以引起男性精子减少而导致不育呢?

  1、性生活混乱及不洁。

  性生活混乱及不洁易引起男性生殖道感染。引起生殖道感染的病原有淋球菌、结核杆菌、病毒、支原体、衣原体、滴虫等,其中以支原体和衣原体感染最为常见。生殖道感染首先影响精子的生成和精子的运输,造成少精症而引起生殖能力下降。生殖道感染也可引起精子活力变化,生殖道感染可抑制附属性腺分泌,引起精液分泌不足,精液营养缺乏,酸碱度改变,精液成分发生变化,从而影响精子的生长环境,使精子的活力和数量严重下降而致不育。

  2、嗜烟与酗酒。

  男子对烟、酒中的毒素颇为敏感,尤其是生殖细胞更易受害。据研究表明,烟叶中的尼古丁有降低性激素分泌和杀伤精子的作用。凡每天吸30支烟者,精子存活率仅有49%,吸烟者体内雄性激素的分泌量比不吸烟者少16%至47%,从而使生产精子的能力相应降低。长期酗酒会对睾丸的生精细胞造成损害,影响精子产生。

  3、温热环境对睾丸的损害。

  如长期高温作业,热水浴,长期穿紧身裤,会使阴囊调节温度的功能产生障碍。不少男子为表现出健美身材,长期穿紧身裤,殊不知,紧身裤会将阴囊和睾丸牢牢地贴在一起,使阴囊皮肤的散热功能得不到发挥,进而增加睾丸局部温度,有碍精子产生。另外穿紧身裤还会限制和妨碍阴囊部位的血液循环,形成睾丸瘀血,导致不育。睾丸是产生精子的器官,睾丸在生精过程中要求温度必须在35.5℃至36.5℃,比正常体温低1至1.5℃。经常用很热的水洗澡,尤其是盆浴、桑拿浴,使阴囊经常处于高温状态,就会影响睾丸的生精功能。

  4、饮食不当。

  营养缺乏,如维生素A缺乏,可导致生精上皮不长;维生素B缺乏,可影响垂体功能,降低生育力;维生素C在防止精液凝固、保持精子活力方面有一定重要作用;维生素E缺乏可引起睾丸损害;钙、磷缺乏可降低生育能力;微量元素锌和镁的缺乏也会对精子的生成及活力产生较大影响。

  此外,食用粗棉籽油,内中的棉酚可破坏生精细胞,引起不育;食用过多的芹菜,也可引起不育。泰国一名医生经过10年的研究,证明芹菜有避孕的作用,接受试验的男子每天吃75克熟芹菜,连续吃1周至2周之后,这些男子的精子数量便会明显减少,即从正常的每毫升精液含精子数千万至一亿减少为每毫升只有3000,这样少的精子数量难以使女性受孕。

  5、接触有毒物质。

  许多化学物品会影响男性生殖功能。如有机杀虫剂:DDT、狄氏剂、六六六、松油烃等。有机磷类:对硫磷(1605)、敌敌畏等。其它如杀真菌剂、杀螨剂、亚硝基类食品添加剂等。还有一些会金属元素如铜、镉、铅、汞等。

  6、药物的损害。

  现代医学研究证明,不少药物可引起男性不育,主要有抗肿瘤药物、抗风湿药、抗高血压药、激素类药、镇静剂及麻醉剂(大麻,海洛因等毒品)。如环磷酰胺可使睾丸生精功能障碍;甲氨喋呤、考的松类制剂、柳氮磺吡定等可致精子数减少,精子活力降低;西咪替丁等则通过抑制雄性激素分泌,间接降低精子活力。雷公藤等长期服用也可使精子数量减少。

  7、性生活过频或不当。

  尽管睾丸每天可生产数千万至几亿个精子,但一次射精之后,要5至7天后精子才能成熟和达到足够的数量。如果性生活次数过多或无节制,每次射出的精子量少,自然不易受孕。另外,性生活中断,手淫或每次性生活持续时间长,会酿成无菌性前列腺炎,直接影响精液的营养成分和精子活力,引起不育。

  8、接触雌性物质过多。

  随着社会的发展和各种环境的变化,人们广泛而长期接触低剂量雌性物质的机会越来越多,如人工饲养的淡水鱼、家禽等,长期进食这类食物,也是导致男性精子数量下降的重要原因。

  9、香水和香皂伤精子

  美国科学家的一项研究发现,香水中含有的一种化学物质能够损害成年男性精子的DNA(脱氧核糖核酸)。这一化学物质的名称为“酞酸二乙酯”,香皂和女性使用的香水等化妆品或者其他一些芳香类制品中通常含有这种物质。美国哈佛大学一个研究小组以168名成年男子为对象进行了相关的研究。研究结果显示,被调查者精子DNA的损伤和体内“酞酸二乙酯”的含量存在“

  相互关联性”。环境保护主义者一直以来都谴责使用化学制品,认为这将引起健康问题,但是制造商和化学制品产业专家却强调“这是安全的”。

  10、大豆也是“精子杀手”

  一项最新的科学研究显示,大豆中的某些成分能造成精子数量下降,从而影响男性的生殖功能。许多人一致推崇的豆奶和大豆酸奶也成了可以杀死精子的食品。

  11、穿紧身牛仔裤。

  紧身牛仔裤不但压迫男性生殖器官,影响睾丸正常发育,还因不透气、不散热,而不利于精子的生存。

  12、久骑赛车。

  赛车车把的高度低于车座,重心前倾,腰弯曲度增加,会阴部的睾丸、前列腺紧贴在坐垫上,受到长时间挤压后会缺血、水肿、发炎,影响精子的生成以及前列腺液和精液的正常分泌而致不育。因此,男青年不宜久骑赛车,保护会阴部坐垫应用海绵套。

  13、芹菜也是精子杀手。

  男性多吃芹菜会抑制睾丸酮的生成,从而有杀精作用,会减少精子数量。据报道国外有医生经过实验发现,健康良好、有生育能力的年轻男性连续多日食用芹菜后,精子量会明显减少甚至到难以受孕的程度,这种情况在停菜后几个月又会恢复正常。

  14、吸入厨房油烟。

  近期上海铁道大学医学院研究发现,厨房油烟中竟有 74种化学物质能致细胞发生突变,导致不育,成为“家庭杀手”新“罪证”。他们发现喂服了厨房排油烟机油杯中的冷凝油的果蝇,细胞染色体的突变率为 0.54%,并有 2.8%的果蝇不育,这表明其生殖系统受到明显破坏。

  15、缺锌少硒饮食。

  微量元素锌可促进精子的活动力,能防止精子过早解体,利于与卵子结合,可见锌对生育有重大影响。硒也是人体不可少的微量元素,几乎全来自食物。因此,男青年不可偏食,应注意多吃含锌、硒多的食物,如鱼、牡蛎、肝脏、大豆、糙米等。

原文地址:http://www.eeinn.com/lady/moying/yunqian/200605/1718.shtml

posted @ 2006-10-25 09:01 逍遥草 阅读(3408) | 评论 (0)编辑 收藏
打造最完美的BLOG系统需要注意到如下Blog的基本特征和功能要素:

1、RSS-简称“聚合”

RSS是一种技术规范的简称,不同的技术团体将其分别描述为:“Rich Site Summary”(丰富站点摘要)、“RDF Site Summary”(RDF站点摘要)或“Really Simple Syndication”(真正简易聚合)。在形式上,也分别有RSS技术的主导者、哈佛大学研究员Dave Winer的RSS 0.93、RSS2.0(Apple、News.com的出版商CNET Networks等支持),IBM软件工程师SamRuby 2003年发起的Atom(Google和Six Apart――Movable Type的拥有着支持)。不过本质上它们都是一种遵循W3C RDF规范的XML格式,是一种多用途、可扩展的元数据描述及联合推广格式。它允许互联网站点制作人员,为内容整合客户端提供选择性的、汇总过的Web内容。

2、Trackback-引用通告

TrackBack最早是Movable上的功能,后来成为BLOG的标准配置,它是一种将全世界无数个Blog连接起来的功能。通过TrackBack,你可以在自己的Blog上就别人发表的某篇文章做评论和延伸,并通知对方你引用了它文章中的内容。只要对方的Blog也支持TrackBack,你在发布自己的文章时,将同时向对方Blog发出一个TrackBack Ping,向刊载被评论文章的服务器发送你写的Blog的地址、标题和部分征文。这样当其他人浏览那篇文章时,就能够看到你的部分评论和正文,感兴趣的话他们还可以通过链接阅读你评论的详细内容。同样,别人也可以使用TrackBack功能对你Blog中的某篇文章加以评论,在你的文章中留下相应的引申链接

3、Permailink-永久链接

给BLOG上每篇BLOG文章一个永久链接,这样便于他人长期引用,这样不管你的后台是动态程序,首页如何改变,但每篇BLOG的链接都是永久固定的,而且最好是htm等静态链接,这样还有利于搜索引擎的搜录。如果你实在做不到htm静态链接,可以考虑采取URL REWRITING、PATH_INFO、服务器设置等方式将动态链接变为静态链接,将前台链接表现形式和后台程序分离开来,以后即使更换后台程序也不用担心了。

4、Comments-评论

也称作回复功能,用户可以借此对此BLOG进行评论,这是读者同BLOGGER相互交流的最直接渠道。

5、Archive-归档

也称作索引功能,通常都是按月份进行BLOG文件的归档(也有按分类归档的),便于大家在一个页面就查找到归档日期内的所有BLOG文章,通常都生成静态页面,这也是利于搜索引擎搜录的一个重要手段。

6、Calendar-日历

每个BLOG都可以看到的最基本的元素,这也是BLOG最基本的特征,根据日期可以检索到当日发表的BLOG。

以上是BLOG最基本的功能要素,如果以上6点都达不到,称为BLOG就有些牵强了。话虽如此,目前大部分都只支持了其中四、五项,这是BLOG程序设计者需要学习和改进的。

7、Style-个人定制风格

虽然BLOG最大程度的减少了发布者对于网页技术的需求门槛,但是BLOG鲜明的个人化特征要求发布者可以自定义自己的BLOG风格,因此BLOG具有自定义CSS或者SKIN的功能也是必不可少的。

8、CC-创作共用约定

创作共用约定是BLOG发布者尊重原创者所默认遵从的规则。当然这个并非必须,现在许多新兴的BLOGGER已经忘记或不知道这个约定。

创作共用(Creative Commons)允许拷贝、分发、呈现和表演当前作品,制作派生作品。但是必须遵守一下规则:署名。你必须明确标明作者的名字。非商业用途:你不可将当前作品用于商业目的。保持一致:如果你基于当前作品更改、变换或构造新作品,你应当按照与当前协议完全相同的协议分发最终作品。

对于任何二次使用或分发,你必须让其他人明确当前作品的授权条款,在得到作者的明确允许下,这里的某些条款可以放弃。

9、Catalog-分类

这个并非必须,但基本上BLOGGER都设置有不同的分类,用于区分自己BLOG文章的类别。

0、Search-搜索

基本功能,通常提供的都是简单模糊搜索,基本上已经够用了,所以这项功能也一直没有进行过特别的加强。

11、Statistic-统计

BLOG的基本统计数据,例如访问次数,在线人数,BLOG发表篇数,引用篇数,评论篇数,注册用户数。

12、Links-链接

放置一些友情链接。

13、Favorite-收藏

收藏一些有用的文章或链接。

14、Roll-交换链接

用于显示其他博客的链接,自己的博客也会同时显示在其他blog roll列表里,动态循环显示,有点象国内的文本链广告交换,国外的例子可以参看这里Blogrolling.com。

15、Visual Editor-可视化编辑器

早期都是使用文本,对于HTML标签制作起来就比较麻烦,最近BLOG程序已经普遍采用可视化的文章编辑器,方便BLOGGER更加有效的组织文章结构和显示效果。

16、Tag-标签

通常BLOG文章的分类只有一层,很少有多级分类,有时这也是许多信息量大的用户比较头疼的地方,实现多级分类功能还不如使用Tag功能,方便实用,也比较社会化。

17、AutoLink-自动链接

大家可以看到许多BLOG中许多网站、人名、名词、事件通常都加有超链接,也许很多人就奇怪,作者怎么又这么多精力呢,实际上是关键字自动转换超链接功能在起作用。作者在后台可以设置关键字及其指向的链接,添加文章时就会自动将普通文本关键字变为带超链接的显示方式,有的还可以将关键字进行指定字符转换。这其实也是BLOG一项重要的功能,可惜国内很多BLOG程序很少实现这一点。

18、Album-相册

用于分类上传各类图片,是BLOG的附属功能。

19、Antispam-反垃圾信息

目前的评论系统,容易产生垃圾广告和垃圾信息,需要在系统上对垃圾信息的发布进行限制,例如加入验证码等。

20、Keywords-关键字

通常用于新闻系统的相关文章,但是博客基本上都没有这项功能,对于分类过大,没有TAG功能的博客来讲,利用关键字自动获取相关文章还是很有必要的,实现起来也不难。

21、SN-社会化网络

目前除了rss的应用突飞猛进外,BLOG自身的发展似乎停滞不前了,而增强BLOG的SN功能,是BLOG功能拓展的重要途径。例如“团体博客”,BLOG浏览同好等,具体就不多说了,网上SN服务一大把,参考一下就知道哪些SN功能可以结合进来了。

22、Export-导出

用户数据的导出,例如文章、评论、引用等。

23、Management-管理

管理功能,设置BLOG的基本参数,设置和管理以上所有要素,数据库管理,后台各项内容的导出等。


++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

1、群组功能: 志趣相投的朋友,可以把大家的Blog Post聚合到一个页面。发文章时,可以选择同时在哪些组的首页显示。
2、编辑器
2-1 采用跨平台编辑器
2-2 支持表情
2-3 支持代码格式化
2-4 支持直接上传图片(编辑器上传的图片,放到缺省分类:我的文章图片)
3、对BlogAPI的更好支持(客户端通过WebService发文等)
4、移动Blog支持(通过手机WAP、短信管理自己的Blog,浏览文章等)
5、数据本地备份和恢复
6、从其他Blog转移文章的功能(通过RSS)
7、个人助理系统
提供可以网络化处理一些个人生活或者程序开发等方面的助手功能。
如:珍藏代码库。此功能可以按语言分类,按分类建立代码库,提供给用户在网上看的好代码片断的收藏。
又如:备忘录功能,用户可以建立系列的待办事情的备忘录,一到时间,系统通过手机短信的形式提醒用户。


8、临时保存功能,在提交失败时能自动保存在客户端
9、文章收藏功能(*)
10、发表文章时的预览功能(*)
11、从其他Blog网站聚合文章
12、好友功能,在自己的Blog页面上显示好友的最新文章
13、留言簿
14、文章置顶功能
15、显示最新评论
16、向其他Blog网站发表文章的功能
这个功能主要方便那些拥有多个Blog的用户,通过这个功能在一个站点维护多个Blog中的内容


17、后台管理功能:
17-1、文章的管理:禁止文章显示在首页、文章归类等等
17-2、用户管理:禁用帐户, 管理员修改密码, 限制帐户等等
18、多语言支持
19、计数器
20、日历
21、用户分组功能
22、共享Blog功能, 多个用户维护同一个Blog
23、其他人文章的回复邮件通知
24、登录发表评论, 可以对登录发表过的评论进行编辑、删除
25、通讯录
26、在线RSS阅读器
27、与outlook进行同步
28、日程表
29、自定义兴趣小组,一个Blogger可以自己建立一个组, 然后邀请其他人加入, 只有加入该小组的人才能向该小组发表文章
posted @ 2006-10-24 16:21 逍遥草 阅读(674) | 评论 (7)编辑 收藏
本文是J2EE Web服务开发系列文章的第三篇,本文将首先介绍JAX-RPC基本构架,然后重点讨论把Servlet作为JAX-RPC Web服务端点时的开发步骤,以及各个步骤中要使用的工具和编程技巧。在内容的组织上,仍然结合本系列文章第一篇(《用JAXM开发Web服务》)中的案例,一步步引导读者使用JAX-RPC开发Web服务。

阅读本文前您需要以下的知识和工具:

  • JavaTM Web Services Developer Pack 1.1,并且会使用初步使用;
  • 辽倩崾褂靡恢諩JB容器来开发、部署EJB,并且了解怎么在客户端访问EJB组件;
  • 对Apache axis Web服务开发工具有基本的了解;
  • 基本的Java编程知识。

如果使用JAX-RPC开发Web服务,我们几种选择:

  • Servlet作为Web服务端点;
  • 无状态会话Bean作为Web服务端点;
  • 基于消息(如JMS)的应用程序作为Web服务端点。

本文以Servlet作为Web服务端点的情况来介绍JAX-RPC Web服务开发,关于本篇文章中案例的介绍详见本系列文章第一篇: 《用JAXM开发Web服务》

本文的参考资料见 参考资料

本文的全部代码在这里 下载

JAX-RPC快速入门

JAX-RPC,Java™ API for XMLbased RPC,顾名思义,它是一种远程方法调用(或者说远程过程调用),那么它和其它的远程方法调用(RPC, COM,CORBA,RMI)有什么区别呢?我们看一般的远程方法调用的结构,如图1所示。


图1 远程方法调用

综合比较常用的远程方法调用技术,它们有以下的共性:

  • 在客户端和服务端有通用编程接口;
  • 在客户端有Stub,在服务端有Tie(有的叫Skeleton);
  • 客户端和服务端有专门的协议进行数据传输。

对于通用接口的描述,比如CORBA有IDL of CORBA,Java RMI有Java RMI interface in RMI,对于XMLbased RPC来说,IDL就是WSDL(Web服务描述语言)。那么XMLbased RPC来说,什么是这个结构中的"传输协议",当然是SOAP,SOAP消息通过以传输文本为基础的协议(HTTP、SMTP、FTP)为载体来使用的,也就是说,SOAP消息的传输建立在HTTP、SMTP、FTP传输协议之上。

JAX-RPC的构架如下。


图2 JAX-RPC 的构架

从上图可以看出,客户端调用的是JAX-RPC服务端点(Service Endpoint),这个服务端点是通过WSDL语言描述的。在这个体系结构中,对于客户端,可以是JS2E、J2ME或者J2EE平台运行环境;对于服务端,可以是J2EE1.3或者J2EE1.4容器(Servlet容器或者EJB容器)。Apache axis是一个很好的JAX-RPC运行环境实现,同时也提供了优秀的开发工具,本文将使用它进行开发。

使用Servlet作为服务端点,本案例的基本构架如下图所示。


图3 案例的基本构架

客户端通过SOAP消息和JAX-RPC服务端交互,JAX-RPC服务端运行在Servlet容器中,它通过调用EJB容器中的EJB组件来处理具体的业务逻辑。

使用JAX-RPC开发Web服务,可以按照以下的步骤进行:

  1. 服务端点定义;
  2. 服务描述;
  3. 服务端点实现;
  4. 服务端点部署;
  5. 服务发布和发现。

注意:对于服务的发布和发现,由于机制比较复杂,本文不讨论,可能会在本系列文章进行专题讨论。





回页首


开发快速入门

一个完整的JAX-RPC开发实例,将按照上面的5个步骤进行,但是我们也可以使用非常简单的方式来发布一个Web服务。在介绍我们的案例前,让我们用一分钟快速开发一个Web服务。

首先安装好JWSDP,你可以从 http://java.sun.com/webservices下载。

把本案例源代码中的\src\bookservice.ear\web.war目录拷贝到%JWSDP_HOME%\webapps目录下,web.war文件里已经包括了Apache axis运行环境。

在%JWSDP_HOME%\classes目录下新建一个HelloWorld.java文件,它的代码如下:

例程1 最简单的Web服务HelloWorld

												
														package com.hellking.webservice;
public class HelloWorld
{
 public String sayHello(String name)
 {
  return "Hello! "+name;
 }
}

												
										

编译这个类,然后编辑%JWSDP_HOME%\webapps\WEB-INF\server-config.wsdd文件,找到</service>标记,在其后面加入以下内容:

												
														 <service name="HelloWorld" provider="java:RPC">
  <parameter name="allowedMethods" value="sayHello"/>
  <parameter name="className" value="com.hellking.webservice.HelloWorld"/>
 </service>
 
												
										

在浏览器例输入:

http://localhost:8080/web/services/HelloWorld?wsdl

如果出现部署WSDL描述文件,那么最简单的Web服务已经部署成功!

下面我们使用最简单的方式来调用这个Web服务,在浏览器里输入:

http://localhost:8080/web/services/HelloWorld?wsdl&method=sayHello&name=hellking

那么在浏览器将会显示以下内容:

例程2 在浏览器里调用Web服务

												
														     <?xml version="1.0" encoding="UTF-8" ?> 
 <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
 xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
 <soapenv:Body>
 <sayHelloResponse soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
  <sayHelloReturn xsi:type="xsd:string">Hello! hellking</sayHelloReturn> 
  </sayHelloResponse>
  </soapenv:Body>
  </soapenv:Envelope>
  
												
										

如果结果是这样,那么最简单的Web服务已经部署成功,并且测试也通过了。注意"Hello!hellking"是调用Web服务返回的结果,它是我们期望的。下面我们来看一个完整的Web服务开发的例子。





回页首


服务端点定义

服务端点定义的工作主要是确定"服务定义接口"(Service Definition Interface),有时也叫Web服务端点接口(Web services endpoint interface)。服务端点定义有两中方法获得:

  • 使用某些工具从WSDL文件获得;
  • 直接使用Java语言编写。

Apache axis提供了从WSDL文件中获得Web服务端点的工具。您可以这样使用:

												
														java org.apache.axis.wsdl.WSDL2Java (WSDL-file-URL)

												
										

使用这个命令前先设置好以下的环境变量,后面的介绍中还会使用axis工具,它们也要这样设置环境变量:

												
														SET AXIS_HOME=<axis安装目录>
set CLASSPATH=%CLASSPATH%;
%AXIS_HOME%/axis-1_1/lib/axis.jar; 
%AXIS_HOME%/axis-1_1/lib/jaxrpc.jar; 
%AXIS_HOME%/axis-1_1/lib/saaj.jar;
%AXIS_HOME%/axis-1_1/lib/commons-logging.jar;
%AXIS_HOME%/axis-1_1/lib/commons-discovery.jar;
%AXIS_HOME%/axis-1_1/lib/wsdl4j.jar;.

												
										

关于WSDL2Java的更详细的使用,请参考Apache axis的User Guides( http://ws.apache.org/axis/)。

我们这里直接使用Java编写服务端点接口的方法。在本案例中,定义了三个业务方法,它们分别是查找所有的图书、按书名查找图书、按类别查找图书。那么安照这三个业务方法,可以定义出以下的服务端点接口:

例程3 服务端点定义(BookServiceInterface.java)

												
														package com.hellking.webservice.servlet;
/**
  *@author hellking
  */
import java.util.Collection;
import com.hellking.webservice.BookVO;
public interface BookServiceInterface
{
   
   /**
    * @return Vector
    */
   public Collection getAllBooks();//查找所有的图书
   
   /**
    * @param name
    * @return BookVO
    */
   public BookVO getTheBookDetail(String name);//按照书名查找图书
   
   /**
    * @return Collection
    */
   public Collection getBookByCategory(String category);//按类别查找
}

												
										

上面代码中的BookVO是一个序列化的对象,它有以下属性,每个属性都提供了getter和setter方法。

例程4 BookVO的部分代码

												
														public class BookVO implements java.io.Serializable
{
   private String name;
   private String publisher;
   private float price;
   private String isbn;
   private String description;
   private String category;
   private Collection authors;   
     
   public void setName(String name)
   {
     this.name=name;
   }
public String getName()
    {
     return this.name;
    }
…
}

												
										

编译好这两个类。





回页首


服务端点描述

可以使用Java2WSDL从以上定义的服务端点接口中获得服务描述(WSDL文件)。使用Apache axis工具,只要使用以下命令即可:

												
														 java org.apache.axis.wsdl.Java2WSDL -o temp.wsdl 
-l"http://localhost:8080/axis/services/BookServletService"
 -n "urn:BookServletService"
 -p"com.hellking.webservice" "urn:BookServletService"
 com.hellking.webservice.servlet.BookServiceInterface
 
												
										

以上命令的解释:

-o:生成的WSDL文件;
-l:Web服务的位置;
-n:这个WSDL文件的名字空间;
-p:包到名字空间的映射;

最后一个参数是Web服务端点接口。

使用以上命令后,将生成一个名为temp.wsdl Web服务描述文。





回页首


服务端点实现

有了服务描述文件,就可以使用它来生成JAX-RPC 的框架,这个框架使得我们编程变得简单,当然您也可以直接编写实现代码,然后部署,但是那样编程会变得困难。

使用以下的命令就可以生成这个框架:

												
														java org.apache.axis.wsdl.WSDL2Java -o . -d Session -s -S true 
-Nurn:BookServletService com.hellking.webservice.servlet temp.wsdl

												
										

使用这个命令后将生成以下文件:

BookServiceInterface.java:新的BookServiceInterface接口,它扩展了java.rmi.Remote接口;

BookServiceInterfaceService.java:客户端服务接口,用来获得BookServiceInterface对象的引用;

BookServiceInterfaceServiceLocator.java:在客户端使用,主要用来服务定位;

BookServletServiceSoapBindingImpl.java:服务端实现类,它实现了BookServiceInterface接口,服务端的业务方法实现代码就在这里编写;

BookServletServiceSoapBindingSkeleton.java:服务端Skeleton;

BookServletServiceSoapBindingStub.java:客户端Stub;

BookVO.java:新的BookVO序列化对象;

deploy.wsdd:部署这个Web服务的脚本;

undeploy.wsdd:卸载这个Web服务的脚本。

服务端点实现类的基本框架已经生成出来了,我们的任务就是往里面增加具体的业务内容。下面我们来看具体的服务端点的实现。如例程3所示。

例程5 服务端点实现类

												
														package com.hellking.webservice.servlet;
import java.util.*;
import javax.naming.*;
import com.hellking.webservice.ejb.*;

public class BookServletServiceSoapBindingImpl
 implements com.hellking.webservice.servlet.BookServiceInterface{
   InitialContext init=null;
 BookServiceFacadeHome facadeHome;
 
    public BookServletServiceSoapBindingImpl()
    {
     try
     {
      init=new InitialContext();
     }
     catch(Exception e)
     {
     }
    } 
       
   //业务方法,查找所有的图书
 public java.lang.Object[] getAllBooks() throws java.rmi.RemoteException {
             System.out.println("getAllBooks");

        try
        {
         Object objref = init.lookup("ejb/bookfacade");  
         facadeHome = (BookServiceFacadeHome)javax.rmi.PortableRemoteObject.narrow(
objref, BookServiceFacadeHome.class); 
      Collection result=facadeHome.create().getAllBook(); 
      System.out.println(result.size());
              Object[] ret=new Object[result.size()];
       Iterator it=result.iterator();
      int i=0;
      while(it.hasNext())
      {
       ret[i++]=it.next();
      } 
  // System.out.println(((BookVO)ret[0]).getName());
        return ret;   
  }
  catch(Exception e)
  {
   e.printStackTrace();
   return null;
  }  
    }
    //业务方法,按书名查找图书
    public com.hellking.webservice.BookVO getTheBookDetail(java.lang.String in0)
 throws java.rmi.RemoteException {
         com.hellking.webservice.BookVO ret=null;
        try
        {
         Object objref = init.lookup("ejb/bookfacade");  
         facadeHome = (BookServiceFacadeHome)javax.rmi.PortableRemoteObject.narrow(
objref, BookServiceFacadeHome.class); 
      Collection result=facadeHome.create().getBookDetail(in0);
      Iterator it=result.iterator();
      while(it.hasNext())
      {
       ret=( com.hellking.webservice.BookVO)it.next();
      } 

   }   
  catch(Exception e)
  {
  }  
  return ret;
    }
//业务方法,按类别查找图书
    public java.lang.Object[] getBookByCategory(java.lang.String in0)
 throws java.rmi.RemoteException {
         try
        {
         Object objref = init.lookup("ejb/bookfacade");  
         facadeHome = (BookServiceFacadeHome)javax.rmi.PortableRemoteObject.narrow(
objref, BookServiceFacadeHome.class); 
      System.out.println(in0);
      Collection result=facadeHome.create().findByCategory(in0); 
      Object[] ret=new Object[result.size()];
      Iterator it=result.iterator();
      int i=0;
      while(it.hasNext())
      {
       ret[i++]=it.next();
       System.out.println(i);
      } 
   return ret;   
  }
  catch(Exception e)
  {
   e.printStackTrace();
   return null;
  }  
 }
}

												
										

可以看出,服务端点的主要任务是调用EJB组件来完成业务逻辑的。

需要向读者说明的是,为了和本系列第一篇文章中的客户端框架兼容(客户端使用的值对象是com.hellking.webservice.BookVO,而这里由WSDL2Java生成的值对象是com.hellking.webservice.servlet.BookVO)。我们需要做以下的改动:

把生成的这些代码中的com.hellking.webservice.servlet.BookVO全部改为com.hellking.webservice.BookVO,然后在Apache axis服务配置文件中申明这个BeanMapping,具体的声明方法在后面介绍。

接下来的工作是编译服务端相关的文件:BookServletServiceSoapBindingImpl、BookServletServiceSoapBindingSkeleton、BookServiceInterfaceService、BookServiceInterface。





回页首


服务端点部署

启动服务器,这个服务器可以是任何能够运行Apache引擎Web服务器,当然最好是同时有EJB容器和EJB容器的服务器,如Webphere 、Weblogic、JBOSS,如果没有EJB容器,还需要一个额外的EJB容器,并且需要更改BookServletServiceSoapBindingImpl中获得上下文(InitialContext)的方法,如:

例程6 获得上下文环境

												
														     Properties p = new Properties();   
     p.put(Context.INITIAL_CONTEXT_FACTORY, "xxxxx");
     p.put(Context.URL_PKG_PREFIXES, "xxxx");
     p.put(Context.PROVIDER_URL, "xxxx");
     init=new javax.naming.InitialContext(p);
     
												
										

在控制台中,转到deploy.wsdd目录下,执行以下的命令就可以完成部署:

												
														 java org.apache.axis.client.AdminClient deploy.wsdd
 
												
										

由于我们使用的是自己的序列化Bean对象,故要在%Web-Apps%/WEB-INF/ server-config.wsdd文件中做以下更改:
找到

												
														<service name="BookServletService" provider="java:RPC">
…
</service>

												
										

在中间加入以下内容:

												
														 <beanMapping languageSpecificType="java:com.hellking.webservice.BookVO"
 qname="ns7:BookServletService" xmlns:ns7="BookServletService"/>
 
												
										

部署后您必须确保在%Web-Apps%/WEB-INF/classes目录下有服务端相关的类(BookServletServiceSoapBindingImpl、BookServletServiceSoapBindingSkeleton等)。

在浏览器里输入(这个地址您需要根据具体情况更改):

http://localhost:8080/axis/services/BookServletService?wsdl

来验证Web服务是否已经部署成功,如果部署不成功,您可以先尝试重新启动服务器。





回页首


客户端

如果服务端已经成功部署,下一步的工作就是编写客户端程序了。由于使用WSDL2Java已经生成了客户端的框架,所以我们的任务将相对简单了。

客户端编程任务主要有以下几个:

  • 在BookServletServiceSoapBindingStub里注册BeanMapping;
  • 编写客户端业务代表,这里使用了JAXRPCDelegate;
  • 更改以前的BookGUI的部分程序。




回页首


在BookServletServiceSoapBindingStub里注册BeanMapping

由于在SOAP消息中使用了序列化的BookVO对象,故在BookServletServiceSoapBindingStub中要进行BeanMapping注册。具体方法:

找到BookServletServiceSoapBindingStub中的getAllBooks,getTheBookDetail,getBookByCategory方法,在每个方法中的

												
														 java.lang.Object _resp = _call.invoke(new java.lang.Object[] {in0});
 
												
										

前加入以下代码:

例程7 在BookServletServiceSoapBindingStub注册BeanMapping

												
														 QName    qn      = new QName( "BookServletService", "BookServletService" );
 _call.registerTypeMapping(com.hellking.webservice.BookVO.class, qn,                
new org.apache.axis.encoding.ser.BeanSerializerFactory(com.hellking.webservice.BookVO.class, qn),        
 new org.apache.axis.encoding.ser.BeanDeserializerFactory(com.hellking.webservice.BookVO.class, qn));
 
												
										

注意这里的Qname要和server-config.wsdd中描述的名称空间一致。在中server-config.wsdd,我们使用了以下的映射:

												
														 <beanMapping languageSpecificType="java:com.hellking.webservice.BookVO"
 qname="ns7:BookServletService" xmlns:ns7="BookServletService"/>
 
												
										

在编写业务代表程序前,我们先来对Web服务做一个调用测试。在测试前您必须保证数据库里已经有图书信息。如果EJB和Web Application都部署好,您可以通过以下页面来往数据库里增加数据:

http://localhost:8080/axis/insert_data.jsp

测试代码如下:

例程8 测试Web服务

												
														package com.hellking.webservice.servlet;
import java.net.URL;

import javax.xml.namespace.QName;
import javax.xml.rpc.Service;
import javax.xml.rpc.ServiceFactory;
import com.hellking.webservice.ejb.*;

public class Client { 
    public static void main(String[] args) {      
        try {
            
            BookServiceInterfaceServiceLocator locator=new BookServiceInterfaceServiceLocator();
            
        
        BookServiceInterface myProxy=locator.getBookServletService();
            Object[] c=myProxy.getAllBooks();
            com.hellking.webservice.BookVO 
book=(com.hellking.webservice.BookVO)c[0];
            System.out.println(book.getName());            
        } catch (Exception ex) {
            ex.printStackTrace();
        } 
    } 
}

      
      
												
										

如果在控制台里打印出某个图书的名字,那么就验证了客户端和服务端的部署是正确的。在进行下面的工作前,请确保这个测试是成功的。





回页首


编写客户端业务代表

对于客户端程序来说,业务代表直接和Web服务打交道,获得Web服务返回的数据,并做对应的处理,然后把数据返回给GUI程序,GUI程序只负责数据显示。业务代表的代码如下:

例程9 JAXRPCDelegate业务代表

												
														package com.hellking.webservice.servlet;

import java.net.URL;
import javax.xml.namespace.QName;
import javax.xml.rpc.Service;
import javax.xml.rpc.ServiceFactory;
import com.hellking.webservice.ejb.*;
import java.util.*;

public class JAXRPCDelegate implements com.hellking.webservice.BookBusiness
{
  BookServiceInterfaceServiceLocator locator;
     com.hellking.webservice.servlet.BookServiceInterface bookService;
     
     public JAXRPCDelegate()
  {
   try
   {
    locator=new BookServiceInterfaceServiceLocator();
          bookService=locator.getBookServletService();
         }
         catch(Exception e)
         {
         }
    }
  
 public Collection getBookByCategory(String category)
 {
     System.out.println("by_category");
  Collection ret=new ArrayList();
  try
  {   
            Object[] books=bookService.getBookByCategory(category);
            System.out.println(category);
            int i=0;
            
            while(true)
            {
             ret.add(books[i++]);
             System.out.println(i);
            }   
  }
  catch(Exception e)
  {
  }
  return ret; 
 }
 
 public Collection getAllBooks()
 {
  Collection ret=new ArrayList();
  try
  {   

            Object[] books=bookService.getAllBooks();
            int i=0;
            
            while(true)
            {
             ret.add(books[i++]);
            } 
  }
  catch(Exception e)
  {
  }
  return ret;
 }
 
 public com.hellking.webservice.BookVO getTheBookDetail(String name)
 {
  System.out.println("bookdetail");
  com.hellking.webservice.BookVO ret=new com.hellking.webservice.BookVO();
  try
  {   
           ret=bookService.getTheBookDetail(name);
  }
  catch(Exception e)
  {
  }
  return ret;  
 } 
}

												
										

和第一篇文章介绍的JAXMDelegate一样,JAXRPCDelegate 同样实现了BookBusiness接口,BookBusiness接口是以前设计的接口,我们在这里进行重用,这样的好处是BookClientGUI程序几只要做很少的更改就可以运行。





回页首


更改以前的BookClientGUI的部分程序

在BookGUI构造方法里增加以下内容:

例程10 更改BookGUI程序

												
														public BookClientGUI()
{
 business=new JAXRPCDelegate();
…
}

												
										

好了,经过以上的奋战,让我们来看运行的结果吧。

java com.hellking.webservice.BookClientGUI

运行结果如图4所示。


图4 运行结果.




回页首


总结

通过以上的介绍,相信读者对JAX-RPC Web服务开发已经有一个比较深刻的认识。总结一下,使用JAX-RPC开发Web服务时,主要有以下的工作:

  • 服务端点定义;
  • 服务描述;
  • 服务端点实现;
  • 服务端点部署;




回页首


下一步

本文已经介绍了把Servlet作为Web服务端点开发Web服务的全过程,下一篇将是把EJB作为Web服务端点来开发。





回页首


参考资料

Apache axis User's Guides: http://ws.apache.org/axis/
Sun jwsdp-1_1-tutorial, http://java.sun.com/webservices/downloads/webservicestutorial.html
http://www.ibm.com/developerworks/cn/xml/index.shtmlXML & Web services专区
JAX-RPC API http://java.sun.com/webservices
Jwdp1.1 http://java.sun.com/webservices
下载 样例代码





回页首


关于作者

陈亚强:北京华园天一科技有限公司高级软件工程师,擅长J2EE技术,曾参与多个J2EE项目的设计和开发,对Web服务有很大的兴趣并且有一定的项目经验。热爱学习,喜欢新技术。即将由电子工业出版社出版的《J2EE企业应用开发》正在最终定稿阶段,目前正从事J2EE方面的开发和J2EE Web服务方面的图书写作。您可以通过 cyqcims@mail.tsinghua.edu.cn和他联系。


引用地址:http://www-128.ibm.com/developerworks/cn/webservices/ws-jax-rpc/part1/index.html
posted @ 2006-09-28 18:43 逍遥草 阅读(5539) | 评论 (1)编辑 收藏
在 Apache Geronimo 上远程部署 Web 应用程序
作者:Michael … 文章来源:IBM developerWorks
引用自:http://www.crackj2ee.com/Article/ShowArticle.asp?ArticleID=693

Apache Geronimo 是一种认证的 Java™ 2 Platform Enterprise Edition(J2EE) 1.4 应用服务器。大多数人在想到 J2EE 时,会想到事务管理、Web 应用程序和异步消息传递等东西。但是,有了这些特性也不一定能够通过 J2EE 认证。应用服务器必须提供任务关键型生产系统所需的许多工具。这些工具之一是远程部署。Geronimo 是为满足大多数部署场景而设计的,所以它包含对远程部署的支持。本文解释使用 Geronimo 远程部署应用程序的许多方式。学习如何使用命令行工具(Geronimo 部署工具)和基于浏览器的工具(Geronimo Administration Console)远程部署应用程序,以及如何在集成开发环境(Eclipse)中部署应用程序。本文还提供一个对小型 Web 应用程序进行部署的简单示例。

远程部署和 JSR 88

远程部署是任何 J2EE 认证的应用服务器的重要特性之一。任务关键型应用服务器需要运行在专用的系统上。安全性也是许多系统必须关注的问题,所以会限制对系统的访问。受到限制的访问意味着应用程序不能在进行部署和运行的系统上进行构建和打包。

Java 社区认识到了远程部署的重要性。2000 年 10 月,引入了 Java Specification Request 88:Java Application Deployment(JSR 88)来解决这个问题。Java Community Process(JCP)通过 JSR 对应用程序的许多方面进行标准化。这种标准化的一个例子是应用程序的打包。Web 应用程序具有标准的布局并打包为 Web 应用程序存档(WAR)。这使应用程序开发人员在开发 Web 应用程序时不需要太多考虑在什么环境中部署应用程序。这是经典的 Java 格言 “一次编写,到处运行 ” 在企业部署方面的应用。

与通过 JCP 建立的其他 JSR 一样,JSR 88 是许多行业领先公司的代表之间协商的成果,比如 IBM®、Sun Microsystems、BEA 和 Oracle。这个规范引入了一种将任何 J2EE 应用程序部署到任何 J2EE 应用服务器的标准方式。它提供了部署(尤其是远程部署)的许多重要方面的细节,从而实现了标准化。它确定了应该如何识别和定位远程应用服务器,并为访问应用服务器建立了基本的安全模型。它还选定了应用服务器应该支持的几个核心部署阶段,比如部署、取消部署和重新部署。

许多工作成果集中在 JSR 88 中。这个规范的草案于 2001 年 10 月提交给 JCP。当然,在此之前,所有主流应用服务器厂商已经在自己的产品中提供了某种远程部署支持。不同的厂商采用不同的方法,因此关于如何对部署进行标准化有许多争论。JCP 拟订了一个草案,于 2002 年 1 月向公众发布。JSR 88 于 2002 年 6 月定稿并获得批准。自此之后,它在 2003 年进行了更新,并于当年随 Java Platform, Enterprise Edition(Java EE) 5 的发布再次更新。(关于 JSR 88 的更多细节和历史,请参阅本文后面的 参考资料。)

JSR 88 使独立软件厂商能够开发可以部署在任何 J2EE 认证应用服务器上的 J2EE 应用程序。当然,在支持 JSR 88 的同时,每个应用服务器的开发者可以添加额外的部署功能。例如,Apache Geronimo 通过它的 Geronimo 部署计划提供了许多高级部署特性。部署计划将关于应用程序的重要元数据告诉 Geronimo。对于 Web 应用程序,要做的重要事情之一是设置应用程序的上下文根。这样就很容易让应用程序出现在 http://<host> 这样的位置,而不需要在 URL 上提供额外路径。本文包含一个简单的 Web 应用程序,其中包含一个 Geronimo 部署计划(关于部署计划的更多信息,请参见 参考资料)。







Web 应用程序示例

为了了解远程部署在 Geronimo 上如何工作,最好有一个要部署的应用程序。图 1 显示本文使用的简单 Web 应用程序 remoteApp 的布局。


图 1. 简单 Web 应用程序 remoteApp 的文件结构
简单 Web 应用程序 remoteApp 的文件结构

这个应用程序只包含一个 Web 页面 index.jsp。清单 1 给出这个 Web 页面,这个页面显示 Hello World 以及当前时间。


清单 1. remoteApp 的 index.jsp
<?xml version="1.0" encoding="ISO-8859-1" ?>
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1" session="false"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
<title>My Remote Web Application</title>
</head>
<body>
	Hello Remote World! The current time is: <%= new
 java.util.Date().toString() %>
</body>
</html>

这个应用程序使用 Ant 进行构建和打包。清单 2 给出构建脚本。它所做的仅仅是调用 Java jar 函数将应用程序打包为 .war 文件。为了对应用程序进行构建和打包,只需运行 ant buildwar


清单 2. 简单的 Ant 构建文件
<project name="remoteApp" basedir="." default="usage">
    <property name="src.dir" value="src"/>
    <property name="web.dir" value="war"/>
    <property name="build.dir" value="${web.dir}/WEB-INF/classes"/>
    <property name="name" value="remoteApp"/>
    <target name="build" description="Compile main source 
tree java files">
        <mkdir dir="${build.dir}"/>
        <javac destdir="${build.dir}" debug="true"
               deprecation="false" optimize="false" failonerror="true">
            <src path="${src.dir}"/>
            <classpath refid="master-classpath"/>
        </javac>
    	<copy todir="${build.dir}" preservelastmodified="true">
    		<fileset dir="${src.dir}">
    			<include name="**/*.hbm.xml"/>
    		</fileset>
    	</copy>
    </target>
    <target name="buildwar" depends="build"
 description="Builds application as a WAR file">
        <war destfile="${name}.war"
             webxml="${web.dir}/WEB-INF/web.xml">
            <fileset dir="${web.dir}">
                <include name="**/*.*"/>
            </fileset>
        </war>
    </target>
</project>

最后(但并非不重要),这个应用程序包含一个 Geronimo 部署计划。Geronimo 在释放 .war 文件时寻找部署计划。这个部署计划指定上下文根是 /helloRemote(见 清单 3)。因此能够在 http://<host>:<port>/helloRemote 访问这个 Web 应用程序。这个计划还给应用程序分配 IDHelloRemote


清单 3. remoteApp 的 Geronimo 部署计划
<web-app xmlns="http://geronimo.apache.org/xml/ns/j2ee/web-1.0"
         configId="HelloRemote">
    <context-root>/helloRemote</context-root>
   
<context-priority-classloader>false</context-priority-classloader>
</web-app>

有了这个简单的应用程序,现在就可以使用 Geronimo 的远程部署特性将应用程序部署到 Geronimo 的远程实例。进行远程部署有几种不同的方式;下一节讨论不同的方法以及它们如何工作。







Geronimo 上的远程部署

JSR 88 提出的规范是对任何 J2EE 1.4 应用服务器的要求,Apache Geronimo 完全实现了这个规范。Geronimo 提供了几种将应用程序部署到本地和远程系统的方式。它提供了一个命令行实用程序 —— Geronimo 部署工具。这个工具提供完整的 JSR 88 支持,甚至可以用于其他应用服务器。

Geronimo 还通过 Geronimo Administration Console 提供部署,这是一个供 Geronimo 管理员使用的 Web 应用程序。最后,可以在 Geronimo 上使用提供了 JSR 88 支持的其他第三方工具,比如流行的 Eclipse Web Tools Platform(更多信息见 参考资料)。本文讲解如何使用 Geronimo 部署工具部署示例应用程序,以及如何使用 Geronimo Administration Console 来检验它的部署。首先看看 Geronimo 部署工具。

Geronimo 部署工具

Geronimo 部署工具在 $GERONIMO_HOME/bin/deployer.jar 中。它提供 JSR 88 指定的所有选项以及 Geronimo 特有的额外选项,比如指定外部 Geronimo 部署计划。对于习惯使用命令行的系统管理员,这个工具是自然的选择,可以用于本地和远程部署。它的语法很简单:

java -jar deployer.jar <general_options> <command>
<command_options>


有几个启用远程部署的选项。--uri 选项允许使用 JSR 88 中定义的 URI 语法识别远程服务器。URI 像下面这样:

deployer:geronimo:jmx:rmi:///jndi/rmi:[//host[:port]]/JMXConnector

这允许指定远程服务器(主机)并可选地指定主机监听的端口。如果没有指定主机和端口,那么默认值分别是 localhost 和 1099。另外,也可以使用 --host--port 选项指定主机和端口。

当然,部署必须是安全的。因此,需要向部署工具提供用户名和密码作为凭证。使用 --user 选项指定用户名,使用 --password 选项指定密码。如果没有提供密码,那么部署工具会提示用户输入密码。

还可以使用部署工具对应用程序进行启动、停止和取消部署。它甚至可以用于其他 J2EE 应用服务器。为此,需要用 --driver 选项指定一个 JSR 88 兼容驱动程序 JAR。还可以将各种选项组合成一个部署脚本(一个简单的 XML 文件),然后将部署脚本传递给部署工具。

部署工具还有几个您应该知道的需求。本地机器需要打开它的 Remote Method Invocation(RMI)端口。默认端口是 1099。它还必须与远程服务器共享它的文件系统。这样远程服务器才能读取应用程序存档文件(常常是 EAR 或 WAR)。远程服务器也必须打开 RMI 端口和 HTTP 端口(默认情况下是 8080)。最后,它必须正在运行 remote-deploy Web 应用程序,这是 Geronimo 上默认包含和运行的程序。

在本文的后面,您将看到使用 Geronimo 部署工具将 remoteApp 部署在一个 Geronimo 远程实例上。在此之前,先看看另一种部署方式,Geronimo Administration Console。

使用 Geronimo Administration Console 进行远程部署

remote-deploy Web 应用程序允许使用 Geronimo Administration Console 进行部署(见 图 2)。可以从 http://<host>:<port>/console 访问 Geronimo Administration Console。


图 2. Geronimo Administration Console:欢迎页面
Geronimo Administration Console:欢迎页面

点击左边导航面板中 Applications 文件夹下面的 Deploy New 链接,见 图 3


图 3. Geronimo Administration Console:Deploy new application 屏幕
Geronimo Administration Console:Deploy new application 屏幕

这允许上传应用程序的 .ear 或 .war 文件和部署计划。可以将 Geronimo 部署计划包含在 EAR 或 WAR 中,示例 Web 应用程序 remoteApp 中就是这么做的。也可以单独指定它。这对于已经部署在其他应用服务器上的应用程序是有用的。例如,如果有一个 Web 应用程序当前正在 JBoss 上运行,希望将它迁移到 Geronimo 上。使用这个选项,可以在 Web 应用程序 .war 文件之外的部署计划中编写任何特殊的 Geronimo 元数据,并对现有的 WAR 进行部署。

Geronimo Administration Console 是 Geronimo 部署工具的简单图形化替代品。这个控制台是一个 Web 应用程序,所以必须部署它(它是默认的),还必须安装一个 Web 容器(Tomcat 或 Jetty)。在某些生产系统上,可能不希望部署这个 Web 应用程序,因为它会使用一些资源,而且它提供的是已经通过命令行特性提供了的管理功能。另外,您在 Geronimo 上运行的应用程序可能根本不需要 Web 容器。在这种情况下,可以利用 Geronimo 的模块性,通过删除 Web 容器去掉这个应用程序。这可以释放一些资源,从而提高 Geronimo 的性能。但是,它对于开发人员仍然是好工具。在开发期间,另一个好办法是使用 Eclipse Web Tools Platform 和 Geronimo 插件(请参见 参考资料 中一篇解释这个方法的 developerWorks 文章的链接)。

使用 Eclipse Web Tools Platform 进行部署

J2EE 应用程序部署的标准化允许构建其他工具来提供部署功能,并支持各种应用服务器。还可以使用 Eclipse 的 Web Tools Platform 将应用程序部署到 Geronimo 的本地和远程实例上。在本节其余部分中,您将看到一个用来在 Geronimo 远程实例上进行部署的 Eclipse 示例。需要安装用于 Eclipse 的 Geronimo 插件(参见 参考资料 中的下载链接)。然后,在 Eclipse 中创建一个新的服务器实例(通常使用 New Server 向导),再指定要部署到这个服务器上的应用程序。

在默认情况下,这个向导使用 localhost 作为服务器的主机名,所以需要将它改为自己的远程主机名,见 图 4。注意,在本地机器上也需要安装 Geronimo,因为需要使用它的部署工具。在 图 4 中,本地已经安装了一个 Geronimo 运行时;如果不是这样,就需要使用 Installed Runtimes... 按钮设置它。


图 4. 步骤 1:选择要使用的 J2EE 服务器类型
步骤 1:选择要使用的 J2EE 服务器类型

图 5 显示连接任何 Geronimo 实例所需的常用信息,比如 Geronimo 使用的 Web、RMI 和 Enterprise JavaBeans(EJB)端口,以及安全凭证。


图 5. 步骤 2:指定连接 Geronimo 所需的参数
步骤 2:指定连接 Geronimo 所需的参数

最后一步是选择要部署到服务器上的应用程序(见 图 6)。当然,可以选择其他应用程序来部署到 Eclipse 中配置好的任何服务器上。(关于设置 Eclipse、WTP 和 Geronimo 插件,然后使用 Eclipse 将应用程序部署到 Geronimo 上的详细说明,请参见 参考资料。)


图 6. 步骤 3:指定要部署的应用程序
步骤 3:指定要部署的应用程序

既然已经讨论了进行远程部署的一些不同方法,就让我们使用 Geronimo 部署工具对示例应用程序进行部署。







部署示例:部署 remoteApp

这个示例使用 Apache Geronimo 部署工具。但是,使用 Administration Console 或 Eclipse 来部署这个应用程序也一样容易。在开发期间,选择哪种工具只是个人喜好问题,但是生产系统可能要求使用某种部署工具。

要使用部署工具,必须确保远程环境能够访问本地文件系统。在 Microsoft® Windows® 环境中,可以通过对网络驱动器进行映射来实现共享。在这个示例中,远程系统有一个映射的网络驱动器 Y:,它映射到本地系统的 %GERONIMO_HOME%/deploy 目录。这是一个合乎逻辑的选择,因为开发人员很可能先在本地对应用程序进行测试;所以应用程序可能已经放在这个目录中了。现在,进行部署的命令就很简单了:

java -jar %GERONIMO_HOME%/bin/deployer.jar --user system
--password manager --host aristotle deploy remoteApp.war


其中,aristotle 是远程服务器的名称。使用 --host 选项来指定远程主机而不是使用 URI。没有使用 --port 选项;因此 Geronimo 将使用默认的 RMI 端口 1099。应该会看到与 清单 4 相似的输出。


清单 4. 使用部署工具对示例应用程序进行远程部署
C:\dev\geronimo-1.0\deploy>java -jar %GERONIMO_HOME%/bin/deployer.jar 
--host aristotle --user system --password manager deploy remoteApp.war
    Uploading 1 file(s) to server

    File upload complete (Server: OK)

    1 file(s) transferred to server.  Resuming deployment operation.

    Deployed HelloRemote @ http://aristotle:8080/helloRemote

在部署应用程序之后,就可以登录到远程管理控制台并看到应用程序已经出现了(见 图 7)。


图 7. Geronimo Administration Console:安装的 Web 应用程序
Geronimo Administration Console:安装的 Web 应用程序

为了看到已经安装的 Web 应用程序的列表,点击左边菜单中 Applications 文件夹下面的 Web App WARs 链接。应该会在列表的顶部看到 HelloRemote(这是 Geronimo 部署计划中为应用程序指定的 ID)。注意,Administration Console 显示 HelloRemote 正在运行,并提供了停止和卸载的功能。它还显示 Geronimo 上运行的其他 Web 应用程序。图 7 所示的列表显示正在 Geronimo with Jetty 默认安装上运行的所有标准 Web 应用程序。它包含 JavaServer Pages(JSP)和 servlet 示例。还记得前面提到的 remote-deploy Web 应用程序吗?在这个列表中也应该会看到它。

当然,确定您的 Web 应用程序正在运行的最容易的方法是,直接从 Web 浏览器访问它。在使用 Geronimo 部署工具部署示例应用程序时,它提供了 Web 应用程序的 URL。将这个地址输入浏览器中,应该会看到与 图 8 相似的显示。


图 8. 部署在远程服务器上的 remoteApp
部署在远程服务器上的 remoteApp

图 8 所示的结果说明这个应用程序已经部署到了远程服务器上并正在运行。







结束语

远程部署是任何 J2EE 应用服务器的必要特性。它是使 Java 技术非常适合企业环境的原因之一。Geronimo 完全实现了 JSR 88,从而以标准化方式提供了远程部署功能。它还提供其他部署方法来简化应用程序的开发、部署和测试。







参考资料

学习

获得产品和技术





关于作者

Michael Galpin 拥有 California Institute of Technology 的数学学位。他从 20 世纪 90 年代晚期开始成为 Java 开发人员,作为软件工程师为加州 Sunnyvale 的 Vitria Technology 公司工作。

posted @ 2006-09-20 11:21 逍遥草 阅读(464) | 评论 (0)编辑 收藏

创建、部署和调试 Apache Geronimo 应用程序

如何使用针对 Geronimo 的新 Eclipse 插件

developerWorks
文档选项
将此页作为电子邮件发送

将此页作为电子邮件发送

未显示需要 JavaScript 的文档选项


最新推荐

Java 应用开发源动力 - 下载免费软件,快速启动开发


级别: 初级

Tim Francis , 高级技术人员, WebSphere Application Integration Middleware

2005 年 6 月 06 日

Eclipse 项目在过去几年中一直为开放源码社区提供高质量的和可扩展的集成开发环境。开始学习使用新的 Eclipse 插件来开发和部署 Web 应用程序到 Apache Geromimo 服务器吧。IBM 高级技术人员 Tim Francis 将为您介绍其中的细节。

插件为 Eclipse 添加了功能

Eclipse 平台吸引了许多开发人员,因为可以通过添加功能来扩展其核心能力。Eclipse 为这种扩展能力提供了定义良好的机制。Eclipse 的每一个方面都包含在 插件 中,而插件可以动态扩展其他插件,也可定义自身的 扩展点使其他插件可以扩展它们。插件本身定义了通过这些扩展可以提供的、而不属于基本的 Eclipse 基础设施的功能的类型。例如,扩展可以简单到只是弹出菜单中的一个新项,也可以像一个完全的新型项目、或是一系列的编辑器和视图这样包括众多。

基本 Eclipse 支持包括 Java 开发工具(Java Development Tool,JDT),它提供了完全的 Java 开发环境。不过,去年宣布了一个名为 Web Tools Platform (WTP) 的新 Eclipse 工具项目,其目的是提供开发 J2EE™ Web 应用程序所需的基本能力。IBM 已经为这个项目贡献了很多的代码,而其他几家公司正在合作开发它。WTP 的首次发布定于 2005 年 7 月 29 日。

尽管 WTP 项目没有提供当前商业集成开发环境(如 IBM Rational® Application Developer)所具有的高级开发能力或易用的功能,但是它提供了一个公共开放源码库,后者定义了必要的底层结构。这个代码库包括基本项目类型的定义和结构和可以用来修改各种工件的基本编辑器,并支持对应用服务器的定义和交互。(您可以从本文后面的 参考资料 部分中找到更多关于 Eclipse 和 Web Tools Platform的信息)。





回页首


Web Tools Platform 和 Apache Geronimo

WTP 项目当前支持部署项目到几种开放源码和 Web 应用服务器上,包括 Apache Tomcat servlet 容器。一个正在开发的新开放源码项目 —— Apache Geronimo —— 提供了完全的应用服务器,不仅包括 servlet 容器,包括对消息收发的支持,还包括一个包含 JDBC 连接器的数据库和一个门户框架。在 eclipse.org 网站上有一个正在开发的针对 WTP 的新插件,它提供了 WTP 与 Apache Geronimo 之间的集成(该插件的链接请参阅 参考资料)。这个插件允许您将 WTP 作为一个创建、部署和调试 Geronimo 应用程序的很基本的开发环境。





回页首


部署和使用基本 WTP 项目

在写本文的时候,WTP 项目的 M4 里程碑刚刚发布,并可以下载了(请参阅 参考资料)。正如在 eclipse.org 上对该项目的概述中所说,安装 WTP 需要一些先决条件,在安装 WTP 之前必须先下载并安装它们。这些先决条件包括基本 Eclipse 驱动和其他针对 GEF、EMF 和 Java EMF 模型的驱动。所有这些文件的正确版本的链接可从 eclipse.org 中得到 (请参阅 参考资料)。

下载并解压缩基本 WTP 项目和 Geronimo 插件

下载了先决条件并解压缩基本 WTP 项目以及最新的 WTP 里程碑构建之后,您可以下载 Geronimo 插件了。在 WTP 以后的构建中会包括该插件,但是如果使用的是 WTP M4 驱动,可以单独下载该插件(请参阅 参考资料)。将这个插件解压缩到以下位置: eclipse/plugins/org.eclipse.jst.server.geronimo.core_1.0.0。

启动 Eclipse

准备过程的最后一步是用 –clean 选项第一次启动 Eclipse,以确保能识别新插件。启动 Eclipse 之后,您就会看到如下的启动屏幕:


图 1. Eclipse 启动屏幕
Eclipse 启动屏幕

启动 Eclipse 后,下一步就是在环境中定义 Geronimo 服务器。选择 File > New file wizard 以创建一个新的服务器。在这个向导的第二页,当提示选择服务器类型时,选择 Apache Geronimo,如图 2 所示。


图 2. 定义一个新的服务器
定义一个新的服务器

然后将提示输入 Apache 服务器的安装位置以及用来定位开发项目的类路径所必需的转移地址寄存器的根目录。在下一页中,可以定义关于服务器的附加信息,尤为重要的是在安装 Geronimo 时指定的管理员用户 ID 和密码。在向导的最后一页上,可以向服务器添加已有的项目。因为还没有创建任何项目,所以就选择 Finish

现在您已经获得了在 Eclipse 中启动和停止 Geronimo 服务器所需的足够信息。要看服务器的状态,最容易的方法是进入 J2EE 透视图;选择 Window > Open Perspective > Other 菜单,然后从出现的对话框中选择 J2EE perspective。在这个透视图中,在屏幕的右下角有一个 Servers 视图,如图 3 所示:


图 3. J2EE 透视图中的 Servers 视图
J2EE 透视图中的 Servers 视图

选择这个视图中的 Geronimo 服务器,并从弹出菜单中选择 start。这将启动服务器并在控制台窗口中显示输出。还可以从调试模式下的同一视图启动服务器。





回页首


创建项目和模块定义

服务器运行后,下一步就是创建一个在其上运行的应用程序。WTP 支持使您可以在一个 Eclipse 项目中有多个 Web 模块 —— 因此,现在您需要创建项目和模式定义。从 J2EE navigator 中,选中 Dynamic Web Projects 图标,再从弹出菜单中选择 Create a new J2EE Web module。在得到的向导中,可以选择一个已有的项目或者新建一个项目来包含 Web 模块。因为这是一个空白工作区,选择 New 来新建一个项目。在 New project 对话框中,输入项目名并选择 Geronimo 作为目标服务器。完成这个向导之后,输入要创建的新 Web 模块的名字。完成新模块向导之后,将会在 Dynamic Web projects 图标下面看到新创建的项目和模块,如图 4 所示。


图 4. 新创建的项目和模块
新创建的项目和模块




回页首


创建和部署 Web 项目

在 navigator 视图中展开项目和模块节点,并找到 WebContent 文件夹。这个文件夹包含要放在生成的 Web 应用程序中的文件。从这个图标上的弹出菜单中,新建一个 HTML 文件。可以任意命名这个文件,并在出现的编辑器中输入一些简单的 HTML 文本。在 navigator 视图中,选择刚创建的文件,出现弹出菜单,然后选择 Run As > Run on server。在出现的对话框中,确保选中了 Geronimo 服务器,选择复选框以将 Geronimo 设置为这个项目的默认服务器,然后选择 Finish。现在这个 Web 应用程序就被创建并部署到运行中的 Geronimo 服务器上了,而一个 Web 浏览器将会打开,显示出刚创建的文件。如果不希望打开外部浏览器,那么 Eclipse 可以使用一个嵌入式窗口中的浏览器:如要设置偏好,则选择 Open window > Preferences > General > Web browser





回页首


在 Eclipse 中调试应用程序

成功地部署 Web 项目之后,就可以探究如何在 Eclipse 中调试应用程序了。最简单的方法是在刚创建的 Web 应用程序中添加一个 JSP 文件。

第一步是返回 Navigator 视图,并用弹出菜单在 WebContent 文件夹中新建一个 JSP 文件。在随后打开的 JSP 编辑器中,在 JSP 文件中加入一些非常基本的内容,包括一些嵌入式 Java 代码,如图 5 所示的示例。现在您可以通过双击相应行左栏来在该Java 代码中设置中断点。

下一步是在调试模式下重启 Geronimo 服务器。当 WTP 项目完成后,这项操作将自动进行,但是目前您需要在“Debug”模式下手动重启服务器。在右下窗格中选择 Servers 选项卡,并从弹出菜单中停止 Geronimo 服务器,然后再在“Debug”模式下重启它。现在您可以选择新建的 JSP 文件,并从其弹出菜单中选择 Debug as > Debug on server。新建的 JSP 文件会被编译,应用程序会重新部署到服务器上,而调试器会停在设置中断点的位置。现在您可以单步调试 JSP 文件,同时查看并更改变量值,而当您继续执行(使用绿色箭头),JSP 文件就被提交给浏览器。


图 5. 向 Web 浏览器提交 JSP文件
向 Web 浏览器提交 JSP文件

您可以对应用程序做任何需要的更改,然后,如上所述,选择 Run on server 操作,将更改重新部署到 Geronimo中。servers 视图的“Publish”操作也会将与所选服务器相关的所有应用程序重新部署。

使用 Eclipse XML 编辑器

这个编辑器预计将会被扩展以支持整个部署计划方案,但是目前您可以用它来编辑这个文件。





回页首


部署计划

Geronimo Web 应用程序在部署计划中定义了它们的基本行为。对于 Web 应用程序来说,这个计划被命名为 geronimo-jetty.xml,它在 WebContent > WEB-INF 目录中。在将应用程序部署到 Geronimo 中时,如果还没有基本部署计划,就会自动创建一个。您必须修改这个文件来为应用程序指定一个新的上下文路径。有一个编辑器可用来操纵这个文件的基本方面。要使用这个编辑器,在 navigator 视图中找到该文件,并选择 Open with > Deployment plan editor 来打开编辑器。部署计划的一些方面还没有展现在编辑器中,这些数据没有显示在编辑器中,但是保存文件时它们也不会丢失。


图 6. Geronimo 部署计划编辑器
 Geronimo 部署计划编辑器




回页首


结束语

Geronimo 服务器适配器插件还处于初期。它为与 Geronimo 的交互提供了基本支持,但是还需要做很多改进和完善。该插件是作为 Eclipse WTP 项目的一部分开发的,欢迎有兴趣的开发人员访问 Eclipse 网站并为该插件仍在进行的开发尽一份力。





回页首


参考资料





回页首


关于作者

Tim Francis

Tim Francis 是 IBM 加拿大多伦多实验室 WebSphere Tools 团组的高级技术人员和架构师。他在滑铁卢大学取得了应用电子工程学学士学位(BASc)和软件工程数学硕士学位(MMath),并于 1990 年加入 IBM。Tim 是 WebSphere Architecture Board 的高级成员,并且是 Rational Tools Development Council 的核心成员。Tim 与人合著了 J2EE 书籍 Professional IBM WebSphere 5.0 Application Server(Wrox Press,2002 年)。

引用地址:http://www-128.ibm.com/developerworks/cn/opensource/os-gerplug/index.html
posted @ 2006-09-20 10:48 逍遥草 阅读(387) | 评论 (0)编辑 收藏
 
我们已经了解了很多关于Web Services开发方面的知识,而对于Web Services测试所面临的挑战却知之甚少。本文将阐述对Web Services功能性和互用性的测试。本文同时也指出了与传统测试模式相比Web Services测试所面临的挑战。本文的目标读者是开发人员、测试人员以及那些对Web Services的技术知识或工作方式没有深入了解的项目经理。同时本文假设读者已经很熟悉Web Services的基本知识。

下载作者提供的与本文相关的文件

以下所述及的示例的环境由WebLogic Server 8.1Microsoft Windows .Net构成,二者所用操作系统均为Windows 2000

挑战

测试Web Services的有效性、性能、可伸缩性、可靠性以及安全性时所面临的主要挑战是 Web Services的分布性。

为了使完整的Web Services能够实现预期的功能,就要求客户端和服务都要满足一系列的要求。接口必须在其WSDL文档中正确描述出来,消息必须遵守传输协议规范(如HTTP1.1)和消息协议(如SOAP 1.1)。同时消息必须遵守描述该服务的WSDL文档中的契约,要求同时考虑到消息的内容和传输层的绑定。加上综合的安全条款、互操作性问题、UDDI注册要求以及一定负载下的性能需求,就很容易发现为什么网络测试不是无足轻重的事情。

Web Services组件可由多个利益相关者来共同构建和部署。因此,测试这些组件过程中会发现确定代码质量、可用性等都有很大的难度。Web Services的标准是简单的,数据驱动的,并且共享一个公共的基于XML的基础。传统的测试工具可能不足以有效地测试这些标准。而且GUI自动化工具也不足以有效地测试Web Services的接口点和消息格式。

功能测试

该测试的目标相当直观易懂:确保服务器能够对给定的请求发送正确的响应。然而,由于Web Services的复杂性,该任务原非想象的那么简单。对于大多数的Web Services而言,它不可能精确预见客户端会发来什么类型的请求。枚举所有可能的请求并不切实可行,因为可能输入的空间要么是没有边界,要么就是无穷大。因此,验证服务器是否能处理大范围的请求类型和参数是极其重要的。

  public boolean execute(String action, String symbol, int quantity)

  throws javax.xml.soap.SOAPException{

     Detail detail = null;

     detail = SOAPFactory.newInstance().createDetail();

     detail.addChildElement( "Stock Trade" ).addTextNode( "failed" );

      System.out.println("execute() in webservices.stock.trade webservice has been invoked

      with following arguments:: action:" + action +

      " symbol:" + symbol + " quantity:" + quantity);

      if(action == null) {

        throw new SOAPFaultException(new QName( "http://StockTrade/execute", "ServerFailed" ),

                                                "action parameter is null.",

                                                null,

                                                detail);

      }

      if(symbol == null) {

        throw new SOAPFaultException(new QName( "http://StockTrade/execute", "ServerFailed" ),

                                                "symbol parameter is null.",

                                                null,

                                                detail);

   }

      if(action.equalsIgnoreCase("BUY"))

        System.out.println("BUYING quantity: "+ quantity + " of symbol:" + symbol);

        // Invoke method to execute trade here.

      else if(action.equalsIgnoreCase("SELL"))

        System.out.println("SELLING quantity: "+ quantity + " of symbol:" + symbol);

        // Invoke method to execute trade here.

      else

      {

        System.out.println("INVALID action: "+ action);

        throw new SOAPFaultException(new QName( "http://StockTrade/execute", "ServerFailed" ),

                                                "Invalid Action:" + action,

                                                null,

                                                detail);

      }

      return true;

    }

代码摘录Stock Trade Web Services

该段摘录的代码是Stock Trade Web Services“execute()”方法的实现代码。该方法首先验证输入参数的有效性,验证成功才执行功能。举例说明,如果参数action是空值,它就会抛出一个SoapFaultException异常,用faultstring参数(第二个参数)说明造成异常的原因。为了举例说明,在对参数symbol进行相似的验证之后,Web Services给出了处理机。在实际的情况下,商业逻辑应该在此位置中实现:

  try{

       // Setup the global JAXM message factory

       System.setProperty("javax.xml.soap.MessageFactory",

         "weblogic.webservice.core.soap.MessageFactoryImpl");

       // Setup the global JAX-RPC service factory

       System.setProperty( "javax.xml.rpc.ServiceFactory",

         "weblogic.webservice.core.rpc.ServiceFactoryImpl");

       StockTrade_Impl ws = new StockTrade_Impl();

       StockTradePort port  = ws.getStockTradePort();

       boolean returnVal = port.execute(action, symbol, quantity);

       System.out.println("The webservice got back the following result:" + returnVal);

      }catch(Exception e) {

      }

代码摘录Web Services的客户端

上面的一段代码描述了测试客户端如何激活前面讨论的Stock Trade Web Services该例子使用了JAX-RPC APIJAX远程处理应用程序接口函数),并且假设在读者的CLASSPATH中已经含有了必要的BEA提供的JAR文件。这是一个静态实现,在这里可获得一个stub实现的实例。获得stub实现后,Web Services的“execute”方法就会被激活。

互操作性测试

SOAPWeb Services的承诺之一就是互操作性。就是两个应用系统可以自动交互而不需要人为的介入。Web Services未来成功的关键就在于互操作性。

Web Services互操作性测试套件的目标应针对于测试以下方面:

·                 服务器分析客户端的SOAP包的能力。

·                 服务器对包中所含的已编码参数进行反串行化的能力。

·                 客户端对由服务器作为响应发送而来的SOAP包进行分析的能力。

·                 客户端对从服务器发回的已编码参数进行反串行化的能力。

测试模式

对于一个WLS客户和.NET Web Services

·                 Microsoft Visual Studio在目录/InetPub/wwwroot/DotNetServices/下创建一个.NET Web Services

·                 WLS端,在为DotNetService 提供了WSDL URL后,用WebLlogic clientgen ant task生成一个clientjar

·                 testclient,对JAVA Stub进行一次调用。

  WebLogic Server

  .NET Server

  .NET Web Service

  WLS Client

         // STOCK TRADE WEB SERVICE

         // The Stock Trade web service executes a trade and returns result.

          [WebMethod]

          public bool execute(string action, string symbol, int quantity)

          {

                           if(action == null) {

                             Console.WriteLine("action null");

                        return false;

                                         }

                   if(symbol == null) {

                           Console.WriteLine("symbol null");

                          return false;

                                         }

                    if(action.Equals("BUY"))

                            Console.WriteLine("BUYING quantity: "+ quantity + " of symbol:" + symbol);

                    else if(action.Equals("SELL"))

                    Console.WriteLine("SELLING quantity: "+ quantity + " of symbol:" + symbol);

                             else {

                    Console.WriteLine("INVALID action: "+ action);

                    return false;

                                         }              

                             return true;

                                }

代码摘录.NET Web Services

上面摘录的一段代码是Stock Trade Web Services它是前面所设计的WLS Web Services.NET版。它用与JAVA非常相似的C#语言编写。文件名是“StockTrade.asmx.cs”

代码编写完成后,在WebLogic服务器上部署WLS客户程序,在.NET框架上部署.NET Web Services,验证客户端是否能调用Web Services

.NET客户端和WLS Web 服务器端

·                 创建一个WLS Web ServicesEAR文件)

·                 使用WLS Web 服务WSDL并通过运行wsdl.exe生成一个.NetClient Stub。这一过程将生成一个.cs文件,该文件包含对应于WSDL提供的Web Services的方法定义。

·                 另外一步是在Stub中定义一个新的构造函数,并将WSL URL作为一个参数。这一步是必须的,因为wsdl.exe所生成的Stub在缺省情况下指向USDL URL中的本地主机。

·                 创建一个.NetClient 类(另外一个.cs文件),该类实际上以WSDL URL作为构造函数参数。该类是一个代理类,它含有与Stub中所定义的相同的方法。.Net客户首先对Stub类进行了实例化,然后将方法的调用委托到Stub

  .NET Server

  .Net Client

  WebLogic Server

  WLS Web Service

  using System;

  namespace interop

  {

                /// <summary>

                /// Client for StockTrade web service

                /// </summary>

                public class StockTradeClient

                {

                                public StockTradeClient()

                                {

                                        //

                                        // TODO: Add constructor logic here

                                        //

                                }

                static void Main()

                {

                                string action = "BUY";

                string symbol = "BEAS";

                int quantity = 100;

                StockTradeService stService = new StockTradeService();

                Console.WriteLine("Stock Trade Service: ");

                bool result = stService.execute(action,symbol, quantity);

                Console.Write("Result of Stock Trade: ");

                Console.WriteLine(result.ToString());

                                }

                }

  }

代码摘录.NET客户端

上面摘录的的一段代码是对应于我们前面创建的Stock Trade Web Services.NET客户端代码,该段代码是用与JAVA语言极为相似的C#语言开发的。文件名是“StockTradeClient.cs”

代码编写完成后,在.NET框架上部署.NET客户端,并且在WebLogic Server上部署WLS Web Services,验证客户端是否能正确调用Web Services

下面的就是在WebLogic Server中显示的日志的格式:

  SELLING quantity: 300 of symbol:IBM

  execute() in webservices.stock.trade webservice has been invoked with following

  arguments:: action:SELL123 symbol:IBM quantity:300

  INVALID action: SELL123

  execute() in webservices.stock.trade webservice has been invoked with following

  arguments:: action:SELL symbol:IBM quantity:300

  SELLING quantity: 300 of symbol:IBM

  execute() in webservices.stock.trade webservice has been invoked with following

  arguments:: action:SELL123 symbol:IBM quantity:300

  INVALID action: SELL123


结束语

通过将所讨论的测试方法集成到 Web 服务开发过程中,我们就可以确保Web Services服务器能够良好处理可能类型和数量的客户端请求,而且Web Services的客户端也能正确地访问和检索服务所提供的任何数据。

您可以从开发流程中的任何一点开始实施所讨论的方法,但如果您较早的开始测试,那么您防止错误以及发现错误的能力就强。通常,错误发现得越早,其解决就越早,而且也越有可能避免因创建与有问题模块交互的代码或组件而在不经意中使问题变得更为糟糕的情况,也越有可能避免在其他服务器或者客户中重用有问题的模块。


注:
文章来自:http://dev2dev.bea.com.cn/techdoc/200408234.html
作者:Abhijit PatilSeetharam Param

posted @ 2006-09-18 15:51 逍遥草 阅读(344) | 评论 (0)编辑 收藏
JUnit入门
作者:佚名    来自:未知

  一、简介

  JUnit是一个开源的java单元测试框架。在1997年,由 Erich Gamma 和 Kent Beck 开发完成。这两个牛人中 Erich Gamma 是 GOF 之一;Kent Beck 则在 XP 中有重要的贡献(你觉得眼熟一点都不奇怪)。
  正如常言道:“麻雀虽小,五脏俱全。” JUnit设计的非常小巧,但是功能却非常强大。
  下面是JUnit一些特性的总结:
  1) 提供的API可以让你写出测试结果明确的可重用单元测试用例
  2) 提供了三种方式来显示你的测试结果,而且还可以扩展
  3) 提供了单元测试用例成批运行的功能
  4) 超轻量级而且使用简单,没有商业性的欺骗和无用的向导
  5) 整个框架设计良好,易扩展 
  对不同性质的被测对象,如Class,Jsp,Servlet,Ejb等,Junit有不同的使用技巧。由于本文的性质,以下仅以Class测试为例。

  二、下载

  点击http://www.junit.org可以下载到最新版本的JUnit,本文使用的为3.8.1版。至于安装或者配置之类,你只需要轻松的将下载下来的压缩包中的jar文件,放到你工程的classpath中就可以了。
  这样,你的系统中就可以使用JUnit编写单元测试代码了(是不是很简单)!

  三、HelloWorld

  记得在几乎每本语言教学书上都能找到HelloWorld这个入门代码。今天在这里,我们也从一个简单到根本不用单元测试的例子入手。这是一个只会做两数加减的超级简单的计算器(小学一年级必备极品)。代码如下:

public class SampleCalculator
{
       public int add(int augend , int addend)
       {
              return augend + addend ;
       }

       public int subtration(int minuend , int subtrahend)

       {

              return minuend - subtrahend ;

       }

}

  将上面的代码编译通过。下面就是我为上面程序写的一个单元测试用例:

//请注意这个程序里面类名和方法名的特征
import junit.framework.TestCase;
public class TestSample extends TestCase

{

       public void testAdd()

       {     

SampleCalculator calculator = new SampleCalculator();   

              int result = calculator.add(50 , 20);

              assertEquals(70 , result);

       }

       public void testSubtration()

       {

              SampleCalculator calculator = new SampleCalculator();

              int result = calculator.subtration(50 , 20);

              assertEquals(30 , result);

       }

}

  好了,在DOS命令行里面输入javac  TestSample.java 将测试类编译通过。然后再输入 java  junit.swingui.TestRunner TestSample 运行测试类,你会看到如下的窗口。

  绿色说明单元测试通过,没有错误产生;如果是红色的,则就是说测试失败了。这样一个简单的单元测试就完成了.

  按照框架规定:编写的所有测试类,必须继承自junit.framework.TestCase类;里面的测试方法,命名应该以Test开头,必须是public void 而且不能有参数;而且为了测试查错方便,尽量一个TestXXX方法对一个功能单一的方法进行测试;使用assertEquals等junit.framework.TestCase中的断言方法来判断测试结果正确与否。

  你可以对比着上面测试类中的实现来体会下规定——很简单!而且你在这个测试类中有加入多少个测试方法,就会运行多少个测试方法。

  四、向前一步

  学完了HelloWorld,你已经可以编写标准的单元测试用例了。但是还有一些细节,这里还要说明一下。不要急,很快的!
  另外你是否注意到,上面弹出窗口的一个细节,在绿条下面有Errors、Failures统计。这两者有何区别呢?
  Failures作为单元测试所期望发生的错误,它预示你的代码有bug,不过也可能是你的单元测试代码有逻辑错误(注意是逻辑错误)。Errors不是你所期待的,发生了Error你可以按照下面的顺序来检查:

  检查测试所需的环境,如:数据库连接

  检查单元测试代码

  检查你的系统代码

  五、成批运行test case

  这是前面提到的JUnit特性之一。它方便于系统单元测试的成批运行。使用起来也是非常简单,先看下使用代码:

import junit.framework.Test;

import junit.framework.TestSuite;

public class TestAll{

    public static Test suite(){

        TestSuite suite = new TestSuite("TestSuite Test");

        suite.addTestSuite( TestSample.class);

        return suite;

    }

}

  这个测试程序的编译、运行,和上面TestSample的方式是一样的。

  javac  TestAll.java

  java  junit.swingui.TestRunner TestAll

  怎么样?这样你在suite方法里面添加几个TestCase就会运行几个,而且它也可以添加TestSuite来将小一点的集合加入大的集合中来,方便了对于不断增加的TestCase的管理和维护。

  你觉得suite方法的作用是不是于java应用程序的main很类似?并且这里的suite必须严格遵守上面的写法!
本文引自:http://www.javafan.net/article/20051227090707319.html

posted @ 2006-09-15 14:47 逍遥草 阅读(343) | 评论 (0)编辑 收藏
Connector的选择
  选择合适的Connector对于性能、配置的方便性有很重要的影响,目前大致上有JK1。x, JK2, mod_webapp三种connector可以使用。 JK使用比较广泛。JK2是JK1.x的改进,比较新。但是不太容易配置,相关的文档也比较少。此外,JK可以支持其他Web服务器和tomcat的集成。 但mod_webapp不支持。 因此,目前JK1.x是最好的选择。
  获得JK
  
  使用二进制版本
  如果你对手工编译源代码心有余悸,使用二进制版本也许是个明智的选择。你可以从http://apache。linuxforum。net/dist/jakarta/tomcat-connectors/jk/binaries/下载JK1.x的最新版本。
  然而,不幸的是二进制版本的JK和Apache的版本是捆绑在一起的,如果你使用了比较新的Apache(比如httpd-2.0.29)的话,往往很难找到对应的二进制版本的JK。
  
  手工编译源代码
  对于不同的操作系统和Apache的版本,如果没有预编译好的JK,则需要进行手工编译。除了Linux以外,其他操作系统一般不会安装编译环境。这时你还需要安装编译器。典型的例子是在Solaris上安装GCC,或是在Windows上安装Visual C++。另外,通常Open Source的软件一般都是用GNU的autoconf、automake生成自动配置脚本和Makefile的,JK也不例外。除了Linux以外的Unix系统中的make不一定能够兼容这些脚本。 所以如果你碰到这些问题就需要安装gmake。下面以Solaris8为例说明如何安装配置编译环境:
  在Solaris8中系统自带的make不能兼容automake产生的某些Makefile。
  需要的软件包:
  gcc-3.3-sol9-sparc-local.gz
  make-3.80-sol8-sparc-local.tar.gz
  所有需要的软件包都可以在www.sunfreeware.com上下载到。
  解压缩:
  代码:
  $gunzip gcc-3.3-sol9-sparc-local.gz
  $gunzip make-3.80-sol8-sparc-local.gz
  
  用pkgadd安装,需要root权限:
  代码:
  #pkgadd -d gcc-3.3-sol9-sparc-local
  #pkgadd -d make-3.80-sol8-sparc-local
  用pkgadd安装后,通常gcc, make会被安装在/usr/local/bin目录下。这是需要让gmake
  成为系统默认的make。检查PATH环境变量,确保/usr/local/bin目录的位置在Solaris8自带的make的bin之前:
  代码:
  $which make
  /usr/ccs/bin/make
  $echo $PATH
  /usr/bin:/usr/ccs/bin:/usr/local/bin
  
  如果发现gmake还不是系统默认的make,可以修改/etc/profile调整PATH。但有一种更简单有效的方法,在/usr/bin目录下建一个到/usr/local/bin/make的符号连接make,这样就能使gmake成为系统默认的make了:
  代码:
  # cd /usr/bin
  # ln -s /usr/local/bin/make make
  同样的技巧可以解决一些Perl脚本对perl解释器可执行文件路径引用的不正确。如某个perl脚本的头信息有#!/usr/local/bin/perl -w但Perl在系统上被安装在/usr/bin/目录下。这时需要在
  /usr/local/bin/下建立一个到/usr/bin/perl的符号连接perl。
  编译完JK后,把它安装到apache中去,执行:
  代码:
  # make install
  如果不成功,可以手工把mod_jk.so拷贝到apache的modules目录下。
  配置
  在具体动手配置之前应该考虑一下你集成的目标:仅仅是简单的把某个subcontext由tomcat处理,还是更高层次的动态/静态内容整合?是否允许HTTPS的转发;是否要进行负载平衡?具体配置的复杂度会因你的集成目标不同而大相径庭。
  
  假定我们的集成目标是:
  1. 所有的静态资源由Apache处理
  2. 所有的动态资源由Tomcat处理
  配置Tomcat
  apache和tomcat整合大致上有三种方式:
  1. 在apache进程中运行tomcat来处理动态内容
  2. 通过ajp13协议,apache将动态内容的请求转发给tomcat
  3. 使用本地高速Unix domain socket,apache将动态内容的请求转发给tomcat
  
  方式2可以将apache和tomcat分布在不同的机器上,从而可以实现负载平衡。方式3速度比较快,当apache和tomcat分布在相同的机器上时可以考虑使用。
  本文以方式2的为例说明tomcat和apache的集成。
  为了能处理ajp13请求,tomcat需要起一个服务。 这是通过在tomcat的server.xml中定义一个Connector来实现的。 在最新的tomcat4.1.30版本中该Connector默认情况下是启用的。如果没有启用在server.xml加入
  代码:
    <Connector className="org。apache。coyote。tomcat4。CoyoteConnector"
          port="8009" minProcessors="5" maxProcessors="75"
          enableLookups="true" redirectPort="8443"
          acceptCount="10" debug="0" connectionTimeout="20000"
          useURIValidationHack="false"
          protocolHandlerClassName="org.apache.jk.server.JkCoyoteHandler"/>
  
  启动tomcat, 检查ajp13服务是否运行
  netstat -a | grep 8009
  或则查看tomcat标准输出上是否有类似的输出:
  代码:
  info: JK2: ajp13 listening on /0.0.0.0:8009
  2004-5-22 14:50:35 org.apache.jk.server.JkMain start
  info: Jk running ID=0 time=20/200 config=D:\Tomcat4.1\conf\jk2.properties
  
  配置Apache
  配置完Tomcat后,进行Apache的配置。首先,我们需要确定整个web应用所在的context,确定了context也就能确定用户通过什么样的URL可以访问该web应用。比如,网站为www.example.com, 如果web应用的context为purchase,那么用户可以通过URL http://www.example.com/purchase访问该应用;如果web应用的context为/,那么用户可以通过URL http://www.example.com访问该应用。一般而言,将web应用的context设定为/可以方便用户。如果存在多个独立的应用,可以考虑把它们放到不同的子context中去。下面介绍把应用context设为/情况下如何配置,其他情况类似。将jk的配置放在一个独立的文件里,然后在httpd。conf中Include该文件即可。
  第一步,让apache加载mod_jk:
  代码:
  #mod jk for tomcat-apache integration
  LoadModule jk_module modules/mod_jk.so
  
  把应用context映射到存放该应用静态资源的目录:
  代码:
  # Static files in the examples webapp are served by apache
  Alias / /www/tomcat4。1/webapps/ROOT/ 
  
  同时,因为现在静态资源不是由tomcat处理了,所以出于安全考虑和遵守JSP/Servlet规范需要禁止对WEB-INF子目录的访问:
  代码:
  # The following line prohibits users from directly access WEB-INF
  <Location "ROOT/WEB-INF/">
   AllowOverride None
   deny from all
  </Location>
  
  在集成的调试阶段可以考虑允许目录列表功能:
  代码:
  <Directory "/www/tomcat4。1/webapps/ROOT">
    AllowOverride FileInfo AuthConfig Limit Indexes
    Options MultiViews Indexes SymLinksIfOwnerMatch IncludesNoExec
  </Directory>
  
  接下来一步告诉apache哪些动态内容应该让tomcat处理,为了确定动态内容URL的特征,应该把web.xml中的所有servlet mapping中出现的URL模式在jk.conf中声明:
  代码:
  JkMount /BaseServlet worker1
  JkMount /Servlet/* worker1
  JkMount /ProductUploadServlet worker1
  JkMount /upload worker1
  JkMount /test worker1
  JkMount /*.jsp worker1
  JkMount /*.do worker1
  
  其它可能需要修改的配置
  配置项 说明
  JkWorkersFile 指定jk workers.properties的位置,如果是相对路径,则假定在apache的ServerRoot目录下
  JkLogFile 指定jk log文件的位置,如果是相对路径,则假定在apache的ServerRoot目录下
  JkLogLevel 指定jk log的级别有效的选项有:debug/error/info
  JkLogStampFormat 指定log中的时间格式,使用c函数strftime()的格式字符串语法
  
  总结Tomcat和Apache集成时通常需要一下步骤:
  1. 决定使用哪种connector
  2. 获得connector,如果没有现成的二进制的connector,则需要手工编译,根据操作系统的不同可能还要设置编译环境。
  3. 配置tomcat
  4. 配置apache,确定context,将context对应到应用的顶层目录。根据web.xml中的servlet映射把所有的动态内容的url模式配置在apache中
  5. 测试
  
  附录
  一个完整的配置例子:
  代码:
  #mod jk for tomcat-apache integration
  LoadModule jk_module modules/mod_jk.so
  
  JkWorkersFile conf/workers.properties
  # Where to put jk logs
  
  JkLogFile logs/mod_jk。log
  # Set the jk log level [debug/error/info]
  JkLogLevel debug
  
  # Select the log format
  JkLogStampFormat "[%Y-%m-%d %H:%M:%S] "
  
  # JkOptions indicate to send SSL KEY SIZE,
  JkOptions +ForwardKeySize +ForwardURICompat +ForwardURICompatUnparsed -ForwardDirectories
  
  # JkRequestLogFormat set the request format
  JkRequestLogFormat "%w %V %T"
  
  # Static


本文引用地址:http://www.uplinux.net/article/2006/0703/article_963.html

posted @ 2006-09-12 11:41 逍遥草 阅读(353) | 评论 (0)编辑 收藏
仅列出标题
共5页: 1 2 3 4 5