|
-Xms
|
初始Heap大小
|
|
-Xmx
|
java heap最大值
|
|
-Xmn
|
young generation的heap大小
|
|
-Xss
|
每个线程的Stack大小
|
sitemesh一个系统,添加到Web应用中并促进模式HTML世界里的应用。
可从http://www.opensymphony.com/sitemesh/ 获得。
sitemesh仅处理html的内容,象图象,PDF文件和下载这样的媒体是被忽略的。
下面我们将用实例来介绍如何分析内容网页和装饰器如何被映射到网页。以及从sitemesh中获取
信息的一些技术。
整个事例用到login.jsp, date.jsp , 索引的index.html
配置文件decorators.xml
装饰文件:window.jsp ,simple.jsp
运用的样式表:style.css
目标是把内容与布局分离,一达到简化布局,以及重用代码的作用。
实质是使用simple.jsp,window.jsp以及提取的longin.jsp,date,jsp的实际主体来构成最终显示
给用户的页面。
布局主体是simple.jsp控制:它控制了网页的整体架构。
<%@ taglib uri="sitemesh-decorator" prefix="decorator" %>
<%@ taglib uri="sitemesh-page" prefix="page" %>
<html>
<head>
<title><decorator:title/></title>
<link rel="stylesheet" href="decorators/style.css">
<decorator:head/>
</head>
<body>
<table width="100%">
<tr>
<td class="title" colspan="2">
<decorator:title/>
</td>
</tr>
<tr>
<td class="body" valign="top">
<decorator:body/>
</td>
<td valign="top">
<page:applyDecorator name="window" page="date.jsp"/>
<page:applyDecorator name="window" title="Disclaimer">
This site is not legally binding in any way. <br>
All rights reserved. Elvis has left the building.
</page:applyDecorator>
</td>
</tr>
<tr>
<td class="footer" valign="top" colspan="2">
<b>Title:</b> <decorator:title/> <br>
<b>Author:</b> <decorator:getProperty property="meta.author"/> <br>
</td>
</tr>
</table>
</body>
</html>
这个文件将在decorators.xml中被定义,其中给出装饰器的名称,位置,模式匹配。
模式匹配可以使用通配符和正则表达式。在这对于simple.jsp使用了通配符*配置该
装饰器用来匹配Web应用中的所有网页。有关正则表达式的相关内容请参看本博客 http://192.168.0.3/blog3/meiking_archive_2005_05_20_18525.html)。
<decorators>
<decorator name="simple" page="/decorators/simple.jsp">
<pattern>*</pattern>
</decorator>
</decorators>
上面我们讨论了装饰器设计模式,将装饰器和内容组合,下面我们来看看如何运用组合设计模式
在页面中引用子装饰器 ,子内容。
让我们来看看一个子装饰器window.jsp
<%@ taglib uri="sitemesh-decorator" prefix="decorator" %>
<table class="window">
<tr>
<th><img src="decorators/snazzy.gif"><decorator:title/></th>
</tr>
<tr>
<td>
<decorator:body/>
</td>
</tr>
</table>
在回头看看simple.jsp在其中我们已经包含了window.jsp的运用,我们把他运用到了date.jsp
上,运用样式表date.jsp的主体内容应该会出现在最终显示页面的右上角。
在decorators.xml中被定义
<decorators>
<decorator name="window" page="/decorators/window.jsp"/>
</decorators>
现在我们可以给出完整的decorators.xml了:
<decorators>
<decorator name="simple" page="/decorators/simple.jsp">
<pattern>*</pattern>
</decorator>
<decorator name="window" page="/decorators/window.jsp"/>
</decorators>
在装饰器中拥有一个技术:sitemesh有一个pageparser对象,它通过内容网页获取输出的内容
并把它解析到一个page对象中
假如一个内容网页有如下列标题:
<html>
<head>
<title>Please login</title>
<meta name="author" content="Homer Simpson">
</head>
...
装饰器使用JSP标识符可以访问title属性,也能访问auther属性
让我们看看simple是如何做的:
<%@ taglib uri="sitemesh-decorator" prefix="decorator" %>
...
<b>Title:</b> <decorator:title/> <br>
<b>Author:</b> <decorator:getProperty property="meta.author"/> <br>
...
简单的login.jsp,date.jsp页面
login.jsp
<html>
<head>
<title>Please login</title>
<meta name="author" content="Homer Simpson">
</head>
<body>
<form action="#" method="post">
<input type="hidden" name="section" value="store">
Login Name:<br>
<input type="text" name="loginname"><br>
Password:<br>
<input type="password" name="password"><br>
<input type="submit" value="Login">
</form>
</body>
</html>
<--------------------------------------------------->
date.jsp
<html>
<head>
<title>Time and date</title>
<meta name="author" content="Fred Flintstone">
</head>
<body>
Right now, it's:<br>
<b><%= new java.util.Date().toString() %></b>
</body>
</html>
其他:1 对于页面可将公共代码重构到应用文件中来简化代码和重用代码
2 对于页面可以使用样式表做的更彻底,使页面的主体部分不会淹没带大量的结构代码中
作者:by Will Iverson 03/11/2004
汉化:by AndNeT 03/24/2005
注:sitemesh,一个不错的tiles替代方案,比tiles做的更漂亮优雅。本文是sitemesh官方推荐的入门文档,本来想自己翻译的,突然发现有人先行一步了,就转过来看吧。
以前我通常使用旧式的方法来建立自己的web应用:手工排版,仔细使用每一个字节使其工作在Unicode下,同时使用make文件来适应不同的CPU……
或许现在我们可以换一种方式。
尽管我从没有感觉到需要使用assembly (CISC or RISC)来建立web应用,但也会偶尔觉得我的开发伙伴的工作相当繁琐。特别是我发现很多的开发者在痛苦的寻求一种比较好的方式来控制web应用的基本 模块:例如那些页头、页尾、导航栏、打印页面、手持设备的轻量级页面,以及其他更多的问题。到了最后,令人惊异的是大部分人都采用了落后的 includes和复制粘贴方式。
根据经验,我可以采用在 java.net 上开源的servlet 过滤器 SiteMeshn 来简单明了并优雅的解决这些问题。作为一种替代新的templating语言(XSLT)或部署您的页面到新的系统的解决方法,应用SiteMesh可以 相当容易处理你的页面,这一切只需要普通的HTML,JSP,servlet(包括Struts),以及其他常用的技术。
工作原理
SiteMesh利用了一种很少人知道的servlet规范实现了一种页面过滤器。设想一下,现在有一个简单的jsp页面用来返回当前的日期和时 间。通常这个页面请求来到应用服务器,页面被处理,最后处理结果返回到web浏览器。SiteMesh作为一个页面过滤器,在页面被处理之后,返回web 浏览器之前,对页面做了一些附加的操作。这个变化简单描述为图一和图二所示的附加步骤。

