??xml version="1.0" encoding="utf-8" standalone="yes"?>亚洲中文字幕无码一久久区,亚洲今日精彩视频,久久噜噜噜久久亚洲va久http://www.tkk7.com/kuxiaoku/收藏zh-cnSat, 10 May 2025 20:25:22 GMTSat, 10 May 2025 20:25:22 GMT60Java正则表达式详?/title><link>http://www.tkk7.com/kuxiaoku/archive/2007/07/21/131668.html</link><dc:creator>苦笑?/dc:creator><author>苦笑?/author><pubDate>Sat, 21 Jul 2007 14:18:00 GMT</pubDate><guid>http://www.tkk7.com/kuxiaoku/archive/2007/07/21/131668.html</guid><wfw:comment>http://www.tkk7.com/kuxiaoku/comments/131668.html</wfw:comment><comments>http://www.tkk7.com/kuxiaoku/archive/2007/07/21/131668.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/kuxiaoku/comments/commentRss/131668.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/kuxiaoku/services/trackbacks/131668.html</trackback:ping><description><![CDATA[<strong>仙h掌工作室</strong><br>如果你曾l用qPerl或Q何其他内建正则表辑ּ支持的语aQ你一定知道用正则表达式处理文本和匚w模式是多么简单。如果你不熟悉这个术语,那么“正则表达?#8221;QRegular ExpressionQ就是一个字W构成的Ԍ它定义了一个用来搜索匹配字W串的模式? <table align="center" width="620"> <tbody> <tr> <td class="a14"> 许多语言Q包括Perl、PHP、Python、JavaScript和JScriptQ都支持用正则表辑ּ处理文本Q一些文本编辑器用正则表辑ּ实现? U?#8220;搜烦-替换”功能。那么Java又怎样呢?本文写作Ӟ一个包含了用正则表辑ּq行文本处理的Java规范需求(Specification RequestQ已l得到认可,你可以期待在JDK的下一版本中看到它?</td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> 然而,如果现在需要用正则表辑ּQ又该怎么办呢Q你可以从Apache.org下蝲源代码开攄Jakarta-ORO库。本文接下来的内容先要地介绍正则表达式的入门知识Q然后以Jakarta-ORO APIZ介绍如何使用正则表达式?</td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> <strong><font size="4"> 一、正则表辑ּ基础知识</font></strong> </td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> 我们先从单的开始。假设你要搜索一个包含字W?#8220;cat”的字W串Q搜索用的正则表辑ּ是“cat”。如果搜索对大小写不敏感Q单?#8220;catalog”?#8220;Catherine”?#8220;sophisticated”都可以匹配。也是_ </td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> <img src="http://www.ccw.com.cn/htm/app/aprog/01_7_31_4_a.jpg" border="0"> </td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> <strong> 1.1 句点W号</strong> </td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> 假设你在玩英文拼字游戏,惌扑և三个字母的单词,而且q些单词必须?#8220;t”字母开_?#8220;n”字母l束。另外,假设有一本英文字典,你可以用正则表达? 搜烦它的全部内容。要构造出q个正则表达式,你可以用一个通配W——句点符?#8220;.”。这P完整的表辑ּ是“t.n”Q它匚w“tan”? “ten”?#8220;tin”?#8220;ton”Q还匚w“t#n”?#8220;tpn”甚至“t n”Q还有其他许多无意义的组合。这是因为句点符号匹配所有字W,包括I格、Tab字符甚至换行W: </td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> <img src="http://www.ccw.com.cn/htm/app/aprog/01_7_31_4_b.jpg" border="0"> </td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> <strong> 1.2 ҎL?/strong> </td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> Z解决句点W号匚w范围q于q泛q一问题Q你可以在方括号Q?#8220;[]”Q里面指定看来有意义的字W。此Ӟ只有Ҏ号里面指定的字符才参与匹配。也是 _正则表达?#8220;t[aeio]n”只匹?#8220;tan”?#8220;Ten”?#8220;tin”?#8220;ton”。但“Toon”不匹配,因ؓ在方括号之内你只能匹配单个字 W: </td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> <img src="http://www.ccw.com.cn/htm/app/aprog/01_7_31_4_c.jpg" border="0"></td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> <strong> 1.3 “?#8221;W号</strong> </td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> 如果除了上面匚w的所有单词之外,你还惌匚w“toon”Q那么,你可以?#8220;|”操作W?#8220;|”操作W的基本意义是“?#8221;q算。要匚w “toon”Q?#8220;t(a|e|i|o|oo)n”正则表达式。这里不能用方扩号Q因为方括号只允许匹配单个字W;q里必须使用圆括?#8220;()”。圆? 可可以用来分组Q具体请参见后面介绍?</td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> <img src="http://www.ccw.com.cn/htm/app/aprog/01_7_31_4_d.jpg" border="0"> </td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> <strong> 1.4 表示匚wơ数的符?/strong> </td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> 表一昄了表C匹配次数的W号Q这些符L来确定紧靠该W号左边的符号出现的ơ数Q?</td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> <p align="center"><img src="http://www.ccw.com.cn/htm/app/aprog/01_7_31_4n.jpg" border="0"></p> </td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> 假设我们要在文本文g中搜索美国的C会安全L。这个号码的格式?99-99-9999。用来匹配它的正则表辑ּ如图一所C。在正则表达式中Q连字符 Q?#8220;-”Q有着Ҏ的意义,它表CZ个范_比如??。因此,匚wC会安全L中的q字W号Ӟ它的前面要加上一个{义字W?#8220;\”?</td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> <p align="center"><img src="http://www.ccw.com.cn/htm/app/aprog/01_7_31_4a.gif" border="0"> </p> </td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> <p align="center"> 图一Q匹配所?23-12-1234形式的社会安全号?/p> </td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> 假设q行搜烦的时候,你希望连字符号可以出玎ͼ也可以不出现——即Q?99-99-9999?99999999都属于正的格式。这Ӟ你可以在q字W号后面加上“Q?#8221;数量限定W号Q如图二所C: </td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> <p align="center"><img src="http://www.ccw.com.cn/htm/app/aprog/01_7_31_4b.gif" border="0"> </p> </td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> <p align="center"> 图二Q匹配所?23-12-1234?23121234形式的社会安全号?/p> </td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> 下面我们再来看另外一个例子。美国汽车牌照的一U格式是四个数字加上二个字母。它的正则表辑ּ前面是数字部?#8220;[0-9]{4}”Q再加上字母部分“[A-Z]{2}”。图三显CZ完整的正则表辑ּ?</td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> <p align="center"><img src="http://www.ccw.com.cn/htm/app/aprog/01_7_31_4c.gif" border="0"> </p> </td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> <p align="center"> 图三Q匹配典型的国汽R牌照LQ如8836KV</p> </td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> 1.5 “?#8221;W号 </td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> “^”W号UCؓ“?#8221;W号。如果用在方括号内,“^”表示不想要匹配的字符。例如,囑֛的正则表辑ּ匚w所有单词,但以“X”字母开头的单词除外?</td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> <p align="center"><img src="http://www.ccw.com.cn/htm/app/aprog/01_7_31_4d.gif" border="0"> </p> </td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> <p align="center"> 囑֛Q匹配所有单词,?#8220;X”开头的除外</p> </td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> 1.6 圆括号和I白W号 </td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> 假设要从格式?#8220;June 26, 1951”的生日日期中提取出月份部分,用来匚w该日期的正则表达式可以如图五所C: </td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> <p align="center"><img src="http://www.ccw.com.cn/htm/app/aprog/01_7_31_4e.gif" border="0"> </p> </td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> <p align="center"> 图五Q匹配所有Moth DD,YYYY格式的日?/p> </td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> 新出现的“\s”W号是空白符P匚w所有的I白字符Q包括Tab字符。如果字W串正确匚wQ接下来如何提取出月份部分呢Q只需在月份周围加上一个圆括号创徏一个组Q然后用ORO APIQ本文后面详l讨论)提取出它的倹{修改后的正则表辑ּ如图六所C: </td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> <p align="center"><img src="http://www.ccw.com.cn/htm/app/aprog/01_7_31_4f.gif" border="0"> </p> </td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> <p align="center"> 囑օQ匹配所有Month DD,YYYY格式的日期,定义月䆾gؓW一个组</p> </td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> <strong> 1.7 其它W号</strong> </td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> 为简便v见,你可以用一些ؓ常见正则表达式创建的快捷W号。如表二所C: </td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> 表二Q常用符?</td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> <p align="center"><img src="http://www.ccw.com.cn/htm/app/aprog/01_7_31_4o.jpg" border="0"> </p> </td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> 例如Q在前面C会安全L的例子中Q所有出?#8220;[0-9]”的地Ҏ们都可以使用“\d”。修改后的正则表辑ּ如图七所C: </td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> <p align="center"><img src="http://www.ccw.com.cn/htm/app/aprog/01_7_31_4g.gif" border="0"> </p> </td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> <p align="center">图七Q匹配所?23-12-1234格式的社会安全号?/p> </td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> <strong><font size="4"> 二、Jakarta-ORO?/font></strong> </td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> 有许多源代码开攄正则表达式库可供JavaE序员用,而且它们中的许多支持Perl 5兼容的正则表辑ּ语法。我在这里选用的是Jakarta-ORO正则表达式库Q它是最全面的正则表辑ּAPI之一Q而且它与Perl 5正则表达式完全兼宏V另外,它也是优化得最好的API之一?</td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> Jakarta-ORO库以前叫做OROMatcherQDaniel Savarese大方地把它赠送给了Jakarta Project。你可以按照本文最后参考资源的说明下蝲它?</td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> 我首先将要介l用Jakarta-ORO库时你必d建和讉K的对象,然后介绍如何使用Jakarta-ORO API?</td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> <strong> ?PatternCompiler对象</strong> </td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> 首先Q创Z个Perl5Compilercȝ实例Qƈ把它赋值给PatternCompiler接口对象。Perl5Compiler是PatternCompiler接口的一个实玎ͼ允许你把正则表达式编译成用来匚w的Pattern对象?</td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> <img src="http://www.ccw.com.cn/htm/app/aprog/01_7_31_4_e.jpg" border="0"> </td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> <strong> ?Pattern对象</strong> </td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> 要把正则表达式编译成Pattern对象Q调用compiler对象的compile()ҎQƈ在调用参C指定正则表达式。例如,你可以按照下面这U方式编译正则表辑ּ“t[aeio]n”Q?</td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> <img src="http://www.ccw.com.cn/htm/app/aprog/01_7_31_4_f.jpg" border="0"> </td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> 默认情况下,~译器创Z个大写敏感的模式(patternQ。因此,上面代码~译得到的模式只匚w“tin”?#8220;tan”?“ten”?#8220;ton”Q但不匹?#8220;Tin”?#8220;taN”。要创徏一个大写不敏感的模式Q你应该在调用编译器的时候指定一个额外的参数Q?</td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> <img src="http://www.ccw.com.cn/htm/app/aprog/01_7_31_4_g.jpg" border="0"> </td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> 创徏好Pattern对象之后Q你可以通过PatternMatchercȝ该Pattern对象q行模式匚w?</td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> <strong> ?PatternMatcher对象</strong> </td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> PatternMatcher对象ҎPattern对象和字W串q行匚w查。你要实例化一个Perl5Matchercdƈ把结果赋值给 PatternMatcher接口。Perl5MatchercLPatternMatcher接口的一个实玎ͼ它根据Perl 5正则表达式语法进行模式匹配: </td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> <img src="http://www.ccw.com.cn/htm/app/aprog/01_7_31_4_h.jpg" border="0"> </td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> 使用PatternMatcher对象Q你可以用多个方法进行匹配操作,q些Ҏ的第一个参数都是需要根据正则表辑ּq行匚w的字W串Q?</td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> · boolean matches(String input, Pattern pattern)Q当输入字符串和正则表达式要_匚w时用。换句话_正则表达式必d整地描述输入字符丌Ӏ?</td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> · boolean matchesPrefix(String input, Pattern pattern)Q当正则表达式匹配输入字W串起始部分时用?</td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> · boolean contains(String input, Pattern pattern)Q当正则表达式要匚w输入字符串的一部分时用(卻I它必L一个子Ԍ?</td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> 另外Q在上面三个Ҏ调用中,你还可以用PatternMatcherInput对象作ؓ参数替代String对象Q这Ӟ你可以从字符串中最后一ơ匹? 的位|开始l进行匹配。当字符串可能有多个子串匚wl定的正则表辑ּӞ用PatternMatcherInput对象作ؓ参数很有用了。用 PatternMatcherInput对象作ؓ参数替代StringӞ上述三个Ҏ的语法如下: </td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> · boolean matches(PatternMatcherInput input, Pattern pattern) </td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> · boolean matchesPrefix(PatternMatcherInput input, Pattern pattern) </td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> · boolean contains(PatternMatcherInput input, Pattern pattern) </td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> <strong><font size="4"> 三、应用实?/font></strong> </td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> 下面我们来看看Jakarta-ORO库的一些应用实例?</td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> <strong> 3.1 日志文g处理</strong> </td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> dQ分析一个Web服务器日志文Ӟ定每一个用戯在网站上的时间。在典型的BEA WebLogic日志文g中,日志记录的格式如下: </td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> <img src="http://www.ccw.com.cn/htm/app/aprog/01_7_31_4_i.jpg" border="0"></td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> 分析q个日志记录Q可以发玎ͼ要从q个日志文g提取的内Ҏ两项QIP地址和页面访问时间。你可以用分l符P圆括P从日志记录提取出IP地址和时间标记?</td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> 首先我们来看看IP地址。IP地址?个字节构成,每一个字节的值在0?55之间Q各个字节通过一个句点分隔。因此,IP地址中的每一个字节有臛_一个、最多三个数字。图八显CZ为IP地址~写的正则表辑ּQ?</td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> <p align="center"><img src="http://www.ccw.com.cn/htm/app/aprog/01_7_31_4h.gif" border="0"> </p> </td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> <p align="center"> 囑օQ匹配IP地址</p> </td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> IP地址中的句点字符必须q行转义处理Q前面加?#8220;\”Q,因ؓIP地址中的句点h它本来的含义Q而不是采用正则表辑ּ语法中的Ҏ含义。句点在正则表达式中的特D含义本文前面已l介l?</td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> 日志记录的时间部分由一Ҏ括号包围。你可以按照如下思\提取出方括号里面的所有内容:首先搜烦起始Ҏ号字W(“[”Q,提取出所有不过l束Ҏ号字W(“]”Q的内容Q向前寻扄x到结束方括号字符。图九显CZq部分的正则表达式?</td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> <p align="center"><img src="http://www.ccw.com.cn/htm/app/aprog/01_7_31_4i.gif" border="0"> </p> </td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> <p align="center"> 图九Q匹配至一个字W,直至扑ֈ“]”</p> </td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> 现在Q把上述两个正则表达式加上分l符P圆括P后合q成单个表达式,q样可以从日志记录提取出IP地址和时间。注意,Z匚w“- -”Q但不提取它Q,正则表达式中间加入了“\s-\s-\s”。完整的正则表达式如囑֍所C?</td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> <p align="center"><img src="http://www.ccw.com.cn/htm/app/aprog/01_7_31_4j.gif" border="0"> </p> </td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> <p align="center"> 囑֍Q匹配IP地址和时间标?/p> </td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> 现在正则表达式已l编写完毕,接下来可以编写用正则表辑ּ库的Java代码了?</td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> Z用Jakarta-ORO库,首先创徏正则表达式字W串和待分析的日志记录字W串Q?</td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> <img src="http://www.ccw.com.cn/htm/app/aprog/01_7_31_4_j.jpg" border="0"> </td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> q里使用的正则表辑ּ与图十的正则表达式差不多完全相同Q但有一点例外:在Java中,你必d每一个向前的斜杠Q?#8220;\”Q进行{义处理。图十不? Java的表CŞ式,所以我们要在每?#8220;\”前面加上一?#8220;\”以免出现~译错误。遗憄是,转义处理q程很容易出现错误,所以应该小心}慎。你可以首先 输入未经转义处理的正则表辑ּQ然后从左到右依ơ把每一?#8220;\”替换?#8220;\\”。如果要复检Q你可以试着把它输出到屏q上?</td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> 初始化字W串之后Q实例化PatternCompiler对象Q用PatternCompiler~译正则表达式创Z个Pattern对象Q?</td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> <img src="http://www.ccw.com.cn/htm/app/aprog/01_7_31_4_k.jpg" border="0"> </td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> 现在Q创建PatternMatcher对象Q调用PatternMatcher接口的contain()Ҏ查匹配情况: </td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> <img src="http://www.ccw.com.cn/htm/app/aprog/01_7_31_4_l.jpg" border="0"> </td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> 接下来,利用PatternMatcher接口q回的MatchResult对象Q输出匹配的l。由于logEntry字符串包含匹配的内容Q你可以看到cd下面的输出: </td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> <img src="http://www.ccw.com.cn/htm/app/aprog/01_7_31_4_m.jpg" border="0"></td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> <strong> 3.2 HTML处理实例一</strong> </td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> 下面一个Q务是分析HTML面内FONT标记的所有属性。HTML面内典型的FONT标记如下所C: </td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> <font color="red" face="Arial, serif" size="+2"> </font><img src="http://www.ccw.com.cn/htm/app/aprog/01_7_31_4_n.jpg" border="0"> </td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> E序按照如下Ş式,输出每一个FONT标记的属性: </td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> <img src="http://www.ccw.com.cn/htm/app/aprog/01_7_31_4_o.jpg" border="0"> </td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> 在这U情况下Q我你用两个正则表辑ּ。第一个如囑֍一所C,它从字体标记提取?#8220;"face="Arial, Serif" size="+2" color="red"”?</td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> <p align="center"><img src="http://www.ccw.com.cn/htm/app/aprog/01_7_31_4k.gif" border="0"> </p> </td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> <p align="center"> 囑֍一Q匹配FONT标记的所有属?/p> </td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> W二个正则表辑ּ如图十二所C,它把各个属性分割成名字-值对?</td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> <p align="center"><img src="http://www.ccw.com.cn/htm/app/aprog/01_7_31_4l.gif" border="0"> </p> </td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> <p align="center"> 囑֍二:匚w单个属性,q把它分割成名字-值对</p> </td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> 分割l果为: </td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> <img src="http://www.ccw.com.cn/htm/app/aprog/01_7_31_4_p.jpg" border="0"> </td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> 现在我们来看看完成这个Q务的Java代码。首先创Z个正则表辑ּ字符Ԍ用Perl5Compiler把它们编译成Pattern对象。编译正则表? 式的时候,指定Perl5Compiler.CASE_INSENSITIVE_MASK选项Q得匹配操作不区分大小写?</td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> 接下来,创徏一个执行匹配操作的Perl5Matcher对象?</td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> <img src="http://www.ccw.com.cn/htm/app/aprog/01_7_31_4_q.jpg" border="0"> </td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> 假设有一个Stringcd的变量htmlQ它代表了HTML文g中的一行内宏V如果html字符串包含FONT标记Q匹配器返回true。此Ӟ你可以用匚w器对象返回的MatchResult对象获得W一个组Q它包含了FONT的所有属性: </td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> <img src="http://www.ccw.com.cn/htm/app/aprog/01_7_31_4_r.jpg" border="0"> </td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> 接下来创Z个PatternMatcherInput对象。这个对象允怽从最后一ơ匹配的位置开始l进行匹配操作,因此Q它很适合于提取FONT? 记内属性的名字-值对。创建PatternMatcherInput对象Q以参数形式传入待匹配的字符丌Ӏ然后,用匹配器实例提取出每一个FONT的属 性。这通过指定PatternMatcherInput对象Q而不是字W串对象Qؓ参数Q反复地调用PatternMatcher对象的contains ()Ҏ完成。PatternMatcherInput对象之中的每一ơP代将把它内部的指针向前移动,下一ơ检将从前一ơ匹配位|的后面开始?</td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> 本例的输出结果如下: </td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> <img src="http://www.ccw.com.cn/htm/app/aprog/01_7_31_4_s.jpg" border="0"> </td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> <strong> 3.3 HTML处理实例?/strong> </td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> 下面我们来看看另一个处理HTML的例子。这一ơ,我们假定Web服务器从widgets.acme.comUd了newserver.acme.com。现在你要修改一些页面中的链接: </td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> <img src="http://www.ccw.com.cn/htm/app/aprog/01_7_31_4_t.jpg" border="0"> </td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> 执行q个搜烦的正则表辑ּ如图十三所C: </td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> <p align="center"><img src="http://www.ccw.com.cn/htm/app/aprog/01_7_31_4m.gif" border="0"> </p> </td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> <p align="center"> 囑֍三:匚w修改前的链接</p> </td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> 如果能够匚wq个正则表达式,你可以用下面的内Ҏ换图十三的链接: </td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> <img src="http://www.ccw.com.cn/htm/app/aprog/01_7_31_4_u.jpg" border="0"></td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> 注意#字符的后面加上了$1。Perl正则表达式语法用$1?2{表C已l匹配且提取出来的组。图十三的表辑ּ把所有作Z个组匚w和提取出来的内容附加到链接的后面?</td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> 现在Q返回Java。就象前面我们所做的那样Q你必须创徏试字符Ԍ创徏把正则表辑ּ~译到Pattern对象所必需的对象,以及创徏一个PatternMatcher对象Q?img src="http://www.ccw.com.cn/htm/app/aprog/01_7_31_4_v.jpg" border="0"> </td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> 接下来,用com.oroinc.text.regex包Utilcȝsubstitute()静态方法进行替换,输出l果字符Ԍ </td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> <img src="http://www.ccw.com.cn/htm/app/aprog/01_7_31_4_w.jpg" border="0"> </td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> Util.substitute()Ҏ的语法如下: </td> </tr> </tbody> </table> <table align="center" height="17" width="620"> <tbody> <tr> <td class="a14" height="13"> <img src="http://www.ccw.com.cn/htm/app/aprog/01_7_31_4_x.jpg" border="0"> </td> </tr> </tbody> </table> <table align="center" width="620"> <tbody> <tr> <td class="a14"> q个调用的前两个参数是以前创建的PatternMatcher和Pattern对象。第三个参数是一个Substiution对象Q它军_了替换操作如 何进行。本例用的是Perl5Substitution对象Q它能够q行Perl5风格的替换。第四个参数是想要进行替换操作的字符Ԍ最后一个参数允 许指定是否替换模式的所有匹配子ԌUtil.SUBSTITUTE_ALLQ,或只替换指定的次数?</td> </tr> </tbody> </table> <strong>【结束语?/strong>? q篇文章中,我ؓ你介l了正则表达式的强大功能。只要正运用,正则表达式能够在字符串提取和文本修改中v到很大的作用。另外,我还介绍了如何在Java E序中通过Jakarta-ORO库利用正则表辑ּ。至于最l采用老式的字W串处理方式Q用StringTokenizerQcharAtQ和 substringQ,q是采用正则表达式,q就有待你自己决定了?img src ="http://www.tkk7.com/kuxiaoku/aggbug/131668.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/kuxiaoku/" target="_blank">苦笑?/a> 2007-07-21 22:18 <a href="http://www.tkk7.com/kuxiaoku/archive/2007/07/21/131668.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java 位运?/title><link>http://www.tkk7.com/kuxiaoku/archive/2007/06/16/124674.html</link><dc:creator>苦笑?/dc:creator><author>苦笑?/author><pubDate>Sat, 16 Jun 2007 10:13:00 GMT</pubDate><guid>http://www.tkk7.com/kuxiaoku/archive/2007/06/16/124674.html</guid><wfw:comment>http://www.tkk7.com/kuxiaoku/comments/124674.html</wfw:comment><comments>http://www.tkk7.com/kuxiaoku/archive/2007/06/16/124674.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.tkk7.com/kuxiaoku/comments/commentRss/124674.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/kuxiaoku/services/trackbacks/124674.html</trackback:ping><description><![CDATA[<p><strong>UMq算W?/strong></p> <p>    包括Q?br>    “>> 右移”Q?#8220;<< 左移”Q?#8220;>>> 无符号右U?#8221;</p> <p>例子Q?br>-5>>3=-1<br>1111 1111 1111 1111 1111 1111 1111 1011<br>1111 1111 1111 1111 1111 1111 1111 1111<br>其结果与 Math.floor((double)-5/(2*2*2)) 完全相同?/p> <p>-5<<3=-40<br>1111 1111 1111 1111 1111 1111 1111 1011<br>1111 1111 1111 1111 1111 1111 1101 1000 <br>其结果与 -5*2*2*2 完全相同?/p> <p>5>>3=0<br>0000 0000 0000 0000 0000 0000 0000 0101<br>0000 0000 0000 0000 0000 0000 0000 0000<br>其结果与 5/(2*2*2) 完全相同?/p> <p>5<<3=40<br>0000 0000 0000 0000 0000 0000 0000 0101<br>0000 0000 0000 0000 0000 0000 0010 1000<br>其结果与 5*2*2*2 完全相同?/p> <p>-5>>>3=536870911      <br>1111 1111 1111 1111 1111 1111 1111 1011<br>0001 1111 1111 1111 1111 1111 1111 1111</p> <p>无论正数、负敎ͼ它们的右UR左UR无W号右移 32 位都是其本nQ比?-5<<32=-5?5>>32=-5?5>>>32=-5?br>一个有的现象是,?1 左移 31 位再右移 31 位,其结果ؓ -1?br>0000 0000 0000 0000 0000 0000 0000 0001<br>1000 0000 0000 0000 0000 0000 0000 0000<br>1111 1111 1111 1111 1111 1111 1111 1111</p> <p><strong><br>位逻辑q算W?/strong></p> <p>    包括Q?br>    & 与;| 或;~ 非(也叫做求反)Q^ 异或</p> <p>    “& ?#8221;?#8220;| ?#8221;?#8220;~ ?#8221;是基本逻辑q算Q由此可以演变出“与非”?#8220;或非”?#8220;与或?#8221;复合逻辑q算?#8220;^ 异或”是一U特D的逻辑q算Q对它求反可以得?#8220;同或”Q所?#8220;同或”逻辑也叫“异或?#8221;逻辑?/p> <p>例子Q?br>5&3=1<br>0000 0000 0000 0000 0000 0000 0000 0101<br>0000 0000 0000 0000 0000 0000 0000 0011<br>0000 0000 0000 0000 0000 0000 0000 0001</p> <p>-5&3=1<br>1111 1111 1111 1111 1111 1111 1111 1011<br>0000 0000 0000 0000 0000 0000 0000 0011<br>0000 0000 0000 0000 0000 0000 0000 0011</p> <p>5|3=7<br>0000 0000 0000 0000 0000 0000 0000 0101<br>0000 0000 0000 0000 0000 0000 0000 0011<br>0000 0000 0000 0000 0000 0000 0000 0111</p> <p>-5|3=-5<br>1111 1111 1111 1111 1111 1111 1111 1011<br>0000 0000 0000 0000 0000 0000 0000 0011<br>1111 1111 1111 1111 1111 1111 1111 1011</p> <p>~5=-6<br>0000 0000 0000 0000 0000 0000 0000 0101<br>1111 1111 1111 1111 1111 1111 1111 1010</p> <p>~-5=4<br>1111 1111 1111 1111 1111 1111 1111 1011<br>0000 0000 0000 0000 0000 0000 0000 0100</p> <p>5^3=6<br>0000 0000 0000 0000 0000 0000 0000 0101<br>0000 0000 0000 0000 0000 0000 0000 0011<br>0000 0000 0000 0000 0000 0000 0000 0110</p> -5^3=-8<br>1111 1111 1111 1111 1111 1111 1111 1011<br>0000 0000 0000 0000 0000 0000 0000 0011<br>1111 1111 1111 1111 1111 1111 1111 1000<img src ="http://www.tkk7.com/kuxiaoku/aggbug/124674.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/kuxiaoku/" target="_blank">苦笑?/a> 2007-06-16 18:13 <a href="http://www.tkk7.com/kuxiaoku/archive/2007/06/16/124674.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Eclipse快速上手指南之使用ANThttp://www.tkk7.com/kuxiaoku/archive/2007/06/11/123389.html苦笑?/dc:creator>苦笑?/author>Mon, 11 Jun 2007 06:51:00 GMThttp://www.tkk7.com/kuxiaoku/archive/2007/06/11/123389.htmlhttp://www.tkk7.com/kuxiaoku/comments/123389.htmlhttp://www.tkk7.com/kuxiaoku/archive/2007/06/11/123389.html#Feedback0http://www.tkk7.com/kuxiaoku/comments/commentRss/123389.htmlhttp://www.tkk7.com/kuxiaoku/services/trackbacks/123389.html

