??xml version="1.0" encoding="utf-8" standalone="yes"?> l策略对象(GPOQ是Zzd目录QADQ的对象Q用户可以通过它集中地对Win2K台式机和服务器系l进行配|,它的功能包括从NT 4.0台式机的锁定到安全性配|和软g安装{? q篇文章主要讲述l策略是如何对系lv作用的、系l内部的工作原理以及在Win2K环境中采用这一技术时应该注意的问题? 一、组{略是什么? 微Y理控制収ͼMMCQ中的组{略~辑器(GPEQ插件与NT 4.0中的pȝ{略~辑器poledit.exe相当。在GPE中的每个功能节点Q例如Y件设|、Windows 讄、管理模块等Q都是MMC插g扩展Q在MMC插g中扩展是可选的理工具Q如果你是应用程序开发者,可以通过定制的扩展拓展GPO的功能,从而针对你的应用程序提供附加的{略控制? 只有q行Win2K的系l可以执行组{略Q运行NT 4.0和Windows 9x的客h则无法识别到或运行具有AD架构的GPO? 二、组{略和AD q个操作的作用与NT 4.0中的poledit.exe相同Q可以打开本地{略文g。第2U方法,可以通过在MMC控制C选择GPE插gQƈ选择本地或远E计机来h工地~辑本地GPO? 本地GPO支持除Y件安装和文g多w定向之外的所有缺省扩展,因此Q只利用本地GPO你不能完成这些工作,如果惛_分发挥GPO的功能,q是需要AD的支持? 三、GPO的多h和l承 在一个域或组l单位(OUQ中~辑{略的途径有几U。在zd目录用户或计机MMC插g中,叛_一个域或组l单位(OUQ,在菜单中选择“属?#8221;Q然后选择“l策?#8221;标签。在~辑地址中的{略Ӟ需要右?#8220;zd目录地址和服?#8221;插gQ然后右击需要的地址得到其GPO。此外,q可以从“开?#8221;菜单Q选择“q行”Q然后键入: mmc.exe 启动MMCQ选择“控制?#8221;Q?#8220;增加/删除”插gQ然后选择“l策?#8221;插g?#8220;览”Q在AD域内的GPO׃昄出来Q可以选择一个GPOq行~辑? ҎGPO在AD名字I间中的不同位置Q可以有几个GPO对用户对象或计算机对象v作用。只有域中的其他对象是通过l承生成时GPO才是通过l承生成的。Win2K通过下面的方式执行GPOQ首先,操作pȝ执行现有的本地系l上的策略,然后QWin2K执行定义的地址U的GPO、域一U的GPO和基于OU的GPOQ微软把q一优先序取其首个字母~写为LSDOUQ执行的序依次是本地、地址、域、OU层次的GPOQ,用户可以在这个链上的许多层次上定义GPO。我们以pilot域ؓ例说明如何察看一个系l中的GPOQ启?#8220;zd目录用户和计机MMC”工具Q右击pilot域名Q从菜单中选择“属?#8221;,然后选择l策略标{。在q个列表端的GPOQ例如域范围的安全策略)有最高的优先权,因此QWin2K最后才会执行它。除了本地系l外Q可以在每个层次上定义几个GPOQ因此如果不能严格地理GPOQ就会出C必要的问题? GPO的承模型与Novell公司的Zenworks{略方式截然不同。在Zenworks中,如果在Novell目录服务QNDSQ树上的不同点用多个策略包Q只有距ȝ户对象最q的{略包才起作用。在Win2K中,如果在AD的不同层ơ上定义四个GPOQ操作系l?#8220;LSDOU”优先序来执行这些策略,对计机或用L作用是这四个{略执行?#8220;?#8221;。此外,有时在一个GPO中的讄会被其他GPO中的讄抵销。通过ADUGPOQ用户可以拥有更多的{略控制委托Q例如,公司的安全部门负责在域一U上设计用于所有系l设备的安全GPO。通过使用GPO,可以让某个OU的系l管理员拥有在OU上安装Y件的权利。在Zenworks模型中,必须在希望用策略的所有层ơ上复制q些{略Q而且{略对用h计算机对象的作用q是所有策略的“?#8221;? Zq一步地控制GPOQ微软提供了三种讄来限制GPOl承的复杂性。在地址、域、OU三个层次上用户都可以通过选择一个检查框L从更高一个层ơ上q行l承Q同P在每一个层ơ上Q用户可以选择~省的域{略选项Q方法是打开“zd目录用户和计机”插gQ右击GPO所在的域或OUQ从菜单中选择“属?#8221;Q然后选择“l策?#8221;标签。让你希望修改的目变亮Q然后选择“选项”按钮Q可供选择的选项?#8220;不覆?#8221;?#8220;止”。如果选择?#8220;不覆?#8221;选项Q即佉K择了不能承的查框Q该GPOq是会v作用。如果想在Q何一个地Ҏ行一个GPOӞq一功能很有用处。如果一个OU的管理员试图L对安全策略的l承Q包含安全策略的GPO仍然会被pȝ执行?#8220;止”查框可以完全止一个GPO执行Q这一功能在你对一个GPOq行~辑而不惌其他的用h行它时特别有效? 四、GPO的执行和qo 管只有AD中的计算机和用户对象才能执行GPOQ但我们可以qoGPO的效果。用Win2K中的安全l、应用组{略━━q是Win2K中的一Ҏ的安全特性,可以使特定的用户l不能执行某一个GPO。右击MMC中GPO的名字,选择“属?#8221;Q然后再选择“安全”Q就可以看到GPO目前的安全设|。认证用Lh应用l策略权利,从而附属这一GPO的所有用户可以执行它。在Win2K中,安全l可以包括用户和计算机对象。因此,利用安全l可以仔l地调整用户、计机对象如何执行一个GPO。你q可以对个别的应用程序应用安全组Q可以指z一个GPO的Y件安装部分。例如,假设你在一个GPO中发?0个应用程序,可以指定只让金融用户用户l访问其中的5个,其他用户d到这个域Ӟ它们也不会发现这5个应用程序? 五、GPO的内部构?/strong> 六、GPO带来的难?/strong> 另一个难题是{略的执行。如果在AD链上的许多层ơ上都存在有GPOQ在用户每次d或系l启动时都会执行所有的GPO。在Win2Kpȝ中,微Y推出了一些新的功能来优化pȝ的性能。首先,GPO的版本信息依赖于工作站和GPOQ如果GPO没有变化Q系l就不会执行它。另外,在GPE的属性页上,可以止用户或计机对GPO的执行。如果徏立一个GPO用来分发关闭pȝ或启动系l时的脚本,用GPO的用户配|部分,q样会工作站不能解析GPOq判断它是否已经发生了什么变化? 最后的一个难题v源于GPC和GPT是两个单独的实体。GPC是AD中的一个对象,它与GPT中包含的文g的复制不同步Q这意味着创徏一个GPOӞ在GPT开始向域控制器上的Sysvol复制文g之前GPC可能已经开始进行复制了? 所有问题的h都是׃AD使用了一U多M的复制模式。理ZQ当另一个系l管理员在一个域控制器上~辑一个GPOӞ你也可以在某个域上对它进行编辑。因此,当徏立一个GPEӞ~省状态下指的是在“操作M”中充当PDC的域控制器。(“操作M”是AD基础l构中的一pd托管功能Q用作PDC的服务器可以兼容q行NT和Win9x的工作站。)一般情况下Q可以通过只向数的系l管理员授予~辑GPO的权利来避免q种情况的发生,q保证如果有人在~辑GPOӞ让其他的人都知道。此外,需要注意的是,在对一个GPOq行~辑Ӟ?#8220;止”它,修改l束后重C能?/p>
GPO是一U与域、地址或组l单元相联系的物理策略。在NT 4.0pȝ中,一个单一的系l策略文Ӟ例如ntconfig.polQ包括所有的可以执行的策略功能,但它依赖于用戯机中的pȝ注册表的讄。在Win2K中,GPO包括文g和AD对象。通过l策略,可以指定Z注册表的讄、用NT 4.0格式.adm模板文g的运行Win2K的本地计机、域的安全设|和使用Windows安装E序的网lY件安装,q样在安装Y件时可以对文g夹进行重定向?
要充分发挥GPO的功能,需要有AD域架构的支持Q利用AD可以定义一个集中的{略Q所有的Win2K服务器和工作站都可以采用它。然而,每台q行Win2K的计机都有一个本地GPOQ驻留在本地计算机文件系l上的GPOQ,通过本地GPOQ可以ؓ每台工作站指定一个策略,它在AD域中不v作用。例如,Z安全原因Q你不会在AD域中配置公用的计机。利用本地GPOQ可以通过修改本地{略来得到安全性和对台式机的限制用而无需利用ZAD域的GPO。访问本地GPO的方法有2U,W?U方法,在需要修改GPO的计机?#8220;开?#8221;菜单上选择“q行”Q然后键入:gpedit.msc?
在AD中,可以在域、组l单位(OUQ或地址三个不同的层ơ上定义GPO。OU是AD中的一个容器,可以指派它对用户、组、计机{对象进行管理,地址是网l上子网的集合,地址形成了AD的复制分界线。GPO的名字空间被划分机配置和用户配|两个大c,只有用户和计机可以使用GPOQ象打印机对象甚至用L都不能应用GPO?
只有用户和计机对象才能执行l策略。在计算机的启动和关闭时QWin2K执行在GPO的计机配置部分定义的策略,在用L录和注销ӞWin2K执行在GPO中用户配|部分定义的{略。事实上Q在用户d时可以通过手动方式执行一些的{略Q例如可以在命o行方式下q行secedit.exeE序执行安全{略应用E序。此外,通过理员模块策略可以定期地对用户和计算机的GPO讄q行hQ缺省情况下Q这U刷新每90分钟q行一ơ,q种h可以使其他用户不Ҏ修改通过l策略定义的{略。但是,软g安装{略是不会刷新的Q因为没有h希望周期性地改变{略引v软g?#8220;??#8221;Q尤其是有其他用户在使用Ӟ更是这样了。计机、用户对象只有在计算机启动或用户d时才会Y件安装策略?
一个GPO是由两部分组成的Q组{略容器QGPCQ和l策略模板(GPTQ。GPC是GPO在AD中的一个实例,在一个特D的被称作系l的容器内有一?28位的全球唯一的ID码(GUIDQ。在“zd用户目录用户和计机”插g中选择“览”Q从MMC菜单中选择“高属?#8221;Q就可以看到“pȝ”容器。GPT是组{略在Win2K文gpȝ中的表现Q与一个GPO有关的所有文件依赖于GPT?
虽然GPO的功能很强大Q但要掌握它可不Ҏ。最难掌握的是如何判断一条有效的{略如何对域中的计算机或用户起作用,׃GPO可以存在于AD链中不同的层ơ上Q这U判断就特别困难。同Ӟ׃可以指派一个GPO的控Ӟ因此不大Ҏ清楚其他的GPO是否会对你没有控制权的容器中的GPO有媄响。因此,计算一个计机或用户对象接收的“{略的结果集”QRSoPQ是相当困难的。尽微软还没有提供计算RSoP的工P但已l有W三方厂商提供了相应的计RSoP的工兗?
]]>
Resource Kit实际上是Microsoft为管理员提供的一套额外的工具集,包括了超q?00个各U工PvbsQdllQmscQ涵盖了理TCP/IPQ网l,注册表,安全Q远E管理,配置QBatch文gQ以及操作系l的其他斚w。可以让你更Ҏ的管理一个NTpȝ。不得不承认q是一个非常庞大的工具集,包括C已经被h们所遗忘2K所应该h的功能。当你了解到了里面一些工L性能以后Q你会知道即仅仅只是一个C2U的操作pȝ也具有相当的安全性,对于l心配置的系l,d也只能伤其表面。但是,但是M东西都有他的两面性,ResKit非常具有代表性,在Hacker体中大家习惯把q个玩意叫做“Hacker的工L”。当然如果你惛_一个Hacker你得掌握里面的东西,而想当一个好的administrator你也得掌握里面的东西。希望大安可以好好看看?
W一部分Q管理你的计机
1. Appsec.exe QApplication SecurityQ?
Appsec.exe是一个基于GUI的应用程序,它允许管理员在一个多用户环境下限制普通用戯问一l网l上l预订的应用E序。启用这U应用程序安全性,会Dpȝ拒绝普通用h行或使用一个未l许可的应用E序。大?看这是不是一个很有用的工具呢Q对某些特定的程序进行限制以后,可以减少一些Hacker入R的可能,下面我们 l箋讨论?
对于2000来说一个显著的特点是引入了GPOQGroup PolicyQ这U东西,实际上就是一个界面化了的注册表编辑器Q但是因为GPO的存?000大大提高了他的安全性。一般来_我们可以通过配置GPO从启动菜单和桌面 上隐藏一个应用程序,但是不能止用户用其它手D访问它QAppsec增加了这U安全性,可以止用户执行应用 E序甚至是从命o行模式或者用其他的应用E序。Microsoft的徏议是和GPO一起用,攑֜Terminal Server上运行或者说是在应用E序q行的机器上使用。Appsec对于应用E序的限制还严|除了应用E序的名UC外还要包括该应用E序的全路径Q只有二者都附和才能够运行?
下面提几Ҏ意:
a. 只有理员或理员组的成员可以运行所有程序,用户Q包括PowerUserl)只能q行列表中的应用E序?
b. AppsecW一ơ启用时QTerminal Server的会话必M断,否则Appsec不能在本次会话中启用?
c. 实际上Appsec只能限制调用CreateProcessҎ的应用程序,不能限制使用NTCreateProcessҎ的程序,但是q种E序非常的少见?
d. Appsec只能限制32位的E序Q但是在默认情况下,一旦启用appsecM?6位程序的讉K都是止的,?是可以添加ntvdm.exe来16位程序可以被讉K?
e. 我想q个也是Appsec最大的~点QAppsecq不对程序本w进行检查,也就是所如果该有效E序q行替换 的话QAppsec不会发现。所以说我们必须止用户替换和重命名应用E序Q这可以用Security Template来做?
f. q有Appsec只可限制可执行文Ӟ不可以是DLLs?
g. Appsec的用是对于计算机的Q也是说一l启用用本机的用户都要受到限制?
另外Q应该要提到的一ҎQ按照Microsoft的要求,Appsec的列表中臛_应该有:
\Wtsrv\explorer.exe
\Wtsrv\system32\cmd.exe
\Wtsrv\system32\net.exe
\Wtsrv\system32\regini.exe
\Wtsrv\system32\subst.exe
\Wtsrv\system32\systray.exe
\Wtsrv\system32\xcopy.exe
q么几项?
当然啦!你去掉也是可以的Q但是会造成用户难以正常使用。嗯Q以我个人的Q如果你想防止Hacker入RLnet.exe会有意想不到的收P呵呵Qcmd.exe也是不错的选择Q如果不想管理员以外的Q何h讉Kql去掉就好,后果你们试试q道了?
p.s. q个E序所需要的文gAppsec.exeQ这个倒是在)QAppsec.hlpQ这个也在)Q但是Appsec.dllQ?
psec.cntQInstappsec.exeq没有包括在Resource Kit里面Q要ȝ站上自己下蝲Q!q简直是搞笑嘛!?
只有Microsoftq得出来。你可以在这个地方下载这个hotfix:
http://download.microsoft.com/download/win2000platform/Appsec/1.0/NT5/EN-US/appsec_hot
fix.exeQ?
安装以后可以用了?启用以后Q换个用P不是理员组Q登陆本机随便点个应用程序,你就可以看到Access to specified device, path or file is denied的警告,很厉害的Q哈哈!
2. Cachemov.exe (Offline Files Cache Mover)
Cachemov.exe一个有的东东Q用来移动离U文件的~存Q默认保存在根卷下)Q如果你觉得那东西在那个地方的你事的话Q把它挪个地方也没有什么问题。这个工h较简单就不再多说什么了Q就一个GUIQ然后选择 一个卷Q它p动帮你做完了Q很单。你也可以用无人值守模式 cachemov -unattend x:\ 电脑自己?定,此时需?Cchmvmsg.dll)。所有的l果会保存至应用E序日志?只是注意一下,q行旉要管理员的n份,q有是不能够移动到|络驱动器和可移动驱动器上去。移动以后不要改letterQ不然你会有ȝ的!
3. Defptr.exe QDefault PrinterQ?
如果你闲着没有事的话,可以用用q个东西。它允许你随意改变你的默认打印机Q可以在可用的网l和本地打印机间交换Q一旦运行以后会在右下角有个图标(如果不想看到图标可以使用defptr -i), q个东西可能ҎO游用户会有一点好处吧Q?
4. Delprof.exeQUser Profile Deletion UtilityQ?
删除用户的Profile时用的工P本来q个是可以在System Properties里面做的。而这个工具可以在本地?
是远E运行,看v来的好处是可以指定多长旉不用就删除Q在处理比较多的用户的时候才昑־出好处来Q就那么个把的话Q就自己做好了。稍微介l一下语法好了?
delprof /q /i /p /c:\\computername /days /?
/q 后台悄悄执行Q不用确认?
/i 忽略错误l箋删除?
/p 在删除前提示认?
/c:\\computername q个不用解释了吧Q?
/days 指定多少天不使用的Profile删除,days用整数?
/? 出现上面q些东东?
5. DelSrv.exe QDelete ServiceQ?
一个拿来删除服务用的工P使用h非常单,只要delsrv servicename可以了。没有什么好说的?
6. Dureg.exe QRegistry Size EstimatorQ?
q是一个用来评C的注册表储存了多数据的工具Q?
B*qp|?wE#&SIj
可以从Q何一个hiveQsubtree和subkey中读出。另?
Q这个工兯可以用来搜烦注册表中的text字符Ԍq种搜烦q可以具体到某个subtree中?
q个工具主要用于得出注册表具体占用空_对于开发h员和理员来说都是一个非常有用的工具。虽然我们可以用控刉板中的System选项和系l监视器中的Registry Quota in Use来监视注册表Q但是如果你只想知道某个单独的Key或者是Subkey所占用的空_?3o?]?3Fn|专\lz上面q些工具无能ؓ力了?
语法Q?
dureg /cr /cu /u /lm /a /s?d "registry_path" "string to search"
/a
表示查找整个注册表的大小?
dureg /a
Size of HKEY_CLASSES_ROOT : 7740324
Size of HKEY_USERS : 995732
Size of HKEY_LOCAL_MACHINE : 17265663
Total Registry data size: 26001719
/cr "registry_path"
默认情况下,q回的是HKEY_CLASSES_ROOT的大?
/cu "registry_path"
默认情况下,q回的是HKEY_CURRENT_USER的大?
/lm "registry_path"
默认情况下,q回的是HKEY_LOCAL_MACHINE的大?
/u "registry_path"
默认情况下,q回的是HKEY_USERS的大?
以上四个选项都可以在 "registry_path"中填入该Subkey下的Lkey。比如:
dureg /lm "software\microsoft",查找HKEY_LOCAL_MACHINE\Software\Microsoft key的大?
/s "string"
在注册表中搜索该字符丌Ӏ比如:
dureg /s "run" L和run相关的字W串。当然你也可以和/cr{这几个参数一起用,kS';`Bw育U8中L?(mE?/font>比如Qdureg /cr
/s "run"?
会看C大串昄Q这里就不写出来了?
7. Elogdmp.exe QEvent Log Query ToolQ?
一个命令行工具用来导出选定的日志中的信息。这是在屏幕上进行显C,最好和Find或者是Findstrq样的工?
一起用,不然太难扑ֈ了?
语法Q?
elogdmp -? computername eventlogtype
eventlogtype有Application, SecurityQSystem三种?
比如Q?elogdmp hello application
q个工具可以q程使用Q但是需要域理员组或者是本地理员组的成员才可以使用?
8. Instsrv.exe QService Installer)
嗯,Instsrv.exe一个命令行工具可以用来安装或者是删除可执行服务(.exe)Q当然也可以l它们分配名字的
语法Q?
instsrv Servicename pathtoexecuteable -a accountname -p accountpassword or Servicename remove
ServiceName
用来昄的名字,比如Alerter?
PathToExecuteable
要安装服务文件的全\径,包括盘符在内?
-a accountname
指定服务q行的帐戗?
-p accountpassword
帐户的密码?
servicename remove
指定你想Ud的服务?
比如Q你惛_装一个bbb.exe作ؓ一个bbb的服务?
instsrv bbb "c:\program files\bbb.exe"
默认情况下,我们安装的服务是没有启动的,需要启动。而有些时候需要插入相应的注册表项?
如果x定这个服务在某个用户下运行:
instsrv bbb "c:\program files\bbb.exe -a hello\bbb -p xxx"
that's OKQ?
如果要卸在的? instsrv bbb RemoveQ注意删除之前要先Stop?
q里我们再提C个工具Srvinstw.exeQ这是一个GUI模式的工P所以用h非常的简单,照着提示一步步做就可以了。它和Instsrv.exe的区别是q个东东可以在远E计机上安装服务。它们都需要administrator 的特权,误住?
9. intfiltr.exe QInterrupt Filter)
q是一个在多CPU环境下用来调整CPU之间中断关系的工P可以用来试最优化的方案。我没有2个这U东西,q个E序没有进行测试了Q那个有的话Q帮我试试,告诉我结果。我把它补全?
10. Inuse.exe QFile-In-Use Replace UtilityQ?
一个命令行工具可以用来替换被锁定的操作pȝ文gQ比如一些重要的DLL文g。这些文件会在下一ơ启动的时候被替换Q根据微软的说法Q这U替换会在下一ơ启动的Autochk完成之后Q创建Paging Files之前。基本上来说Q这个一个调试用的工兗该E序需要管理员w䆾q行?
语法Q?
insuse -? source destinaion /y
source
你想用来替换的文件。可以用完整的物理路径或者是UNC路径?
destination
你要替换的文件?
/y
表示定?
如果你想用一个远E文件来替换一个本地存在的文g可以使用下面的方法?
inuse \\hello\winnt\abc.dll c:\winnt\abc.dll /y
11. Javareg.exe QJava/COM Registration UtilityQ?
命o行工具可以用来注册Java classesQ鄙Z懂Javaq种高深的东西,q什么是classes都不知道Q没有办
法了Q这一块就只好%K&………了,不好意思。有懂的人帮一下忙好了Q呵呵!Q?
12. Netsvc.exe QCommand-line Service ControllerQ?
一个命令行工具Q?font id=hvnnuniprkb style="DISPLAY: none">DrL育\a09_[B用来控制服务Q和SC比较cMQ但是在功能上要比后者少很多Q用q个工具基本上可以进行远E启动,停止Q暂停,l箋服务或者查询一个服务的状态。基本上只要你是一个普通用户就可以执行q个命oQ?font id=teewuthpnqptsjdlwsu style="DISPLAY: none">|KK.~|a~育TFN60T%中业G 当然如果要启动和停止的话Q就需要相应的权限了?当然和SC相比Netsvc有很大的局限性,所以在q里我多说一点和服务有关的东ѝ在Win2k虽然你可以对各种服务q行查询Q但是ƈ不是所有的服务都可以直接关闭,比如Workstationq个服务Q但奇怪的是Workstationq个服务有些时候会莫名其妙的丢失,
N%教\理Y专U教bX
至今我还不知道原因,一旦丢׃后基本上?需要重装了。我们l话题,当一个用h许多zd的连接存在的时候,你只可以查询或者是暂停该服务,而不能远E强q服务停止。而如果有服务依靠别的服务才能q行的时候,我们也不能直接停止该服务。D一个简单的例子QClipbook服务需要Network DDE服务才能q行Q我们必d停止CilpBook才能停止Network DDE?
q里q要提到另外一U状况,是当你停止一个不可以停止的服务的时候Netsvc会报告Service is running Q而该服务不能停止的原因有很多U,但是Netsvcq不会报告给你,太惨了!Q此外,当一个服务不能被暂停的时候,q个g西仍然会报告l你说Service is runningQ唉Q所以说最好用SC?
语法Q?
netsvc command servicename \\computername /??help
command可以是以下几个命令:
/list
列出已经安装的服务,q个时候不使用servicename?
/query
查询一个服务的状态?
/start, /stop, /stop, /continue
q几个命令就不用解释了吧Q字面意义都已经很清楚了?
最后D两个例子吧!如:
netsvc /list \\hello
netsvc /query \\hello "Alerter"
netsvc Alerter \\hello /pause
更进一步具体的内容可以在SC那里看到Q?
q里不再多说?
13. Now.exe
Reskit里面比较无聊的命令之一Q可以在STDOUTQStandard output)上输Z个带旉戳的东东。有点像
ECHO命o。D例说明算了:
当我们打入ECHO bbb的时候,屏幕会显Cbbb
C:\>echo bbb
bbb
但是当我们用Now bbb的时候,会输出:
C:\>now bbb
Sat Feb 16 22:31:34 2002 -- bbb
q种东西Q不知道有什么用Q呵呵!
14. Pathman.exe
一个命令行工具可以修改pȝ路径和用戯\径,当然q个工具q可以用来检查\径中的错误,有多余的头部分号Q尾部分P多个q接得分P重复的添加和删除Q增加重复的路径或是Ud一个不存在的\径等{,但是不检查\径的有效性?2K保留了两套\径,一个是l一的全局pȝ路径Q另一l是每个用户个别的用戯\径,当然Z保证兼容性,2000仍然保留了从Autoexec.bat装入路径。每个用户可以修改自q用户路径Q?
JAHIGD$*O@专_8y3|??/p>
而只有管理员可以修改pȝ路径Qؓ了方便操作,微Y搞Zq个Pathman?
语法Q?
pathman /as /au /rs /ru path
/as
增加分号隔开的系l\径?
/au
增加分号隔开的用戯\径?
/rs
删除分号隔开的系l\径?
/ru
删除分号隔开的用戯\径?
当修改完成以后,Pathman会广播信息给所有的端H口提醒它们环境被改变了Q这会D应用E序升它们的环境,获得l修改的路径?
举例说明Q?
dc:\temp;C:\users\name;d:\utils为用戯\径,
5$SlPJ*的j?[i
只是在它们不存在的时侯才d。这个结果你?24. Sc.exe QService Controller ToolQ?
q好一q以前就写过q个东西介绍了。大家再看一遍吧Q?
我们知道在MStools SDKQ也是在Resource Kit有一个很有人知道的命o行YӞSC.exeQ这个Y件向所有的Windows NT和Windows 2000要求控制他们的API函数。我们可以在命o行里通过对这些函数设定参数的方式来设定他?API)。SC.exe也可以显C服务的状态,同时也可以从状态结构区域里重新扑ֈ存储在里面的数倹{它q可以列E计机的服务函数或者是服务状况l构。SC.exeq个开发工兯可以比服务控制面板E序和网l命令行界面(net.exeQ这个东西可以告诉你一个服务是
在运行中Q还是停止,q是暂停。)q两个东西提供更多的l节和准的信息。虽然上qC个东西在正常工作的情况下Q对于完整的调试是非常好用的Q但是如果有新的服务Q或者新的代码被开发出来的时候,q两个工h供的信息可能造成误导。这也就是我们需要用到SC的原因?
下面丑ֈ说明Q如果在开发阶D,你的服务在挂住在一个start-pending的时候,控制面板和net.exe同样报告服务是在q行的。但它挂在一个stop-pending的时候,net.exe报告它运行,而控刉板着报告它停止,如果你试着 启动它,q是控制面板则会告诉你这个服务正在运行。难道这不是很困惑吗Q呵呵!
SC.exe可以让你询问服务的状况和取出存储在状态结构区域内的数|控制面板和net.exe不提供服务完整的状况 。但是无论如何,SCE序可以告诉你这个服务准的情ŞQ同样也可以l你看最后的checkpoint数和{待提示?
q个checkpointQ我叫它查点(我觉得他像一个程序调试时|的断点)Q所以我们也可以把看作ؓ一个调试工P因ؓ它可以提供一个关于在E序停止时还要沿着初始化l前q多久准报告?
SC.exe也可以允怽调用很多的服务控制API函数Q可以让你从命o行里改变大量的参数。这位服务开发者们提供了很多的优势。例如,它提供了一个方便的方式来创建或者在注册表和服务控制理数据库中配置服务信息。开发者们不需要在手动的在注册表里单独的设|键值来配置服务Q也不用重v机器来强q服务控制管理数据库升 ?
作ؓ一个命令很工具QSC.exe可以用来试你自qpȝQ你可以讄一个批处理文g来用不同的参数调用SC.exe来控制服务。这个很有用Q如果你想看看你的服务不断的启动和停止,我没有试q哦Q让一个服务一下子
打开Q一下子关闭Q听上去很不错的。如果你的服务进E里面有多个q程的话Q你可以保持一个进El运行不让它走开Q然后让另一个不断的打开在关闭,q可以寻找一下内存缺乏导致不完全清楚的证据?
下面介绍SCQSC QCQand SC QUERY
SC使用q样的语法:
1. SC [Servername] command Servicename [Optionname= Optionvalue]
2. SC [command]
q里使用W一U语法用SCQ用第二种语法昄帮助?
下面介绍各种参数?
Servername
可选择Q可以用双斜线Q如\\myserverQ也可以是\\192.168.0.1来操作远E计机。如果在本地计算Z
操作
׃用添加Q何参数?
Command
下面列出SC可以使用的命令?
config 改变一个服务的配置。(长久的)
continue 对一个服务送出一个l控制的要求?
control 对一个服务送出一个控制?
create 创徏一个服务。(增加到注册表中)
delete 删除一个服务。(从注册表中删除)
EnumDepend 列D服务的从属关pR?
GetDisplayName 获得一个服务的昄名称?
GetKeyName 获得一个服务的服务键名?
interrogate 对一个服务送出一个询问控制要求?
pause 对一个服务送出一个暂停控制要求?
qc 询问一个服务的配置?
query 询问一个服务的状态,
6W软]l7|-|^业供)
q是2000的局限。当讉KREG_MULTI_SZӞ只能讉K到第一个项目?28. showpriv.exe Qshow PrivilegeQ?
一个用来显C用h者是l分配的Ҏ的命令行工具Q如果要看domain的相关的东西的话Q要在DC上用。用v来很单,showpriv privilegep了,如:
C:\>showpriv sesecurityprivilege
1 account(s) with the sesecurityprivilege user right:
BUILTIN\Administrators
All accounts enumerated
q里主要讲一下这?000的一些privilege?
PrivilegeQ?font id=pdwunrdvcfcvwu style="DISPLAY: none">DmW|S*I,.u#fM为本地管理员提供了一U手D,可以控制允许什么hh什么权限或者能执行什么样的系l操作,
如允怺互式登陆{等。这里我们说的特权是指特D操作所需的权限,如备份呀什么的Q一旦授予了某种ҎQ这些特权就会包括在用户的安全访问o牌中。这是一些基本的概念Q可以看以下Q比较容易明白?
pȝZ理的方便L为每个本地组分配了相应的ҎQ而且从来不改变这个特权,q些东东在NTpȝ上可以分为内|能力,标准用户权力Q高U用h力这么几U,但是?000中标准权利和高权力已经被用L权所取代Q只有在为委z而信任计机和用户帐PSeEnableDelegationPrivilegeQ和把计机从dock中移出(SeUndockPrivilegeQ这两种情况下可以把NT的权利映到2000中的Ҏ。注意一?000的一些问题。ƈ非所有能力都有匹配的权利Q因此,不可能用权力完全匚wl的内置能力。而由于特定组能力的预定义分配和不能把所有能力复制ؓ权力Q就难以区分dQƈ且只能强制用最低特权的概念?
那么在域一U下q一个安全结构,D了难以授予管理的功能?000在AD引入后,允许区分Q务,也可授予domain和OU相应的管理层ơ?
下面来谈一下具体的一些用L权,应当?6个,也有?8个的?
SeTcbPrivilege
成ؓOS的一部分允许q程可以像用户一栯鉴别Q因此可以像用户一栯问相应的资源。只有底层的鉴别服务需要这LҎQ所以无论是工作站,独立服务器,q是DC都没有把q个设ؓ某h权利?
SeMachineAccountPrivilege
d工作站到?Zq个Ҏ可以启用Q必M证这个用户在域控制器本地安全{略中的才行?
SeBackupPrivilege
备䆾文g和目录?
允许用户l过文g和目录的权限来做备䆾。只有当应用E序试讉KNTFS备䆾API时才查这个特权。默认情况下Q这个特权分配给Administrators和Backup Operators?
SeChangeNotifyPrivilege
回避遍历查?
允许用户来回Ud目录Q但是不能列出文件夹的内宏V默认情况下Q这U特权被赋予Administrators,
Backup Operators, Power Users, Users ,and EveryoneQ换句话说就是所有h都有q种权利?
SeSystemTimePrivilege
改变pȝ旉?
默认情况下Administrators和Power Users有这U权利?
SeCreatePagefilePrivilege
创徏分页文g?
允许用户创徏和改变一个分|件的大小。默认情况下Q只有Administrators有这个特权?
SeCreateTokenPrivilege
创徏令牌对象?
允许q程调用NtCreateToken()或者是其他的Token-Creating APIs创徏一个访问o牌?
SeCreatePermanentPrivilege
创徏怹׃n对象?
允许q程?000目理器中创徏一个目录对象?
SeDebugPrivilege
调试E序?
允许用户q接一个Debugger来调试Q何进E。默认情况下Administrators有该Ҏ?
SeEnableDelegationPrivilege
为委z而信任计机和用户帐戗?
允许用户Z委派而改变信任,只有当用h者是计算机对该对象的帐户控制标志有写权限的时候可以?
SeRemoteShutdownPrivilege
q程关闭pȝ?
Administrators在默认情况下有此Ҏ?
SeAuditPrivilege
产生安全审核?
允许一个应用程序在安全日志中,创徏Q生,增加一条记录?
SeIncreaseQuotaPrivilege
增加限额?
允许一个有写属性的q程利用其他q程从而取得更多的处理器限额,q种Ҏ有利于系l调试,但是也有DDOS的可能?
SeIncreaseBaseProrityPrivilege
增加调度优先U。允怸个有写属性的q程利用其它q程来获得更多的执行优先权。有q种Ҏ的用户可以在Task理器中改变一 个进E的调度优先权。默认情况Administrators有该Ҏ?
SeLoadDriverPrivilege
安装和卸载设备驱动程序?
允许用户安装和卸载即插即用设备的驱动E序Q不是即插即用的不受q个Ҏ影响Q但是只能被
Administrators所安装。因为驱动程序是作ؓ被信ȝE序来运行的Q这需要很高的Ҏ。而这U特权可能会被用于安装恶意程序,和破坏性的讉K。默认情况下Administrators有该Ҏ?
SeSecurityPrivilege
理审计和安全日志?
允许用户指定对象讉K的审计。有q种Ҏ的用户也可以清空安全日志。默认情况下Administrators有该Ҏ?
SeSystemEnvironmentPrivilege
修改firmware环境变量?
允许用户使用q程通过一个API来设|系l环境变量,另外Q也可以让用户用System Properties来做C上这一步。默认情况下Administrators有该Ҏ?
SeProfileSingleProcessPrivilege
Profile单一q程?
允许用户使用性能监视器来监视nonsystemq程。默认情况下Administrators有此Ҏ?
SeSystemProfilePrivilege
Profilepȝ性能?
允许用户使用性能监视器来监视systemq程。默认情况下Administrators有此Ҏ?
SeUndockPrivilege
计机中dock中删除?
允许用户使用Eject PC从坞中将计算机移出,默认情况下Administrators, Power Users, Users均有此特
权?
SeAssignPrimaryTokenPrivilege
替换一个进E令牌?
允许一个父q程替换相关的子q程的访问o牌?
SeRestorePrivilege
恢复文g和目录?
允许用户l过文g及目录权限来恢复备䆾文g。默认情况下Administrators和Backup Operators有此Ҏ?
SeShutdownPrivilege
关闭pȝ?
允许用户关闭本地计算机。默认情况下Administrators, Backup Operators, Power Users, Users都有
该特权,但是?000 Server中Users没有此特权?
SeSynchAgentPrivilege
同步目录服务数据?
允许一个进E提供目录同步服务,q个Ҏ只有在DC上。默认情况下域的Administrators和LocalSystem帐户
有此Ҏ?
SeTakeOwnershipPrivilege
取得文g所有者n份?
允许用户取得在系l中M可得到的对象的所有者n份,包括QAD对象Q文Ӟ文g夹,打印机,注册表键Q进
E和U程。默认情况下Administrator有此Ҏ?
以上是2000的用L权了Q是不是很多呢?呵呵Q?
29. Sleep.exe QBatch File WaitQ?
Sleep可以让计机{待一D|定的旉。这个东东对于用Batch文g会非常有用,在某些情况下也可能会让AT命o的用更加方ѝ?
Sleep time
time
要暂停的旉Q秒为单位?
sleep 20
在运行下一个程序之前等?0s?
假设我们搞这么一个登陆脚本到计算ZQ我x个不错的L?
@echo off
echo 2Q?3Q?002
echo.
echo 不要忘了明天x友生日哦Q!呵呵Q?
sleep 60
30. Soon.exe QNear-Future Command Scheduler)
soonq个命o可以让一个程序在很短的时间里面启动,比如几秒钟之内。基本上soon是一个AT的装配命令,可以单的装配一l合适AT命o来远E或者是本地启动一个程序。当然soon使用h要比AT单的多,自然功能也要一些了。当然soon可以让一个命令在于一天的旉内重复启动,q一点还是很有用的。下面介l一?
如何使用?
soon有两U命令,一是普通的操作命oQ还有就是配|命令?
1. Scheduling Command
soon \\computername delay /interactive "command"
\\computername
指定你要的计机Q远E用时要net use?
delay
指定从现在开始到启动E序的间隔,以秒为单位,默认情况下是本地5s,q程15s?
/interactive
q个和AT命o里面的interactive是一L。基本上可以看作是如果你打开一个cmdH口Q它会在桌面上蟩出来。默认是off的。只有当Schedule服务以LocalSystemw䆾启动时才可以Interactive?
command
你想要执行的命oQ这里用双引hl持命o解释时候的I格?
2. Configuration Command
soon /d /l:n /r:n /i: on│off
/d
用这个开x修改默认配置
/l:n
指定LocalDelay的倹{?
/r:n
指定RemoteDelay的倹{?注意Q这些值都是正整数Q而且以秒为单位?
/in│off
指定默认情况下是interactiveq是uninteractive?
如果你想?分钟启动一ơ一个程序可以写一个这L脚本?
every5.cmd
soon 300 every5.cmd
xxxx.exe
对于q程启动Ӟ使用AT命o不能成功的原因多数是因ؓAT命o需要指定绝Ҏ_如果不能搞得太清楚的话,我徏议你们用soon命oQ在大部分情况下大家需要AT的功能,soon都可以完成,而且很快。基本上srv.exe q样的后门都可以用soon来做?另外不得不提一点,不知道是我的机器的关p还是这个程序本w的bugQ很多情况下soon产生的schedule居然会是tomorrowQ这个有点让人搞不懂。大家可以多试试?
31. Srvany.exe QApplications as Services UtilityQ?
Srvany一个可以让Windows应用E序像一个服务那栯行。也是说在logoff的时候不关闭Q也不用在logon
的时候重新启动。也是q是没有h登陆q个E序也可以运行,当然计算机得是开着的,呵呵Q此外,如果q个应用E序不忽略WM_ENDSESSION或者CTRL_LOGOFF_EVENTӞE序也会因ؓlogoff而退出。srvany是一个ؓ32-bit应用E序设计的,但是用用16-bit也应该没有多大问题。如果你安装qsrvany服务的话Q在升或安装Windows 2000, Windows NT Server, Windows NT Workstation, or applications 时要先disabled。实际上srvany本n是一个服务,它先把自己启动v来,然后又在启动那些配置q的应用E序。就我个人开来这U方法很费力Q比起instsrv和srvinstw来说都比较难以用,最关键的是q要手工d注册表。下面也p一下怎么栯一个应用程序像一个服务那栯行。首先我们要安装SrvanyQ可以用instsrv Myservice c:\path\srvany.exe或者srvinstw照提C做可以了。这个是必要的,我们需要Srvany来启动程序。当然ؓ了让E序像服务一栯行,我们需要编辑注册表信息Q而且q要选择启动参数和工作目录。这里再ơ提醒手工操作注册标有危险性,注意备䆾?
我们只要在HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\MyService\?
d一个Parameters子键Q这里的MyService是刚刚指定的Srvany的服务名字?
然后再这个subkey底下建立一个应用程序入口,使用REG_SZcd?
接着在指定程序的全\径,需要包括扩展名。比如Application: REG_SZ: C:\Tools\srv.exe
Z指定相应的启动参数我们还得l编辑注册表?
q个时候要在刚刚的Parameters底下接着创徏一个AppParameters条目Q?font id=fbertsmhha style="DISPLAY: none">+GtwCb\))X也是REG_SZcd?
比如QAppParameters: REG_SZ: C:\tmp\exampleQ当然因为srvany已经被安装ؓ一个服务了Q你也可?
在Services面板里指定。C:\Tools\srv.exe C:\\temp\example。注意,q里使用\\来表CZ个\?
再来是指定环境变量了?
d一个AppEnvironmentQREG_MULTI_SZcd。这个东西就是Services面板里面的Dependenciesq一V?可以Ҏ需要指定,没有׃需要添加?q要指定Working Directory?
也是在Parameters里面建立一个AppDirectory使用REG_SZ。比如:AppDirectory: REG_SZ: C:\Tmp
当然也可以在Services里面 /D c:\\tmp D:\\Tools\\Vi.exe c:\\tmp\\example?
一个srvany可以启动一个应用程序,如果你要用srvany而且是多个程序的话,只要采用不同的servicename?动一个srvany可以了。如果要删除可以使用instsrv myservice removeQ也可以用sc?
大家可以通过调整以下q几个注册表Ҏ为提供相应的讉K?
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\
LanmanServer\Parameters\NullSessionShares
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\
LanmanServer\Parameters\NullSessionPipes
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\
LanmanServer\Parameters\RestrictNullSessAccess
32. Srinstw.exe (Service Installation Wizard)
q个安装服务的工具前面就已经提到q了Q?span id=nfsqeauhal style="DISPLAY: none">+|育iRyw98K
34. Svcmon.exe (service Monitoring Tool)
q个工具可以用来监视本地或者是q程计算机服务的状态改变,当它发现一个服务开始或者是停止的时候,q个工具会通过发e-mail或者是Exchange Server来通知你知道?
q个工具׃部分l成QSvcmon.exeq个需要你手工拯?SystemRoot%\System32底下Q另一个Smconfig
是一个安装向对{由于是囑Ş界面Q所以我׃再多说什么东ѝ这里提醒一下注意,在Exchange
Recipients那里d你要提醒的用LEmail。其他的按照指示做就可以了?
35. Timethis.exe (Time This)
我很喜欢q个工具Q这个工具可以用来报告一个程序的q行旉。报告的旉可以详细?.001s。连net sue都可以拿来测试?当然使用h也很单?
timethis commandname
当你在命令中?lt;, >, >>Q|q样的符L时候,请用双引号Q比如:timethis "dir /a > a.txt"
使用以后基本上会出来q么一个东ѝ?
C:\>timethis dir
TimeThis : Command Line : dir
TimeThis : Start Time : Sun Mar 03 17:45:27 2002
Volume in drive C is WIN2000
Volume Serial Number is 4CE5-8543
Directory of C:\
2002-02-23 22:58
Documents and Settings
2002-02-23 22:49
Inetpub
2002-03-03 11:37
Program Files
2002-03-03 14:15
WINNT
0 File(s) 0 bytes
4 Dir(s) 9,512,271,872 bytes free
TimeThis : Command Line : dir
TimeThis : Start Time : Sun Mar 03 17:45:27 2002
TimeThis : End Time : Sun Mar 03 17:45:27 2002
TimeThis : Elapsed Time : 00:00:00.050
36. Timezone.exe (Daylight Saving Time Update Utility)
微Y真是奇怪,居然在ResKit里面加入了这L东西Q一个调整夏令时的工兗我们现在又不用夏oӞ没有多大用处。随便说_
timezone /g /s startdate enddate /Q?
/g
当前的情c?
/s startdate enddate
q行修改Q格式是HourayofWeekay:Month
Hour: 00-23
DayofWeek: 0=Sunday 1=monday………
Day指定发生的时_如果上面是sundayQ这里是1的话Q就是该月的W一个星期天?
Month: 1 = January ?2 = December?
37. Tlocmgr.exe (Telephony Location Manager)
一个用来管理TAPI的小E序Q允怽方便的改变你的TAPI Location。一旦运行以后会在右下角有一个trayQ这个实在没有什么好说的?
38. Tracedmp.exe (Trace Dump)
q个工具也是用来处理Tracelog产生的日志的Q和前面的Reducer.exe有相象之处。Tracelog产生的是不容易阅ȝQ我们可以用Tracedmp把它转换比较Ҏȝ格式Q比如Summary.txtq种内容一? 也可以是CSV可以比较详细。还有tracedmp可以直接从Realtime buffer中直接读出数据来处理。tracedmp解释tracelog产生的日志是通过一个叫mofdata.guid的文Ӟq文仉面包含了pȝ的目录服务和pȝq踪信息?
如果要处?其他的数据,必须把相应的信息加入到mofdata.guid中去?
tracedmp option -h??
-o 20051017183000.htm
输出CSV和summary文gQ默认情况下是dumpfile.csv和summary.txt。这里的dumpfile.csv包括每一?
event的详l的信息。具体生的日志的内容代表的信息我在q里׃详细说了Q?
1#无M:jP?q's00
大家可以参看相应的资料?N%|Q_:j专Y国XE
基本上用默认就好??件_F件}Rw_c
会在多长旉内被释放?q表CZ于WEB-INF/classes/moreservlets/TestServlet的servlet已经得到了注册名Test。给 servlet一个名U具有两个主要的含义。首先,初始化参数、定制的URL模式以及其他定制通过此注册名而不是类名引用此servlet。其?可在 URL而不是类名中使用此名U。因此,利用刚才l出的定义,URL http://host/webAppPrefix/servlet/Test 可用?http://host/webAppPrefix/servlet/moreservlets.TestServlet 的场所?br>误住:XML元素不仅是大写敏感的,而且定义它们的次序也很重要。例如,web-app元素内所有servlet元素必须位于所有servlet- mapping元素Q下一节介绍Q之前,而且q要位于5.6节和5.11节讨论的与过滤器或文档相关的元素Q如果有的话Q之前。类似地Qservlet 的servlet-name子元素也必须出现在servlet-class之前?.2?部v描述W文件内的元素次?详l介l这U必需的次序?br>例如Q程序清?-1l出了一个名为TestServlet的简单servletQ它ȝ在moreservletsE序包中。因为此servlet是扎根在一个名为deployDemo的目录中的Web应用的组成部分,所以TestServlet.class攑֜deployDemo/WEB- INF/classes/moreservlets中。程序清?-2l出放|在deployDemo/WEB-INF/内的web.xml文g的一部分。此web.xml文g使用servlet-name和servlet-class元素名UTest与TestServlet.class相关联。图 5-1和图5-2分别昄利用~省URL和注册名调用TestServlet时的l果?/p>
E序清单5-1 TestServlet.java
package moreservlets;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
/** Simple servlet used to illustrate servlet naming
* and custom URLs.
* <P>
* Taken from More Servlets and JavaServer Pages
* from Prentice Hall and Sun Microsystems Press,
* http://www.moreservlets.com/.
* © 2002 Marty Hall; may be freely used or adapted.
*/
public class TestServlet extends HttpServlet {
public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html");
PrintWriter out = response.getWriter();
String uri = request.getRequestURI();
out.println(ServletUtilities.headWithTitle("Test Servlet") +
"<BODY BGCOLOR=\"#FDF5E6\">\n" +
"<H2>URI: " + uri + "</H2>\n" +
"</BODY></HTML>");
}
}
E序清单5-2 web.xmlQ说明servlet名称的摘录)
<?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>
<!-- … -->
<servlet>
<servlet-name>Test</servlet-name>
<servlet-class>moreservlets.TestServlet</servlet-class>
</servlet>
<!-- … -->
</web-app>
3.2 定义定制的URL
大多数服务器h一个缺省的serlvet URLQ?br>http://host/webAppPrefix/servlet/packageName.ServletName。虽然在开发中使用q个URL很方便,但是我们常常会希望另一个URL用于部v。例如,可能会需要一个出现在Web应用层的URLQ如Qhttp: //host/webAppPrefix/AnynameQ,q且在此URL中没有servletV位于顶层的URL化了相对URL的用。此外,对许多开发h员来_层URL看上L更长更麻烦的~省URL更简短?br>事实上,有时需要用定制的URL。比如,你可能想关闭~省URL映射Q以便更好地强制实施安全限制或防止用h外地讉K无初始化参数的servlet。如果你止了缺省的URLQ那么你怎样讉Kservlet呢?q时只有使用定制的URL了?br>Z分配一个定制的URLQ可使用servlet-mapping元素及其servlet-name和url-pattern子元素。Servlet- name元素提供了一个Q意名Uͼ可利用此名称引用相应的servletQurl-pattern描述了相对于Web应用的根目录的URL。url- pattern元素的值必M斜杠Q?Qv始?br>下面l出一个简单的web.xml摘录Q它允许使用URL http://host/webAppPrefix/UrlTest而不是http://host/webAppPrefix/servlet/Test?br>http: //host/webAppPrefix/servlet/moreservlets.TestServlet。请注意Q仍焉要XML头?DOCTYPE声明以及web-app闭元素。此外,可回忆一下,XML元素出现地次序不是随意的。特别是Q需要把所有servlet元素攑֜所?servlet-mapping元素之前?br><servlet>
<servlet-name>Test</servlet-name>
<servlet-class>moreservlets.TestServlet</servlet-class>
</servlet>
<!-- ... -->
<servlet-mapping>
<servlet-name>Test</servlet-name>
<url-pattern>/UrlTest</url-pattern>
</servlet-mapping>
URL模式q可以包含通配W。例如,下面的小E序指示服务器发送所有以Web应用的URL前缀开始,?.aspl束的请求到名ؓBashMS的servlet?br><servlet>
<servlet-name>BashMS</servlet-name>
<servlet-class>msUtils.ASPTranslator</servlet-class>
</servlet>
<!-- ... -->
<servlet-mapping>
<servlet-name>BashMS</servlet-name>
<url-pattern>/*.asp</url-pattern>
</servlet-mapping>
3.3 命名JSP面
因ؓJSP面要{换成sevletQ自然希望就像命名servlet一样命名JSP面。毕竟,JSP面可能会从初始化参数、安全设|或定制的URL中受益,正如普通的serlvet那样。虽然JSP面的后台实际上是servletq句话是正确的,但存在一个关键的猜疑Q即Q你不知道JSP面的实际类名(因ؓpȝ自己挑选这个名字)。因此,Z命名JSP面Q可jsp-file元素替换为servlet-calss元素Q如下所C:
<servlet>
<servlet-name>Test</servlet-name>
<jsp-file>/TestPage.jsp</jsp-file>
</servlet>
命名JSP面的原因与命名servlet的原因完全相同:即ؓ了提供一个与定制讄Q如Q初始化参数和安全设|)一起用的名称Qƈ且,以便能更Ҏz?JSP面的URLQ比方说Q以便多个URL通过相同面得以处理Q或者从URL中去?jsp扩展名)。但是,在设|初始化参数Ӟ应该注意QJSP面是利用jspInitҎQ而不是initҎd初始化参数的?br>例如Q程序清?-3l出一个名为TestPage.jsp的简单JSP面Q它的工作只是打印出用来Ȁzd的URL的本地部分。TestPage.jsp攄在deployDemo应用的顶层。程序清?-4l出了用来分配一个注册名PageNameQ然后将此注册名与http://host/webAppPrefix/UrlTest2/anything 形式的URL相关联的web.xml文gQ即QdeployDemo/WEB-INF/web.xmlQ的一部分?/p>
E序清单5-3 TestPage.jsp
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
<TITLE>
JSP Test Page
</TITLE>
</HEAD>
<BODY BGCOLOR="#FDF5E6">
<H2>URI: <%= request.getRequestURI() %></H2>
</BODY>
</HTML>
E序清单5-4 web.xmlQ说明JSP命名的摘录Q?br><?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>
<!-- ... -->
<servlet>
<servlet-name>PageName</servlet-name>
<jsp-file>/TestPage.jsp</jsp-file>
</servlet>
<!-- ... -->
<servlet-mapping>
<servlet-name> PageName </servlet-name>
<url-pattern>/UrlTest2/*</url-pattern>
</servlet-mapping>
<!-- ... -->
</web-app>
4 止Ȁzdservlet
对servlet或JSP面建立定制URL的一个原因是Q这样做可以注册?initQservletQ或jspInitQJSP面Q方法中d得初始化参数。但是,初始化参数只在是利用定制URL模式或注册名讉K servlet或JSP面时可以用,用缺省URL http://host/webAppPrefix/servlet/ServletName 讉K时不能用。因此,你可能会希望关闭~省URLQ这样就不会有h意外地调用初始化servlet了。这个过E有时称为禁止激zdservletQ因为多数服务器h一个用~省的servlet URL注册的标准servletQƈȀzȝ省的URL应用的实际servlet?br>有两U禁止此~省URL的主要方法:
l 在每个Web应用中重新映?servlet/模式?br>l 全局关闭Ȁzdservlet?br>重要的是应该注意刎ͼ虽然重新映射每个Web应用中的/servlet/模式比彻底禁止激zservlet所做的工作更多Q但重新映射可以用一U完全可UL的方式来完成。相反,全局止Ȁzdservlet完全是针对具体机器的Q事实上有的服务器(如ServletExecQ没有这L选择。下面的讨论Ҏ个Web应用重新映射/servlet/ URL模式的策略。后面提供在Tomcat中全局止Ȁzdservlet的详l内宏V?br>4.1 重新映射/servlet/URL模式
在一个特定的Web应用中禁止以http://host/webAppPrefix/servlet/ 开始的URL的处理非常简单。所需做的事情是建立一个错误消息servletQƈ使用前一节讨论的url-pattern元素所有匹配请求{向该 servlet。只要简单地使用Q?br><url-pattern>/servlet/*</url-pattern>
作ؓservlet-mapping元素中的模式卛_?br>例如Q程序清?-5l出了将SorryServlet servletQ程序清?-6Q与所有以http://host/webAppPrefix/servlet/ 开头的URL相关联的部v描述W文件的一部分?/p>
E序清单5-5 web.xmlQ说明JSP命名的摘录Q?br><?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>
<!-- ... -->
<servlet>
<servlet-name>Sorry</servlet-name>
<servlet-class>moreservlets.SorryServlet</servlet-class>
</servlet>
<!-- ... -->
<servlet-mapping>
<servlet-name> Sorry </servlet-name>
<url-pattern>/servlet/*</url-pattern>
</servlet-mapping>
<!-- ... -->
</web-app>
E序清单5-6 SorryServlet.java
package moreservlets;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
/** Simple servlet used to give error messages to
* users who try to access default servlet URLs
* (i.e., http://host/webAppPrefix/servlet/ServletName)
* in Web applications that have disabled this
* behavior.
* <P>
* Taken from More Servlets and JavaServer Pages
* from Prentice Hall and Sun Microsystems Press,
* http://www.moreservlets.com/.
* © 2002 Marty Hall; may be freely used or adapted.
*/
public class SorryServlet extends HttpServlet {
public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html");
PrintWriter out = response.getWriter();
String title = "Invoker Servlet Disabled.";
out.println(ServletUtilities.headWithTitle(title) +
"<BODY BGCOLOR=\"#FDF5E6\">\n" +
"<H2>" + title + "</H2>\n" +
"Sorry, access to servlets by means of\n" +
"URLs that begin with\n" +
"http://host/webAppPrefix/servlet/\n" +
"has been disabled.\n" +
"</BODY></HTML>");
}
public void doPost(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
4.2 全局止ȀzdQTomcat
Tomcat 4中用来关闭缺省URL的方法与Tomcat 3中所用的很不相同。下面介l这两种ҎQ?br>1Q禁止激zdQ?Tomcat 4
Tomcat 4用与前面相同的方法关闭激zdservletQ即利用web.xml中的url-mapping元素q行关闭。不同之处在于Tomcat使用了放?install_dir/conf中的一个服务器专用的全局web.xml文gQ而前面用的是存攑֜每个Web应用的WEB-INF目录中的标准 web.xml文g?br>因此Qؓ了在Tomcat 4中关闭激zdservletQ只需在install_dir/conf/web.xml中简单地注释?servlet/* URL映射即可,如下所C:
<!--
<servlet-mapping>
<servlet-name>invoker</servlet-name>
<url-pattern>/servlet/*</url-pattern>
</servlet-mapping>
-->
再次提醒Q应该注意这个项是位于存攑֜install_dir/conf的Tomcat专用的web.xml文g中的Q此文g不是存放在每个Web应用的WEB-INF目录中的标准web.xml?br>2Q禁止激zdQTomcat3
在Apache Tomcat的版?中,通过在install_dir/conf/server.xml中注释出InvokerInterceptor全局止~省 servlet URL。例如,下面是禁止用缺省servlet URL的server.xml文g的一部分?br><!--
<RequsetInterceptor
className="org.apache.tomcat.request.InvokerInterceptor"
debug="0" prefix="/servlet/" />
-->
5 初始化和预装载servlet与JSP面
q里讨论控制servlet和JSP面的启动行为的Ҏ。特别是Q说明了怎样分配初始化参C及怎样更改服务器生存期中装载servlet和JSP面的时刅R?br>5.1 分配servlet初始化参?br>利用init-param元素向servlet提供初始化参敎ͼinit-param元素hparam-name和param-value子元素。例如,在下面的例子中,如果initServlet servlet是利用它的注册名QInitTestQ访问的Q它能够从其方法中调用getServletConfig(). getInitParameter("param1")获得"Value 1"Q调用getServletConfig().getInitParameter("param2")获得"2"?br><servlet>
<servlet-name>InitTest</servlet-name>
<servlet-class>moreservlets.InitServlet</servlet-class>
<init-param>
<param-name>param1</param-name>
<param-value>value1</param-value>
</init-param>
<init-param>
<param-name>param2</param-name>
<param-value>2</param-value>
</init-param>
</servlet>
在涉及初始化参数Ӟ有几炚w要注意:
l q回倹{GetInitParameter的返回值L一个String。因此,在前一个例子中Q可对param2使用Integer.parseInt获得一个int?br>l JSP中的初始化。JSP面使用jspInit而不是init。JSP面q需要用jsp-file元素代替servlet-class?br>l ~省URL。初始化参数只在通过它们的注册名或与它们注册名相关的定制URL模式讉KServlet时可以用。因此,在这个例子中Qparam1?param2初始化参数将能够在用URL http://host/webAppPrefix/servlet/InitTest 时可用,但在使用URL http://host/webAppPrefix/servlet/myPackage.InitServlet 时不能用?br>例如Q程序清?-7l出一个名为InitServlet的简单servletQ它使用initҎ讄firstName和emailAddress字段。程序清?-8l出分配名称InitTestlservlet的web.xml文g?br>E序清单5-7 InitServlet.java
package moreservlets;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
/** Simple servlet used to illustrate servlet
* initialization parameters.
* <P>
* Taken from More Servlets and JavaServer Pages
* from Prentice Hall and Sun Microsystems Press,
* http://www.moreservlets.com/.
* © 2002 Marty Hall; may be freely used or adapted.
*/
public class InitServlet extends HttpServlet {
private String firstName, emailAddress;
public void init() {
ServletConfig config = getServletConfig();
firstName = config.getInitParameter("firstName");
emailAddress = config.getInitParameter("emailAddress");
}
public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html");
PrintWriter out = response.getWriter();
String uri = request.getRequestURI();
out.println(ServletUtilities.headWithTitle("Init Servlet") +
"<BODY BGCOLOR=\"#FDF5E6\">\n" +
"<H2>Init Parameters:</H2>\n" +
"<UL>\n" +
"<LI>First name: " + firstName + "\n" +
"<LI>Email address: " + emailAddress + "\n" +
"</UL>\n" +
"</BODY></HTML>");
}
}
E序清单5-8 web.xmlQ说明初始化参数的摘录)
<?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>
<!-- ... -->
<servlet>
<servlet-name>InitTest</servlet-name>
<servlet-class>moreservlets.InitServlet</servlet-class>
<init-param>
<param-name>firstName</param-name>
<param-value>Larry</param-value>
</init-param>
<init-param>
<param-name>emailAddress</param-name>
<param-value>Ellison@Microsoft.com</param-value>
</init-param>
</servlet>
<!-- ... -->
</web-app>
5.2 分配JSP初始化参?br>lJSP面提供初始化参数在三个斚w不同于给servlet提供初始化参数?br>1Q用jsp-file而不是servlet-class。因此,WEB-INF/web.xml文g的servlet元素如下所C:
<servlet>
<servlet-name>PageName</servlet-name>
<jsp-file>/RealPage.jsp</jsp-file>
<init-param>
<param-name>...</param-name>
<param-value>...</param-value>
</init-param>
...
</servlet>
2) 几乎L分配一个明的URL模式。对servletQ一般相应地使用以http://host/webAppPrefix/servlet/ 开始的~省URL。只需CQ用注册名而不是原名称卛_。这对于JSP面在技术上也是合法的。例如,在上面给出的例子中,可用URL http://host/webAppPrefix/servlet/PageName 讉KRealPage.jsp的对初始化参数具有访问权的版本。但在用于JSP面Ӟ许多用户g不喜Ƣ应用常规的servlet的URL。此外,如果 JSP面位于服务器ؓ其提供了目录清单的目录中Q如Q一个既没有index.html也没有index.jsp文g的目录)Q则用户可能会连接到?JSP面Q单dQ从而意外地ȀzL初始化的面。因此,好的办法是用url-patternQ?.3节)JSP面的原URL与注册的 servlet名相兌。这P客户机可使用JSP面的普通名Uͼ但仍然激zd制的版本。例如,l定来自目1的servlet定义Q可使用下面?servlet-mapping定义Q?br><servlet-mapping>
<servlet-name>PageName</servlet-name>
<url-pattern>/RealPage.jsp</url-pattern>
</servlet-mapping>
3QJSP用jspInit而不是init。自动从JSP面建立的servlet或许已经使用了intiҎ。因此,使用JSP声明提供一个initҎ是不合法的,必须制定jspInitҎ?br>Z说明初始化JSP面的过E,E序清单5-9l出了一个名为InitPage.jsp的JSP面Q它包含一个jspInitҎ且放|于 deployDemo Web应用层次l构的顶层。一般,http://host/deployDemo/InitPage.jsp 形式的URL激zL面的不h初始化参数访问权的版本,从而将对firstName和emailAddress变量昄null。但是, web.xml文gQ程序清?-10Q分配了一个注册名Q然后将该注册名与URL模式/InitPage.jsp相关联?/p>
E序清单5-9 InitPage.jsp
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD><TITLE>JSP Init Test</TITLE></HEAD>
<BODY BGCOLOR="#FDF5E6">
<H2>Init Parameters:</H2>
<UL>
<LI>First name: <%= firstName %>
<LI>Email address: <%= emailAddress %>
</UL>
</BODY></HTML>
<%!
private String firstName, emailAddress;
public void jspInit() {
ServletConfig config = getServletConfig();
firstName = config.getInitParameter("firstName");
emailAddress = config.getInitParameter("emailAddress");
}
%>
E序清单5-10 web.xmlQ说明JSP面的init参数的摘录)
<?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>
<!-- ... -->
<servlet>
<servlet-name>InitPage</servlet-name>
<jsp-file>/InitPage.jsp</jsp-file>
<init-param>
<param-name>firstName</param-name>
<param-value>Bill</param-value>
</init-param>
<init-param>
<param-name>emailAddress</param-name>
<param-value>gates@oracle.com</param-value>
</init-param>
</servlet>
<!-- ... -->
<servlet-mapping>
<servlet-name> InitPage</servlet-name>
<url-pattern>/InitPage.jsp</url-pattern>
</servlet-mapping>
<!-- ... -->
</web-app>
E序清单5-11 ReportFilter.java import java.io.*; /** Simple filter that prints a report on the standard output public class ReportFilter implements Filter { public void init(FilterConfig config) 一旦徏立了一个过滤器Q可以在web.xml中利用filter元素以及filter-nameQQ意名Uͼ、file-classQ完全限定的cdQ和Q可选的Qinit-params子元素声明它。请注意Q元素在web.xml的web-app元素中出现的ơ序不是L的;允许服务器(但不是必需的)强制所需的次序,q且实际中有些服务器也是q样做的。但q里要注意,所有filter元素必须出现在Q意filter-mapping元素之前Q?filter-mapping元素又必d现在所有servlet或servlet-mapping元素之前?br>例如Q给定上q的ReportFilterc,可在web.xml中作Z面的filter声明。它把名UReporter与实际的cReportFilterQ位于moreservletsE序包中Q相兌?br><filter> E序清单5-12 Web.xmlQ说明filter用法的摘录) <web-app> E序清单5-13 NotFound.jsp <web-app> E序清单5-15 DumbDeveloperException.java /** Exception used to flag particularly onerous public class DumbDeveloperException extends Exception { public static int dangerousComputation(int n) <web-app> 9 提供安全?/strong> E序清单5-19 web.xmlQ说明login-config的摘录) <web-app> E序清单5-20 ContextReporterjava import javax.servlet.*; /** Simple listener that prints a report on the standard output public class ContextReporter implements ServletContextListener { public void contextDestroyed(ServletContextEvent event) { <web-app>
5.3 提供应用范围内的初始化参?br>一般,对单个地servlet或JSP面分配初始化参数。指定的servlet或JSP面利用ServletConfig的getInitParameterҎdq些参数。但是,在某些情形下Q希望提供可׃Q意servlet或JSP面借助ServletContext的getInitParameterҎd的系l范围内的初始化参数?br>可利用context-param元素声明q些pȝ范围内的初始化倹{context-param元素应该包含param-name、param-value以及可选的description子元素,如下所C:
<context-param>
<param-name>support-email</param-name>
<param-value>blackhole@mycompany.com</param-value>
</context-param>
可回忆一下,Z保证可移植性,web.xml内的元素必须以正的ơ序声明。但q里应该注意Qcontext-param元素必须出现L与文档有关的元素Qicon、display-name或descriptionQ之后及filter、filter-mapping、listener?servlet元素之前?br>5.4 在服务器启动时装载servlet
假如servlet或JSP面有一个要花很长时间执行的init QservletQ或jspInitQJSPQ方法。例如,假如init或jspInitҎ从某个数据库或ResourceBundle查找产量。这U情况下Q在W一个客hh时装载servlet的缺省行为将对第一个客h产生较长旉的gq。因此,可利用servlet的load-on- startup元素规定服务器在W一ơ启动时装蝲servlet。下面是一个例子?br><servlet>
<servlet-name> … </servlet-name>
<servlet-class> … </servlet-class> <!-- Or jsp-file -->
<load-on-startup/>
</servlet>
可以为此元素体提供一个整数而不是用一个空的load-on-startup。想法是服务器应该在装蝲较大数目的servlet或JSP面之前装蝲较少数目的servlet或JSP面。例如,下面的servlet(攄在Web应用的WEB-INF目录下的web.xml文g中的web-app元素内)指C服务器首先装蝲和初始化SearchServletQ然后装载和初始化由位于Web应用的result目录中的index.jsp文g产生?servlet?br><servlet>
<servlet-name>Search</servlet-name>
<servlet-class>myPackage.SearchServlet</servlet-class> <!-- Or jsp-file -->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet>
<servlet-name>Results</servlet-name>
<servlet-class>/results/index.jsp</servlet-class> <!-- Or jsp-file -->
<load-on-startup>2</load-on-startup>
</servlet>
6 声明qo?/strong>
servlet版本2.3引入了过滤器的概c虽然所有支持servlet API版本2.3的服务器都支持过滤器Q但Z使用与过滤器有关的元素,必须在web.xml中用版?.3的DTD?br>qo器可截取和修改进入一个servlet或JSP面的请求或从一个servlet或JSP面发出的相应。在执行一个servlet或JSP面之前Q必L行第一个相关的qo器的doFilterҎ。在该过滤器对其FilterChain对象调用doFilterӞ执行链中的下一个过滤器。如果没有其他过滤器Qservlet或JSP面被执行。过滤器h对到来的ServletRequest对象的全部访问权Q因此,它们可以查看客户机名、查扑ֈ来的cookie{。ؓ了访问servlet或JSP面的输出,qo器可响应对象包裹在一个替w对象(stand-in objectQ中Q比方说把输出篏加到一个缓冲区。在调用FilterChain对象的doFilterҎ之后Q过滤器可检查缓冲区Q如有必要,对它进行修改,然后传送到客户机?br>例如Q程序清?-11帝国难以了一个简单的qo器,只要讉K相关的servlet或JSP面Q它截取请求ƈ在标准输Z打印一个报告(开发过E中在桌面系l上q行Ӟ大多数服务器都可以用这个过滤器Q?/p>
package moreservlets;
import javax.servlet.*;
import javax.servlet.http.*;
import java.util.*;
* whenever the associated servlet or JSP page is accessed.
* <P>
* Taken from More Servlets and JavaServer Pages
* from Prentice Hall and Sun Microsystems Press,
* http://www.moreservlets.com/.
* © 2002 Marty Hall; may be freely used or adapted.
*/
public void doFilter(ServletRequest request,
ServletResponse response,
FilterChain chain)
throws ServletException, IOException {
HttpServletRequest req = (HttpServletRequest)request;
System.out.println(req.getRemoteHost() +
" tried to access " +
req.getRequestURL() +
" on " + new Date() + ".");
chain.doFilter(request,response);
}
throws ServletException {
}
public void destroy() {}
}
<filter-name>Reporter</filter-name>
<filter-class>moresevlets.ReportFilter</filter-class>
</filter>
一旦命名了一个过滤器Q可利用filter-mapping元素把它与一个或多个servlet或JSP面相关联。关于此工作有两种选择?br>首先Q可使用filter-name和servlet-name子元素把此过滤器与一个特定的servlet名(此servlet名必ȝ后在相同?web.xml文g中用servlet元素声明Q关联。例如,下面的程序片断指C系l只要利用一个定制的URL讉K名ؓSomeServletName 的servlet或JSP面Q就q行名ؓReporter的过滤器?br><filter-mapping>
<filter-name>Reporter</filter-name>
<servlet-name>SomeServletName</servlet-name>
</filter-mapping>
其次Q可利用filter-name和url-pattern子元素将qo器与一lservlet、JSP面或静态内容相兌。例如,盔R的程序片D|C系l只要访问Web应用中的LURLQ就q行名ؓReporter的过滤器?br><filter-mapping>
<filter-name>Reporter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
例如Q程序清?-12l出了将ReportFilterqo器与名ؓPageName的servlet相关联的web.xml文g的一部分。名?PageName依次又与一个名为TestPage.jsp的JSP面以及以模式http: //host/webAppPrefix/UrlTest2/ 开头的URL相关联。TestPage.jsp的源代码已经JSP面命名的谈论在前面??分配名称和定制的URL"中给出。事实上Q程序清?- 12中的servlet和servlet-name从该节原封不动地拿q来的。给定这些web.xml,可看C面的标准输出形式的调试报告(换行是ؓ了容易阅读)?br>audit.irs.gov tried to access
http://mycompany.com/deployDemo/UrlTest2/business/tax-plan.html
on Tue Dec 25 13:12:29 EDT 2001.
<?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">
<filter>
<filter-name>Reporter</filter-name>
<filter-class>moresevlets.ReportFilter</filter-class>
</filter>
<!-- ... -->
<filter-mapping>
<filter-name>Reporter</filter-name>
<servlet-name>PageName</servlet-name>
</filter-mapping>
<!-- ... -->
<servlet>
<servlet-name>PageName</servlet-name>
<jsp-file>/RealPage.jsp</jsp-file>
</servlet>
<!-- ... -->
<servlet-mapping>
<servlet-name> PageName </servlet-name>
<url-pattern>/UrlTest2/*</url-pattern>
</servlet-mapping>
<!-- ... -->
</web-app>
7 指定Ƣ迎?/strong>
假如用户提供了一个像http: //host/webAppPrefix/directoryName/ q样的包含一个目录名但没有包含文件名的URLQ会发生什么事情呢Q用戯得到一个目录表Q一个错误?q是标准文g的内容?如果得到标准文g内容Q是 index.html、index.jsp、default.html、default.htm或别的什么东西呢Q?br>Welcome-file-list 元素及其辅助的welcome-file元素解决了这个模p的问题。例如,下面的web.xmlҎ出,如果一个URLl出一个目录名但未l出文g名,服务器应该首先试用index.jspQ然后再试用index.html。如果两者都没有扑ֈQ则l果有赖于所用的服务器(如一个目录列表)?br><welcome-file-list>
<welcome-file>index.jsp</welcome-file>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
虽然许多服务器缺省遵循这U行为,但不一定必这栗因此,明确C用welcom-file-list保证可移植性是一U良好的习惯?br>
8 指定处理错误的页?/strong>
现在我了解到Q你在开发servlet和JSP面时从不会犯错误,而且你的所有页面是那样的清晎ͼ一般的E序员都不会被它们的搞糊涂。但是,是hM犯错误的Q用户可能会提供不合规定的参敎ͼ使用不正的URL或者不能提供必需的表单字D倹{除此之外,其它开发h员可能不那么l心Q他们应该有些工h克服自己的不?br>error-page元素是用来克服q些问题的。它有两个可能的子元素,分别是:error-code和exception- type。第一个子元素error-code指出在给定的HTTP错误代码出现时用的URL。第二个子元素excpetion-type指出在出现某个给定的Java异常但未捕捉到时使用的URL。error-code和exception-type都利用location元素指出相应的URL。此 URL必须?开始。location所指出的位|处的页面可通过查找HttpServletRequest对象的两个专门的属性来讉K关于错误的信息,q两个属性分别是Qjavax.servlet.error.status_code和javax.servlet.error.message?br>可回忆一下,在web.xml内以正确的次序声明web-app的子元素很重要。这里只要记住,error-page出现在web.xml文g的末Nq,servlet、servlet-name和welcome-file-list之后卛_?br>
8.1 error-code元素
Z更好C解error-code元素的|可考虑一下如果不正确地输入文件名Q大多数站点会作Z么反映。这样做一般会出现一?04错误信息Q它表示不能扑ֈ该文Ӟ但几乎没提供更多有用的信息。另一斚wQ可以试一下在www.microsoft.com、www.ibm.com 处或者特别是在www.bea.com 处输出未知的文g名。这是会得出有用的消息,q些消息提供可选择的位|,以便查找感兴的面。提供这h用的错误面对于Web应用来说是很有h值得。事实上Qhttp://www.plinko.net/404/ 是把整个站点专门用?04错误面q个内容。这个站点包含来自全世界最好、最p和最搞笑?04面?br>E序清单5-13l出一个JSP面Q此面可返回给提供位置E序名的客户机。程序清?-14l出指定E序清单5-13作ؓq回404错误代码时显C的面的web.xml。请注意Q浏览器中显C的URL仍然是客h所提供的。错误页面是一U后台实现技术?br>最后一点,误住IE5的缺省配|显然不W合HTTP规范Q它忽略了服务器生成的错误消息,而是昄自己的标准出错信息。可转到其Tools菜单Q选择 Internet OptionsQ单击AdvancedQ取消Show Friendly HTTP Error Message来解x问题?/p>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD><TITLE>404: Not Found</TITLE></HEAD>
<BODY BGCOLOR="#FDF5E6">
<H2>Error!</H2>
I'm sorry, but I cannot find a page that matches
<%= request.getRequestURI() %> on the system. Maybe you should
try one of the following:
<UL>
<LI>Go to the server's <A HREF="/">home page</A>.
<LI>Search for relevant pages.<BR>
<FORM ACTION="http://www.google.com/search">
<CENTER>
Keywords: <INPUT TYPE="TEXT" NAME="q"><BR>
<INPUT TYPE="SUBMIT" VALUE="Search">
</CENTER>
</FORM>
<LI>Admire a random multiple of 404:
<%= 404*((int)(1000*Math.random())) %>.
<LI>Try a <A >
random 404 error message</A>. From the amazing and
amusing plinko.net <A >
404 archive</A>.
</UL>
</BODY></HTML>
E序清单5-14 web.xmlQ指出HTTP错误代码的错误页面的摘录Q?br><?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">
<error-page>
<error-code>404</error-code>
<location>/NotFound.jsp</location>
</error-page>
<!-- ... -->
</web-app>
8.2 exception-type元素
error-code元素处理某个h产生一个特定的HTTP状态代码时的情c然而,对于servlet或JSP面q回200但生运行时异常q种同样是常见的情况怎么办呢Q这正是exception-type元素要处理的情况。只需提供两样东西卛_Q即提供如下的一个完全限定的异常cd一个位|:
<error-page>
<exception-type>packageName.className</exception-type>
<location>/SomeURL</location>
</error-page>
q样Q如果Web应用中的Mservlet或JSP面产生一个特定类型的未捕捉到的异常,则用指定的URL。此异常cd可以是一个标准类型,?javax.ServletException或java.lang.OutOfMemoryErrorQ或者是一个专门针对你的应用的异常?br>例如Q程序清?-15l出了一个名为DumbDeveloperException的异常类Q可用它来特别标记经验较的E序员(不是说你的开发组中一定有q种人)所犯的错误。这个类q包含一个名为dangerousComputation的静态方法,它时不时地生成这U类型的异常。程序清?-16l出寚w机整数D用dangerousCompution的一个JSP面。在抛出此异常时Q如E序清单5-18的web.xml版本中所l出?exception-type所指出的那P对客h昄DDE.jspQ程序清?-17Q。图5-16和图5-17分别l出q运和不q的l果?/p>
package moreservlets;
programmer blunders. Used to illustrate the
exception-type web.xml element.
* <P>
* Taken from More Servlets and JavaServer Pages
* from Prentice Hall and Sun Microsystems Press,
* http://www.moreservlets.com/.
* © 2002 Marty Hall; may be freely used or adapted.
*/
public DumbDeveloperException() {
super("Duh. What was I *thinking*?");
}
throws DumbDeveloperException {
if (n < 5) {
return(n + 10);
} else {
throw(new DumbDeveloperException());
}
}
}
E序清单5-16 RiskyPage.jsp
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD><TITLE>Risky JSP Page</TITLE></HEAD>
<BODY BGCOLOR="#FDF5E6">
<H2>Risky Calculations</H2>
<%@ page import="moreservlets.*" %>
<% int n = ((int)(10 * Math.random())); %>
<UL>
<LI>n: <%= n %>
<LI>dangerousComputation(n):
<%= DumbDeveloperException.dangerousComputation(n) %>
</UL>
</BODY></HTML>
E序清单5-17 DDE.jsp
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD><TITLE>Dumb</TITLE></HEAD>
<BODY BGCOLOR="#FDF5E6">
<H2>Dumb Developer</H2>
We're brain dead. Consider using our competitors.
</BODY></HTML>
E序清单5-18 web.xmlQؓ异常指定错误面的摘录)
<?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">
<!-- ... -->
<servlet> … </servlet>
<!-- ... -->
<error-page>
<exception-type>
moreservlets.DumbDeveloperException
</exception-type>
<location>/DDE.jsp</location>
</error-page>
<!-- ... -->
</web-app>
利用web.xml中的相关元素为服务器的内建功能提供安全性?br>9.1 指定验证的方?br>使用login-confgi元素规定服务器应该怎样验证试图讉K受保护页面的用户。它包含三个可能的子元素Q分别是Qauth-method、realm -name和form-login-config。login-config元素应该出现在web.xml部v描述W文件的l尾附近Q紧跟在 security-constraint元素之后?br>l auth-method
login-config的这个子元素列出服务器将要用的特定验证机制。有效gؓBASIC、DIGEST、FORM和CLIENT-CERT。服务器只需要支持BASIC和FORM?br>BASIC 指出应该使用标准的HTTP验证Q在此验证中服务器检查Authorization头。如果缺这个头则返回一?01状态代码和一个WWW- Authenticate头。这D客户机弹Z个用来填写Authorization头的对话框。此机制很少或不提供Ҏ击者的防范Q这些攻击者在 Internetq接上进行窥探(如通过在客h的子|上执行一个信息包探测装置Q,因ؓ用户名和口o是用单的可逆base64~码发送的Q他们很Ҏ得手。所有兼容的服务器都需要支持BASIC验证?br>DIGEST指出客户机应该利用加密Digest Authentication形式传输用户名和口o。这提供了比BASIC验证更高的防范网l截取得的安全性,但这U加密比SSLQHTTPSQ所用的Ҏ更容易破解。不q,此结论有时没有意义,因ؓ当前很少有浏览器支持Digest AuthenticationQ所以servlet容器不需要支持它?br>FORM 指出服务器应该检查保留的会话cookieq且把不h它的用户重定向到一个指定的登陆c此登陆应该包含一个收集用户名和口令的常规HTML表单。在登陆之后Q利用保留会话的cookie跟踪用户。虽然很复杂Q但FORM验证防范|络H探q不比BASIC验证更安全,如果有必要可以在层安排诸如 SSL或网l层安全Q如IPSEC或VPNQ等额外的保护。所有兼容的服务器都需要支持FORM验证?br>CLIENT-CERT规定服务器必M用HTTPSQSSL之上的HTTPQƈ利用用户的公开密钥证书QPulic Key CertificatQ对用户q行验证。这提供了防范网l截取的很强的安全性,但只有兼容J2EE的服务器需要支持它?br>l realm-name
此元素只在auth-method为BASIC时用。它指出览器在相应对话框标题用的、ƈ作ؓAuthorization头组成部分的安全域的名称?br>l form-login-config
此元素只在auth-method为FORM旉用。它指定两个面Q分别是Q包含收集用户名及口令的HTML表单的页面(利用form-login- page子元素)Q用来指C验证失败的面Q利用form-error-page子元素)。由form-login-pagel出的HTML表单必须h一个j_security_check的ACTION属性、一个名为j_username的用户名文本字段以及一个名为j_password的口令字Dc?br>例如Q程序清?-19指示服务器用基于表单的验证。Web应用的顶层目录中的一个名为login.jsp的页面将攉用户名和口oQƈ且失败的登陆由相同目录中名为login-error.jsp的页面报告?/p>
<?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">
<!-- ... -->
<security-constraint> ... </security-constraint>
<login-config>
<auth-method> FORM </auth-method>
<form-login-config>
<form-login-page>/login.jsp</form-login-page>
<form-error-page>/login-error.jsp</form-error-page>
</form-login-config>
</login-config>
<!-- ... -->
</web-app>
9.2 限制对Web资源的访?br>现在Q可以指C服务器使用何种验证Ҏ了?了不P"你说道,"除非我能指定一个来收到保护?URLQ否则没有多大用处?没错。指些URLq说明他们应该得CU保护正是security-constriaint元素的用途。此元素?web.xml中应该出现在login-config的紧前面。它包含是个可能的子元素Q分别是Qweb-resource-collection?auth-constraint、user-data-constraint和display-name。下面各节对它们进行介l?br>l web-resource-collection
此元素确定应该保护的资源。所有security-constraint元素都必d含至一个web-resource-collectionV此元素׃个给ZQ意标识名U的web-resource-name元素、一个确定应该保护的URL的url-pattern元素、一个指出此保护所适用?HTTP命oQGET、POST{,~省为所有方法)的http-method元素和一个提供资料的可选description元素l成。例如,下面?Web-resource-collection(在security-constratint元素内)指出Web应用的proprietary目录中所有文档应该受C护?br><security-constraint>
<web-resource-coolection>
<web-resource-name>Proprietary</web-resource-name>
<url-pattern>/propritary/*</url-pattern>
</web-resource-coolection>
<!-- ... -->
</security-constraint>
重要的是应该注意刎ͼurl-pattern仅适用于直接访问这些资源的客户机。特别是Q它不适合于通过MVC体系l构利用 RequestDispatcher来访问的面Q或者不适合于利用类似jsp:forward的手D|讉K的页面。这U不匀U如果利用得当的话很有好处。例如,servlet可利用MVC体系l构查找数据Q把它放到bean中,发送请求到从bean中提取数据的JSP面q显C它。我们希望保证决不直接访问受保护的JSP面Q而只是通过建立该页面将使用的bean的servlet来访问它。url-pattern和auth-contraint元素可通过声明不允怓Q何用L接访问JSP面来提供这U保证。但是,q种不匀U的行ؓ可能让开发h员放松警惕,使他们偶然对应受保护的资源提供不受限制的讉K?
l auth-constraint
管web-resource-collention元素质出了哪些URL应该受到保护Q但是auth-constraint元素却指出哪些用户应该具有受保护资源的访问权。此元素应该包含一个或多个标识h讉K权限的用L别role- name元素Q以及包含(可选)一个描q角色的description元素。例如,下面web.xml中的security-constraint元素部门规定只有指定为Administrator或Big KahunaQ或两者)的用户具有指定资源的讉K权?br><security-constraint>
<web-resource-coolection> ... </web-resource-coolection>
<auth-constraint>
<role-name>administrator</role-name>
<role-name>kahuna</role-name>
</auth-constraint>
</security-constraint>
重要的是认识刎ͼ到此为止Q这个过E的可移植部分结束了。服务器怎样定哪些用户处于M角色以及它怎样存放用户的口令,完全有赖于具体的pȝ?br>例如QTomcat使用install_dir/conf/tomcat-users.xml用户名与角色名和口令相兌Q正如下面例子中所C,它指出用户joeQ口令bigshotQ和janeQ口令enajQ属于administrator和kahuna角色?br><tomcat-users>
<user name="joe" password="bigshot" roles="administrator,kahuna" />
<user name="jane" password="enaj" roles="kahuna" />
</tomcat-users>
l user-data-constraint
q个可选的元素指出在访问相兌源时使用M传输层保护。它必须包含一个transport-guarantee子元素(合法gؓNONE?INTEGRAL或CONFIDENTIALQ,q且可选地包含一个description元素。transport-guarantee为NONE值将Ҏ用的通讯协议不加限制。INTEGRALDC数据必M一U防止截取它的h阅读它的方式传送。虽然原理上Qƈ且在未来的HTTP版本中)Q在 INTEGRAL和CONFIDENTIAL之间可能会有差别Q但在当前实践中Q他们都只是单地要求用SSL。例如,下面指示服务器只允许对相兌源做 HTTPSq接Q?br><security-constraint>
<!-- ... -->
<user-data-constraint>
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
</user-data-constraint>
</security-constraint>
l display-name
security-constraint的这个很用的子元素给予可能由GUI工具使用的安全约束项一个名U?br>9.3 分配角色?br>q今为止Q讨论已l集中到完全由容器(服务器)处理的安全问题之上了。但servlet以及JSP面也能够处理它们自q安全问题?br>例如Q容器可能允许用户从bigwig或bigcheese角色讉K一个显CZh员额外紧贴的面Q但只允许bigwig用户修改此页面的参数。完成这U更l致的控制的一U常见方法是调用HttpServletRequset的isUserInRoleҎQƈ据此修改讉K?br>Servlet?security-role-ref子元素提供出现在服务器专用口令文件中的安全角色名的一个别名。例如,假如~写了一个调?request.isUserInRoleQ?boss"Q的servletQ但后来该servlet被用在了一个其口o文g调用角色manager而不是boss的服务器中。下面的E序D该servlet能够使用q两个名UC的Q何一个?br><servlet>
<!-- ... -->
<security-role-ref>
<role-name>boss</role-name> <!-- New alias -->
<role-link>manager</role-link> <!-- Real name -->
</security-role-ref>
</servlet>
也可以在web-app内利用security-role元素提供出现在role-name元素中的所有安全角色的一个全局列表。分别地生命角色佉KUIDEҎ处理安全信息?br>
10 控制会话时
如果某个会话在一定的旉内未被访问,服务器可把它扔掉以节U内存。可利用HttpSession的setMaxInactiveIntervalҎ直接讄个别会话对象的超时倹{如果不采用q种ҎQ则~省的超时值由具体的服务器军_。但可利用session-config和session- timeout元素来给Z个适用于所有服务器的明的时倹{超时值的单位为分钟,因此Q下面的例子讄~省会话时gؓ三个时Q?80分钟Q?br><session-config>
<session-timeout>180</session-timeout>
</session-config>
11 Web应用的文档化
来多的开发环境开始提供servlet和JSP的直接支持。例子有Borland Jbuilder Enterprise Edition、Macromedia UltraDev、Allaire JRun StudioQ写此文Ӟ已被Macromedia收购Q以及IBM VisuaAge for Java{?br>大量的web.xml元素不仅是ؓ服务器设计的Q而且q是为可视开发环境设计的。它们包括icon、display-name和discription{?br>可回忆一下,在web.xml内以适当地次序声明web-app子元素很重要。不q,q里只要Cicon、display-name和description是web.xml的web-app元素内的前三个合法元素即可?br>l icon
icon元素指出GUI工具可用来代表Web应用的一个和两个囑փ文g。可利用small-icon元素指定一q?6 x 16的GIF或JPEG囑փQ用large-icon元素指定一q?2 x 32的图像。下面D一个例子:
<icon>
<small-icon>/images/small-book.gif</small-icon>
<large-icon>/images/tome.jpg</large-icon>
</icon>
l display-name
display-name元素提供GUI工具可能会用来标记此Web应用的一个名U。下面是个例子?br><display-name>Rare Books</display-name>
l description
description元素提供解释性文本,如下所C:
<description>
This Web application represents the store developed for
rare-books.com, an online bookstore specializing in rare
and limited-edition books.
</description>
12 兌文g与MIMEcd
服务器一般都h一U让Web站点理员将文g扩展名与媒体相关联的Ҏ。例如,会自动l予名ؓmom.jpg的文件一个image/jpeg的MIME cd。但是,假如你的Web应用h几个不寻常的文gQ你希望保证它们在发送到客户机时分配为某UMIMEcd。mime-mapping元素Q具?extension和mime-type子元素)可提供这U保证。例如,下面的代码指C服务器application/x-fubar的MIMEcd分配l所有以.fool尾的文件?br><mime-mapping>
<extension>foo</extension>
<mime-type>application/x-fubar</mime-type>
</mime-mapping>
或许Q你的Web应用希望重蝲QoverrideQ标准的映射。例如,下面的代码将告诉服务器在发送到客户机时指定.ps文g作ؓU文本(text/plainQ而不是作为PostScriptQapplication/postscriptQ?br><mime-mapping>
<extension>ps</extension>
<mime-type>application/postscript</mime-type>
</mime-mapping>
13 定位TLD
JSP taglib元素h一个必要的uri属性,它给Z个TLDQTag Library DescriptorQ文件相对于Web应用的根的位|。TLD文g的实际名U在发布新的标签库版本时可能会改变,但我们希望避免更Ҏ有现有JSP面。此外,可能q希望用保持taglib元素的简l性的一个简短的uri。这是部v描述W文件的taglib元素z场的所在了。Taglib包含两个子元素:taglib-uri和taglib-location。taglib-uri元素应该与用于JSP taglib元素的uri属性的东西相匹配。Taglib-location元素l出TLD文g的实际位|。例如,假如你将文gchart-tags- 1.3beta.tld攑֜WebApp/WEB-INF/tlds中。现在,假如web.xml在web-app元素内包含下列内宏V?br><taglib>
<taglib-uri>/charts.tld</taglib-uri>
<taglib-location>
/WEB-INF/tlds/chart-tags-1.3beta.tld
</taglib-location>
</taglib>
l出q个说明后,JSP面可通过下面的简化Ş式用标{ֺ?br><%@ taglib uri="/charts.tld" prefix="somePrefix" %>
14 指定应用事g监听E序
应用事g监听器程序是建立或修改servlet环境或会话对象时通知的类。它们是servlet规范的版?.3中的新内宏V这里只单地说明用来向Web应用注册一个监听程序的web.xml的用法?br>注册一个监听程序涉及在web.xml的web-app元素内放|一个listener元素。在listener元素内,listener-class元素列出监听E序的完整的限定cdQ如下所C:
<listener>
<listener-class>package.ListenerClass</listener-class>
</listener>
虽然listener元素的结构很单,但请不要忘记Q必L地l出web-app元素内的子元素的ơ序。listener元素位于所有的servlet 元素之前以及所有filter-mapping元素之后。此外,因ؓ应用生存期监听程序是serlvet规范?.3版本中的新内容,所以必M?web.xml DTD?.3版本Q而不?.2版本?br>例如Q程序清?-20l出一个名为ContextReporter的简单的监听E序Q只要Web应用的Servlet-Context建立Q如装蝲Web应用Q或消除Q如服务器关闭)Ӟ它就在标准输Z昄一条消息。程序清?-21l出此监听程序注册所需要的web.xml文g的一部分?/p>
package moreservlets;
import java.util.*;
* when the ServletContext is created or destroyed.
* <P>
* Taken from More Servlets and JavaServer Pages
* from Prentice Hall and Sun Microsystems Press,
* http://www.moreservlets.com/.
* © 2002 Marty Hall; may be freely used or adapted.
*/
public void contextInitialized(ServletContextEvent event) {
System.out.println("Context created on " +
new Date() + ".");
}
System.out.println("Context destroyed on " +
new Date() + ".");
}
}
E序清单5-21 web.xmlQ声明一个监听程序的摘录Q?br><?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">
<!-- ... -->
<filter-mapping> … </filter-mapping>
<listener>
<listener-class>package.ListenerClass</listener-class>
</listener>
<servlet> ... </servlet>
<!-- ... -->
</web-app>
15 J2EE元素
本节描述用作J2EE环境l成部分的Web应用的web.xml元素。这里将提供一个简明的介绍Q详l内容可以参阅http://java.sun.com/j2ee/j2ee-1_3-fr-spec.pdf的Java 2 Plantform Enterprise Edition版本1.3规范的第5章?br>l distributable
distributable 元素指出QWeb应用是以q样的方式编E的Q即Q支持集的服务器可安全地在多个服务器上分布Web应用。例如,一个可分布的应用必d使用 Serializable对象作ؓ其HttpSession对象的属性,而且必须避免用实例变量(字段Q来实现持箋性。distributable元素直接出现在discription元素之后Qƈ且不包含子元素或数据Q它只是一个如下的标志?br><distributable />
l resource-env-ref
resource -env-ref元素声明一个与某个资源有关的管理对象。此元素׃个可选的description元素、一个resource-env-ref- name元素Q一个相对于java:comp/env环境的JNDI名)以及一个resource-env-type元素Q指定资源类型的完全限定的类Q,如下所C:
<resource-env-ref>
<resource-env-ref-name>
jms/StockQueue
</resource-env-ref-name>
<resource-env-ref-type>
javax.jms.Queue
</resource-env-ref-type>
</resource-env-ref>
l env-entry
env -entry元素声明Web应用的环境项。它׃个可选的description元素、一个env-entry-name元素Q一个相对于java: comp/env环境JNDI名)、一个env-entry-value元素Q项|以及一个env-entry-type元素Qjava.langE序包中一个类型的完全限定cdQjava.lang.Boolean、java.lang.String{)l成。下面是一个例子:
<env-entry>
<env-entry-name>minAmout</env-entry-name>
<env-entry-value>100.00</env-entry-value>
<env-entry-type>minAmout</env-entry-type>
</env-entry>
l ejb-ref
ejb -ref元素声明对一个EJB的主目录的应用。它׃个可选的description元素、一个ejb-ref-name元素Q相对于java: comp/env的EJB应用Q、一个ejb-ref-type元素Qbean的类型,Entity或SessionQ、一个home元素Qbean的主目录接口的完全限定名Q、一个remote元素Qbean的远E接口的完全限定名)以及一个可选的ejb-link元素Q当前bean链接的另一?bean的名Uͼl成?br>l ejb-local-ref
ejb-local-ref元素声明一个EJB的本C目录的引用。除了用local-home代替home外,此元素具有与ejb-ref元素相同的属性ƈ以相同的方式使用?/p>
选择允许使用 '|' 字符来在两个或多个候选项中进行选择。通过扩展章节标题的正则表辑ּQ可以将其扩充ؓ不仅仅适用于章节标题的表达式。不q,q可没有惌的那么直接。在使用选择Ӟ匹?|' 字符每边最可能的表辑ּ。你可能认ؓ下面?JScript ?VBScript 表达式将匚w位于一行的开始和l束位置且后跟一个或两个数字?'Chapter' ?'Section'Q?/p>
/^Chapter|Section [1-9][0-9]{0,1}$/ "^Chapter|Section [1-9][0-9]{0,1}$"
不幸的是Q真正的情况是上面所C的正则表达式要么匹配位于一行开始处的单?'Chapter'Q要么匹配一行结束处的后跟Q何数字的 'Section'。如果输入字W串?'Chapter 22'Q上面的表达式将只匹配单?'Chapter'。如果输入字W串?'Section 22'Q则该表辑ּ匹?'Section 22'。但q种l果不是我们此处的目的,因此必须有一U办法来使正则表辑ּ对于所要做的更易于响应Q而且实也有q种Ҏ?/p>
可以使用圆括h限制选择的范_也就是说明确该选择只适用于这两个单词 'Chapter' ?'Section'。不q,圆括号同样也是难处理的,因ؓ它们也用来创建子表达式,有些内容在后面关于子表辑ּ的部分介l。通过采用上面所C的正则表达式ƈ在适当位置d圆括P可以该正则表辑ּ既可以匹?'Chapter 1'Q也可以匚w 'Section 3'?
下面的正则表辑ּ使用圆括号将 'Chapter' ?'Section' l成一l,所以该表达式才能正工作。对 JScript 为:
/^(Chapter|Section) [1-9][0-9]{0,1}$/
?VBScript 为:
"^(Chapter|Section) [1-9][0-9]{0,1}$"
q些表达式工作正,只是产生了一个有的副品。在 'Chapter|Section' 两边攄圆括号徏立了适当的编l,但也D两个待匹配单词之一都被捕获供今后用。由于在上面所C的表达式中只有一l圆括号Q因此只能有一个捕L submatch。可以?VBScript ?strong>Submatches 集合或者JScript ?strong>RegExp 对象?$1-$9 属性来引用q个子匹配?/p>
有时捕获一个子匚w是所希望的,有时则是不希望的。在说明所C的CZ中,真正惛_的就是用圆括号对单?'Chapter' ?'Section' 之间的选择~组。ƈ不希望在后面再引用该匚w。实际上Q除非真的是需要捕获子匚wQ否则请不要使用。由于不需要花旉和内存来存储那些子匹配,q种正则表达式的效率更高?/p>
可以在正则表辑ּ模式圆括号内部的前面使用 '?:'来防止存储该匚w供今后用。对上面所C正则表辑ּ的下qCҎ供了免除子匹配存储的相同功能。对 JScriptQ?/p>
/^(?:Chapter|Section) [1-9][0-9]{0,1}$/
?VBScriptQ?/p>
"^(?:Chapter|Section) [1-9][0-9]{0,1}$"
除了 '?:' 元字W,q有两个非捕获元字符用于UC?em>预查的匹配。一个ؓ正向预查Q用 ?= 表示Q?在Q何开始匹配圆括号内的正则表达式模式的位置来匹配搜索字W串。一个ؓ负向预查Q用 '?!' 表示Q在M开始不匚w该正则表辑ּ模式的位|来匚w搜烦字符丌Ӏ?/p>
例如Q假定有一个包含引用有 Windows 3.1、Windows 95、Windows 98 以及 Windows NT 的文档。进一步假N要更新该文档Q方法是查找所有对 Windows 95、Windows 98 以及 Windows NT 的引用,q将q些引用更改?Windows 2000。可以用下面的 JScript 正则表达式,q是一个正向预查,来匹?Windows 95、Windows 98 以及 Windows NTQ?/p>
/Windows(?=95 |98 |NT )/
?VBScript 要进行同L匚w可以使用下述表达式:
"Windows(?=95 |98 |NT )"
扑ֈ一个匹配后Q紧接匹配到的文字(而不包括预查中用的字符Q就开始对下一ơ匹配的搜烦。例如,如果上面所C的表达式匹配到 'Windows 98'Q则从 'Windows' 而不?'98' 之后l箋查找?/p>
正则表达式一个最重要的特性就是将匚w成功的模式的某部分进行存储供以后使用q一能力。请回想一下,对一个正则表辑ּ模式或部分模式两Ҏ加圆括号导致这部分表达式存储到一个时缓冲区中。可以用非捕获元字W?'?:', '?=', or '?!' 来忽略对q部分正则表辑ּ的保存?/p>
所捕获的每个子匚w都按照在正则表达式模式中从左臛_所遇到的内容存储。存储子匚w的缓冲区~号?1 开始,q箋~号直至最?99 个子表达式。每个缓冲区都可以?'\n' 讉KQ其?n Z个标识特定缓冲区的一位或两位十进制数?
后向引用一个最单,最有用的应用是提供了确定文字中q箋出现两个相同单词的位|的能力。请看下面的句子Q?/p>
Is is the cost of of gasoline going up up?
Ҏ所写内容,上面的句子明昑֭在单词多ơ重复的问题。如果能有一U方法无需查找每个单词的重复现象就能修改该句子好了。下面的 JScript 正则表达式用一个子表达式就可以实现q一功能?
/\b([a-z]+) \1\b/gi
{h?VBScript 表达式ؓQ?/p>
"\b([a-z]+) \1\b"
在这个示例中Q子表达式就是圆括号之间的每一V所捕获的表辑ּ包括一个或多个字母字符Q即?[a-z]+' 所指定的。该正则表达式的W二部分是对前面所捕获的子匚w的引用,也就是由附加表达式所匚w的第二次出现的单词?\1'用来指定W一个子匚w。单词边界元字符保只检单独的单词。如果不q样Q则诸如 "is issued" ?"this is" q样的短语都会被该表辑ּ不正地识别?
?JScript 表达式中Q正则表辑ּ后面的全局标志 ('g') 表示该表辑ּ用来在输入字符串中查找可能多的匹配。大写敏感性由表达式结束处的大写敏感性标?('i') 指定。多行标记指定可能出现在换行W的两端的潜在匹配。对 VBScript 而言Q在表达式中不能讄各种标记Q但必须使用 RegExp 对象的属性来昑ּ讄?/p>
使用上面所C的正则表达式,下面?JScript 代码可以使用子匹配信息,在一个文字字W串中将q箋出现两次的相同单词替换ؓ一个相同的单词Q?/p>
var ss = "Is is the cost of of gasoline going up up?.\n"; var re = /\b([a-z]+) \1\b/gim; //
创徏正则表达式样?code>. var rv = ss.replace(re,"$1"); //用一个单词替代两个单?code>.
最接近的等?nbsp; VBScript 代码如下Q?/p>
Dim ss, re, rv ss = "Is is the cost of of gasoline going up up?." & vbNewLine Set re = New RegExp re.Pattern = "\b([a-z]+) \1\b" re.Global = True re.IgnoreCase = True re.MultiLine = True rv = re.Replace(ss,"$1")
h意在 VBScript 代码中,全局、大写敏感性以及多行标记都是?RegExp 对象的适当属性来讄的?/p>
?strong>replace Ҏ中?$1 来引用所保存的第一个子匚w。如果有多个子匹配,则可以用 $2, $3 {l引用?/p>
后向引用的另一个用途是一个通用资源指示W?(URI) 分解为组仉分。假定希望将下述的URI 分解为协?(ftp, http, etc)Q域名地址以及面/路径Q?/p>
http://msdn.microsoft.com:80/scripting/default.htm
下面的正则表辑ּ可以提供q个功能。对 JScriptQؓQ?/p>
/(\w+):\/\/([^/:]+)(:\d*)?([^# ]*)/
?VBScript 为:
"(\w+):\/\/([^/:]+)(:\d*)?([^# ]*)"
W一个附加子表达式是用来捕获?web 地址的协议部分。该子表辑ּ匚w位于一个冒号和两个正斜杠之前的M单词。第二个附加子表辑ּ捕获该地址的域名地址。该子表辑ּ匚w不包?'^'?'/' ?':' 字符的Q何字W序列。第三个附加子表辑ּ捕获|站端口LQ如果指定了该端口号。该子表辑ּ匚w后跟一个冒L零或多个数字。最后,W四个附加子表达式捕L?web 地址指定的\径以及\或者页面信息。该子表辑ּ匚w一个和多个?#' 或空g外的字符?/p>
该正则表达式应用于上面所C的 URI 后,子匹配包含下q内容:
RegExp.$1 包含 "http"
RegExp.$2 包含 "msdn.microsoft.com"
RegExp.$3 包含 ":80"
RegExp.$4 包含 "/scripting/default.htm"
有时候不知道要匹配多字W。ؓ了能适应q种不确定性,正则表达式支持限定符的概c这些限定符可以指定正则表达式的一个给定组件必要出现多少ơ才能满_配?/p>
下表l出了各U限定符及其含义的说明:
字符 | 描述 |
---|---|
* | 匚w前面的子表达式零ơ或多次。例如,zo* 能匹?"z" 以及 "zoo"?* {h于{0,}?/td> |
+ | 匚w前面的子表达式一ơ或多次。例如,'zo+' 能匹?"zo" 以及 "zoo"Q但不能匚w "z"? {h?{1,}?/td> |
? | 匚w前面的子表达式零ơ或一ơ。例如,"do(es)?" 可以匚w "do" ?"does" 中的"do" ? {h?{0,1}?/td> |
{n} | n 是一个非负整数。匹配确定的 n ơ。例如,'o{2}' 不能匚w "Bob" 中的 'o'Q但是能匚w "food" 中的两个 o?/td> |
{n,} | n 是一个非负整数。至匹?em>n ơ。例如,'o{2,}' 不能匚w "Bob" 中的 'o'Q但能匹?"foooood" 中的所?o?o{1,}' {h?'o+'?o{0,}' 则等价于 'o*'?/td> |
{n,m} | m ?n 均ؓ非负整数Q其?em>n <= m。最匹?n ơ且最多匹?m ơ。刘Q?"o{1,3}" 匹?"fooooood" 中的前三?o?o{0,1}' {h?'o?'。请注意在逗号和两个数之间不能有空根{?/td> |
对一个很大的输入文档而言Q章节数很轻易就过九章Q因此需要有一U方法来处理两位数或者三位数的章节号。限定符提供了q个功能。下面的JScript 正则表达式可以匹配具有Q何位数的章节标题Q?/p>
/Chapter [1-9][0-9]*/
下面?VBScript 正则表达式执行同L匚wQ?/p>
"Chapter [1-9][0-9]*"
h意限定符出现在范围表辑ּ之后。因此,它将应用于所包含的整个范围表辑ּQ在本例中,只指定了?0 ?9 的数字?/p>
q里没有使用 '+' 限定W,因ؓW二位或后箋位置上ƈ不一定需要一个数字。同样也没有使用 '?' 字符Q因把章节数限制ؓ只有两位数字。在 'Chapter' 和空格字W之后至要匚w一个数字?/p>
如果已知章节数限制只?9 章,则可以用下面的 JScript 表达式来指定臛_有一位数字,但不过两个数字?/p>
/Chapter [0-9]{1,2}/
?VBScript 可以使用下述正则表达式:
"Chapter [0-9]{1,2}"
上述表达式的~点是如果有一个章节号大于 99Q它仍只会匹配前两位数字。另一个缺Ҏ某些人可以创Z?Chapter 0Q而且仍能匚w。一个更好的用来匚w两位数的 JScript 表达式如下:
/Chapter [1-9][0-9]?/
或?/p>
/Chapter [1-9][0-9]{0,1}/
?VBScript 而言Q下q表辑ּ与上面等P
"Chapter [1-9][0-9]?"
或?/p>
"Chapter [1-9][0-9]{0,1}"
'*
'?'+'
?'?'
限定W都UC?em>贪婪?/em>Q也是_他们可能多地匹配文字。有时这Ҏ׃是所希望发生的情c有时则正好希望最匹配?
例如Q你可能要搜索一?HTML 文档来查找一处包含在 H1 标记中的章节标题。在文档中该文字可能h如下形式Q?/p>
<H1>Chapter 1 – Introduction to Regular Expressions</H1>
下面的表辑ּ匚w从开始的于?(<) ?H1 标记l束处的大于号之间的所有内宏V?/p>
/<.*>/
VBScript 的正则表辑ּ为:
"<.*>"
如果所要匹配的是开始的 H1 标记Q则下述非贪婪地表达式就只匹?<H1>?/p>
/<.*?>/
或?/p>
"<.*?>"
通过?'*'?'+' ?'?' 限定W后攄 '?'Q该表达式就从贪婪匹配{Z非贪婪或最匹配?/p>
到现在ؓ止,所看到的示例都只考虑查找M地方出现的章节标题。出现的M一个字W串 'Chapter' 后跟一个空格和一个数字可能是一个真正的章节标题Q也可能是对其他章节的交叉引用。由于真正的章节标题L出现在一行的开始,因此需要设计一个方法只查找标题而不查找交叉引用?/p>
定位W提供了q个功能。定位符可以一个正则表辑ּ固定在一行的开始或l束。也可以创徏只在单词内或只在单词的开始或l尾处出现的正则表达式。下表包含了正则表达式及其含义的列表Q?/p>
字符 | 描述 |
---|---|
^ | 匚w输入字符串的开始位|。如果设|了 RegExp 对象?Multiline 属性,^ 也匹?'\n' ?'\r' 之后的位|?/td> |
$ | 匚w输入字符串的l束位置。如果设|了RegExp 对象?Multiline 属性,$ 也匹?'\n' ?'\r' 之前的位|?/td> |
\b | 匚w一个单词边界,也就是指单词和空格间的位|?/td> |
\B | 匚w非单词边界?/td> |
不能对定位符使用限定W。因为在一个换行符或者单词边界的前面或后面不会有q箋多个位置Q因此诸?'^*' 的表辑ּ是不允许的?/p>
要匹配一行文字开始位|的文字Q请在正则表辑ּ的开始处使用 '^' 字符。不要把 '^' 的这个语法与其在括号表达式中的语法弄淗它们的语法Ҏ不同?
要匹配一行文字结束位|的文字Q请在正则表辑ּ的结束处使用 '$' 字符?/p>
要在查找章节标题时用定位符Q下面的 JScript 正则表达式将匚w位于一行的开始处最多有两个数字的章节标题:
/^Chapter [1-9][0-9]{0,1}/
VBScript 中相同功能的正则表达式如下:
"^Chapter [1-9][0-9]{0,1}"
一个真正的章节标题不仅出现在一行的开始,而且q一行中也仅有这一个内容,因此Q它必然也位于一行的l束。下面的表达式确保所指定的匹配只匚w章节而不会匹配交叉引用。它是通过创徏一个只匚w一行文字的开始和l束位置的正则表辑ּ来实现的?/p>
/^Chapter [1-9][0-9]{0,1}$/
?VBScript 则用:
"^Chapter [1-9][0-9]{0,1}$"
匚w单词边界有少怸同,但却l正则表辑ּ增加了一个非帔R要的功能。单词边界就是单词和I格之间的位|。非单词边界是其他M位置。下面的 JScript 表达式将匚w单词 'Chapter' 的前三个字符Q因为它们出现在单词边界后:
/\bCha/
?VBScript 为:
"\bCha"
q里 '\b' 操作W的位置很关键。如果它位于要匹配的字符串的开始,则将查找位于单词开头处的匹配;如果它位于改字符串的末尾Q则查找位于单词l束处的匚w。例如,下面的表辑ּ匹配单?'Chapter' 中的 'ter'Q因为它出现在单词边界之前:
/ter\b/
以及
"ter\b"
下面的表辑ּ匹?'apt'Q因为它位于 'Chapter' 中间Q但不会匚w 'aptitude' 中的'apt'Q?/p>
/\Bapt/
以及
"\Bapt"
q是因ؓ在单?'Chapter' ?'apt' 出现在非单词边界位置Q而在单词 'aptitude' 中位于单词边界位|。非单词边界操作W的位置不重要,因ؓ匚w与一个单词的开头或l尾无关?/p>
如果原来没有使用q正则表辑ּQ那么可能对q个术语和概念会不太熟悉。不q,它们q不是您惌的那么新奇?/p>
请回想一下在盘上是如何查找文g的。您肯定会?? ?* 字符来帮助查找您正寻扄文g? 字符匚w文g名中的单个字W,?* 则匹配一个或多个字符。一个如 'data?.dat' 的模式可以找Cq文Ӟ
data1.dat
data2.dat
datax.dat
dataN.dat
如果使用 * 字符代替 ? 字符Q则扩大找到的文g数量?data*.dat' 可以匚w下述所有文件名Q?/p>
data.dat
data1.dat
data2.dat
data12.dat
datax.dat
dataXYZ.dat
管q种搜烦文g的方法肯定很有用Q但也十分有限? ?* 通配W的有限能力可以使你Ҏ则表辑ּ能做什么有一个概念,不过正则表达式的功能更强大,也更灉|?/p>
正则表达式的“先”可以一直上溯至对hcȝl系l如何工作的早期研究。Warren McCulloch ?Walter Pitts q两位神l生理学家研I出一U数学方式来描述q些经|络?/p>
1956 q? 一位叫 Stephen Kleene 的美国数学家?McCulloch ?Pitts 早期工作的基上,发表了一标题ؓ“经|事件的表示?#8221;的论文,引入了正则表辑ּ的概c正则表辑ּ是用来描述他称?#8220;正则集的代数”的表辑ּQ因此采?#8220;正则表达?#8221;q个术语?
随后Q发现可以将q一工作应用于用Ken Thompson 的计搜索算法的一些早期研IӞKen Thompson是Unix 的主要发明h。正则表辑ּ的第一个实用应用程序就?Unix 中的qed ~辑器?/p>
如他们所_剩下的就是众所周知的历史了。从那时L至现在正则表辑ּ都是Z文本的编辑器和搜索工具中的一个重要部分?/p>
在典型的搜烦和替换操作中Q必L供要查找的确切文字。这U技术对于静态文本中的简单搜索和替换d可能_了,但是׃它缺乏灵zL,因此在搜索动态文本时有困难了,甚至是不可能的?
使用正则表达式,可以:
例如Q如果需要搜索整?web 站点来删除某些过时的材料q替换某些HTML 格式化标讎ͼ则可以用正则表辑ּҎ个文件进行测试,看在该文件中是否存在所要查扄材料?HTML 格式化标记。用q个ҎQ就可以受影响的文件范围羃到包含要删除或更改的材料的那些文g。然后可以用正则表辑ּ来删除过时的材料Q最后,可以再次使用正则表达式来查找q替换那些需要替换的标记?/p>
q里有一些可能会遇到的正则表辑ּCZQ?/p>
JScript | VBScript | 匚w |
---|---|---|
/^\[ \t]*$/ | "^\[ \t]*$" | 匚w一个空白行?/td> |
/\d{2}-\d{5}/ | "\d{2}-\d{5}" | 验证一个ID L是否׃?位数字,一个连字符以及一?位数字组成?/td> |
/<(.*)>.*<\/\1>/ | "<(.*)>.*<\/\1>" | 匚w一?HTML 标记?/td> |
下表是元字符及其在正则表辑ּ上下文中的行为的一个完整列表:
字符 | 描述 |
---|---|
\ | 下一个字W标Cؓ一个特D字W、或一个原义字W、或一?后向引用、或一个八q制转义W。例如,'n' 匚w字符 "n"?\n' 匚w一个换行符。序?'\\' 匚w "\" ?"\(" 则匹?"("?/td> |
^ | 匚w输入字符串的开始位|。如果设|了 RegExp 对象?Multiline 属性,^ 也匹?'\n' ?'\r' 之后的位|?/td> |
$ | 匚w输入字符串的l束位置。如果设|了RegExp 对象?Multiline 属性,$ 也匹?'\n' ?'\r' 之前的位|?/td> |
* | 匚w前面的子表达式零ơ或多次。例如,zo* 能匹?"z" 以及 "zoo"?* {h于{0,}?/td> |
+ | 匚w前面的子表达式一ơ或多次。例如,'zo+' 能匹?"zo" 以及 "zoo"Q但不能匚w "z"? {h?{1,}?/td> |
? | 匚w前面的子表达式零ơ或一ơ。例如,"do(es)?" 可以匚w "do" ?"does" 中的"do" ? {h?{0,1}?/td> |
{n} | n 是一个非负整数。匹配确定的 n ơ。例如,'o{2}' 不能匚w "Bob" 中的 'o'Q但是能匚w "food" 中的两个 o?/td> |
{n,} | n 是一个非负整数。至匹?em>n ơ。例如,'o{2,}' 不能匚w "Bob" 中的 'o'Q但能匹?"foooood" 中的所?o?o{1,}' {h?'o+'?o{0,}' 则等价于 'o*'?/td> |
{n,m} | m ?n 均ؓ非负整数Q其?em>n <= m。最匹?n ơ且最多匹?m ơ。刘Q?"o{1,3}" 匹?"fooooood" 中的前三?o?o{0,1}' {h?'o?'。请注意在逗号和两个数之间不能有空根{?/td> |
? | 当该字符紧跟在Q何一个其他限制符 (*, +, ?, {n}, {n,}, {n,m}) 后面Ӟ匚w模式是非贪婪的。非贪婪模式可能少的匹配所搜烦的字W串Q而默认的贪婪模式则尽可能多的匚w所搜烦的字W串。例如,对于字符?"oooo"Q?o+?' 匹配单?"o"Q?'o+' 匹配所?'o'?/td> |
. | 匚w?"\n" 之外的Q何单个字W。要匚w包括 '\n' 在内的Q何字W,请用象 '[.\n]' 的模式?/td> |
(pattern) | 匚wpattern q获取这一匚w。所获取的匹配可以从产生?Matches 集合得到Q在VBScript 中?SubMatches 集合Q在JScript 中则使用 $0…$9 属性。要匚w圆括号字W,请?'\(' ?'\)'?/td> |
(?:pattern) | 匚w pattern 但不获取匚wl果Q也是说这是一个非获取匚wQ不q行存储供以后用。这在?"? 字符 (|) 来组合一个模式的各个部分是很有用。例如, 'industr(?:y|ies) 是一个比 'industry|industries' 更简略的表达式?/td> |
(?=pattern) | 正向预查Q在M匚w pattern 的字W串开始处匚w查找字符丌Ӏ这是一个非获取匚wQ也是_该匹配不需要获取供以后使用。例如, 'Windows (?=95|98|NT|2000)' 能匹?"Windows 2000" 中的 "Windows" Q但不能匚w "Windows 3.1" 中的 "Windows"。预查不消耗字W,也就是说Q在一个匹配发生后Q在最后一ơ匹配之后立卛_始下一ơ匹配的搜烦Q而不是从包含预查的字W之后开始?/td> |
(?!pattern) | 负向预查Q在M不匹配Negative lookahead matches the search string at any point where a string not matching pattern 的字W串开始处匚w查找字符丌Ӏ这是一个非获取匚wQ也是_该匹配不需要获取供以后使用。例?Windows (?!95|98|NT|2000)' 能匹?"Windows 3.1" 中的 "Windows"Q但不能匚w "Windows 2000" 中的 "Windows"。预查不消耗字W,也就是说Q在一个匹配发生后Q在最后一ơ匹配之后立卛_始下一ơ匹配的搜烦Q而不是从包含预查的字W之后开? |
x|y | 匚w x ?y。例如,'z|food' 能匹?"z" ?"food"?(z|f)ood' 则匹?"zood" ?"food"? |
[xyz] | 字符集合。匹配所包含的Q意一个字W。例如, '[abc]' 可以匚w "plain" 中的 'a'? |
[^xyz] | 负值字W集合。匹配未包含的Q意字W。例如, '[^abc]' 可以匚w "plain" 中的'p'? |
[a-z] | 字符范围。匹配指定范围内的Q意字W。例如,'[a-z]' 可以匚w 'a' ?'z' 范围内的L写字母字符? |
[^a-z] | 负值字W范围。匹配Q何不在指定范围内的Q意字W。例如,'[^a-z]' 可以匚wM不在 'a' ?'z' 范围内的L字符? |
\b | 匚w一个单词边界,也就是指单词和空格间的位|。例如, 'er\b' 可以匚w"never" 中的 'er'Q但不能匚w "verb" 中的 'er'? |
\B | 匚w非单词边界?er\B' 能匹?"verb" 中的 'er'Q但不能匚w "never" 中的 'er'?/td> |
\cx | 匚w?em>x指明的控制字W。例如, \cM 匚w一?Control-M 或回车符?x 的值必Mؓ A-Z ?a-z 之一。否则,?c 视ؓ一个原义的 'c' 字符? |
\d | 匚w一个数字字W。等价于 [0-9]? |
\D | 匚w一个非数字字符。等价于 [^0-9]? |
\f | 匚w一个换늬。等价于 \x0c ?\cL?/td> |
\n | 匚w一个换行符。等价于 \x0a ?\cJ?/td> |
\r | 匚w一个回车符。等价于 \x0d ?\cM?/td> |
\s | 匚wMI白字符Q包括空根{制表符、换늬{等。等价于 [ \f\n\r\t\v]?/td> |
\S | 匚wM非空白字W。等价于 [^ \f\n\r\t\v]?/td> |
\t | 匚w一个制表符。等价于 \x09 ?\cI?/td> |
\v | 匚w一个垂直制表符。等价于 \x0b ?\cK?/td> |
\w | 匚w包括下划U的M单词字符。等价于'[A-Za-z0-9_]'? |
\W | 匚wM非单词字W。等价于 '[^A-Za-z0-9_]'? |
\xn | 匚w nQ其?n 为十六进制{义倹{十六进制{义值必Mؓ定的两个数字长。例如, '\x41' 匚w "A"?\x041' 则等价于 '\x04' & "1"。正则表辑ּ中可以?ASCII ~码? |
\num | 匚w numQ其?num 是一个正整数。对所获取的匹配的引用。例如,'(.)\1' 匚w两个q箋的相同字W? |
\n | 标识一个八q制转义值或一个后向引用。如?\n 之前臛_ n 个获取的子表辑ּQ则 n 为后向引用。否则,如果 n 为八q制数字 (0-7)Q则 n Z个八q制转义倹{?/td> |
\nm | 标识一个八q制转义值或一个后向引用。如?\nm 之前臛_有is preceded by at least nm 个获取得子表辑ּQ则 nm 为后向引用。如?\nm 之前臛_?n 个获取,?n Z个后跟文?m 的后向引用。如果前面的条g都不满Q若 n ?m 均ؓ八进制数?(0-7)Q则 \nm 匹配八q制转义?nm?/td> |
\nml | 如果 n 为八q制数字 (0-3)Q且 m ?l 均ؓ八进制数?(0-7)Q则匚w八进制{义?nml?/em> |
\un | 匚w nQ其?n 是一个用四个十六q制数字表示?Unicode 字符。例如, \u00A9 匚w版权W号 (?)?/td> |
在构造正则表辑ּ之后Q就可以象数学表辑ּ一h求|也就是说Q可以从左至叛_ƈ按照一个优先权序来求倹{?
下表从最高优先到最低优先列出各种正则表达式操作符的优先权序Q?/p>
操作W?/th> | 描述 |
---|---|
\ | 转义W?/td> |
(), (?:), (?=), [] | 圆括号和Ҏ?/td> |
*, +, ?, {n}, {n,}, {n,m} | 限定W?/td> |
^, $, \anymetacharacter | 位置和顺?/td> |
| | “?#8221;操作 |
最单的正则表达式是一个单独的普通字W,可以匚w所搜烦字符串中的该字符本n。例如,单字W模?'A' 可以匚w所搜烦字符串中M位置出现的字?'A'。这里有一些单字符正则表达式模式的CZQ?/p>
/a/ /7/ /M/
{h?VBScript 单字W正则表辑ּ为:
"a" "7" "M"
可以多个单字符l合在一起得C个较大的表达式。例如,下面?JScript 正则表达式不是别的,是通过l合单字W表辑ּ 'a'?7'以及 'M' 所创徏出来的一个表辑ּ?
/a7M/
{h?VBScript 表达式ؓQ?/p>
"a7M"
h意这里没有连接操作符。所需要做的就是将一个字W放在了另一个字W后面?/p>
有不元字符在试囑֯其进行匹配时需要进行特D的处理。要匚wq些Ҏ字符Q必首先将q些字符转义Q也是在前面用一个反斜杠 (\)。下表给Zq些Ҏ字符及其含义Q?/p>
Ҏ字符 | 说明 |
---|---|
$ | 匚w输入字符串的l尾位置。如果设|了 RegExp 对象?Multiline 属性,?$ 也匹?'\n' ?'\r'。要匚w $ 字符本nQ请使用 \$?/td> |
( ) | 标记一个子表达式的开始和l束位置。子表达式可以获取供以后使用。要匚wq些字符Q请使用 \( ?\)?/td> |
* | 匚w前面的子表达式零ơ或多次。要匚w * 字符Q请使用 \*?/td> |
+ | 匚w前面的子表达式一ơ或多次。要匚w + 字符Q请使用 \+?/td> |
. | 匚w除换行符 \n之外的Q何单字符。要匚w .Q请使用 \?/td> |
[ | 标记一个中括号表达式的开始。要匚w [Q请使用 \[? |
? | 匚w前面的子表达式零ơ或一ơ,或指明一个非贪婪限定W。要匚w ? 字符Q请使用 \??/td> |
\ | 下一个字W标Cؓ或特D字W、或原义字符、或后向引用、或八进制{义符。例如, 'n' 匚w字符 'n'?\n' 匚w换行W。序?'\\' 匚w "\"Q?'\(' 则匹?"("?/td> |
^ | 匚w输入字符串的开始位|,除非在方括号表达式中使用Q此时它表示不接受该字符集合。要匚w ^ 字符本nQ请使用 \^?/td> |
{ | 标记限定W表辑ּ的开始。要匚w {Q请使用 \{?/td> |
| | 指明两项之间的一个选择。要匚w |Q请使用 \|?/td> |
有不很有用的非打印字符Q偶必M用。下表显CZ用来表示q些非打印字W的转义序列Q?/p>
字符 | 含义 |
---|---|
\cx | 匚w?em>x指明的控制字W。例如, \cM 匚w一?Control-M 或回车符?x 的值必Mؓ A-Z ?a-z 之一。否则,?c 视ؓ一个原义的 'c' 字符?/td> |
\f | 匚w一个换늬。等价于 \x0c ?\cL?/td> |
\n | 匚w一个换行符。等价于 \x0a ?\cJ?/td> |
\r | 匚w一个回车符。等价于 \x0d ?\cM?/td> |
\s | 匚wMI白字符Q包括空根{制表符、换늬{等。等价于 [ \f\n\r\t\v]?/td> |
\S | 匚wM非空白字W。等价于 [^ \f\n\r\t\v]?/td> |
\t | 匚w一个制表符。等价于 \x09 ?\cI?/td> |
\v | 匚w一个垂直制表符。等价于 \x0b ?\cK?/td> |
句点 (.) 匚w一个字W串中Q何单个的打印或非打印字符Q除了换行符 (\n) 之外。下面的 JScript 正则表达式可以匹?'aac'?abc'?acc'?adc'如此{等Q同样也可以匚w 'a1c'?a2c'、a-c'以及 a#c'Q?
/a.c/
{h?VBScript 正则表达式ؓQ?/p>
"a.c"
如果试图匚w一个包含文件名的字W串Q其中句?(.) 是输入字W串的一部分Q则可以在正则表辑ּ中的句点前面加上一个反斜杠 (\) 字符来实现这一要求。D例来_下面?JScript 正则表达式就能匹?'filename.ext'Q?/p>
/filename\.ext/
?VBScript 而言Q等L表达式如下所C:
"filename\.ext"
q些表达式仍然是相当有限的。它们只允许匚wM单字W。很多情况下Q对从列表中匚wҎ字符十分有用。例如,如果输入文字中包含用数字表示为Chapter 1, Chapter 2诸如此类的章节标题,你可能需要找到这些章节标题?
可以在一个方括号 ([ ?]) 中放入一个或多个单字W,来创Z个待匚w的列表。如果字W被攑օ括号中括hQ则该列表称?em>括号表达?/em>。括号内和其他Q何地方一P普通字W代表其本nQ也是_它们匚w输入文字中出现的一处自己。大多数Ҏ字符在位于括可辑ּ中时都将失去其含义。这里有一些例外:
括号表达式中所包含的字W只匚w该括可辑ּ在正则表辑ּ中所处位|的一个单字符。下面的 JScript 正则表达式可以匹?'Chapter 1'?Chapter 2'?Chapter 3'?Chapter 4' 以及 'Chapter 5'Q?/p>
/Chapter [12345]/
?VBScript 中要匚w同样的章节标题,请用下面的表达式:
"Chapter [12345]"
h意单?'Chapter' 及后面的I格与括号内的字W的位置关系是固定的。因此,括号表达式只用来指定满紧跟在单?'Chapter' 和一个空g后的单字W位|的字符集合。这里是W九个字W位|?/p>
如果希望使用范围而不是字W本w来表示待匹配的字符Q则可以使用q字W将该范围的开始和l束字符分开。每个字W的字符值将军_其在一个范围内的相寚w序。下面的 JScript 正则表达式包含了一个等价于上面所C的括号列表的范围表辑ּ?/p>
/Chapter [1-5]/
VBScipt 中相同功能的表达式如下所C:
"Chapter [1-5]"
如果以这U方式指定范_则开始和l束值都包括在该范围内。有一点特别需要注意的是,?Unicode 排序中v始g定要在结束g前?/p>
如果惛_括号表达式中包括q字W,则必M用下q方法之一Q?
[\-]
[-a-z] [a-z-]
[!--] [!-~]
同样Q通过在列表开始处攄一个插入符(^)Q就可以查找所有不在列表或范围中的字符。如果该插入W出现在列表的其他位|,则匹配其本nQ没有Q何特D含义。下面的 JScript 正则表达式匹配章节号大于 5 的章节标题:
/Chapter [^12345]/
?VBScript 则用:
"Chapter [^12345]"
在上面所C的CZ中,表达式将匚wW九个位|处?, 2, 3, 4, or 5 之外的Q何数字字W。因此, 'Chapter 7' Z个匹配,同样 'Chapter 9' 也是如此?
上面的表辑ּ可以使用q字W?(-) 表示。对 JScript 为:
/Chapter [^1-5]/
或者,?VBScript 为:
"Chapter [^1-5]"
括号表达式的典型用法是指定对M大写或小写字母字W或M数字的匹配。下面的 JScript 表达式给Zq一匚wQ?/p>
/[A-Za-z0-9]/
{h?VBScript 表达式ؓQ?/p>
"[A-Za-z0-9]"