图一:普通页面处理情况

图二:SiteMesh对页面处理情况
现在看一个简单的例子。
<html>
<head>
<title>Simple Document</title>
</head>
<body>
Hello World! <br />
<%= 1+1 %>
</body>
</html>
你会发现这个页面有一个title和body(类似普通的HTML页面)。你也会发现一小段JSP代码——它将会如同你期望的那样被处理。同时你可以使用任何你想使用的JSP语法和特性来替换这一小段代码。
现在来看一个简单的SiteMesh "装饰(decorator)"页面。列表2显示了一个被SiteMesh调用的JSP页面。
<%@ taglib uri="sitemesh-decorator"
prefix="decorator" %>
<html>
<head>
<title>
My Site - <decorator:title default="Welcome!" />
</title>
<decorator:head />
</head>
<body>
<h1><decorator:title default="Welcome!" /></h1>
<p><decorator:body /></p>
<p><small>
(<a
href="http://www.zhmy.com/?printable=true">printable version</a>
</small></p>
</body>
</html>
查看这个装饰器(decorator),我们能看到一些有趣的东西。首先,在第一行申明了一个SiteMesh标签库。这个标签库包含了与原始页面一起工作时所需的所有东西。你能看到我们使用了两个SiteMesh的装饰标签(declared tags), <decorator:title> 和 <decorator:body> 。不要惊讶于标签<decorator:title>在原始页面中显示<title>标签中的内容, <decorator:body> 中的内容也是如此。我们在这个页面的HEAD和BODY元素都使用了同一个title标签。(We're making a few fairly radical changes to the page, including repeating the title both in the HEAD element as well as the BODY. )同时,我们还增加了一个到可打印版本页面的链接。
作为对照,图三显示了原始处理页面,图四显示了被修饰过的处理页面。留意被装饰页面在浏览器窗口显示的标题文字和HTML内容。同时也可以看到增加了一个可打印页面的链接——这个我们回头再说。

图三:原始未修饰页面

图四:被修饰页面
很明显,对比起使用include(例如<jsp:include page="foo.jsp" flush="true" />)来说,以这样的方式使用页头、页尾系统结构要清晰得多。这种方式更易移植、更易理解,同时也鼓励了JSP页面不再使用导航或其他类似的表现层代码。我发现在JSP页面中使用装饰器和CSS的组合比标准HTML的标签更容易去除格式信息。
安装SiteMesh
注意下面的屏幕截图是基于Windows XP Professional, Tomcat 5.0.19, 和Java 2 SDK 1.4.2_03的环境之上的。在这里我假定你的Tomcat已经安装完毕并且可以正常工作了。你或许会有一些混淆,但我们已经成功地在Tomcat 4.1 和 WebLogic 测试过,同时 SiteMesh 也支持大部分的web应用服务器。
本文描述的SiteMesh 2.0.1可以在 下载到。 在java.net 上SiteMesh's 的项目库中有四个文件可以下载。sitemesh-2.0.1.jar 是其核心 JAR 文件, sitemesh-2.0.1-sources.zip 的作用正如同其名字所述, sitemesh-example.war 则提供了一个复杂的例子用来显示一些SiteMesh的高级特性。
为了使描述更加简单,我们从sitemesh-blank.war 文件开始。将该WAR文件放入Tomcat 的webapps 目录,WAR包将自动解压显示内容(SoSo注:这里的前提是你的tomcat已经开始工作),如图五所示。

图五: SiteMesh_blank.WAR解开后的内容
我们花点时间描述一下这些文件的作用。
web.xml
首先,WEB-INF/web.xml 文件显示如列表3,这些语句用来安装SiteMesh 过滤器和标签库。如果你决定在一个已有的Web应用中使用SiteMesh,你必须把这些语句添加到你的WEB-INF/web.xml 文件中。
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
<!-- Start of SiteMesh stuff -->
<filter>
<filter-name>sitemesh</filter-name>
<filter-class>com.opensymphony.module.sitemesh.filter.PageFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>sitemesh</filter-name>
<url-pattern>*.jsp</url-pattern>
</filter-mapping>
<taglib>
<taglib-uri>sitemesh-page</taglib-uri>
<taglib-location>/WEB-INF/sitemesh-page.tld</taglib-location>
</taglib>
<taglib>
<taglib-uri>sitemesh-decorator</taglib-uri>
<taglib-location>/WEB-INF/sitemesh-decorator.tld</taglib-location>
</taglib>
<!-- End of SiteMesh stuff -->
</web-app>
注意:这里需要注意一下url-pattern的写法-- 如果使用的是Tomcat 5(而不是 Tomcat 4 ),需要将默认的*修改如*.jsp的形式。最新的servlet规范不再支持*样式。
decorators.xml
WEB-INF/decorators.xml 文件用来将一个装饰器名字同一个专门的JSP装饰文件绑定。作为一个例子,这里将JSP装饰文件minimal.jsp同一个称为handheld的装饰器绑定起来。
<decorators defaultdir="/decorators">
<decorator name="main" page="main.jsp">
<pattern>*</pattern>
</decorator>
<decorator name="panel" page="panel.jsp"/>
<decorator name="printable" page="printable.jsp"/>
</decorators>
正如我们在代码列表里看到的一样,我们定义了三个装饰器,他们分别绑定了三个类似的JSP页面。我们可以看到一个默认装饰器(main.jsp),它将被默认运用于所有文件。
缺省的,SiteMesh使用下面的逻辑来选择使用哪一个装饰器:
|
这个逻辑在sitemesh-2.0.1.jar 包的 \com\opensymphony\module\sitemesh\factor\sitemesh-default.xml 文件里被描述。你可以针对诸如:客户端操作系统,web浏览器,用户代理等在WEB-INF\sitemesh.xml文件里,通过一个变量覆盖这个行为。(You can override this behavior with a wide variety of built-in mappers for things like language, client operating system, web browser/user agent, etc. by creating a WEB-INF\sitemesh.xml file. )可以在sitemesh-example.war 找到例子。 |
- 页面是否使用meta装饰器标签(meta decorator tag)特别指定了一个装饰器?
- 页面是否是一个框架集(是的话则不应用装饰器)?
- 页面是否使用了
printable=true参数(是的话则使用打印装饰器) - 页面时候使用装饰器文件名特别指定了一个装饰器?
- 页面是否匹配 decorators.xml 文件里描述的样式?
通常第一条规则仅用来确定该装饰器是否被使用(Conceptually, the first rule that evaluates to true determines the decorator that is used. )在上面的例子中,当出现printable=true 参数的时候,装饰器printable.jsp (规则 #3)替代了 main.jsp (规则 #5)。在SiteMesh中,这些规则被描述为 mappers。
decorators/*.jsp
这三个decorators目录下的文件是decorators.xml文件中描述的不同装饰器JSP文件。上面是一个简单的装饰器例子,在后面我们将讨论更复杂的示例。
sitemesh-2.0.1.jar
这是SiteMesh最主要的二进制文件,通常被安装在 WEB-INF/lib 目录下。可以在www.opensymphony.com/sitemesh/api 找到这个库的javadoc。
*.tld
SiteMesh使用两个标签库,但大多数人都只需要sitemesh-decorator.tld。你可以在 www.opensymphony.com/sitemesh/tags.html 找到相应的文档。我们已经讲述了最主要的标签:head,title和body。在下一章我们来讨论剩下的标签:getProperty。
SiteMesh高级特性
SiteMesh的一个重要特性是使用原始HTML的meta标签(例如<meta name="foo" content="bar">)从基础页面传递信息到装饰器。作为一个例子,下面我们使用一个meta标签来定义HTML页面的作者。
<html>
<meta name="author" content="test@example.com">
<head>
<title>Simple Document</title>
</head>
<body>
Hello World! <br />
<%= 1+1 %>
</body>
</html>
我们定义一个“smart”装饰器来研究meta标签,如果出现这个标签,则可以得到一个相应的HTML:
<%@ taglib uri="sitemesh-decorator" prefix="decorator" %>
<decorator:usePage id="myPage" />
<html>
<head>
<title>My Site -
<decorator:title default="Welcome!" />
</title>
<decorator:head />
</head>
<body>
<h1><decorator:title default="Welcome!" /></h1>
<h3>
<a href="mailto:<decorator:getProperty property="meta.author"
default="staff@example.com" />">
<decorator:getProperty property="meta.author"
default="staff@example.com" />
</a></h3><hr />
<decorator:body />
<p><small>
(<a href="http://www.zhmy.com/?printable=true">printable version</a>
</small>
</p>
</body>
</html>
可以看到我们使用了getProperty标签的一个默认属性——如果没有指定 author,我们就设定其为staff。如果你决定使用这个模型储存页面的meta数据,你或许需要和你的开发伙伴一起来确定将使用什么标签以及如何使 用他们。简单的,你或许想要使用meta标签来描述诸如页面作者及时间戳之类的东西。更复杂一些,你或许会想像XML文件一样标准化的管理你的站点导航, 同时使用meta标签来通过页面节点转到装饰器。(At the complex end, you may do things like standardize on an XML file to manage your site navigation and use a meta tag to pass the page's node to the decorator. )
图六显示了应用上面的装饰器JSP页面之后生成的结果。

图六:meta标签显示
这些页面属性非常强大,并且拥有着很多不同的特性,并不仅止于meta标签( 常用页面特性列表)。使用SiteMesh一段时间之后,你就会开始思考HTML和JSP作为一种简单标记语言的机制——接近最原始的HTML——无需操作就可以完整的切换到XML/XSL 或其他模版引擎。
小结
综上所述,SiteMesh 提供了一个强大、易用、易结合的机制来使用页面模版。可以想象,它将会有很广泛的用户群。例如,你可以定义一个装饰器针对不同的浏览器输出额外的页面调试 信息(和特定web浏览器结合之后将产生一个特别的功能,你可以强制指定使用某一种用户代理)。你也可以定义一个装饰器产生stripped-down XML输出,用来进行简单的自动化测试。你甚至可以使用装饰器从其他页面提取内容,例如输出到一些简单的门户容器。
从sitemesh-blank.war入手比较容易,但我建议学习 sitemesh-example.war 以获取更多的特性和思想。
不论你如何使用SiteMesh,我都发现它将大量的代码从表现层中移到我的装饰器中,而无需学习一种新的编程语言或是模版系统。
对了,作为最后的补充,如果你仍然对组合建立web页面感兴趣,可以查看home.worldonline.dk/viksoe/asmil.htm 。
祝好运并享受编程的乐趣!
━正方━━━━━━━━━━━━
可以把普通的Java程序做成真正的exe,也就是单一个exe就可以在没有安装JVM的机器上运行。这样的工具
常见的有JET和gcj.前者是收费的,而且做出来的exe还是需要一堆dll。推荐使用gcj.他有windows和
Linux版,直接下载zip包,不需要安装,里面有不少例子,一些build的批处理文件。从原理来说gcj自己
实现了JVM规范,也就是你编写一个HelloWorld.java,其中的main方法为System.out.println("foo");
当使用gcj把它做成exe(大约2M),运行这个exe时,会启动里面的一个小型jvm,在这上面跑HelloWorld。
其实,把Java做成纯exe实在是吃力不讨好,有很多限制,文件又大。
我比较倾向另几种做法:
. 使用InstallAnywhere等工具,制作一个exe的安装包
用户可以选择使用他机器上的JRE或是这个安装包内的JRE来运行程序
这是很常见的一种做法,如JBuilder就是这么做的。
这样的好处是不要求对方机器上装有JRE,而且你原来的程序不需要任何改动。
InstallAnywhere中一个压缩的JRE大概是8M。
. 制作成可执行的jar,也就是在META-INF的MANIFEST文件制定Main-Class
可以通过命令行java -jar jarfile.jar来执行,windows默认的把*.jar使用javaw -jar打开,所以有些
机器上可以直接双击jar运行。
. 制作伪exe,其实和上一种做法是一样的,只不过做成exe,调用系统的java.exe来运行它,这样的工具有
nativeJ,exe4j等
━反方━━━━━━━━━━━━━━━━━━
class文件是一种跨平台的字节码,必须依赖平台相关的JRE来运行。Java以此来实现跨平台.有些开发工
具可以将java文件编译为exe文件。
作者反对这种做法,因为这样就取消了跨平台性。如果你确信你的软件只在Windows平台上运行,你可以
作者:cleverpig
版权声明:本文可以自由转载,转载时请务必以超链接形式标明文章原始出处和作者信息及本声明
作者:cleverpig(
http://blog.matrix.org.cn/page/cleverpig)
原文:[
http://www.matrix.org.cn/resource/article/43/43987_JGroups.html ]
http://www.matrix.org.cn/resource/article/43/43987_JGroups.html [/url]
关键字:jGroups,群组,通讯
项目简介:
JGroups 是一个开源的纯java编写的可靠的群组通讯工具。其工作模式基于IP多播,但可以在可靠性和群组成员管理上进行扩展。其结构上设计灵活,提供了一种灵活 兼容多种协议的协议栈,对于每个产品都有不同的可靠性需求。这种协议栈可以让用户定义的自己可靠性指标和性能指标。
一、可靠性:
* 通过使用重传丢失信息的技术保证每条群组消息被发送到所有接收者;
* 将大块消息分解为多个小块消息发送,并在接收方重新组装;
* 确保消息的顺序性,例如由发送者P发送的两条消息m1和m2按照相同的顺序(FIFO)被所有接收者接收;
* 保证消息收发的原子性,一条消息或者被所有接收者接收或者没有一个接收者收到。
二、群组成员管理:
* 轻松获得每个分组的成员信息;
* 当新成员加入、当前成员离开或者一个当前成员掉线时,组内成员均会获得通知。
三、JGroups支持的多种协议堆栈:
下表是JGroups支持的协议:
工作模式 不可靠的 可靠的
单播 UDP TCP
多播 IP多播 JGroups
1.单播模式:
在单播通讯模式下,系统使用UDP和TCP两种协议完成一下过程:一个消息发送者发送一个消息给某个接收者。
众所周知,UDP协议是不可靠的,数据包可能在传输过程中丢失、重复、没有按照发送顺序到达,而且作为UDP数据包大小还受限于数据包的最大上限。
TCP协议也是一种单播的方式,但是它对于信息的丢失采取了消息重传的手段,有效地避免了数据重复,并将长度大于数据包的最大上限的数据进行分解,提供了这些分解后的数据给应用程序进行发送。
2.多播模式:
在 多播通讯模式下,一个消息发送者可以将一条消息发送给多个接收者。IP多播扩展了UDP协议:一个发送者发送一条消息到一个多播地址,导致加入这个多播地 址的接收者都会接收到此消息。像UDP一样,这种消息传输方式仍然是不可靠的,在这里对于加入到多播地址的接受者来讲并不被作为成员对待。
四、JGruops的灵活性体现:
JGroups 扩展了可靠的单播消息传输到多播的设置中。就像上面所讲的,它提供了基于IP多播的群组成员管理和可靠性。之所以这样说,是因为每个应用程序具有不同的可 靠性需求,JGroups将一套灵活的协议堆栈作为其协议构架,允许用户使用自定义的混合协议堆栈,自由的在不可靠性但是速度较快的协议堆栈--到高可靠 性但速度稍慢的协议堆栈之间选择。
例如,一个使用者可能在开始时采用IP多播作为唯一的协议堆栈。为了增加消息传输的无损性,他可能增加 NAKACK协议(一种可以减少重复数据包的协议)。此时当消息总能够从发送者发送到接收者,但是数据包发送与接收的顺序却无法定义。因此,使用者将选择 利用每个发送者发送顺序的FIFO层对消息进行排序。当要求此排序应用于所有发送者时,使用者就要在协议堆栈中增加TOTAL协议。群组成员关系服务 (GMS)和FLUSH协议应用于群组管理中:它允许使用者注册一个回调函数,此函数在成员关系变化(例如成员加入、离开、掉线等事件)时被调用。最后, 失败检测(FD)协议是GMS在通知掉线成员时所需要的,如果一个新成员需要获得当前所有成员状态,状态传输(STATE_TRANSFER)协议就需要 添加到自定义协议堆栈中。当使用者需要加密信息,则可以方便的加密(CRYPT)协议(负责加密/解密消息,使用密钥发布工具来重新发布密钥)。
通过使用这些协议的集合可以灵活的根据应用需求建立可靠的多播(或者单播)通讯,它给我们带来了以下的便利:
* 用户只使用定义好的协议堆栈,而不是全部协议;
* 由于这些协议互不依赖,并且可以被修改、替换、增加新协议,从而提高了系统的模块程度及维护能力。
五、参考资料:
Apache论坛:
http://www.matrix.org.cn/topic.shtml?forumId=17
jgroups官方文档:
http://www.jgroups.org/javagroupsnew/docs/overview.html
如果你曾经用过Perl或任何其他内建正则表达式支持的语言,你一定知道用正则表达式处理文本和匹配模式是多么简单。如果你不熟悉这个术语,那么“正则表达式”(Regular Expression)就是一个字符构成的串,它定义了一个用来搜索匹配字符串的模式。
| 许 多语言,包括Perl、PHP、Python、JavaScript和JScript,都支持用正则表达式处理文本,一些文本编辑器用正则表达式实现高级 “搜索-替换”功能。那么Java又怎样呢?本文写作时,一个包含了用正则表达式进行文本处理的Java规范需求(Specification Request)已经得到认可,你可以期待在JDK的下一版本中看到它。 |
| 然而,如果现在就需要使用正则表达式,又该怎么办呢?你可以从Apache.org下载源代码开放的Jakarta-ORO库。本文接下来的内容先简要地介绍正则表达式的入门知识,然后以Jakarta-ORO API为例介绍如何使用正则表达式。 |
| 一、正则表达式基础知识 |
| 我们先从简单的开始。假设你要搜索一个包含字符“cat”的字符串,搜索用的正则表达式就是“cat”。如果搜索对大小写不敏感,单词“catalog”、“Catherine”、“sophisticated”都可以匹配。也就是说: |
|
| 1.1 句点符号 |
| 假 设你在玩英文拼字游戏,想要找出三个字母的单词,而且这些单词必须以“t”字母开头,以“n”字母结束。另外,假设有一本英文字典,你可以用正则表达式搜 索它的全部内容。要构造出这个正则表达式,你可以使用一个通配符——句点符号“.”。这样,完整的表达式就是“t.n”,它匹配“tan”、“ten”、 “tin”和“ton”,还匹配“t#n”、“tpn”甚至“t n”,还有其他许多无意义的组合。这是因为句点符号匹配所有字符,包括空格、Tab字符甚至换行符: |
|
| 1.2 方括号符号 |
| 为 了解决句点符号匹配范围过于广泛这一问题,你可以在方括号(“[]”)里面指定看来有意义的字符。此时,只有方括号里面指定的字符才参与匹配。也就是说, 正则表达式“t[aeio]n”只匹配“tan”、“Ten”、“tin”和“ton”。但“Toon”不匹配,因为在方括号之内你只能匹配单个字符: |
![]() |
| 1.3 “或”符号 |
| 如 果除了上面匹配的所有单词之外,你还想要匹配“toon”,那么,你可以使用“|”操作符。“|”操作符的基本意义就是“或”运算。要匹配“toon”, 使用“t(a|e|i|o|oo)n”正则表达式。这里不能使用方扩号,因为方括号只允许匹配单个字符;这里必须使用圆括号“()”。圆括号还可以用来分 组,具体请参见后面介绍。 |
|
| 1.4 表示匹配次数的符号 |
| 表一显示了表示匹配次数的符号,这些符号用来确定紧靠该符号左边的符号出现的次数: |
|
|
| 假 设我们要在文本文件中搜索美国的社会安全号码。这个号码的格式是999-99-9999。用来匹配它的正则表达式如图一所示。在正则表达式中,连字符 (“-”)有着特殊的意义,它表示一个范围,比如从0到9。因此,匹配社会安全号码中的连字符号时,它的前面要加上一个转义字符“\”。 |
|
|
|
图一:匹配所有123-12-1234形式的社会安全号码 |
| 假设进行搜索的时候,你希望连字符号可以出现,也可以不出现——即,999-99-9999和999999999都属于正确的格式。这时,你可以在连字符号后面加上“?”数量限定符号,如图二所示: |
|
|
|
图二:匹配所有123-12-1234和123121234形式的社会安全号码 |
| 下面我们再来看另外一个例子。美国汽车牌照的一种格式是四个数字加上二个字母。它的正则表达式前面是数字部分“[0-9]{4}”,再加上字母部分“[A-Z]{2}”。图三显示了完整的正则表达式。 |
|
|
|
图三:匹配典型的美国汽车牌照号码,如8836KV |
| 1.5 “否”符号 |
| “^”符号称为“否”符号。如果用在方括号内,“^”表示不想要匹配的字符。例如,图四的正则表达式匹配所有单词,但以“X”字母开头的单词除外。 |
|
|
|
图四:匹配所有单词,但“X”开头的除外 |
| 1.6 圆括号和空白符号 |
| 假设要从格式为“June 26, 1951”的生日日期中提取出月份部分,用来匹配该日期的正则表达式可以如图五所示: |
|
|
|
图五:匹配所有Moth DD,YYYY格式的日期 |
| 新出现的“\s”符号是空白符号,匹配所有的空白字符,包括Tab字符。如果字符串正确匹配,接下来如何提取出月份部分呢?只需在月份周围加上一个圆括号创建一个组,然后用ORO API(本文后面详细讨论)提取出它的值。修改后的正则表达式如图六所示: |
|
|
|
图六:匹配所有Month DD,YYYY格式的日期,定义月份值为第一个组 |
| 1.7 其它符号 |
| 为简便起见,你可以使用一些为常见正则表达式创建的快捷符号。如表二所示: |
| 表二:常用符号 |
|
|
| 例如,在前面社会安全号码的例子中,所有出现“[0-9]”的地方我们都可以使用“\d”。修改后的正则表达式如图七所示: |
|
|
|
图七:匹配所有123-12-1234格式的社会安全号码 |
| 二、Jakarta-ORO库 |
| 有 许多源代码开放的正则表达式库可供Java程序员使用,而且它们中的许多支持Perl 5兼容的正则表达式语法。我在这里选用的是Jakarta-ORO正则表达式库,它是最全面的正则表达式API之一,而且它与Perl 5正则表达式完全兼容。另外,它也是优化得最好的API之一。 |
| Jakarta-ORO库以前叫做OROMatcher,Daniel Savarese大方地把它赠送给了Jakarta Project。你可以按照本文最后参考资源的说明下载它。 |
| 我首先将简要介绍使用Jakarta-ORO库时你必须创建和访问的对象,然后介绍如何使用Jakarta-ORO API。 |
| ▲ PatternCompiler对象 |
| 首先,创建一个Perl5Compiler类的实例,并把它赋值给PatternCompiler接口对象。Perl5Compiler是PatternCompiler接口的一个实现,允许你把正则表达式编译成用来匹配的Pattern对象。 |
|
| ▲ Pattern对象 |
| 要把正则表达式编译成Pattern对象,调用compiler对象的compile()方法,并在调用参数中指定正则表达式。例如,你可以按照下面这种方式编译正则表达式“t[aeio]n”: |
|
| 默认情况下,编译器创建一个大小写敏感的模式(pattern)。因此,上面代码编译得到的模式只匹配“tin”、“tan”、 “ten”和“ton”,但不匹配“Tin”和“taN”。要创建一个大小写不敏感的模式,你应该在调用编译器的时候指定一个额外的参数: |
|
| 创建好Pattern对象之后,你就可以通过PatternMatcher类用该Pattern对象进行模式匹配。 |
| ▲ PatternMatcher对象 |
| PatternMatcher 对象根据Pattern对象和字符串进行匹配检查。你要实例化一个Perl5Matcher类并把结果赋值给PatternMatcher接口。 Perl5Matcher类是PatternMatcher接口的一个实现,它根据Perl 5正则表达式语法进行模式匹配: |
|
| 使用PatternMatcher对象,你可以用多个方法进行匹配操作,这些方法的第一个参数都是需要根据正则表达式进行匹配的字符串: |
| · boolean matches(String input, Pattern pattern):当输入字符串和正则表达式要精确匹配时使用。换句话说,正则表达式必须完整地描述输入字符串。 |
| · boolean matchesPrefix(String input, Pattern pattern):当正则表达式匹配输入字符串起始部分时使用。 |
| · boolean contains(String input, Pattern pattern):当正则表达式要匹配输入字符串的一部分时使用(即,它必须是一个子串)。 |
| 另 外,在上面三个方法调用中,你还可以用PatternMatcherInput对象作为参数替代String对象;这时,你可以从字符串中最后一次匹配的 位置开始继续进行匹配。当字符串可能有多个子串匹配给定的正则表达式时,用PatternMatcherInput对象作为参数就很有用了。用 PatternMatcherInput对象作为参数替代String时,上述三个方法的语法如下: |
| · boolean matches(PatternMatcherInput input, Pattern pattern) |
| · boolean matchesPrefix(PatternMatcherInput input, Pattern pattern) |
| · boolean contains(PatternMatcherInput input, Pattern pattern) |
| 三、应用实例 |
| 下面我们来看看Jakarta-ORO库的一些应用实例。 |
| 3.1 日志文件处理 |
| 任务:分析一个Web服务器日志文件,确定每一个用户花在网站上的时间。在典型的BEA WebLogic日志文件中,日志记录的格式如下: |
![]() |
| 分析这个日志记录,可以发现,要从这个日志文件提取的内容有两项:IP地址和页面访问时间。你可以用分组符号(圆括号)从日志记录提取出IP地址和时间标记。 |
| 首先我们来看看IP地址。IP地址有4个字节构成,每一个字节的值在0到255之间,各个字节通过一个句点分隔。因此,IP地址中的每一个字节有至少一个、最多三个数字。图八显示了为IP地址编写的正则表达式: |
|
|
|
图八:匹配IP地址 |
| IP地址中的句点字符必须进行转义处理(前面加上“\”),因为IP地址中的句点具有它本来的含义,而不是采用正则表达式语法中的特殊含义。句点在正则表达式中的特殊含义本文前面已经介绍。 |
| 日志记录的时间部分由一对方括号包围。你可以按照如下思路提取出方括号里面的所有内容:首先搜索起始方括号字符(“[”),提取出所有不超过结束方括号字符(“]”)的内容,向前寻找直至找到结束方括号字符。图九显示了这部分的正则表达式。 |
|
|
|
图九:匹配至少一个字符,直至找到“]” |
| 现在,把上述两个正则表达式加上分组符号(圆括号)后合并成单个表达式,这样就可以从日志记录提取出IP地址和时间。注意,为了匹配“- -”(但不提取它),正则表达式中间加入了“\s-\s-\s”。完整的正则表达式如图十所示。 |
|
|
|
图十:匹配IP地址和时间标记 |
| 现在正则表达式已经编写完毕,接下来可以编写使用正则表达式库的Java代码了。 |
| 为使用Jakarta-ORO库,首先创建正则表达式字符串和待分析的日志记录字符串: |
|
| 这 里使用的正则表达式与图十的正则表达式差不多完全相同,但有一点例外:在Java中,你必须对每一个向前的斜杠(“\”)进行转义处理。图十不是Java 的表示形式,所以我们要在每个“\”前面加上一个“\”以免出现编译错误。遗憾的是,转义处理过程很容易出现错误,所以应该小心谨慎。你可以首先输入未经 转义处理的正则表达式,然后从左到右依次把每一个“\”替换成“\\”。如果要复检,你可以试着把它输出到屏幕上。 |
| 初始化字符串之后,实例化PatternCompiler对象,用PatternCompiler编译正则表达式创建一个Pattern对象: |
|
| 现在,创建PatternMatcher对象,调用PatternMatcher接口的contain()方法检查匹配情况: |
|
| 接下来,利用PatternMatcher接口返回的MatchResult对象,输出匹配的组。由于logEntry字符串包含匹配的内容,你可以看到类如下面的输出: |
![]() |
| 3.2 HTML处理实例一 |
| 下面一个任务是分析HTML页面内FONT标记的所有属性。HTML页面内典型的FONT标记如下所示: |
|
| 程序将按照如下形式,输出每一个FONT标记的属性: |
|
| 在这种情况下,我建议你使用两个正则表达式。第一个如图十一所示,它从字体标记提取出“"face="Arial, Serif" size="+2" color="red"”。 |
|
|
|
图十一:匹配FONT标记的所有属性 |
| 第二个正则表达式如图十二所示,它把各个属性分割成名字-值对。 |
|
|
|
图十二:匹配单个属性,并把它分割成名字-值对 |
| 分割结果为: |
|
| 现 在我们来看看完成这个任务的Java代码。首先创建两个正则表达式字符串,用Perl5Compiler把它们编译成Pattern对象。编译正则表达式 的时候,指定Perl5Compiler.CASE_INSENSITIVE_MASK选项,使得匹配操作不区分大小写。 |
| 接下来,创建一个执行匹配操作的Perl5Matcher对象。 |
|
| 假设有一个String类型的变量html,它代表了HTML文件中的一行内容。如果html字符串包含FONT标记,匹配器将返回true。此时,你可以用匹配器对象返回的MatchResult对象获得第一个组,它包含了FONT的所有属性: |
|
| 接 下来创建一个PatternMatcherInput对象。这个对象允许你从最后一次匹配的位置开始继续进行匹配操作,因此,它很适合于提取FONT标记 内属性的名字-值对。创建PatternMatcherInput对象,以参数形式传入待匹配的字符串。然后,用匹配器实例提取出每一个FONT的属性。 这通过指定PatternMatcherInput对象(而不是字符串对象)为参数,反复地调用PatternMatcher对象的contains() 方法完成。PatternMatcherInput对象之中的每一次迭代将把它内部的指针向前移动,下一次检测将从前一次匹配位置的后面开始。 |
| 本例的输出结果如下: |
|
| 3.3 HTML处理实例二 |
| 下面我们来看看另一个处理HTML的例子。这一次,我们假定Web服务器从widgets.acme.com移到了newserver.acme.com。现在你要修改一些页面中的链接: |
|
| 执行这个搜索的正则表达式如图十三所示: |
|
|
|
图十三:匹配修改前的链接 |
| 如果能够匹配这个正则表达式,你可以用下面的内容替换图十三的链接: |
![]() |
| 注意#字符的后面加上了$1。Perl正则表达式语法用$1、$2等表示已经匹配且提取出来的组。图十三的表达式把所有作为一个组匹配和提取出来的内容附加到链接的后面。 |
现在,返回Java。就象前面我们所做的那样,你必须创建测试字符串,创建把正则表达式编译到Pattern对象所必需的对象,以及创建一个PatternMatcher对象: |
| 接下来,用com.oroinc.text.regex包Util类的substitute()静态方法进行替换,输出结果字符串: |
|
| Util.substitute()方法的语法如下: |
|
| 这 个调用的前两个参数是以前创建的PatternMatcher和Pattern对象。第三个参数是一个Substiution对象,它决定了替换操作如何 进行。本例使用的是Perl5Substitution对象,它能够进行Perl5风格的替换。第四个参数是想要进行替换操作的字符串,最后一个参数允许 指定是否替换模式的所有匹配子串(Util.SUBSTITUTE_ALL),或只替换指定的次数。 |
Java语言规格说明(译自Java language specification, 略加详述)
词法问题
Java程序的编写采用泛代码Unicode字符集,若采用其它的字符集,则需在编译前转换成Unicode。
1 Java语言提供了3种形式的注释:
//text 从//到本行结束的所有字符均作为注释而被编译器忽略。
/* text */ 从/*到*/ 间的所有字符会被编译器忽略。
/** text */
当这类注释出现在任何声明之前时将会作特殊处理,它们不能再用
在代码的任何地方。这类注释意味着被括起来的正文部分,应该作为声
明项目的描述,而被包含在自动产生的文档中。
(一)断点续传的原理
其实断点续传的原理很简单,就是在Http的请求上和一般的下载有所不同而已。
打个比方,浏览器请求服务器上的一个文时,所发出的请求如下:
假设服务器域名为wwww.sjtu.edu.cn,文件名为down.zip。
GET /down.zip HTTP/1.1
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-
excel, application/msword, application/vnd.ms-powerpoint, */*
Accept-Language: zh-cn
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)
Connection: Keep-Alive