Eclipse快速上手指南之使用ANT

2004-07-30 17:35 作者: 出处Q? J2ME开发网     Ant是Javaq_下非常棒的批处理命o执行E序Q能非常方便地自动完成编译,试Q打包,部v{等一pddQ大大提高开发效率。如果你现在q没有开始用AntQ那p赶快开始学习用,使自q开发水q上一个新台阶?br>

  Eclipse中已l集成了AntQ我们可以直接在Eclipse中运行Ant?br>
  以前面徏立的Hello工程ZQ创Z下目录结构:


  新徏一个build.xmlQ放在工E根目录下。build.xml定义了Ant要执行的批处理命令。虽然Ant也可以用其它文件名Q但是遵循标准能更开发更规范Q同时易于与别h交流?br>
  通常Qsrc存放Java源文Ӟclasses存放~译后的class文gQlib存放~译和运行用到的所有jar文gQweb存放JSP{web文gQdist存放打包后的jar文gQdoc存放API文档?br>
  然后在根目录下创建build.xml文gQ输入以下内容:

Q?xml version="1.0"?Q?br>Qproject name="Hello world" default="doc"Q?/font>

Q?-- properies --Q?br>Qproperty name="src.dir" value="src" /Q?br>Qproperty name="report.dir" value="report" /Q?br>Qproperty name="classes.dir" value="classes" /Q?br>Qproperty name="lib.dir" value="lib" /Q?br>Qproperty name="dist.dir" value="dist" /Q?br>Qproperty name="doc.dir" value="doc"/Q?/font>

Q?-- 定义classpath --Q?br>Qpath id="master-classpath"Q?br>Qfileset file="${lib.dir}/*.jar" /Q?br>Qpathelement path="${classes.dir}"/Q?br>Q?pathQ?/font>

Q?-- 初始化Q?--Q?br>Qtarget name="init"Q?br>Q?targetQ?/font>

Q?-- ~译 --Q?br>Qtarget name="compile" depends="init" description="compile the source files"Q?br>Qmkdir dir="${classes.dir}"/Q?br>Qjavac srcdir="${src.dir}" destdir="${classes.dir}" target="1.4"Q?br>Qclasspath refid="master-classpath"/Q?br>Q?javacQ?br>Q?targetQ?/font>

Q?-- 试 --Q?br>Qtarget name="test" depends="compile" description="run junit test"Q?br>Qmkdir dir="${report.dir}"/Q?br>Qjunit printsummary="on"
haltonfailure="false"
failureproperty="tests.failed"
showoutput="true"Q?br>Qclasspath refid="master-classpath" /Q?br>Qformatter type="plain"/Q?br>Qbatchtest todir="${report.dir}"Q?br>Qfileset dir="${classes.dir}"Q?br>Qinclude name="**/*Test.*"/Q?br>Q?filesetQ?br>Q?batchtestQ?br>Q?junitQ?br>Qfail if="tests.failed"Q?br>***********************************************************
**** One or more tests failed! Check the output ... ****
***********************************************************
Q?failQ?br>Q?targetQ?/font>

Q?-- 打包成jar --Q?br>Qtarget name="pack" depends="test" description="make .jar file"Q?br>Qmkdir dir="${dist.dir}" /Q?br>Qjar destfile="${dist.dir}/hello.jar" basedir="${classes.dir}"Q?br>Qexclude name="**/*Test.*" /Q?br>Qexclude name="**/Test*.*" /Q?br>Q?jarQ?br>Q?targetQ?/font>

Q?-- 输出api文档 --Q?br>Qtarget name="doc" depends="pack" description="create api doc"Q?br>Qmkdir dir="${doc.dir}" /Q?br>Qjavadoc destdir="${doc.dir}"
author="true"
version="true"
use="true"
windowtitle="Test API"Q?br>Qpackageset dir="${src.dir}" defaultexcludes="yes"Q?br>Qinclude name="example/**" /Q?br>Q?packagesetQ?br>QdoctitleQ<![CDATA[Qh1QHello, testQ?h1Q]]Q</doctitleQ?br>QbottomQ<![CDATA[QiQAll Rights Reserved.Q?iQ]]Q</bottomQ?br>Qtag name="todo" scope="all" description="To do:" /Q?br>Q?javadocQ?br>Q?targetQ?br>Q?projectQ?/font>

  以上xml依次定义了initQ初始化Q,compileQ编译)QtestQ测试)QdocQ生成文档)QpackQ打包)dQ可以作为模ѝ?br>
  选中Hello工程Q然后选择“Project”Q?#8220;Properties”Q?#8220;Builders”Q?#8220;New…”Q选择“Ant Build”Q?br>

填入NameQAnt_BuilderQBuildfileQbuild.xmlQBase DirectoryQ?{workspace_loc:/Hello}Q按“Browse Workspace”选择工程根目录)Q由于用Cjunit.jar包,搜烦Eclipse目录Q找到junit.jarQ把它复制到 Hello/lib目录下,q添加到Ant的Classpath中:


  然后在Builder面板中钩上Ant_BuildQ去掉Java BuilderQ?br>

  再次~译Q即可在控制台看到Ant的输出:

Buildfile: F:\eclipse-projects\Hello\build.xml

init:

compile:
[mkdir] Created dir: F:\eclipse-projects\Hello\classes
[javac] Compiling 2 source files to F:\eclipse-projects\Hello\classes


test:
[mkdir] Created dir: F:\eclipse-projects\Hello\report
[junit] Running example.HelloTest
[junit] Tests run: 1, Failures: 0, Errors: 0, Time elapsed: 0.02 sec


pack:
[mkdir] Created dir: F:\eclipse-projects\Hello\dist
[jar] Building jar: F:\eclipse-projects\Hello\dist\hello.jar


doc:
[mkdir] Created dir: F:\eclipse-projects\Hello\doc
[javadoc] Generating Javadoc
[javadoc] Javadoc execution
[javadoc] Loading source files for package example...
[javadoc] Constructing Javadoc information...
[javadoc] Standard Doclet version 1.4.2_04
[javadoc] Building tree for all the packages and classes...
[javadoc] Building index for all the packages and classes...
[javadoc] Building index for all classes...
[javadoc] Generating F:\eclipse-projects\Hello\doc\stylesheet.css...
[javadoc] Note: Custom tags that could override future standard tags: @todo. To avoid potential overrides, use at least one period character (.) in custom tag names.
[javadoc] Note: Custom tags that were not seen: @todo
BUILD SUCCESSFUL
Total time: 11 seconds

Ant依次执行初始化,~译Q测试,打包Q生成API文档一pddQ极大地提高了开发效率。将来开发J2EE目Ӟq可加入部v{Q务。ƈ且,即 q了Eclipse环境Q只要正安装了AntQ配|好环境变量ANT_HOME=QAnt解压目录Q,Path=…;%ANT_HOME%\binQ? 在命令行提示W下切换到Hello目录Q简单地键入ant卛_?img src ="http://www.tkk7.com/kuxiaoku/aggbug/123389.html" width = "1" height = "1" />

]]>
ant打包一?/title><link>http://www.tkk7.com/kuxiaoku/archive/2007/06/11/123388.html</link><dc:creator>苦笑?/dc:creator><author>苦笑?/author><pubDate>Mon, 11 Jun 2007 06:49:00 GMT</pubDate><guid>http://www.tkk7.com/kuxiaoku/archive/2007/06/11/123388.html</guid><wfw:comment>http://www.tkk7.com/kuxiaoku/comments/123388.html</wfw:comment><comments>http://www.tkk7.com/kuxiaoku/archive/2007/06/11/123388.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/kuxiaoku/comments/commentRss/123388.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/kuxiaoku/services/trackbacks/123388.html</trackback:ping><description><![CDATA[<table border="0" cellpadding="0" cellspacing="0" width="100%"> <tbody> <tr> <td valign="top"><span id="6y4m24s" class="arttitle">ant打包一?/span></td> </tr> <tr> <td class="details" align="right" valign="top">By  <a target="_blank" class="biuser">凌云?/a> 发表?2007-6-10 13:21:00  </td> </tr> <tr> <td class="artbody" valign="top"><br> <p>以前对于ant的用L避而不触,M为有炚w度,最q一直看我们目中的build.xml忽而觉得非常简单,也模仿着在我?a >www.javaedu.com</a>开发上使用了一下,非常不错Q以下是我的打包文gbuild.xmlQ?br><br><?xml version="1.0"?><br> <br><project name="payManager" default="all" basedir="."><br> <br> <property name="src.dir"       value="JavaSource" /><br> <property name="classes.dir"   value="WebContent/WEB-INF/classes" /><br> <property name="lib.dir"       value="WebContent/WEB-INF/lib" /><br> <property name="WebContent.dir"     value="WebContent" /><br> <br> <!--用于输出的时文件夹与打包的文g?-><br> <property name="temp.dir"     value="D:\temp" /><br> <property name="war.dir"      value="D:\war" /></p> <p> <!--对于不同环境的war包,使用不同的配|文?-><br> <property name="生.dir"     value="bak\生" /><br> <property name="开?dir"     value="bak\开? /><br> <br> <!-- 定义classpath --><br> <path id="master-classpath"><br>  <fileset file="${lib.dir}/*.jar" /><br>  <pathelement path="${classes.dir}" /><br> </path></p> <p> <target name="clean"> <br>  <delete dir="${temp.dir}" /><br>  <delete dir="${classes.dir}" /><br>  <delete file="${war.dir}/开?ROOT.war"/><br>  <delete file="${war.dir}/生/ROOT.war"/><br> </target></p> <p> <!-- 初始化Q?--><br> <target name="init" depends="clean"><br> </target></p> <p> <!-- ~译 --><br> <target name="compile" depends="init" description="compile the source files"><br>  <mkdir dir="${temp.dir}/生" /><br>  <mkdir dir="${temp.dir}/开? />  <br>  <mkdir dir="${classes.dir}" /></p> <p>  <javac srcdir="${src.dir}" destdir="${classes.dir}"  debug="true" encoding="GB2312"><br>   <classpath refid="master-classpath" /><br>  </javac></p> <p>  <copy todir="${temp.dir}/生" overwrite="true"><br>   <fileset dir="${WebContent.dir}"><br>    <include name="**/**" /><br>   </fileset><br>  </copy><br>  <br>  <copy todir="${temp.dir}/生/WEB-INF/classes" overwrite="true"><br>   <fileset dir="${生.dir}"><br>    <include name="jlo_logging.xml" /><br>    <include name="log4j.properties" /><br>    <include name="mvncore.xml" /><br>    <include name="mvnForum_i18n_zh_CN.properties" /><br>    <include name="mvnforum.xml" />    <br>    <include name="whirlycache.xml" /><br>   </fileset><br>  </copy><br>  <br>  <copy todir="${temp.dir}/开? overwrite="true"><br>   <fileset dir="${WebContent.dir}"><br>    <include name="**/**" /><br>   </fileset><br>  </copy><br>    <br>  <copy todir="${temp.dir}/开?WEB-INF/classes" overwrite="true"><br>   <fileset dir="${开?dir}"><br>    <include name="jlo_logging.xml" /><br>    <include name="log4j.properties" /><br>    <include name="mvncore.xml" /><br>    <include name="mvnForum_i18n_zh_CN.properties" /><br>    <include name="mvnforum.xml" /><br>    <include name="whirlycache.xml" /><br>   </fileset><br>  </copy><br>  <br> </target></p> <p> <!--打包--><br> <target name="war" depends="compile"><br>  <mkdir dir="${war.dir}/生" /><br>  <mkdir dir="${war.dir}/开? /><br>  <br>  <jar jarfile="${war.dir}/生/ROOT.war"><br>   <fileset dir="${temp.dir}/生"><br>    <include name="**/*" /><br>   </fileset><br>  </jar><br>  <br>  <jar jarfile="${war.dir}/开?ROOT.war"><br>   <fileset dir="${temp.dir}/开?><br>    <include name="**/*" /><br>   </fileset><br>  </jar><br>  <br>  <delete dir="${temp.dir}"/><br> </target><br> <br> <target name="all" depends="war"><br>  <delete dir="${classes.dir}" /><br>  <delete dir="${temp.dir}" /><br> </target></p> <p></project></p> <p>值得注意的是Q在书写build.xml的时候一定要心Q别写错了,我就是因为粗心,在写下面代码的时候:<br><br>   <fileset dir="${生.dir}"><br>    <strong><font color="#ff0033">.<include name="jlo_logging.xml" /></font></strong><br>    <include name="log4j.properties" /><br>    <include name="mvncore.xml" /><br>    <include name="mvnForum_i18n_zh_CN.properties" /><br>    <include name="mvnforum.xml" />    <br>    <include name="whirlycache.xml" /><br>   </fileset><br><br>不小心在U色代码前加了一?#8220;.”Q结果报了一?font color="#ff0033">type   doesn't   support   nested   text   data.   </font>的错Q我找了半天没找出原因,到网上搜了一下竟然没有找到答案,后来才发现自己写错了Q大汗,Ҏ后,搞定Q爽啊。是?/p> </td> </tr> </tbody> </table><img src ="http://www.tkk7.com/kuxiaoku/aggbug/123388.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/kuxiaoku/" target="_blank">苦笑?/a> 2007-06-11 14:49 <a href="http://www.tkk7.com/kuxiaoku/archive/2007/06/11/123388.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ANT的安?配置W记http://www.tkk7.com/kuxiaoku/archive/2007/06/11/123385.html苦笑?/dc:creator>苦笑?/author>Mon, 11 Jun 2007 06:44:00 GMThttp://www.tkk7.com/kuxiaoku/archive/2007/06/11/123385.htmlhttp://www.tkk7.com/kuxiaoku/comments/123385.htmlhttp://www.tkk7.com/kuxiaoku/archive/2007/06/11/123385.html#Feedback0http://www.tkk7.com/kuxiaoku/comments/commentRss/123385.htmlhttp://www.tkk7.com/kuxiaoku/services/trackbacks/123385.html 作者:车东 发表于:2003-03-06 17:03 最后更CQ?007-04-12 11:04
版权声明Q可以Q意{载,转蝲时请务必以超链接形式标明文章和作者信息及本声?/a>?br>

内容摘要Q?br> ant是一个基于JAVA的自动化脚本引擎Q脚本格式ؓXML。除了做JAVA~译相关d外,ANTq可以通过插g实现很多应用的调用?br>

  1. ANT的基本概念:
  2. ANT的安装:解包Q设|\?/li>
  3. ANT的用:最好的学习只不q是一个简单实用的例子h……

ANT的基本概念:Java的Makefile

当一个代码项目大了以后,每次重新~译Q打包,试{都会变得非常复杂而且重复Q因此c语言中有make脚本来帮助这些工作的扚w完成。在Java 中应用是q_无关性的Q当然不会用q_相关的make脚本来完成这些批处理d了,ANT本n是q样一个流E脚本引擎,用于自动化调用程序完成项目的~? 译,打包Q测试等。除了基于JAVA是^台无关的外,脚本的格式是ZXML的,比make脚本来说q要好维护一些?br>

每个ant脚本Q缺省叫build.xmlQ中讄了一pdd(target)Q比如对于一个一般的目可能需要有以下d?/p>

  • d1Qusage 打印本脚本的帮助信息Q缺省)
  • d2Qclean <-- init 清空初始化环?
  • d3Qjavadoc <-- build <-- init 生成JAVADOC
  • d4Qjar <-- build <-- init 生成JAR
  • d5Qall <-- jar + javadoc <-- build <-- init 完成以上所有Q务:jar javadoc
而多个Q务之间往往又包含了一定了依赖关系Q比如把整个应用打包d(jar)的这个依赖于~译d(build)Q而编译Q务又依赖于整个环境初始化? ?init){?br>
注:我看到很多项目的ant脚本中的命名基本上都是一致的Q比如:~译一般叫build或者compileQ打包一般叫jar或warQ生成文档一般命? 为javadoc或javadocsQ执行全部Q务all。在每个d的中QANT会根据配|调用一些外部应用ƈ配以相应参数执行。虽然ANT可调用的? 部应用种c非怸富,但其实最常用的就2Q?个:比如javac javadoc jar{?

ANT的安?/h2> 解包后在pȝ可执行\径中加入指向ant的bin的\径就可以了,比如可以在GNU/Linux上把以下配置加入/etc/profile中:
export ANT_HOME=/home/ant
export JAVA_HOME=/usr/java/j2sdk1.4.1
export PATH=$PATH:$JAVA_HOME/bin:$ANT_HOME/bin

q样执行ant 后,如果不指定配|文件ant会缺省找build.xmlq个配置文gQƈҎ配置文g执行dQ缺省的d讄可以指向最常用的Q务,比如Q? buildQ或指向打印帮助信息QusageQ告诉用h那些脚本选项可以使用?br>

ANT的?br>

最好的学习q程是看懂那些open source目中的build.xml脚本Q然后根据自q需要简化成一个更单的QANT和APACHE上很多非常工E派的项目:单易用,而且适应 性非常强Q因些项目的建立往往来源于开发h员日常最直接的需求?br> 以下是的一?a >WebLucene? 用的例子Q修改自JDOM的build.xmlQ?br>
<project default="usage" basedir=".">

  <!-- =================================================================== -->
  <!-- Initialization target                                               -->
  <!-- =================================================================== -->
  <target name="init">
    <tstamp/>
    <property file="${basedir}/build.properties" />
    <property name="Name" value="ProjectFullName"/>
    <property name="name" value="project_name"/>
    <property name="version" value="0.2"/>
    <property name="year" value="2003"/>

    <echo message="----------- ${Name} ${version} [${year}] ------------"/>

    <property name="debug" value="off"/>
    <property name="optimize" value="on"/>
    <property name="deprecation" value="on"/>

    <property name="src.dir" value="./src/WEB-INF/src"/>
    <property name="lib.dir" value="./src/WEB-INF/lib"/>
    <property name="packages" value="com.chedong.*,org.apache.lucene.*"/>

    <property name="build.src" value="./src/WEB-INF/build"/>
    <property name="build.dest" value="./src/WEB-INF/classes"/>
    <property name="build.javadocs" value="./src/doc"/>
   
    <path id="classpath">
        <pathelement path="${jsdk_jar}"/>
        <fileset dir="${lib.dir}">
           <include name="**/*.jar"/>
        </fileset>
    </path>
   
    <filter token="year" value="${year}"/>
    <filter token="version" value="${version}"/>
    <filter token="date" value="${TODAY}"/>
    <filter token="log" value="true"/>
    <filter token="verbose" value="true"/>
  </target>

  <!-- =================================================================== -->
  <!-- Help on usage                                                       -->
  <!-- =================================================================== -->
  <target name="usage" depends="init">
    <echo message="${Name} Build file"/>
    <echo message="-------------------------------------------------------------"/>
    <echo message=""/>
    <echo message=" available targets are:"/>
    <echo message=""/>
    <echo message="   jar      --> generates the ${name}.jar file"/>
    <echo message="   build    --> compiles the source code"/>
    <echo message="   javadoc  --> generates the API documentation"/>
    <echo message="   clean    --> cleans up the directory"/>
    <echo message=""/>
    <echo message=" Please rename build.properties.default to build.properties"/>
    <echo message=" and edit build.properties to specify JSDK 2.3 classpath."/>
    <echo message=""/>
    <echo message=" See the comments inside the build.xml file for more details."/>
    <echo message="-------------------------------------------------------------"/>
    <echo message=""/>
    <echo message=""/>
  </target>

  <!-- =================================================================== -->
  <!-- Prepares the source code                                            -->
  <!-- =================================================================== -->
  <target name="prepare-src" depends="init">
    <!-- create directories -->
    <mkdir dir="${build.src}"/>
    <mkdir dir="${build.dest}"/>
   
    <!-- copy src files -->
    <copy todir="${build.src}">
      <fileset dir="${src.dir}"/>
    </copy>
  </target>

  <!-- =================================================================== -->
  <!-- Compiles the source directory                                       -->
  <!-- =================================================================== -->
  <target name="build" depends="prepare-src">
    <javac srcdir="${build.src}"
           destdir="${build.dest}"
           debug="${debug}"
           optimize="${optimize}">
      <classpath refid="classpath"/>
    </javac>
  </target>

  <!-- =================================================================== -->
  <!-- Creates the class package                                           -->
  <!-- =================================================================== -->
  <target name="jar" depends="build">
    <jar jarfile="${lib.dir}/${name}.jar"
         basedir="${build.dest}"
         includes="**"/>
  </target>

  <!-- =================================================================== -->
  <!-- Creates the API documentation                                       -->
  <!-- =================================================================== -->
  <target name="javadoc" depends="build">
    <mkdir dir="${build.javadocs}"/>
    <javadoc packagenames="${packages}"
             sourcepath="${build.src}"
             destdir="${build.javadocs}"
             author="true"
             version="true"
             use="true"
             splitindex="true"
             windowtitle="${Name} API"
             doctitle="${Name}">
      <classpath refid="classpath"/>
    </javadoc>
  </target>

  <!-- =================================================================== -->
  <!-- Clean targets                                                       -->
  <!-- =================================================================== -->
  <target name="clean" depends="init">
    <delete dir="${build.src}"/>
    <delete dir="${build.dest}/org"/>
    <delete dir="${build.dest}/com"/>
    <delete>
      <fileset dir="${build.dest}" includes="**/*.class"/>
    </delete>
  </target>
</project>
<!-- End of file -->

~省dQusage 打印帮助文档Q告诉有那些d选项Q可用的有build, jar, javadoc和clean.

初始化环境变量:init
所有Q务都Z一些基本环境变量的讄初始化完成,是后l其他Q务的基础Q在环境初始化过E中Q有2Ҏ较可以方便设|:

1 除了使用却缺省的property讄了JAVA源\径和输出路径外,引用了一个外部的build.properties文g中的讄Q?br> <property file="${basedir}/build.properties" />
q样大部分简单配|用户只要会看懂build.properties可以了Q毕竟XML比vkey value的属性文件还是要可读性差一些。用build.properties也可以方便其他用户从~译的细节中解放出来?br>
2 CLASSPATH讄Q用了其中的:
    <path id="classpath">
        <pathelement path="${jsdk_jar}"/>
        <fileset dir="${lib.dir}">
           <include name="**/*.jar"/>
        </fileset>
    </path>
则相当于讄了:CLASSPATH=/path/to/resin/lib/jsdk23.jar; /path/to/project/lib/*.jar;

文g复制Qprepare-src
创徏临时SRC存放目录和输出目录?br>   <!-- =================================================================== -->
  <!-- Prepares the source code                                            -->
  <!-- =================================================================== -->
  <target name="prepare-src" depends="init">
    <!-- create directories -->
    <mkdir dir="${build.src}"/>
    <mkdir dir="${build.dest}"/>
   
    <!-- copy src files -->
    <copy todir="${build.src}">
      <fileset dir="${src.dir}"/>
    </copy>
  </target>

~译dQbuild
~译时的CLASSPATH环境通过一下方式找到引用一个path对象
<classpath refid="classpath"/>

打包dQjar
对应用打包生成项目所写名?jar文g
  <!-- =================================================================== -->
  <!-- Creates the class package                                           -->
  <!-- =================================================================== -->
  <target name="jar" depends="build">
    <jar jarfile="${lib.dir}/${name}.jar"
         basedir="${build.dest}"
         includes="**"/>
  </target>

生成JAVADOC文档d: javadoc
  <!-- =================================================================== -->
  <!-- Creates the API documentation                                       -->
  <!-- =================================================================== -->
  <target name="javadoc" depends="build">
    <mkdir dir="${build.javadocs}"/>
    <javadoc packagenames="${packages}"
             sourcepath="${build.src}"
             destdir="${build.javadocs}"
             author="true"
             version="true"
             use="true"
             splitindex="true"
             windowtitle="${Name} API"
             doctitle="${Name}">
      <classpath refid="classpath"/>
    </javadoc>
  </target>

清空临时~译文gQclean
  <!-- =================================================================== -->
  <!-- Clean targets                                                       -->
  <!-- =================================================================== -->
  <target name="clean" depends="init">
    <delete dir="${build.src}"/>
    <delete dir="${build.dest}/org"/>
    <delete dir="${build.dest}/com"/>
    <delete>
      <fileset dir="${build.dest}" includes="**/*.class"/>
    </delete>
  </target>

TODOQ?br> 更多d/扩展Q(样例Q?br>
  • 试dQJUnit试
  • 代码风格查Q务:CheckStyleQJalopy{?/li>
  • 邮g警报dQ可以把以上q些d的输告发送到制定的用户列表中Q这个Q务可以设|每天自动运行?/li>

参考资料:
Jakarta ANT:
http://ant.apache.org

]]>
Java事g处理模式http://www.tkk7.com/kuxiaoku/archive/2007/04/15/110830.html苦笑?/dc:creator>苦笑?/author>Sun, 15 Apr 2007 15:05:00 GMThttp://www.tkk7.com/kuxiaoku/archive/2007/04/15/110830.htmlhttp://www.tkk7.com/kuxiaoku/comments/110830.htmlhttp://www.tkk7.com/kuxiaoku/archive/2007/04/15/110830.html#Feedback1http://www.tkk7.com/kuxiaoku/comments/commentRss/110830.htmlhttp://www.tkk7.com/kuxiaoku/services/trackbacks/110830.htmlauthorQ板桥里?/p>

出处QJDON.COM

Java的事件模式是动态响应系l重要的基础Q在囑Ş界面领域的事件模式已l有很多文章介绍Q但是在服务器端我们会碰到更多的事g模式Q这里本图ȝ一下:

  事g直接驱动模式

  事g模式的第一个要求就是性能的要求,需要直接而且快,Command模式是必ȝ怋用的Q主要适合于迅速处?前台的命令,Command模式往往是系l架构的重要部分Q也是流E控制的主要模式?

  Command模式l常Java的Reflect一起用,因ؓpȝ的事件处理系l是处于动态变化的Q随着功能要求扩展Q就可能有动态变化事? 处理响应pȝQ以Struts中actionZQ我们知道,Structs的一个主要配|文件是struts-config.xml 如下Q?

Qstruts-configQ?br>  Qaction-mappingsQ?br>    Qaction path="/login" type="com.javapro.struts.LoginAction"/Q?br>    Qaction path="/logout" type="com.javapro.struts.LogoutAction"/Q?br>  Q?action-mappingsQ?br>Q?struts-configQ?

  它实际是个command和event的映关p,通过q个配置文gQ运行时动态装载相应的ActionQ完成Command模式Q?我们查LoginAction代码Q就可以看出Command模式的基本特征:

public final class LoginAction extends Action {
  public ActionForward execute(ActionMapping mapping,
    ActionForm form, HttpServletRequest request, HttpServletResponse response)
    throws Exception {
        .................
  }
}

  很明显,典型的Command模式需要有一个接?接口中有一个统一的方法,q里l一的方法就是execute;

  比如我们有个实时pȝQ客h向服务器发出不同~码代号Q意味着不同的请求,不同的请求有不同的Handlerq行 处理QHandler接口?

public class Handler{

  public byte[] handleRequest();

}

  不同性质的处理过E承这个Handler接口Q如负责q入pȝ的处理过E?

public class EnterHandler implements Handler{

  public byte[] handleRequest(){
  //具体业务处理
  ......
  }

}

  调用Handler时是:

//从cache中获取这个requestId对应的Handler
Handler handler = (Handler)cache.get(new Integer(reqId));
//调用handler的统一ҎhandleRequest()
byte[] outInf = handler.handleRequest();

  以上是常用的一个事仉动模式。它的特Ҏ靠一个事件直接启动对应的事g处理器?

  Chain of Responsibility职责链模式也应该属于q类Q当事g到达后,让这个事件在我们提供的一批处理器中逐个挑选适合的处理器q行处理Q这个模式缺? 是显然的Q性能丧失在逐个挑?上,一般不推荐使用Q这个模式适合在我们无法预知发生的事g内容时用,因ؓ不知道发生事件的具体情况Q? 我们无法在E序q行前事先ؓ其指z应的处理器,只能靠运行时Q事件自己去摸烦“撞运?#8221;?


监控式事件模?/strong>

  监控式事件模式就不同于事件直接驱动模式,它是借助W三者来监控和触发事Ӟq类事g的特ҎQ?有一个观察者置w事外在定期独立q行着Q我们将我们要监听的事g向这个观察者注册,q样观察者就 代替我们来监听这个事Ӟ应用客户端通过观察者来获得事g状况?

  应用客户端有三种与观察者交互的方式Q?.直接融合 2.推方?3.拉方式?

  直接融合是说应用客L自己是观察者,两者融合,q样无疑应用客户端获得的触发旉是最快的?

  推方式就是观察者一旦侦到事g发生Q立卛_事gPush推到应用客户端;拉方式类似收取邮Ӟ应用客户端在需要时才从观察者拉取事件?

  JDK 1.4的None Blocking I/O是监控式事g模式的典型实玎ͼSelector昄是一个监控I/O的第三者,当有外部事gq来Q通过 调用Slector.selectҎ可以获得外部事gQ从而进行处理,可参考我的本栏文章?

  监控式事件模式适合使用在触发性质的场合,比如数据库后端触发器 界面触发 I/O触发 状态改变触发等?

  我们以一个信件触发ؓ例,q其实是个Observer应用例子:

  比如用户提请服务器计一个数据,如果用户同时要求计结果向自己信箱发一,那么我们看如何设计?按照通常思维Q这是一个次序问题,先在? 存中计算数据Q然后将l果发送到他的信箱Q最后返回结果到用户端,我们知道信g的发送是耗时的,因此Q有可能|络的原因造成信g发送很慢,q是用户׃? {不C的计结果,很显Ӟ我们使用监控式事件模式来解决Q让发信的事件由监控者去完成Q只要需要时触发可以了Q?

public class Computer extends Observable{

  public Computer(){
    //sendMailObserver讑֮为本cȝ观察者?
    addObserver(new sendMailObserver());
  }

  .......


  public void compute(String input,boolean needEmail,String email){

    //计算操作
    .........

    if (needEmail){

      //讄变化?
       setChanged();
      //如果需要发送emailQ我们把email地址作ؓ参数传送过?
       notifyObservers(email);

    }   
  }

?/p>

  我们再来看监控观察者代码是如何写的Q?

public class sendMailObserver implements Observer{

  public void update(Observable obj,Object email){

    if (email instanceof String){

      sendMail(email);

    }

  }

}

  q样服务器在执行computeҎӞ没有发送邮件的{待Q一直接l箋执行?

  监控式事件模式和事g直接驱动模式可以在一个系l一起用,外界信号通过事g直接驱动模式启动pȝ处理模块Q?pȝ处理模块处理q程中,可以通过监控式事件模式来触发其它后台d。这样一个架构非帔R合实时处理pȝ?

  既然事g处理模式是众多应用系l的基本模式Q那么应该可以Ş成一个框架标准,JMX的notification Model是q样一个架构设计?

  JMX Notification Model

  我们知道QJMX是提供了一U对MBean资源执行控制和配 |的理机制Q但q只是复杂的Q分布式的系l中的一部分Q?q有需要资源能够感应状态改变或者特定事件变化的机制Q这是JMX Notification Model?在JMX Notification Model中均可以实现"事g直接驱动模式"?监控式事件模?Q这取决于你的应用需求?

  JMX Notification Model允许MBean通过调用notificationsq播事gQ接受者只要注册ؓ一个listernerQ?JMX?MBean notification model 会Ȁz这个listerner注册一ơ,然后一直接受到 来自q播者发出的各种事g?

  事g模式有三个角ԌW一个是事g发出者producer 然后是事件接受者Consumer,W三?是要传输的事件。JMX notification model也是q样分别依靠下列lg来实现这三个角色Q?

  A. NotificationBroadcaster接口, 事gq播发出者, q个接口允许监听者在需要发出的notification中注册他们感兴趣的事件?

  B. 通用事g(Notification)Q这是我们要传输的事件?Notification事g能被直接使用Q也能成为子c,q些都依赖于随同事g传输的信息?通过使用通用事gcdQ监听者将能接受来自广播者所有类型的事g?
  
  C. NotificationListener接口, 事g监听者或者接受者, 用于接受来自q播者的Mnotification信号?

  D. NotificationFilter接口, q个接口为notification的监听者提供一个对发出事g的过滤器?

  E. NotificationEmitter 接口, 扩展了NotificationBroadcaster接口Q当删除监听者时允许更多的控制功能?

  只要是MBeanQ就既可以成为notification的发布广播者,也可以成为notification的监听者接受者,或者同时两者都可以?

  Attribute Change Notifications

  Attribute Change Notifications是一U特D的notification, M时候MBean属性attribute 被修改,外界能够被通知到?

  在JMX架构中,MBean能够在属性attribute变化发生Ӟ发出通知Q关于诊断属性变化的机制以及触发 通知事gq不属于JMX规定部分Q每个MBean可以有自q立的实现方式?

  Timer Service

  Timer Service触发器是在规定的日期和事件发出通知Q它能够一一个恒定的间隙不断重复发出通知Q?通知可以发往所有注册ؓ接受timer通知的对象,Timer Service也是一个可理的MBeanQ允许应用系l设|?一个可配置的调度程度?

  Monitoring

  通过使用monitoring serviceQ一个或多个MBean属性将按规定间隔时间被监视Q? 对于被观察的Mbean,监视器monitor从它上面获得一个|叫derived gaugeQ这个derived gauge可以? 被观察属性的原|也可以是一个数字性属性连l被观察g差?

  当derived gauge值满一pd条gӞ每个monitor server会发出一个特定类型的通知?q些条g都是在monitor被初始化时设定的Q也可以通过monitor MBean的管理接口动态设定?

  ҎMBean内部属性值类型有三种monitor:

  A.CounterMonitor - 使用Java的整数类型来观察属性,有一个行为特征:

   a. L大于或等于零.

   b. 能自?

   c. 能回?

  B.GaugeMonitor - 使用java的整数或点cd观察属性。象gauge(量仪器) 要么上升 要么下降减少?

  C StringMonitor - 使用Stringcd观察属?

  事g处理架构

  JMS是基于Socket的一U消息处理框Ӟ原理cM于监控式事g模式Q但是JMS已经把这U模式上升到架构的高度。不同JVM间也依靠JMS消息可以实现事gpȝQ注意是pȝQ不单是一个小事g了)的触发和ȀzR?

  

  从上面JMS的架构图可以看出事g三个角色Producer和Consumer以及事g信息本nMessageQJMS是在Producer和Consumer之间建立一个连接ConnectionQ?

  JMS可实现同步或异步的事件触发机Ӟ分别是通过Poin to Point(拉方?和Pubilsh/Subscibe(推方?具体完成Q在分布式计环境中Q异步机制是非常重要Q可以v到解耦作用,因ؓ分布环境 中单炚w误或通讯问题是经常发生的Q整个分布式pȝ不能L依靠同步机制来可靠地传递事件或notificationQ?

  由此可见Q事件处理模式从Java诸多架构到我们具体应用程序,随处可见Q根据不同的应用需求选择不同的事件处理模式,才能真正挖掘Java的潜在性能?



]]>
拼包函数及网l封包的异常处理http://www.tkk7.com/kuxiaoku/archive/2007/04/07/109154.html苦笑?/dc:creator>苦笑?/author>Sat, 07 Apr 2007 14:07:00 GMThttp://www.tkk7.com/kuxiaoku/archive/2007/04/07/109154.htmlhttp://www.tkk7.com/kuxiaoku/comments/109154.htmlhttp://www.tkk7.com/kuxiaoku/archive/2007/04/07/109154.html#Feedback0http://www.tkk7.com/kuxiaoku/comments/commentRss/109154.htmlhttp://www.tkk7.com/kuxiaoku/services/trackbacks/109154.html本文作者:sodme
本文出处Q?a >http://blog.csdn.net/sodme
声明Q本文可以不l作者同意Q意{载、复制、传播,但Q何对本文的引用都请保留作者、出处及本声明信息。谢谢!

常见的网l服务器Q基本上?*24时q{的,对于|游来说Q至要求服务器要能q箋工作一周以上的旉q保证不出现服务器崩溃这LN性事件。事 实上Q要求一个服务器在连l的满负药转下不出M异常Q要求它设计的近乎完,q几乎是不太现实的。服务器本n可以出异常(但要可能少得出Q,但是Q? 服务器本w应该被设计得以健壮,“病灾”打不垮它Q这p求服务器在异常处理方面要下很多功夫?/p>

  服务器的异常处理包括的内定w常广泛,本文仅就在网l封包方面出现的异常作一讨论Q希望能Ҏ从事相关工作的朋友有所帮助?/p>

关于|络包斚w的异常,M来说Q可以分Z大类Q一是封包格式出现异常;二是包内容Q即包数据Q出现异常。在包格式的异常处理方面,我们在最 底端的网l数据包接收模块便可以加以处理。而对于封包数据内容出现的异常Q只有依靠游戏本w的逻辑d以判定和验。游戏逻辑斚w的异常处理,是随每个? 戏的不同而不同的Q所以,本文随后的内容将重点阐述在网l数据包接收模块中的异常处理?/p>

  为方便以下的讨论Q先明确两个概念Q这两个概念是ؓ了叙q方面,W者自行取的,q无标准可言Q:
  1、逻辑包:指的是在应用层提交的数据包,一个完整的逻辑包可以表CZ个确切的逻辑意义。比如登录包Q它里面可以含有用户名字段和密码字Dc尽它看上M是一D늼冲区数据Q但q个~冲区里的各个区间是代表一定的逻辑意义的?br>  2、物理包Q指的是使用recv(recvfrom)或wsarecv(wsarecvfrom)从网l底层接收到的数据包Q这h到的一个数据包Q能不能表示一个完整的逻辑意义Q要取决于它是通过UDPcȝ“数据报协?#8221;发的包还是通过TCPcȝ“协?#8221;发的包?/p>

我们知道QTCP是流协议Q?#8220;协?#8221;?#8220;数据报协?#8221;的不同点在于Q?#8220;数据报协?#8221;中的一个网l包本n是一个完整的逻辑包,也就是说Q在应用层? sendto发送了一个逻辑包之后,在接收端通过recvfrom接收到的是刚才使用sendto发送的那个逻辑包,q个包不会被分开发送,也不会与? 它的包放在一起发送。但对于TCP而言QTCP会根据网l状况和neagle法Q或者将一个逻辑包单独发送,或者将一个逻辑包分成若q次发送,或者会? 若干个逻辑包合在一起发送出厅R正因ؓTCP在逻辑包处理方面的q种_合性,要求我们在作ZTCP的应用时Q一般都要编写相应的拼包、解包代码?/p>

  因此Q基于TCP的上层应用,一般都要定义自q包格式。TCP的封包定义中Q除了具体的数据内容所代表的逻辑意义之外Q第一步就是要定以何U方式表C当前包的开始和l束。通常情况下,表示一个TCP逻辑包的开始和l束有两U方式:
  1、以Ҏ的开始和l束标志表示Q比如FF00表示开始,00FF表示l束?br>  2、直接以包长度来表示。比如可以用W一个字节表C包总长度,如果觉得q样的话包比较小Q也可以用两个字节表C包长度?/p>

  下面要l出的代码是以第2U方式定义的数据包,包长度以每个包的前两个字节表示。我结合着代码l出相关的解释和说明?/p>

  函数中用到的变量说明Q?/p>

  CLIENT_BUFFER_SIZEQ缓冲区的长度,定义为:Const int CLIENT_BUFFER_SIZE=4096?br>  m_ClientDataBufQ数据整理缓冲区Q每ơ收到的数据Q都会先被复制到q个~冲区的末尾Q然后由下面的整理函数对q个~冲行整理。它的定义是Qchar m_ClientDataBuf[2* CLIENT_BUFFER_SIZE]?br>  m_DataBufByteCountQ数据整理缓冲区中当前剩余的未整理字节数?br>  GetPacketLen(const char*)Q函敎ͼ可以Ҏ传入的缓冲区首址按照应用层协议取出当前逻辑包的长度?br>  GetGamePacket(const char*, int)Q函敎ͼ可以Ҏ传入的缓冲区生成相应的游戏逻辑数据包?br>  AddToExeList(PBaseGamePacket)Q函敎ͼ指定的游戏逻辑数据包加入待处理的游戏逻辑数据包队列中Q等待逻辑处理U程对其q行处理?br>  DATA_POSQ指的是除了包长度、包cd{这些标志型字段之外Q真正的数据包内容的起始位置?/p>

Bool SplitFun(const char* pData,const int &len)
{
    PBaseGamePacket pGamePacket=NULL;
    __int64 startPos=0, prePos=0, i=0;
    int packetLen=0;

  //先将本次收到的数据复制到整理~冲区尾?br>    startPos = m_DataBufByteCount;  
    memcpy( m_ClientDataBuf+startPos, pData, len );
    m_DataBufByteCount += len;   

    //当整理缓冲区内的字节数少于DATA_POS字节Ӟ取不到长度信息则退?br> //注意Q退出时q不|m_DataBufByteCount?
    if (m_DataBufByteCount < DATA_POS+1)
        return false; 

    //Ҏ正常逻辑Q下面的情况不可能出玎ͼ为稳妥v见,q是加上
    if (m_DataBufByteCount >  2*CLIENT_BUFFER_SIZE)
    {
        //讄m_DataBufByteCount?Q意味着丢弃~冲Z的现有数?br>        m_DataBufByteCount = 0;

  //可以考虑开N误格式数据包的处理接口,处理逻辑交给上层
  //OnPacketError()
        return false;
    }

     //q原起始指针
     startPos = 0;

     //只有当m_ClientDataBuf中的字节个数大于最包长度时才能执行此语句
    packetLen = GetPacketLen( pIOCPClient->m_ClientDataBuf );

    //当逻辑层的包长度不合法Ӟ则直接丢弃该?br>    if ((packetLen < DATA_POS+1) || (packetLen > 2*CLIENT_BUFFER_SIZE))
    {
        m_DataBufByteCount = 0;

  //OnPacketError()
        return false;
    }

    //保留整理~冲区的末尾指针
    __int64 oldlen = m_DataBufByteCount; 

    while ((packetLen <= m_DataBufByteCount) && (m_DataBufByteCount>0))
    {
        //调用拼包逻辑Q获取该~冲区数据对应的数据?br>        pGamePacket = GetGamePacket(m_ClientDataBuf+startPos, packetLen); 

        if (pGamePacket!=NULL)
        {
            //数据包加入执行队列
            AddToExeList(pGamePacket);
        }

        pGamePacket = NULL;
 
  //整理~冲区的剩余字节数和新逻辑包的起始位置q行调整
        m_DataBufByteCount -= packetLen;
        startPos += packetLen; 

        //D留~冲区的字节数少于一个正常包大小Ӟ只向前复制该包随后退?br>        if (m_DataBufByteCount < DATA_POS+1)
        {
            for(i=startPos; i<startPos+m_DataBufByteCount; ++i)
                m_ClientDataBuf[i-startPos] = m_ClientDataBuf[i];

            return true;
        }

        packetLen = GetPacketLen(m_ClientDataBuf + startPos );

         //当逻辑层的包长度不合法Ӟ丢弃该包及缓冲区以后的包
        if ((packetLen<DATA_POS+1) || (packetLen>2*CLIENT_BUFFER_SIZE))
        {
            m_DataBufByteCount = 0;

      //OnPacketError()
            return false;
        }

         if (startPos+packetLen>=oldlen)
        {
            for(i=startPos; i<startPos+m_DataBufByteCount; ++i)
                m_ClientDataBuf[i-startPos] = m_ClientDataBuf[i];          

            return true;
        }
     }//取所有完整的?/p>

     return true;
}

  以上便是数据接收模块的处理函敎ͼ下面是几点简要说明:

  1、用于拼包整理的~冲?m_ClientDataBuf)应该比recv中指定的接收~冲?pData)长度(CLIENT_BUFFER_SIZE)要大Q通常前者是后者的2?2*CLIENT_BUFFER_SIZE)或更大?br>
  2、ؓ避免因ؓ剩余数据前移而导致的额外开销Q徏议m_ClientDataBuf使用环Ş~冲区实现?br>
3、ؓ了避免出现无法拼装的包,我们U定每次发送的逻辑包,其单个逻辑包最大长度不可以过CLIENT_BUFFER_SIZE?倍。因为我们的? 理缓冲区只有2*CLIENT_BUFFER_SIZEq么长,更长的数据,我们无法整理。这p求在协议的设计上以及最l的发送函数的处理上要加上q? L异常处理机制?/p>


  4、对于数据包q短或过长的包,我们通常的情冉||m_DataBufByteCount?Q即舍弃当前 包的处理。如果此处不讄m_DataBufByteCount?也可Q但该客L只要发了一ơ格式错误的包,则其后发过来的包则也将q带着产生格式 错误Q如果设|m_DataBufByteCount?Q则可以比较好的避免后的包受此包的格式错误影响。更好的作法是,在此处开放一个封包格式异? 的处理接?OnPacketError)Q由上层逻辑军_对这U异常如何处|。比如上层逻辑可以对封包格式方面出现的异常q行计数Q如果错误的ơ数过 一定的|则可以断开该客L的连接?/p> 5、徏议不要在recv或wsarecv的函数后Q就紧接着作以上的处理。当recv收到一D| 据后Q生成一个结构体或对?它主要含有data和len两个内容Q前者是数据~冲区,后者是数据长度)Q将q样的一个结构体或对象放C个队列中由后? 的线E对其用SplitFun函数q行整理。这P可以最大限度地提高|络数据的接攉度Q不臛_为数据整理的原因而在此处费旉?img src ="http://www.tkk7.com/kuxiaoku/aggbug/109154.html" width = "1" height = "1" />

]]>
心情日志http://www.tkk7.com/kuxiaoku/archive/2007/04/01/107765.html苦笑?/dc:creator>苦笑?/author>Sun, 01 Apr 2007 07:44:00 GMThttp://www.tkk7.com/kuxiaoku/archive/2007/04/01/107765.htmlhttp://www.tkk7.com/kuxiaoku/comments/107765.htmlhttp://www.tkk7.com/kuxiaoku/archive/2007/04/01/107765.html#Feedback0http://www.tkk7.com/kuxiaoku/comments/commentRss/107765.htmlhttp://www.tkk7.com/kuxiaoku/services/trackbacks/107765.html

]]>
[分n]JDOM1.0的API文档QCHM版)http://www.tkk7.com/kuxiaoku/archive/2007/03/27/106798.html苦笑?/dc:creator>苦笑?/author>Tue, 27 Mar 2007 15:18:00 GMThttp://www.tkk7.com/kuxiaoku/archive/2007/03/27/106798.htmlhttp://www.tkk7.com/kuxiaoku/comments/106798.htmlhttp://www.tkk7.com/kuxiaoku/archive/2007/03/27/106798.html#Feedback1http://www.tkk7.com/kuxiaoku/comments/commentRss/106798.htmlhttp://www.tkk7.com/kuxiaoku/services/trackbacks/106798.htmlhttp://www.tkk7.com/Files/kuxiaoku/JDOMAPIDOCS.rar

点击下蝲


]]>
[分n]Java设计模式资料http://www.tkk7.com/kuxiaoku/archive/2007/03/27/106792.html苦笑?/dc:creator>苦笑?/author>Tue, 27 Mar 2007 15:07:00 GMThttp://www.tkk7.com/kuxiaoku/archive/2007/03/27/106792.htmlhttp://www.tkk7.com/kuxiaoku/comments/106792.htmlhttp://www.tkk7.com/kuxiaoku/archive/2007/03/27/106792.html#Feedback0http://www.tkk7.com/kuxiaoku/comments/commentRss/106792.htmlhttp://www.tkk7.com/kuxiaoku/services/trackbacks/106792.htmlC传上来大家一起分享?br>
http://www.tkk7.com/Files/kuxiaoku/DESIGN.rar

点击卛_下蝲?

]]>
վ֩ģ壺 ˳Ƶ| ձ߿Ƭ| ߹ۿվ| 츾AVպ츾| ѿAVƬ| vva| ƬƵ| ޾Ʒ2021| ޾ƷƵ߿| Ļվ| ĻþþƷ| Ƭѿҹa| AVרߵӰ| ҹƵվ | ձ˳Ƶ| Ʒһ߹ۿ | պAVר | ޾Ʒҹ߹ۿ| ƬAVƬѹۿ| AVƬһ| һ϶| 99Ƶѹۿ| Ů߹ۿ| ѿƬAëƬѿ| һëƬaaaaaaƵѿ| þ99ڹ| ߹ۿɫƬƵ| ؼAëƬѹۿ| AVþüįٸ| eeussӰԺ| ¸߳60Ƶ | 㽶Ƶѿ| ŷղר| yw855.cƵ| վѿAվƵ| a߹ۿ| ҹƵ| avѲۿ| ҹƷ| ձĻ| þwww˳ɿƬ|