﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-心无痕的博客-随笔分类-JAVA</title><link>http://www.blogjava.net/xinwuhen/category/29825.html</link><description /><language>zh-cn</language><lastBuildDate>Wed, 14 May 2008 06:00:24 GMT</lastBuildDate><pubDate>Wed, 14 May 2008 06:00:24 GMT</pubDate><ttl>60</ttl><item><title>关于ANT构建应用时，根据判定条件执行不同任务的实例(以操作系统类型为判定条件举例)</title><link>http://www.blogjava.net/xinwuhen/archive/2008/05/14/200371.html</link><dc:creator>心无痕</dc:creator><author>心无痕</author><pubDate>Wed, 14 May 2008 03:36:00 GMT</pubDate><guid>http://www.blogjava.net/xinwuhen/archive/2008/05/14/200371.html</guid><wfw:comment>http://www.blogjava.net/xinwuhen/comments/200371.html</wfw:comment><comments>http://www.blogjava.net/xinwuhen/archive/2008/05/14/200371.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/xinwuhen/comments/commentRss/200371.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/xinwuhen/services/trackbacks/200371.html</trackback:ping><description><![CDATA[最近在一个项目(湖北质检)，要求搭建一个专门的版本发布服务器，为了将源代码构建并在服务器上测试，而选用ANT来实现。但是，在执行起动Tomcat服务时会有二个起动脚本（startup.sh与startup.bat），这二个脚本分别用于Unix与Windows操作系统；因此，为了适应不同平台的构建，需要根据不同OS来执行不同的脚本。但是，ANT本身还没有条件判断的功能，所以，此处需要借助Ant-Contrib包来实现。具体如下：<br />
一：）下载<font style="background-color: #c7edcc">apache-ant-版本号-bin.zip</font>文件（此处是<font style="background-color: #c7edcc">apache-ant-1.7.0-bin.zip</font>）：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;下载<a title="apache-ant-1.7.0-bin.zip" href="http://ant.apache.org/bindownload.cgi" target="_blank">apache-ant-1.7.0-bin.zip<br />
</a>二：）下载<font style="background-color: #c7edcc">ant-contrib-</font>版本号.jar文件（此处是ant-contrib-1.0b3.jar）：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;下载<a title="ant-contrib-1.0b3.jar" href="http://sourceforge.net/project/showfiles.php?group_id=36177">ant-contrib-1.0b3.jar</a><br />
三：）解压ANT安装文件（<font style="background-color: #c7edcc">apache-ant-1.7.0-bin.zip）到某一目录，如：<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font style="background-color: #c7edcc">D:\Program Files\Apache_ANT_1.7.0<br />
<br />
四：）配置环境变量（path与classpath）：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font style="background-color: #c7edcc">ANT_HOME</font>=<font style="background-color: #c7edcc">D:\Program Files\Apache_ANT_1.7.0<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;path=%path%;%<font style="background-color: #c7edcc">ANT_HOME</font>%\bin;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;classpath=%<font style="background-color: #c7edcc">ANT_HOME</font>%\lib;<br />
五：）安装ant-contrib-1.0b3.jar，下面是ant-contrib-1.0b3.jar解压包中的指南对安装的说明，如下：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<h2><a name="install">Installation</a></h2>
<p>First you must install Apache Ant itself, most of the Ant-Contrib tasks require Ant 1.5 or higher to work properly, however, there are some tasks, specifically &lt;for&gt; which require Ant 1.6. You can download Ant <a href="http://ant.apache.org/bindownload.cgi">from Apache</a>.</p>
<p>Then you need the Ant-Contrib tasks themselves. As there is no release of these tasks yet, you have to build them from sources. Fortunately this is easy, check out the sources (grab the <code>ant-contrib</code> module from <a href="http://sourceforge.net/cvs/?group_id=36177">CVS</a>), change into the source directory of ant-contrib and type <code>ant</code>. After Ant has completed, you'll find <code>ant-contrib-version.jar</code> in the <code>lib</code> subdirectory.</p>
<p>You now have the choice:</p>
<ol>
    <li>Copy <code>ant-contrib-version.jar</code> to the <code>lib</code> directory of your Ant installation, or on your CLASSPATH environment variable. If you want to use one of the tasks in your project, add the line
    <pre>&lt;taskdef resource="net/sf/antcontrib/antlib.xml"/&gt;
    </pre>
    to your build file. <br />
    <br />
    <li>Keep <code>ant-contrib-version.jar</code> in a separate location. You now have to tell Ant explicitly where to find it (say in <code>/usr/share/java/lib</code>):
    <pre>&lt;taskdef resource="net/sf/antcontrib/antlib.xml"&gt;
    &lt;classpath&gt;
    &lt;pathelement location="/usr/share/java/lib/ant-contrib-version.jar"/&gt;
    &lt;/classpath&gt;
    &lt;/taskdef&gt;
    </pre>
    <li>If you would like to use run with Ant Version 1.5 you must use the the .properties file instead. Keep in mind that some tasks will not be available to you , such as the &lt;for&gt; task:
    <pre>&lt;taskdef resource="net/sf/antcontrib/antcontrib.properties"&gt;
    &lt;classpath&gt;
    &lt;pathelement location="/usr/share/java/lib/ant-contrib-version.jar"/&gt;
    &lt;/classpath&gt;
    &lt;/taskdef&gt;</pre>
    </li>
</ol>
<pre>六：）现在可以使用ant-contrib的功能来添加到ANT构建文件中，下面是本项目（湖北质检）的构建文件，如下<span style="color: red">(注意红色部分的条件定义与判断的执行)</span>:</pre>
<pre><font style="background-color: #c7edcc">&lt;?xml version="1.0" encoding="UTF-8" ?&gt;
&lt;project name="QCSystem" default="startWebApplication" basedir="."&gt;<br />
&nbsp;&lt;description&gt;湖北质检ANT构建与Tomcat应用起动配置文件，起动应用时根据不同的操作系统调用不同的Tomcat起运脚本（startup.sh或startup.bat）!&lt;/description&gt;
&nbsp;
&nbsp;&lt;!-- ********** 构件文件相关属性 *********** --&gt;
&nbsp;&lt;!-- 系统环境变量 --&gt;
&nbsp;&lt;property environment="sys-env"/&gt;&nbsp;<br />
&nbsp;&lt;!-- 通用路径或文件夹名称 --&gt;
&nbsp;&lt;property name="srcDir" location="src"/&gt;
&nbsp;&lt;property name="webAppDir" location="webapp"/&gt;<br />
&nbsp;&lt;property name="webInfName" value="WEB-INF"/&gt;
&nbsp;&lt;property name="destDirName" value="classes"/&gt;<br />
&nbsp;&lt;property name="tomcatCommonName" value="common"/&gt;
&nbsp;<br />
&nbsp;<span style="color: red">&lt;!-- 添加"Ant-Contrib"对ANT构建文件的支持 --&gt; &nbsp;<br />
&nbsp;&lt;taskdef resource="net/sf/antcontrib/antcontrib.properties"&gt; &nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;classpath&gt; &nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;pathelement location="${sys-env.ANT_HOME}/Ant-Contrib/ant-contrib-1.0b3.jar"/&gt; &nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;/classpath&gt; &nbsp;<br />
&nbsp;&lt;/taskdef&gt;</span><br />
<br />
&nbsp;<span style="color: red">&lt;!-- 初始化操作系统判断条件 --&gt; &nbsp;<br />
<font style="background-color: #c7edcc"> &lt;property name="winOS" value="win"/&gt;<br />
&nbsp;&lt;property name="unixOS" value="unix"/&gt;</font>
&nbsp;&lt;target name="init"&gt; &nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;echo message="初始化操作系统判断条件[开始]..." /&gt; &nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;condition property="OSType" value="${winOS}"&gt; &nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;os family="Windows"/&gt; &nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;/condition&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;condition property="OSType" value="${unixOS}"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;os family="UNIX"/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;/condition&gt; &nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;echo message="初始化操作系统判断条件[结束]..." /&gt; &nbsp;<br />
&nbsp;&nbsp;&lt;/target&gt;</span></font></pre>
<pre>
<p><font style="background-color: #c7edcc">&nbsp;&lt;!-- 第三方类库--&gt;
&nbsp;&lt;path id="compileLibFiles"&gt;
&nbsp;&nbsp;&lt;fileset dir="${webAppDir}/${webInfName}/lib"&gt;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;include name="**/*.jar"/&gt;
&nbsp;&nbsp;&lt;/fileset&gt;<br />
&nbsp;&nbsp;&lt;fileset dir="${sys-env.CATALINA_HOME}/${tomcatCommonName}/lib"&gt;
&nbsp;&nbsp;&nbsp;&lt;include name="**/*.jar"/&gt;
&nbsp;&nbsp;&lt;/fileset&gt;
&nbsp;&lt;/path&gt;
&nbsp;<br />
&nbsp;&lt;!-- 编译工程 --&gt;
&nbsp;&lt;target name="compile"&gt;
&nbsp;&nbsp;&lt;echo message="湖北质检项目编译[开始] ..."/&gt;
&nbsp;&nbsp;&lt;javac srcdir="${srcDir}" debug="on" destdir="${webAppDir}/${webInfName}/${destDirName}" includes="**/*.java"&gt;
&nbsp;&nbsp;&nbsp;&lt;classpath refid="compileLibFiles"/&gt;
&nbsp;&nbsp;&lt;/javac&gt;<br />
&nbsp;&nbsp;&lt;!-- 拷贝配置文件到编译目录 --&gt;
&nbsp;&nbsp;&lt;copy todir="${webAppDir}/${webInfName}/${destDirName}"&gt;
&nbsp;&nbsp;&nbsp;&lt;fileset dir="${srcDir}" excludes="**/*.java"/&gt;
&nbsp;&nbsp;&lt;/copy&gt;
&nbsp;&nbsp;&lt;echo message="湖北质检项目编译[结束] ..."/&gt;
&nbsp;&lt;/target&gt;<br />
&nbsp;&lt;!-- 根据不同的操作系统调用不同的Tomcat起动程序(Windows操作系统:startup.bat&nbsp; Unix操作系统:startup.sh) --&gt;
&nbsp;&lt;target name="startWebApplication" depends="<span style="color: red">init</span>, compile"&gt;
&nbsp;&nbsp;&lt;echo message="起动湖北质检应用[开始] ..."/&gt;
&nbsp;&nbsp;<span style="color: red">&lt;if&gt; &nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;equals arg1="${OSType}" arg2="${winOS}"/&gt; &nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;!-- 下边这种方式直接判断操作系统也可以 --&gt; &nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;!--os family="WINDOWS"/--&gt; &nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;then&gt; &nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;exec dir="${sys-env.CATALINA_HOME}/bin" executable="${sys-env.CATALINA_HOME}/bin/startup.bat"/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;/then&gt; &nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;else&gt; &nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;exec dir="${sys-env.CATALINA_HOME}/bin" executable="${sys-env.CATALINA_HOME}/bin/startup.sh"/&gt; &nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;/else&gt; &nbsp;&nbsp;<br />
&nbsp;&nbsp;&lt;/if&gt;</span>&nbsp;&nbsp;<br />
&nbsp;&nbsp;&lt;echo message="起动湖北质检应用[结束] ..."/&gt;
&nbsp;&lt;/target&gt;<br />
&lt;/project&gt;</font></p>
</pre>
<br />
</font><br />
</font></font>
<img src ="http://www.blogjava.net/xinwuhen/aggbug/200371.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/xinwuhen/" target="_blank">心无痕</a> 2008-05-14 11:36 <a href="http://www.blogjava.net/xinwuhen/archive/2008/05/14/200371.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Subversion使用手记--转载</title><link>http://www.blogjava.net/xinwuhen/archive/2008/04/22/194676.html</link><dc:creator>心无痕</dc:creator><author>心无痕</author><pubDate>Tue, 22 Apr 2008 01:23:00 GMT</pubDate><guid>http://www.blogjava.net/xinwuhen/archive/2008/04/22/194676.html</guid><wfw:comment>http://www.blogjava.net/xinwuhen/comments/194676.html</wfw:comment><comments>http://www.blogjava.net/xinwuhen/archive/2008/04/22/194676.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/xinwuhen/comments/commentRss/194676.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/xinwuhen/services/trackbacks/194676.html</trackback:ping><description><![CDATA[<p>一直以来对于自己的项目都是使用CVS进行管理，听说Subversion很久了，但是都没有时间去尝试。想想时间都是省出来的，于是决定，一天学一点，不多，积累成河嘛。<br />
&nbsp; Subversion和CVS相比，除了包含了CVS的全部特性之外，也加入了新的理念。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 新理念<br />
&nbsp; 1、路径、改名、以及文件meta-data也可进入版本控制范围。<br />
&nbsp; 缺少这些特性是CVS被抱怨最多的方面之一，subversion不止对文件内容和文件存放位置加入控制，也对目录，拷贝，重命名操作加入版本控制。它也允许文件/目录的相关元数据meta-data和文件/目录本身一起被版本控制起来，并提供一种机制对文件的执行权限进行控制。<br />
&nbsp; 2、Commit动作真正成为原子级的操作了。<br />
直到整个commit动作都成功前不会有任何部分的commit会生效。版本修订号只是预确认，而不是对文件预确认。(翻译不出来 -_-;)日志信息将绑定到修订信息，而不是象CVS那样冗余的存储下来。<br />
&nbsp;3、提供Apache网络服务器选项，支持WebDAV/DeltaV协议。<br />
Subversion可以使用基于http协议的WebDAV/DeltaV协议进行网络通讯，并由Apache服务器提供源码仓库方的网络浏览服务。这为Subversion提供了比CVS更好的协同工作能力，并提供了各式各样的自由的关键特性：授权，基于路径的授权，线性压缩，以及基本源码仓库浏览。<br />
4、独立服务器选项<br />
Subversion也能提供独立服务器选项，使用自定的协议（不是每个人都想运行Apache2.x）独立服务器可以作为系统的inetd服务运行，并提供基本的授权。它也能使用ssh进行加密。<br />
&nbsp;5、建立分支和标签操作成为不耗时的操作。<br />
这些动作没理由耗时，所以我们不再让它们耗时。<br />
6、分支与标签的实现都是基于底层的拷贝操作，一个拷贝占用一块固定大小的空间。任何拷贝都可以作为一份标签；假如你开始对某个版本的拷贝进行commit动作，那它也就成为一个分支。(这与CVS的"分支节点做标签"方式不同)<br />
7、天然的client/server结构，层次化库设计。<br />
Subversion从设计之初即采用client/server机构；因此避免了困扰CVS了许久的一些维护性难题。<br />
代码被构建为一组带有详细接口说明的模块，用以方便的由其他应用程序进行调用。<br />
8、Client/server协议向双方发送对比差异。<br />
网络协议利用宽带有效地发送对比差异给客户端和服务器端双方。( CVS只是 server-&gt;client,?没有client-&gt;server )<br />
&nbsp;9、资源消耗与数据改变的大小成正比，而不是与数据本身大小成正比一般来说，一项Subversion操作所需时间与操作最终变化的大小成正比。而不是与操作所触及的整个项目的大小成正比，这是Subversion源代码仓库模型的一个特性。<br />
&nbsp;10、有效的处理二进制文件<br />
Subversion对于二进制文件和文本文件的处理同样有效，因为subversion使用一种二进制差异比较算法来增量存储那些连续的修订本。<br />
&nbsp;11、易于语法分析的输出。<br />
所有Subversion命令行客户端的输出都是仔细设计的，可轻松为人所理解，也适于程序自动解析。可进行脚本语言处理将是下一步优先考虑的特性。<br />
&nbsp;好了，开始使用吧。<br />
Subversion到目前的安装已经非常简单了。到Subversion网站下载Windows下的安装文件，简单的步骤就可以完成安装，而且安装程序已经自动注册Path，直接在命令行模式就可以使用了。<br />
&nbsp; 首先初始化Repository，输入命令:<br />
&nbsp;svnadmin create D:"TestRepository"<br />
然后，把现有的项目的目录结构以及文件导入到Repository中：<br />
&nbsp;svn import D:"Projects"Project1 <a href="file:///D:/TestRepository/Project1"><font color="#000080">file:///D:"TestRepository"Project1</font></a> -m &#8220;初始化&#8220;<br />
&nbsp;用启动服务<br />
&nbsp;svnserve -d -r D:"TestRepository"<br />
&nbsp;客户端Checkout<br />
&nbsp;svn checkout svn://主机名/Project1?? (即获取Project1的项目)<br />
&nbsp;以上都是很简单的命令。而且上面只用到了一种服务模式，Apache的还在尝试中。<br />
&nbsp;目前只用到了Subversion的基本功能，就已经感觉不错了，觉得入门很轻松，帮助文档也比CVS要好的多。<br />
&nbsp;Subversion也有图形的客户端，可以在 TortoiseSVN 找到。<br />
&nbsp;Subversion也VS.Net的插件，可以在AnkhSVN 找到。<br />
&nbsp;TortoiseSVN相信不错，因为以前用过它的另一个For CVS的工具，可以和浏览器结合在一起，非常方便和美观。<br />
服务<br />
&nbsp;&nbsp;&nbsp; Subversion具有两种服务模式，一个是作为Apache的模块，另一个是自定义协议的Subserve服务。作为Apache的模块，客户端可以通过WebDAV/DeltaV协议访问Repository，而使用Subserve则使用<br />
Subversion的自定义协议。<br />
下表是两种服务模式的比较：</p>
<p>
<table style="width: 100%" cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td style="border-right: #d4d0c8; padding-right: 7.5pt; border-top: #d4d0c8; padding-left: 7.5pt; padding-bottom: 7.5pt; border-left: #d4d0c8; width: 33.32%; padding-top: 7.5pt; border-bottom: #d4d0c8; background-color: transparent" width="33%">
            <p style="margin: 0cm 0cm 0pt; text-align: center" align="center"><span style="font-size: 9pt; color: black; font-family: 宋体">功能</span></p>
            <p>
            <p>
            <p>&nbsp;</p>
            </td>
            <td style="border-right: #d4d0c8; padding-right: 7.5pt; border-top: #d4d0c8; padding-left: 7.5pt; padding-bottom: 7.5pt; border-left: #d4d0c8; width: 33.34%; padding-top: 7.5pt; border-bottom: #d4d0c8; background-color: transparent" width="33%">
            <p style="margin: 0cm 0cm 0pt; text-align: center" align="center"><span style="font-size: 9pt; color: black; font-family: 宋体">Apache + mod_dav_sub </span></p>
            <p>
            <p>
            <p>&nbsp;</p>
            </td>
            <td style="border-right: #d4d0c8; padding-right: 7.5pt; border-top: #d4d0c8; padding-left: 7.5pt; padding-bottom: 7.5pt; border-left: #d4d0c8; width: 33.34%; padding-top: 7.5pt; border-bottom: #d4d0c8; background-color: transparent" width="33%">
            <p style="margin: 0cm 0cm 0pt; text-align: center" align="center"><span style="font-size: 9pt; color: black; font-family: 宋体">Svnserve </span></p>
            <p>
            <p>
            <p>&nbsp;</p>
            </td>
        </tr>
        <tr>
            <td style="border-right: #d4d0c8; padding-right: 7.5pt; border-top: #d4d0c8; padding-left: 7.5pt; padding-bottom: 7.5pt; border-left: #d4d0c8; width: 33.32%; padding-top: 7.5pt; border-bottom: #d4d0c8; background-color: transparent" width="33%">
            <p style="margin: 0cm 0cm 0pt; text-align: center" align="center"><span style="font-size: 9pt; color: black; font-family: 宋体">验证方式</span></p>
            <p>
            <p>
            <p>&nbsp;</p>
            </td>
            <td style="border-right: #d4d0c8; padding-right: 7.5pt; border-top: #d4d0c8; padding-left: 7.5pt; padding-bottom: 7.5pt; border-left: #d4d0c8; width: 33.34%; padding-top: 7.5pt; border-bottom: #d4d0c8; background-color: transparent" width="33%">
            <p style="margin: 0cm 0cm 0pt; text-align: center" align="center"><span style="font-size: 9pt; color: black; font-family: 宋体">基于HTTPS的X.509、LDAP、NTLM或其他Apache支持的验证</span></p>
            <p>
            <p>
            <p>&nbsp;</p>
            </td>
            <td style="border-right: #d4d0c8; padding-right: 7.5pt; border-top: #d4d0c8; padding-left: 7.5pt; padding-bottom: 7.5pt; border-left: #d4d0c8; width: 33.34%; padding-top: 7.5pt; border-bottom: #d4d0c8; background-color: transparent" width="33%">
            <p style="margin: 0cm 0cm 0pt; text-align: center" align="center"><span style="font-size: 9pt; color: black; font-family: 宋体">CRAM-MD5</span><span style="font-size: 9pt; color: black; font-family: 宋体">或者SSH </span></p>
            <p>
            <p>
            <p>&nbsp;</p>
            </td>
        </tr>
        <tr>
            <td style="border-right: #d4d0c8; padding-right: 7.5pt; border-top: #d4d0c8; padding-left: 7.5pt; padding-bottom: 7.5pt; border-left: #d4d0c8; width: 33.32%; padding-top: 7.5pt; border-bottom: #d4d0c8; background-color: transparent" width="33%">
            <p style="margin: 0cm 0cm 0pt; text-align: center" align="center"><span style="font-size: 9pt; color: black; font-family: 宋体">用户帐户管理</span></p>
            <p>
            <p>
            <p>&nbsp;</p>
            </td>
            <td style="border-right: #d4d0c8; padding-right: 7.5pt; border-top: #d4d0c8; padding-left: 7.5pt; padding-bottom: 7.5pt; border-left: #d4d0c8; width: 33.34%; padding-top: 7.5pt; border-bottom: #d4d0c8; background-color: transparent" width="33%">
            <p style="margin: 0cm 0cm 0pt; text-align: center" align="center"><span style="font-size: 9pt; color: black; font-family: 宋体">私有的用户文件</span></p>
            <p>
            <p>
            <p>&nbsp;</p>
            </td>
            <td style="border-right: #d4d0c8; padding-right: 7.5pt; border-top: #d4d0c8; padding-left: 7.5pt; padding-bottom: 7.5pt; border-left: #d4d0c8; width: 33.34%; padding-top: 7.5pt; border-bottom: #d4d0c8; background-color: transparent" width="33%">
            <p style="margin: 0cm 0cm 0pt; text-align: center" align="center"><span style="font-size: 9pt; color: black; font-family: 宋体">私有的用户文件或已有的系统帐户</span></p>
            <p>
            <p>
            <p>&nbsp;</p>
            </td>
        </tr>
        <tr>
            <td style="border-right: #d4d0c8; padding-right: 7.5pt; border-top: #d4d0c8; padding-left: 7.5pt; padding-bottom: 7.5pt; border-left: #d4d0c8; width: 33.32%; padding-top: 7.5pt; border-bottom: #d4d0c8; background-color: transparent" width="33%">
            <p style="margin: 0cm 0cm 0pt; text-align: center" align="center"><span style="font-size: 9pt; color: black; font-family: 宋体">授权管理</span></p>
            <p>
            <p>
            <p>&nbsp;</p>
            </td>
            <td style="border-right: #d4d0c8; padding-right: 7.5pt; border-top: #d4d0c8; padding-left: 7.5pt; padding-bottom: 7.5pt; border-left: #d4d0c8; width: 33.34%; padding-top: 7.5pt; border-bottom: #d4d0c8; background-color: transparent" width="33%">
            <p style="margin: 0cm 0cm 0pt; text-align: center" align="center"><span style="font-size: 9pt; color: black; font-family: 宋体">blanket read/write access</span><span style="font-size: 9pt; color: black; font-family: 宋体">或单一目录的访问控制</span></p>
            <p>
            <p>
            <p>&nbsp;</p>
            </td>
            <td style="border-right: #d4d0c8; padding-right: 7.5pt; border-top: #d4d0c8; padding-left: 7.5pt; padding-bottom: 7.5pt; border-left: #d4d0c8; width: 33.34%; padding-top: 7.5pt; border-bottom: #d4d0c8; background-color: transparent" width="33%">
            <p style="margin: 0cm 0cm 0pt; text-align: center" align="center"><span style="font-size: 9pt; color: black; font-family: 宋体">blanket read/write access </span></p>
            <p>
            <p>
            <p>&nbsp;</p>
            </td>
        </tr>
        <tr>
            <td style="border-right: #d4d0c8; padding-right: 7.5pt; border-top: #d4d0c8; padding-left: 7.5pt; padding-bottom: 7.5pt; border-left: #d4d0c8; width: 33.32%; padding-top: 7.5pt; border-bottom: #d4d0c8; background-color: transparent" width="33%">
            <p style="margin: 0cm 0cm 0pt; text-align: center" align="center"><span style="font-size: 9pt; color: black; font-family: 宋体">加密</span></p>
            <p>
            <p>
            <p>&nbsp;</p>
            </td>
            <td style="border-right: #d4d0c8; padding-right: 7.5pt; border-top: #d4d0c8; padding-left: 7.5pt; padding-bottom: 7.5pt; border-left: #d4d0c8; width: 33.34%; padding-top: 7.5pt; border-bottom: #d4d0c8; background-color: transparent" width="33%">
            <p style="margin: 0cm 0cm 0pt; text-align: center" align="center"><span style="font-size: 9pt; color: black; font-family: 宋体">可选的SSL </span></p>
            <p>
            <p>
            <p>&nbsp;</p>
            </td>
            <td style="border-right: #d4d0c8; padding-right: 7.5pt; border-top: #d4d0c8; padding-left: 7.5pt; padding-bottom: 7.5pt; border-left: #d4d0c8; width: 33.34%; padding-top: 7.5pt; border-bottom: #d4d0c8; background-color: transparent" width="33%">
            <p style="margin: 0cm 0cm 0pt; text-align: center" align="center"><span style="font-size: 9pt; color: black; font-family: 宋体">可选的SSH隧道</span></p>
            <p>
            <p>
            <p>&nbsp;</p>
            </td>
        </tr>
        <tr>
            <td style="border-right: #d4d0c8; padding-right: 7.5pt; border-top: #d4d0c8; padding-left: 7.5pt; padding-bottom: 7.5pt; border-left: #d4d0c8; width: 33.32%; padding-top: 7.5pt; border-bottom: #d4d0c8; background-color: transparent" width="33%">
            <p style="margin: 0cm 0cm 0pt; text-align: center" align="center"><span style="font-size: 9pt; color: black; font-family: 宋体">交互性</span></p>
            <p>
            <p>
            <p>&nbsp;</p>
            </td>
            <td style="border-right: #d4d0c8; padding-right: 7.5pt; border-top: #d4d0c8; padding-left: 7.5pt; padding-bottom: 7.5pt; border-left: #d4d0c8; width: 33.34%; padding-top: 7.5pt; border-bottom: #d4d0c8; background-color: transparent" width="33%">
            <p style="margin: 0cm 0cm 0pt; text-align: center" align="center"><span style="font-size: 9pt; color: black; font-family: 宋体">可通过支持WebDAV的客户端访问</span></p>
            <p>
            <p>
            <p>&nbsp;</p>
            </td>
            <td style="border-right: #d4d0c8; padding-right: 7.5pt; border-top: #d4d0c8; padding-left: 7.5pt; padding-bottom: 7.5pt; border-left: #d4d0c8; width: 33.34%; padding-top: 7.5pt; border-bottom: #d4d0c8; background-color: transparent" width="33%">
            <p style="margin: 0cm 0cm 0pt; text-align: center" align="center"><span style="font-size: 9pt; color: black; font-family: 宋体">无交互性</span></p>
            <p>
            <p>
            <p>&nbsp;</p>
            </td>
        </tr>
        <tr>
            <td style="border-right: #d4d0c8; padding-right: 7.5pt; border-top: #d4d0c8; padding-left: 7.5pt; padding-bottom: 7.5pt; border-left: #d4d0c8; width: 33.32%; padding-top: 7.5pt; border-bottom: #d4d0c8; background-color: transparent" width="33%">
            <p style="margin: 0cm 0cm 0pt; text-align: center" align="center"><span style="font-size: 9pt; color: black; font-family: 宋体">Web</span><span style="font-size: 9pt; color: black; font-family: 宋体">访问</span></p>
            <p>
            <p>
            <p>&nbsp;</p>
            </td>
            <td style="border-right: #d4d0c8; padding-right: 7.5pt; border-top: #d4d0c8; padding-left: 7.5pt; padding-bottom: 7.5pt; border-left: #d4d0c8; width: 33.34%; padding-top: 7.5pt; border-bottom: #d4d0c8; background-color: transparent" width="33%">
            <p style="margin: 0cm 0cm 0pt; text-align: center" align="center"><span style="font-size: 9pt; color: black; font-family: 宋体">有限的内置支持，或通过第三方的工具，例如ViewCVS </span></p>
            <p>
            <p>
            <p>&nbsp;</p>
            </td>
            <td style="border-right: #d4d0c8; padding-right: 7.5pt; border-top: #d4d0c8; padding-left: 7.5pt; padding-bottom: 7.5pt; border-left: #d4d0c8; width: 33.34%; padding-top: 7.5pt; border-bottom: #d4d0c8; background-color: transparent" width="33%">
            <p style="margin: 0cm 0cm 0pt; text-align: center" align="center"><span style="font-size: 9pt; color: black; font-family: 宋体">通过第三方的支持，如ViewCVS </span></p>
            <p>
            <p>
            <p>&nbsp;</p>
            </td>
        </tr>
        <tr>
            <td style="border-right: #d4d0c8; padding-right: 7.5pt; border-top: #d4d0c8; padding-left: 7.5pt; padding-bottom: 7.5pt; border-left: #d4d0c8; width: 33.32%; padding-top: 7.5pt; border-bottom: #d4d0c8; background-color: transparent" width="33%">
            <p style="margin: 0cm 0cm 0pt; text-align: center" align="center"><span style="font-size: 9pt; color: black; font-family: 宋体">速度</span></p>
            <p>
            <p>
            <p>&nbsp;</p>
            </td>
            <td style="border-right: #d4d0c8; padding-right: 7.5pt; border-top: #d4d0c8; padding-left: 7.5pt; padding-bottom: 7.5pt; border-left: #d4d0c8; width: 33.34%; padding-top: 7.5pt; border-bottom: #d4d0c8; background-color: transparent" width="33%">
            <p style="margin: 0cm 0cm 0pt; text-align: center" align="center"><span style="font-size: 9pt; color: black; font-family: 宋体">稍慢</span></p>
            <p>
            <p>
            <p>&nbsp;</p>
            </td>
            <td style="border-right: #d4d0c8; padding-right: 7.5pt; border-top: #d4d0c8; padding-left: 7.5pt; padding-bottom: 7.5pt; border-left: #d4d0c8; width: 33.34%; padding-top: 7.5pt; border-bottom: #d4d0c8; background-color: transparent" width="33%">
            <p style="margin: 0cm 0cm 0pt; text-align: center" align="center"><span style="font-size: 9pt; color: black; font-family: 宋体">稍快</span></p>
            <p>
            <p>
            <p>&nbsp;</p>
            </td>
        </tr>
        <tr>
            <td style="border-right: #d4d0c8; padding-right: 7.5pt; border-top: #d4d0c8; padding-left: 7.5pt; padding-bottom: 7.5pt; border-left: #d4d0c8; width: 33.32%; padding-top: 7.5pt; border-bottom: #d4d0c8; background-color: transparent" width="33%">
            <p style="margin: 0cm 0cm 0pt; text-align: center" align="center"><span style="font-size: 9pt; color: black; font-family: 宋体">初始安装</span></p>
            <p>
            <p>
            <p>&nbsp;</p>
            </td>
            <td style="border-right: #d4d0c8; padding-right: 7.5pt; border-top: #d4d0c8; padding-left: 7.5pt; padding-bottom: 7.5pt; border-left: #d4d0c8; width: 33.34%; padding-top: 7.5pt; border-bottom: #d4d0c8; background-color: transparent" width="33%">
            <p style="margin: 0cm 0cm 0pt; text-align: center" align="center"><span style="font-size: 9pt; color: black; font-family: 宋体">稍复杂</span></p>
            <p>
            <p>
            <p>&nbsp;</p>
            </td>
            <td style="border-right: #d4d0c8; padding-right: 7.5pt; border-top: #d4d0c8; padding-left: 7.5pt; padding-bottom: 7.5pt; border-left: #d4d0c8; width: 33.34%; padding-top: 7.5pt; border-bottom: #d4d0c8; background-color: transparent" width="33%">
            <p style="margin: 0cm 0cm 0pt; text-align: center" align="center"><span style="font-size: 9pt; color: black; font-family: 宋体">相当简单</span></p>
            <p>
            <p>
            <p>&nbsp;</p>
            </td>
        </tr>
    </tbody>
</table>
</p>
<p>&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 启动svnserve服务<br />
svnserve 是一个轻量级的服务， 使用自定义的协议通过TCP/IP与客户端通讯。<br />
客户端通过由 svn:// 或者 svn+ssh:// 开始的URL访问svnserve服务器。<br />
启动服务器<br />
端口监控（inetd）模式<br />
如果你打算用端口监控来启动处理客户的访问请求的进程，你可以通过传入参数-i来启动：<br />
svnserve -i<br />
当使用-i参数启动服务的时候，svnserve通过stdin和stdout用自定义协议和客户端<br />
通讯。同时服务侦听3690端口。<br />
独立端口监控进程<br />
使用参数-d启动服务作为一个独立的端口监控进程。<br />
svnserve -d<br />
当运行svnserve在独立端口监控模式时，你可以使用--listen-port=和--listen-host=参数来自定义需要的端口和主机名称。当前模式默认的端口是3690。<br />
当然，也有第三种方法启动svnserve，也就是使用&#8220;隧道模式&#8221;，使用-t参数启动服务。这个模式要求远程服务程序，如RSH或SSH，已经成功验证用户，并且使用已经校验的用户启动一个属于该用户的svnserve进程。当使用该模式提供服务时，要确认启动的用户帐户具备对Repository的读/写权限。<br />
设置项目目录<br />
当svnserve开始运行时，它将会暴露所有的Repository到网络上。不过，当客户端需要获取一个Repository的内容时，需要指定Reopsitory的绝对路径。例如：一个Repository放在文件路径<br />
C:/Project Repository/Project1<br />
那么当客户端访问时，需要指定绝对路径：<br />
svn://host/C:/Project Repository/Project1<br />
所以，为了增加保密性，你可以使用参数-r指定需要暴露的Repository的路径，当用户访问时，只需指定Repository的名称即可。例如上面的Repository，当启动服务时，使用如下的方法：<br />
svn -d -r C:/Project Repository<br />
那么当客户端访问时，则使用<br />
svn://host/Project1<br />
就可以获取数据了。<br />
内置的验证和授权<br />
当客户端连接到一个svnserve进程时，下面的流程就会触发：<br />
1、客户选择一个指定的Repository；<br />
2、服务处理Repository的配置文件 conf/svnserve.conf文件，并且开始执行在其中定义的所有验证和授权策略；<br />
3、依赖与情形和授权策略：<br />
a)客户端也许允许匿名访问而不需要验证，或者<br />
b)客户但也许需要在任何时候被要求验证，或者<br />
c)假如处于"隧道模式"中，客户端将声明自己已经可以被外部验证。<br />
很显然，如上所说，用户文件是一个名为svnserve.conf的，放在conf目录下的文件。<br />
现在我们来看看如何配置这个文件：<br />
这个配置文件放置在Repository的目录中的conf目录下，它有两个节点：<br />
[general]<br />
[users]<br />
其中，[general]的配置信息有：<br />
anon-access = read<br />
auth-access = write<br />
其中表示对于验证有效的以及没通过验证的用户可以做什么事情。分别有read, write和none<br />
[users]的标签的配置内容有：<br />
USERNAME = PASSWORD<br />
password-db = passwd<br />
realm = My First Repository<br />
其中表示，用户名对应的密码是什么，或者指定一个存储用户名和密码的文件的相对或绝对路径以及指定了Repository的验证领域。如果两个Repository有相同的验证领域，那么它们应该有相同的密码数据库，反之亦然。默认的领域就是指向当前的Repository的路径，与服务器的Repository的根目录相关。<br />
<br />
几个版本控制工具的比较:<br />
</p>
<p>cvs是开源项目，其功能比vss强大很多，可以支持版本合并，多个分支。而vss是比较简单和易用的配置管理工具。在这两个工具的选择上还是要看是项目决定，一般10个人以下的团队vss可能更方便一些~~~</p>
<div class="fabiao">cvs是并行版本管理器，开源，可以多人同时修改一个文件，当出现冲突的时候自动合入或者提示； <br />
vss是微软visual studio中附带的版本管理器，只能在windows局域网环境下使用。使用一个文件同时只能由一个人来修改的方法来避免冲突。最大的优点是易学，并且跟visual studio可以无缝集成。</div>
<div class="fabiao">cvs,vss 都是版本控制的软件工具，可以把源代码或者其他文件的每一次修改的内容都保存起来，算是可以看以前版本的代码。 <br />
vss 基于文件共享的机制，易用性好，安全性不太好。vss 对于同时增加删除多个目录的支持很好。分支合并管理也很容易使用，打标签功能不太好用。vss 基于文件锁机制，同一时刻，只能有一个人修改同一个文件。 <br />
cvs 基于 c/s 结构，也有工具可以让它 b/s 运行，不过 b/s 速度慢，使用者不多。cvs 安全控制比较好，对于同时增加多个目录的支持不太好。cvs 中删除目录很难。cvs可以同一时刻多人修改统一文件然后合并，不过只支持文本文件；对于 office 或者其他格式的文档，多个人同时修改同一个文件很难合并，浪费大家时间。我在网上搜索让cvs支持锁机制，只有少数文章提到在 server 端用 script 控制，语焉不详。 <br />
总体来说，cvs 功能比vss强。</div>
<img src ="http://www.blogjava.net/xinwuhen/aggbug/194676.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/xinwuhen/" target="_blank">心无痕</a> 2008-04-22 09:23 <a href="http://www.blogjava.net/xinwuhen/archive/2008/04/22/194676.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>log4j 配置</title><link>http://www.blogjava.net/xinwuhen/archive/2008/04/17/193689.html</link><dc:creator>心无痕</dc:creator><author>心无痕</author><pubDate>Thu, 17 Apr 2008 03:31:00 GMT</pubDate><guid>http://www.blogjava.net/xinwuhen/archive/2008/04/17/193689.html</guid><wfw:comment>http://www.blogjava.net/xinwuhen/comments/193689.html</wfw:comment><comments>http://www.blogjava.net/xinwuhen/archive/2008/04/17/193689.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/xinwuhen/comments/commentRss/193689.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/xinwuhen/services/trackbacks/193689.html</trackback:ping><description><![CDATA[一、前言：<br />
&nbsp;&nbsp;&nbsp;&nbsp; log4j 是一个开放源码项目，是广泛使用的以Java编写的日志记录包。由于log4j出色的表现，&nbsp;&nbsp;&nbsp;&nbsp; 当时在log4j完成时，log4j开发组织曾建议sun在jdk1.4中用log4j取代jdk1.4 的日志工具类，但当时jdk1.4已接近完成，所以sun拒绝使用log4j，当在java开发中实际使用最多的还是log4j，&nbsp;&nbsp;&nbsp;&nbsp; 人们遗忘了sun的日志工具类。&nbsp;&nbsp;&nbsp;&nbsp; 它的一个独有特性包括在类别中继承的概念。通过使用类别层次结构，这样就减少了日志记录输出量，并将日志记录的开销降到最低。<br />
&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp; 它允许开发者控制以任意间隔输出哪些日志语句。通过使用外部配置文件，完全可以在运行时进行配置。几乎每个大的应用程序都包括其自己的日志记录或跟踪 API。经验表明日志记录是开发周期中的重要组成部分。同样，日志记录提供一些优点。首先，它可以提供运行应用程序的确切 上下文。一旦插入到代码中，生成日志记录输出就不需要人为干涉。其次，日志输出可以保存到永久媒体中以便以后研究。最后，除了在开发阶段中使用，十分丰富 的日志记录包还可以用作审计工具。
<p>&nbsp;&nbsp;&nbsp; 依照该规则，在 1996 年初，EU SEMPER（欧洲安全电子市场）项目就决定编写自己的跟踪 API。 在无数次改进、几次具体化和许多工作之后，该 API 已经演变成 log4j，一种流行的 Java 日志记录包。&nbsp; 这个包按 IBM 公共许可证分发，由开放源码权威机构认证。</p>
<p>&nbsp;&nbsp;&nbsp; 日志记录有其自己的缺点。它会降低应用程序的速度。如果太详细，它可能会使屏幕滚动变得看不见。&nbsp; 为了减低这些影响，log4j 被设计成快速且灵活的。由于应用程序很少将日志记录当作是主要功能，&nbsp; log4j API 力争易于了解和使用。<br />
&nbsp;&nbsp;&nbsp;&nbsp; log4j，它可以控制以任意间隔输出哪些日志语句。</p>
<p>二、主要组件</p>
<p>1、根类别（在类别层次结构的顶部，即全局性的日志级别）<br />
&nbsp;<br />
配置根Logger，其语法为：</p>
<p>log4j.rootLogger = [ level ] , appenderName, appenderName, ...</p>
<p>level 是日志记录的类别<br />
appenderName就是指定日志信息输出到哪个地方。您可以同时指定多个输出目的地。</p>
<p>类别level 为 OFF、FATAL、ERROR、WARN、INFO、DEBUG、log、ALL或自定义的优先级。<br />
og4j常用的优先级FATAL&gt;ERROR&gt;WARN&gt;INFO&gt;DEBUG<br />
配置根Logger，其语法为：<br />
log4j.rootLogger = [ level ] , appenderName, appenderName, &#8230;<br />
如果为log4j.rootLogger=WARN，则意味着只有WARN,ERROR,FATAL被输出，DEBUG,INFO将被屏蔽掉。</p>
<p>举例：log4j.rootCategory=INFO,stdout,Runlog,Errorlog<br />
根日志类别为INFO，DEBUG将被屏蔽，其他的将被输出。 stdout,Runlog,Errorlog分别为3个输出目的地。</p>
<p>&nbsp;2、常用输出格式</p>
<p>&nbsp;-X号:X信息输出时左对齐；<br />
&nbsp;%p:日志信息级别<br />
&nbsp;%d{}:日志信息产生时间<br />
&nbsp;%c:日志信息所在地（类名）<br />
&nbsp;%m:产生的日志具体信息<br />
&nbsp;%n:输出日志信息换行<br />
&nbsp;举例：<br />
log4j.appender.stdout.layout.ConversionPattern= %5p %d{yyyy-MM-dd HH:mm:ss} %c %m %n<br />
log4j.appender.Runlog.layout.ConversionPattern= %5p %d{yyyy-MM-dd HH:mm:ss} %c %m %n<br />
log4j.appender.Errorlog.layout.ConversionPattern= %5p %d{yyyy-MM-dd HH:mm:ss} %c %m %n</p>
<p>3、布局<br />
使用的输出布局，其中log4j提供4种布局：<br />
org.apache.log4j.HTMLLayout（以HTML表格形式布局）<br />
org.apache.log4j.PatternLayout（可以灵活地指定布局模式），<br />
org.apache.log4j.SimpleLayout（包含日志信息的级别和信息字符串），<br />
org.apache.log4j.TTCCLayout（包含日志产生的时间、线程、类别等等信息）</p>
<p>举例：<br />
输出格式为HTML表格<br />
log4j.appender.stdout.layout=org.apache.log4j.HTMLLayout</p>
<p>输出格式为可以灵活地指定布局模式<br />
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout</p>
<p>输出格式为包含日志信息的级别和信息字符串<br />
log4j.appender.stdout.layout=org.apache.log4j.SimpleLayout</p>
<p>输出格式为包含日志产生的时间、线程、类别等等信息<br />
log4j.appender.stdout.layout=org.apache.log4j.TTCCLayout</p>
<p><br />
4、目的地</p>
<p>配置日志信息输出目的地Appender，其语法为</p>
<p><br />
log4j.appender.appenderName = fully.qualified.name.of.appender.class<br />
log4j.appender.appenderName.option1 = value1<br />
...<br />
log4j.appender.appenderName.option = valueN<br />
appenderName就是指定日志信息输出到哪个地方。您可以同时指定多个输出目的地。</p>
<p>log4j支持的输出目的地：<br />
org.apache.log4j.ConsoleAppender 控制台<br />
org.apache.log4j.FileAppender 文件<br />
org.apache.log4j.DailyRollingFileAppender 每天产生一个日志文件<br />
org.apache.log4j.RollingFileAppender （文件大小到达指定尺寸的时候产生一个新的文件），<br />
org.apache.log4j.WriterAppender （将日志信息以流格式发送到任意指定的地方）<br />
org.apache.log4j.net.SMTPAppender 邮件<br />
org.apache.log4j.jdbc.JDBCAppender 数据库<br />
其他如：GUI组件、甚至是套接口服务器、NT的事件记录器、UNIX Syslog守护进程等</p>
<p>举例：</p>
<p><br />
输出到控制台<br />
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender（指定输出到控制台）<br />
log4j.appender.Threshold=DEBUG（指定输出类别）<br />
log4j.appender.CONSOLE.Target=System.out<br />
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout（指定输出布局）<br />
log4j.appender.CONSOLE.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n（指定输出格式）</p>
<p>输出到文件</p>
<p>&nbsp;&nbsp; log4j.appender.FILE=org.apache.log4j.FileAppender（指定输出到文件）<br />
&nbsp;&nbsp; log4j.appender.FILE.File=file.log（指定输出的路径及文件名）<br />
&nbsp;&nbsp; log4j.appender.FILE.Append=false<br />
&nbsp;&nbsp; log4j.appender.FILE.layout=org.apache.log4j.PatternLayout（指定输出的布局）<br />
&nbsp;&nbsp; log4j.appender.FILE.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n（指定输出的格式）</p>
<p>输出到文件（轮换"日志文件",当日志文件达到指定大小时，该文件就被关闭并备份，然后创建一个新的日志文件）</p>
<p>&nbsp; log4j.appender.ROLLING_FILE=org.apache.log4j.RollingFileAppender（指定输出到文件）<br />
&nbsp; log4j.appender.ROLLING_FILE.Threshold=ERROR（指定输出类别）<br />
&nbsp; log4j.appender.ROLLING_FILE.File=rolling.log（指定输出的路径及文件名）<br />
&nbsp; log4j.appender.ROLLING_FILE.Append=true<br />
&nbsp; log4j.appender.ROLLING_FILE.MaxFileSize=10KB（指定输出到文件的大小）<br />
&nbsp; log4j.appender.ROLLING_FILE.MaxBackupIndex=1<br />
&nbsp; log4j.appender.ROLLING_FILE.layout=org.apache.log4j.PatternLayout（指定采用输出布局）<br />
&nbsp; log4j.appender.ROLLING_FILE.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n（指定采用输出格式）</p>
<p>输出到Socket<br />
&nbsp;log4j.appender.SOCKET=org.apache.log4j.RollingFileAppender（指定输出到Socket）<br />
&nbsp;log4j.appender.SOCKET.RemoteHost=localhost（远程主机）<br />
&nbsp;log4j.appender.SOCKET.Port=5001（远程主机端口）<br />
&nbsp;log4j.appender.SOCKET.LocationInfo=true<br />
&nbsp;log4j.appender.SOCKET.layout=org.apache.log4j.PatternLayout（布局）<br />
&nbsp;log4j.appender.SOCET.layout.ConversionPattern =[start]%d{DATE}[DATE]%n%p[PRIORITY]%n%x[NDC]%n%t[THREAD]%n%c[CATEGORY]%n %m[MESSAGE]%n%n（输出格式）</p>
<p>输出到邮件<br />
log4j.appender.MAIL=org.apache.log4j.net.SMTPAppender（指定输出到邮件）<br />
&nbsp;log4j.appender.MAIL.Threshold=FATAL<br />
&nbsp;log4j.appender.MAIL.BufferSize=10<br />
&nbsp;<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#108;&#111;&#103;&#52;&#106;&#46;&#97;&#112;&#112;&#101;&#110;&#100;&#101;&#114;&#46;&#77;&#65;&#73;&#76;&#46;&#70;&#114;&#111;&#109;&#61;&#99;&#104;&#101;&#110;&#121;&#108;&#64;&#104;&#111;&#108;&#108;&#121;&#99;&#114;&#109;&#46;&#99;&#111;&#109;"><font color="#1d58d1">log4j.appender.MAIL.From=chenyl@hollycrm.com</font></a>（发件人）<br />
&nbsp;log4j.appender.MAIL.SMTPHost=mail.hollycrm.com（SMTP服务器）<br />
&nbsp;log4j.appender.MAIL.Subject=Log4J Message<br />
&nbsp;<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#108;&#111;&#103;&#52;&#106;&#46;&#97;&#112;&#112;&#101;&#110;&#100;&#101;&#114;&#46;&#77;&#65;&#73;&#76;&#46;&#84;&#111;&#61;&#99;&#104;&#101;&#110;&#121;&#108;&#64;&#104;&#111;&#108;&#108;&#121;&#99;&#114;&#109;&#46;&#99;&#111;&#109;"><font color="#1d58d1">log4j.appender.MAIL.To=chenyl@hollycrm.com</font></a>（收件人）<br />
&nbsp;log4j.appender.MAIL.layout=org.apache.log4j.PatternLayout（布局）<br />
&nbsp;log4j.appender.MAIL.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n（格式）</p>
<br />
<p>输出到数据库<br />
&nbsp;log4j.appender.DATABASE=org.apache.log4j.jdbc.JDBCAppender（指定输出到数据库）<br />
&nbsp;log4j.appender.DATABASE.URL=jdbc:mysql://localhost:3306/test（指定数据库URL）<br />
&nbsp;log4j.appender.DATABASE.driver=com.mysql.jdbc.Driver（指定数据库driver）<br />
&nbsp;log4j.appender.DATABASE.user=root（指定数据库用户）<br />
&nbsp;log4j.appender.DATABASE.password=root（指定数据库用户密码）<br />
&nbsp;log4j.appender.DATABASE.sql=INSERT INTO LOG4J (Message) VALUES ('[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n')（组织SQL语句）<br />
&nbsp;log4j.appender.DATABASE.layout=org.apache.log4j.PatternLayout（布局）<br />
&nbsp;log4j.appender.DATABASE.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n（格式）</p>
<p>5、日志类别补充<br />
有时我们需要对某个特定的部分指定有别于根类别的日志类别，可以指定某个包的优先级<br />
如：<br />
&nbsp; log4j.category.com.neusoft.mbip.dm.util=ERROR ，其中com.neusoft.mbip.dm.util为我们需要特别指定日志类别的部分。<br />
&nbsp;<br />
&nbsp; 或者可以指定输出文件的优先级<br />
&nbsp; log4j.appender.Errorlog.Threshold=ERROR<br />
&nbsp;<br />
&nbsp;<br />
&nbsp;三、 常用log4j配置&nbsp;</p>
<p>常用log4j配置，一般可以采用两种方式，.properties和.xml,下面举两个简单的例子：</p>
<p>1、log4j.properties</p>
<p>### 设置org.zblog域对应的级别INFO,DEBUG,WARN,ERROR和输出地A1，A2 ##<br />
log4j.category.org.zblog=ERROR,A1<br />
log4j.category.org.zblog=INFO,A2</p>
<p>log4j.appender.A1=org.apache.log4j.ConsoleAppender<br />
### 设置输出地A1，为ConsoleAppender(控制台) ##<br />
log4j.appender.A1.layout=org.apache.log4j.PatternLayout<br />
### 设置A1的输出布局格式PatterLayout,(可以灵活地指定布局模式）##<br />
log4j.appender.A1.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} [%c]-[%p] %m%n<br />
### 配置日志输出的格式##</p>
<p>log4j.appender.A2=org.apache.log4j.RollingFileAppender<br />
### 设置输出地A2到文件（文件大小到达指定尺寸的时候产生一个新的文件）##<br />
log4j.appender.A2.File=E:/study/log4j/zhuwei.html<br />
### 文件位置##<br />
log4j.appender.A2.MaxFileSize=500KB<br />
### 文件大小##<br />
log4j.appender.A2.MaxBackupIndex=1<br />
log4j.appender.A2.layout=org.apache.log4j.HTMLLayout<br />
##指定采用html方式输出</p>
<p>2、log4j.xml</p>
<p>&lt;?xml version="1.0" encoding="GB2312" ?&gt;<br />
&lt;!DOCTYPE log4j:configuration SYSTEM "log4j.dtd"&gt;</p>
<p>&lt;log4j:configuration xmlns:log4j="<a href="http://jakarta.apache.org/log4j/"><font color="#1d58d1">http://jakarta.apache.org/log4j/</font></a>"&gt;</p>
<p>&lt;appender name="org.zblog.all" class="org.apache.log4j.RollingFileAppender"&gt;<br />
&lt;!-- 设置通道ID:org.zblog.all和输出方式：org.apache.log4j.RollingFileAppender --&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;param name="File" value="E:/study/log4j/all.output.log" /&gt;&lt;!-- 设置File参数：日志输出文件名 --&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;param name="Append" value="false" /&gt;&lt;!-- 设置是否在重新启动服务时，在原有日志的基础添加新日志 --&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;layout class="org.apache.log4j.PatternLayout"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;param name="ConversionPattern" value="%p (%c:%L)- %m%n" /&gt;&lt;!-- 设置输出文件项目和格式 --&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;/layout&gt;<br />
&lt;/appender&gt;</p>
<p>&lt;appender name="org.zblog.zcw" class="org.apache.log4j.RollingFileAppender"&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;param name="File" value="E:/study/log4j/zhuwei.output.log" /&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;param name="Append" value="true" /&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;param name="MaxFileSize" value="10240" /&gt; &lt;!-- 设置文件大小 --&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;layout class="org.apache.log4j.PatternLayout"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;param name="ConversionPattern" value="%p (%c:%L)- %m%n" /&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;/layout&gt;<br />
&lt;/appender&gt;</p>
<p>&lt;logger name="zcw.log"&gt; &lt;!-- 设置域名限制，即zcw.log域及以下的日志均输出到下面对应的通道中 --&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;level value="debug" /&gt;&lt;!-- 设置级别 --&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;appender-ref ref="org.zblog.zcw" /&gt;&lt;!-- 与前面的通道id相对应 --&gt;<br />
&lt;/logger&gt;</p>
<p>&lt;root&gt; &lt;!-- 设置接收所有输出的通道 --&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;appender-ref ref="org.zblog.all" /&gt;&lt;!-- 与前面的通道id相对应 --&gt;<br />
&lt;/root&gt;</p>
<p>&lt;/log4j:configuration&gt;</p>
<p><br />
3、配置文件加载方法：</p>
<p>import org.apache.log4j.Logger;<br />
import org.apache.log4j.PropertyConfigurator;<br />
import org.apache.log4j.xml.DOMConfigurator;</p>
<p>public class Log4jApp {<br />
&nbsp;&nbsp;&nbsp; public static void main(String[] args) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DOMConfigurator.configure("E:/study/log4j/log4j.xml");//加载.xml文件<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //PropertyConfigurator.configure("E:/study/log4j/log4j.properties");//加载.properties文件</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Logger log=Logger.getLogger("org.zblog.test");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; log.info("测试");<br />
&nbsp;&nbsp;&nbsp; }<br />
}</p>
<p>4、项目使用log4j<br />
在web应用中，可以将配置文件的加载放在一个单独的servlet中，并在web.xml中配置该servlet在应用启动时候加载。<br />
对于在多人项目中，可以给每一个人设置一个输出通道，这样在每个人在构建Logger时，用自己的域名称，让调试信<br />
息输出到自己的log文件中。</p>
<p>四、log4j配置举例（properties）</p>
<p>#log4j.rootLogger = [ level ] , appenderName, appenderName,<br />
#类别level 为 OFF、FATAL、ERROR、WARN、INFO、DEBUG、log、ALL或自定义的优先级<br />
#Log4j常用的优先级FATAL&gt;ERROR&gt;WARN&gt;INFO&gt;DEBUG</p>
<p>#stdout为控制台 ，Errorlog为错误记录日志 ，<br />
log4j.rootCategory=INFO,stdout,Runlog,Errorlog</p>
<p><br />
#输出的appender的格式为<br />
#log4j.appender.appenderName = fully.qualified.name.of.appender.class<br />
#log4j.appender.appenderName.option1 = value1<br />
#log4j.appender.appenderName.option = valueN<br />
#Log4j中appender支持的输出<br />
#org.apache.log4j.ConsoleAppender 控制台<br />
#org.apache.log4j.FileAppender 文件<br />
#org.apache.log4j.DailyRollingFileAppender 每天产生一个日志文件<br />
#org.apache.log4j.RollingFileAppender （文件大小到达指定尺寸的时候产生一个新的文件），<br />
#org.apache.log4j.WriterAppender （将日志信息以流格式发送到任意指定的地方）<br />
#org.apache.log4j.net.SMTPAppender 邮件<br />
#org.apache.log4j.jdbc.JDBCAppender 数据库</p>
<p>＃定义输出的形式<br />
log4j.appender.stdout=org.apache.log4j.ConsoleAppender<br />
log4j.appender.Runlog=org.apache.log4j.DailyRollingFileAppender<br />
log4j.appender.Errorlog=org.apache.log4j.DailyRollingFileAppender</p>
<p><br />
#可以指定输出文件的优先级<br />
log4j.appender.Errorlog.Threshold=ERROR</p>
<p>#指定输出的文件<br />
log4j.appender.Runlog.File=D:\UserInfoSyn\WebRoot\WEB-INF\runlog\runlog.log<br />
log4j.appender.Errorlog.File=D:\UserInfoSyn\WebRoot\WEB-INF\errorlog\errorlog.log</p>
<p><br />
#Log4j的layout布局<br />
#org.apache.log4j.HTMLLayout 以HTML表格形式布局<br />
#org.apache.log4j.PatternLayout 可以灵活地指定布局模式<br />
#org.apache.log4j.SimpleLayout&nbsp; 包含日志信息的级别和信息字符串<br />
#org.apache.log4j.TTCCLayout&nbsp;&nbsp;&nbsp; 包含日志产生的时间、线程、类别等等信息</p>
<p>log4j.appender.stdout.layout=org.apache.log4j.PatternLayout<br />
log4j.appender.Runlog.layout=org.apache.log4j.PatternLayout<br />
log4j.appender.Errorlog.layout=org.apache.log4j.PatternLayout</p>
<p>#输出格式,log4j javadoc org.apache.log4j.PatternLayout<br />
#-X号:X信息输出时左对齐；<br />
#%p:日志信息级别<br />
# %d{}:日志信息产生时间<br />
# %c:日志信息所在地（类名）<br />
# %m:产生的日志具体信息<br />
# %n:%n:输出日志信息换行<br />
log4j.appender.stdout.layout.ConversionPattern= %5p %d{yyyy-MM-dd HH:mm:ss} %c %m %n<br />
log4j.appender.Runlog.layout.ConversionPattern= %5p %d{yyyy-MM-dd HH:mm:ss} %c %m %n<br />
log4j.appender.Errorlog.layout.ConversionPattern= %5p %d{yyyy-MM-dd HH:mm:ss} %c %m %n</p>
<p>#指定某个包的优先级<br />
log4j.category.com.neusoft.mbip.dm.util=ERROR</p>
<p><br />
#示例<br />
###################<br />
# Console Appender<br />
###################<br />
#log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender<br />
#log4j.appender.Threshold=DEBUG<br />
#log4j.appender.CONSOLE.Target=System.out<br />
#log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout<br />
#log4j.appender.CONSOLE.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n<br />
#log4j.appender.CONSOLE.layout.ConversionPattern=[start]%d{DATE}[DATE]%n%p[PRIORITY]%n%x[NDC]%n%t[THREAD] n%c[CATEGORY]%n%m[MESSAGE]%n%n</p>
<p><br />
#####################<br />
# File Appender<br />
#####################<br />
#log4j.appender.FILE=org.apache.log4j.FileAppender<br />
#log4j.appender.FILE.File=file.log<br />
#log4j.appender.FILE.Append=false<br />
#log4j.appender.FILE.layout=org.apache.log4j.PatternLayout<br />
#log4j.appender.FILE.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n<br />
# Use this layout for LogFactor 5 analysis</p>
<p>########################<br />
# Rolling File????? RollingFileAppender??????????????????<br />
########################<br />
#log4j.appender.ROLLING_FILE=org.apache.log4j.RollingFileAppender<br />
#log4j.appender.ROLLING_FILE.Threshold=ERROR<br />
# 文件位置<br />
#log4j.appender.ROLLING_FILE.File=rolling.log<br />
#log4j.appender.ROLLING_FILE.Append=true<br />
#文件大小<br />
#log4j.appender.ROLLING_FILE.MaxFileSize=10KB<br />
#指定采用输出布局和输出格式<br />
#log4j.appender.ROLLING_FILE.MaxBackupIndex=1<br />
#log4j.appender.ROLLING_FILE.layout=org.apache.log4j.PatternLayout<br />
#log4j.appender.ROLLING_FILE.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n</p>
<p>####################<br />
# Socket Appender<br />
####################<br />
#log4j.appender.SOCKET=org.apache.log4j.RollingFileAppender<br />
#log4j.appender.SOCKET.RemoteHost=localhost<br />
#log4j.appender.SOCKET.Port=5001<br />
#log4j.appender.SOCKET.LocationInfo=true<br />
# Set up for Log Facter 5<br />
#log4j.appender.SOCKET.layout=org.apache.log4j.PatternLayout<br />
#log4j.appender.SOCET.layout.ConversionPattern=[start]%d{DATE}[DATE]%n%p[PRIORITY]%n%x[NDC]%n%t[THREAD]%n%c[CATEGORY]%n%m[MESSAGE]%n%n</p>
<p>########################<br />
# SMTP Appender<br />
#######################<br />
#log4j.appender.MAIL=org.apache.log4j.net.SMTPAppender<br />
#log4j.appender.MAIL.Threshold=FATAL<br />
#log4j.appender.MAIL.BufferSize=10<br />
<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#35;&#108;&#111;&#103;&#52;&#106;&#46;&#97;&#112;&#112;&#101;&#110;&#100;&#101;&#114;&#46;&#77;&#65;&#73;&#76;&#46;&#70;&#114;&#111;&#109;&#61;&#99;&#104;&#101;&#110;&#121;&#108;&#64;&#104;&#111;&#108;&#108;&#121;&#99;&#114;&#109;&#46;&#99;&#111;&#109;"><font color="#1d58d1">#log4j.appender.MAIL.From=chenyl@hollycrm.com</font></a><br />
#log4j.appender.MAIL.SMTPHost=mail.hollycrm.com<br />
#log4j.appender.MAIL.Subject=Log4J Message<br />
<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#35;&#108;&#111;&#103;&#52;&#106;&#46;&#97;&#112;&#112;&#101;&#110;&#100;&#101;&#114;&#46;&#77;&#65;&#73;&#76;&#46;&#84;&#111;&#61;&#99;&#104;&#101;&#110;&#121;&#108;&#64;&#104;&#111;&#108;&#108;&#121;&#99;&#114;&#109;&#46;&#99;&#111;&#109;"><font color="#1d58d1">#log4j.appender.MAIL.To=chenyl@hollycrm.com</font></a><br />
#log4j.appender.MAIL.layout=org.apache.log4j.PatternLayout<br />
#log4j.appender.MAIL.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n</p>
<p>########################<br />
# JDBC Appender<br />
#######################<br />
#log4j.appender.DATABASE=org.apache.log4j.jdbc.JDBCAppender<br />
#log4j.appender.DATABASE.URL=jdbc:mysql://localhost:3306/test<br />
#log4j.appender.DATABASE.driver=com.mysql.jdbc.Driver<br />
#log4j.appender.DATABASE.user=root<br />
#log4j.appender.DATABASE.password=<br />
#log4j.appender.DATABASE.sql=INSERT INTO LOG4J (Message) VALUES ('[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n')<br />
#log4j.appender.DATABASE.layout=org.apache.log4j.PatternLayout<br />
#log4j.appender.DATABASE.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n</p>
<p>########################<br />
# Log Factor 5 Appender<br />
########################<br />
#log4j.appender.LF5_APPENDER=org.apache.log4j.lf5.LF5Appender<br />
#log4j.appender.LF5_APPENDER.MaxNumberOfRecords=2000</p>
<p>###################<br />
#自定义Appender<br />
###################<br />
#log4j.appender.im = net.cybercorlin.util.logger.appender.IMAppender<br />
#log4j.appender.im.host = mail.cybercorlin.net<br />
#log4j.appender.im.username = username<br />
#log4j.appender.im.password = password<br />
#log4j.appender.im.recipient = <a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#99;&#111;&#114;&#108;&#105;&#110;&#64;&#99;&#121;&#98;&#101;&#114;&#99;&#111;&#114;&#108;&#105;&#110;&#46;&#110;&#101;&#116;"><font color="#1d58d1">corlin@cybercorlin.net</font></a><br />
#log4j.appender.im.layout=org.apache.log4j.PatternLayout<br />
#log4j.appender.im.layout.ConversionPattern =[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n</p>
<img src ="http://www.blogjava.net/xinwuhen/aggbug/193689.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/xinwuhen/" target="_blank">心无痕</a> 2008-04-17 11:31 <a href="http://www.blogjava.net/xinwuhen/archive/2008/04/17/193689.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>关于web.xml配置的详细说明</title><link>http://www.blogjava.net/xinwuhen/archive/2008/04/15/193043.html</link><dc:creator>心无痕</dc:creator><author>心无痕</author><pubDate>Tue, 15 Apr 2008 03:42:00 GMT</pubDate><guid>http://www.blogjava.net/xinwuhen/archive/2008/04/15/193043.html</guid><wfw:comment>http://www.blogjava.net/xinwuhen/comments/193043.html</wfw:comment><comments>http://www.blogjava.net/xinwuhen/archive/2008/04/15/193043.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/xinwuhen/comments/commentRss/193043.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/xinwuhen/services/trackbacks/193043.html</trackback:ping><description><![CDATA[<font size="2">1 定义头和根元素<br />
<br />
部署描述符文件就像所有XML文件一样，必须以一个XML头开始。这个头声明可以使用的XML版本并给出文件的字符编码。<br />
DOCYTPE声明必须立即出现在此头之后。这个声明告诉服务器适用的servlet规范的版本（如2.2或2.3）并指定管理此文件其余部分内容的语法的DTD(Document Type Definition，文档类型定义)。<br />
所有部署描述符文件的顶层（根）元素为web-app。请注意，XML元素不像HTML，他们是大小写敏感的。因此，web-App和WEB-APP都是不合法的，web-app必须用小写。<br />
<br />
2 部署描述符文件内的元素次序<br />
<br />
XML 元素不仅是大小写敏感的，而且它们还对出现在其他元素中的次序敏感。例如，XML头必须是文件中的第一项，DOCTYPE声明必须是第二项，而web- app元素必须是第三项。在web-app元素内，元素的次序也很重要。服务器不一定强制要求这种次序，但它们允许（实际上有些服务器就是这样做的）完全拒绝执行含有次序不正确的元素的Web应用。这表示使用非标准元素次序的web.xml文件是不可移植的。<br />
下面的列表给出了所有可直接出现在web-app元素内的合法元素所必需的次序。例如，此列表说明servlet元素必须出现在所有servlet-mapping元素之前。请注意，所有这些元素都是可选的。因此，可以省略掉某一元素，但不能把它放于不正确的位置。<br />
l icon icon元素指出IDE和GUI工具用来表示Web应用的一个和两个图像文件的位置。<br />
l display-name display-name元素提供GUI工具可能会用来标记这个特定的Web应用的一个名称。<br />
l description description元素给出与此有关的说明性文本。<br />
l context-param context-param元素声明应用范围内的初始化参数。<br />
l filter 过滤器元素将一个名字与一个实现javax.servlet.Filter接口的类相关联。<br />
l filter-mapping 一旦命名了一个过滤器，就要利用filter-mapping元素把它与一个或多个servlet或JSP页面相关联。<br />
l listener servlet API的版本2.3增加了对事件监听程序的支持，事件监听程序在建立、修改和删除会话或servlet环境时得到通知。Listener元素指出事件监听程序类。<br />
l servlet 在向servlet或JSP页面制定初始化参数或定制URL时，必须首先命名servlet或JSP页面。Servlet元素就是用来完成此项任务的。<br />
l servlet-mapping 服务器一般为servlet提供一个缺省的URL：</font><a href="http://host/webAppPrefix/servlet/ServletName" target="_blank"><font size="2">http://host/webAppPrefix/servlet/ServletName</font></a><font size="2">。但是，常常会更改这个URL，以便servlet可以访问初始化参数或更容易地处理相对URL。在更改缺省URL时，使用servlet-mapping元素。<br />
l session-config 如果某个会话在一定时间内未被访问，服务器可以抛弃它以节省内存。可通过使用HttpSession的setMaxInactiveInterval方法明确设置单个会话对象的超时值，或者可利用session-config元素制定缺省超时值。<br />
l mime-mapping 如果Web应用具有想到特殊的文件，希望能保证给他们分配特定的MIME类型，则mime-mapping元素提供这种保证。<br />
l welcom-file-list welcome-file-list元素指示服务器在收到引用一个目录名而不是文件名的URL时，使用哪个文件。<br />
l error-page error-page元素使得在返回特定HTTP状态代码时，或者特定类型的异常被抛出时，能够制定将要显示的页面。<br />
l taglib taglib元素对标记库描述符文件（Tag Libraryu Descriptor file）指定别名。此功能使你能够更改TLD文件的位置，而不用编辑使用这些文件的JSP页面。<br />
l resource-env-ref resource-env-ref元素声明与资源相关的一个管理对象。<br />
l resource-ref resource-ref元素声明一个资源工厂使用的外部资源。<br />
l security-constraint security-constraint元素制定应该保护的URL。它与login-config元素联合使用<br />
l login-config 用login-config元素来指定服务器应该怎样给试图访问受保护页面的用户授权。它与sercurity-constraint元素联合使用。<br />
l security-role security-role元素给出安全角色的一个列表，这些角色将出现在servlet元素内的security-role-ref元素的role-name子元素中。分别地声明角色可使高级IDE处理安全信息更为容易。<br />
l env-entry env-entry元素声明Web应用的环境项。<br />
l ejb-ref ejb-ref元素声明一个EJB的主目录的引用。<br />
l ejb-local-ref ejb-local-ref元素声明一个EJB的本地主目录的应用。<br />
<br />
3 分配名称和定制的UL<br />
<br />
在web.xml中完成的一个最常见的任务是对servlet或JSP页面给出名称和定制的URL。用servlet元素分配名称，使用servlet-mapping元素将定制的URL与刚分配的名称相关联。<br />
3.1 分配名称<br />
为了提供初始化参数，对servlet或JSP页面定义一个定制URL或分配一个安全角色，必须首先给servlet或JSP页面一个名称。可通过 servlet元素分配一个名称。最常见的格式包括servlet-name和servlet-class子元素（在web-app元素内），如下所示：<br />
&lt;servlet&gt;<br />
&lt;servlet-name&gt;Test&lt;/servlet-name&gt;<br />
&lt;servlet-class&gt;moreservlets.TestServlet&lt;/servlet-class&gt;<br />
&lt;/servlet&gt; <br />
这表示位于WEB-INF/classes/moreservlets/TestServlet的servlet已经得到了注册名Test。给 servlet一个名称具有两个主要的含义。首先，初始化参数、定制的URL模式以及其他定制通过此注册名而不是类名引用此servlet。其次,可在 URL而不是类名中使用此名称。因此，利用刚才给出的定义，URL </font><a href="http://host/webAppPrefix/servlet/Test" target="_blank"><font size="2">http://host/webAppPrefix/servlet/Test</font></a><font size="2"> 可用于 </font><a href="http://host/webAppPrefix/servlet/moreservlets.TestServlet" target="_blank"><font size="2">http://host/webAppPrefix/servlet/moreservlets.TestServlet</font></a><font size="2"> 的场所。<br />
请记住：XML元素不仅是大小写敏感的，而且定义它们的次序也很重要。例如，web-app元素内所有servlet元素必须位于所有servlet- mapping元素（下一小节介绍）之前，而且还要位于5.6节和5.11节讨论的与过滤器或文档相关的元素（如果有的话）之前。类似地，servlet 的servlet-name子元素也必须出现在servlet-class之前。5.2节"部署描述符文件内的元素次序"将详细介绍这种必需的次序。<br />
例如，程序清单5-1给出了一个名为TestServlet的简单servlet，它驻留在moreservlets程序包中。因为此servlet是扎根在一个名为deployDemo的目录中的Web应用的组成部分，所以TestServlet.class放在deployDemo/WEB- INF/classes/moreservlets中。程序清单5-2给出将放置在deployDemo/WEB-INF/内的web.xml文件的一部分。此web.xml文件使用servlet-name和servlet-class元素将名称Test与TestServlet.class相关联。图 5-1和图5-2分别显示利用缺省URL和注册名调用TestServlet时的结果。<br />
<br />
程序清单5-1 TestServlet.java<br />
package moreservlets;<br />
<br />
import java.io.*;<br />
import javax.servlet.*;<br />
import javax.servlet.http.*;<br />
<br />
/** Simple servlet used to illustrate servlet naming<br />
* and custom URLs.<br />
* &lt;P&gt;<br />
* Taken from More Servlets and JavaServer Pages<br />
* from Prentice Hall and Sun Microsystems Press,<br />
* </font><a href="http://www.moreservlets.com/." target="_blank"><font size="2">http://www.moreservlets.com/.</font></a><br />
<font size="2">* &#169; 2002 Marty Hall; may be freely used or adapted.<br />
*/<br />
<br />
public class TestServlet extends HttpServlet {<br />
public void doGet(HttpServletRequest request,<br />
HttpServletResponse response)<br />
throws ServletException, IOException {<br />
response.setContentType("text/html");<br />
PrintWriter out = response.getWriter();<br />
String uri = request.getRequestURI();<br />
out.println(ServletUtilities.headWithTitle("Test Servlet") +<br />
"&lt;BODY BGCOLOR=\"#FDF5E6\"&gt;\n" +<br />
"&lt;H2&gt;URI: " + uri + "&lt;/H2&gt;\n" +<br />
"&lt;/BODY&gt;&lt;/HTML&gt;");<br />
}<br />
}<br />
<br />
<br />
程序清单5-2 web.xml（说明servlet名称的摘录）<br />
&lt;?xml version="1.0" encoding="ISO-8859-1"?&gt;<br />
&lt;!DOCTYPE web-app<br />
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"<br />
"</font><a href="http://java.sun.com/dtd/web-app_2_3.dtd" target="_blank"><font size="2">http://java.sun.com/dtd/web-app_2_3.dtd</font></a><font size="2">"&gt;<br />
<br />
&lt;web-app&gt;<br />
&lt;!-- &#8230; --&gt;<br />
&lt;servlet&gt;<br />
&lt;servlet-name&gt;Test&lt;/servlet-name&gt;<br />
&lt;servlet-class&gt;moreservlets.TestServlet&lt;/servlet-class&gt;<br />
&lt;/servlet&gt;<br />
&lt;!-- &#8230; --&gt;<br />
&lt;/web-app&gt;<br />
<br />
3.2 定义定制的URL<br />
大多数服务器具有一个缺省的serlvet URL：<br />
</font><a href="http://host/webAppPrefix/servlet/packageName.ServletName" target="_blank"><font size="2">http://host/webAppPrefix/servlet/packageName.ServletName</font></a><font size="2">。虽然在开发中使用这个URL很方便，但是我们常常会希望另一个URL用于部署。例如，可能会需要一个出现在Web应用顶层的URL（如，http: //host/webAppPrefix/Anyname），并且在此URL中没有servlet项。位于顶层的URL简化了相对URL的使用。此外，对许多开发人员来说，顶层URL看上去比更长更麻烦的缺省URL更简短。<br />
事实上，有时需要使用定制的URL。比如，你可能想关闭缺省URL映射，以便更好地强制实施安全限制或防止用户意外地访问无初始化参数的servlet。如果你禁止了缺省的URL，那么你怎样访问servlet呢？这时只有使用定制的URL了。<br />
为了分配一个定制的URL，可使用servlet-mapping元素及其servlet-name和url-pattern子元素。Servlet- name元素提供了一个任意名称，可利用此名称引用相应的servlet；url-pattern描述了相对于Web应用的根目录的URL。url- pattern元素的值必须以斜杠（/）起始。<br />
下面给出一个简单的web.xml摘录，它允许使用URL </font><a href="http://host/webAppPrefix/UrlTest" target="_blank"><font size="2">http://host/webAppPrefix/UrlTest</font></a><font size="2">而不是</font><a href="http://host/webAppPrefix/servlet/Test" target="_blank"><font size="2">http://host/webAppPrefix/servlet/Test</font></a><font size="2">或<br />
http: //host/webAppPrefix/servlet/moreservlets.TestServlet。请注意，仍然需要XML头、 DOCTYPE声明以及web-app封闭元素。此外，可回忆一下，XML元素出现地次序不是随意的。特别是，需要把所有servlet元素放在所有 servlet-mapping元素之前。<br />
&lt;servlet&gt;<br />
&lt;servlet-name&gt;Test&lt;/servlet-name&gt;<br />
&lt;servlet-class&gt;moreservlets.TestServlet&lt;/servlet-class&gt;<br />
&lt;/servlet&gt;<br />
&lt;!-- ... --&gt;<br />
&lt;servlet-mapping&gt;<br />
&lt;servlet-name&gt;Test&lt;/servlet-name&gt;<br />
&lt;url-pattern&gt;/UrlTest&lt;/url-pattern&gt;<br />
&lt;/servlet-mapping&gt;<br />
URL模式还可以包含通配符。例如，下面的小程序指示服务器发送所有以Web应用的URL前缀开始，以..asp结束的请求到名为BashMS的servlet。<br />
&lt;servlet&gt;<br />
&lt;servlet-name&gt;BashMS&lt;/servlet-name&gt;<br />
&lt;servlet-class&gt;msUtils.ASPTranslator&lt;/servlet-class&gt;<br />
&lt;/servlet&gt;<br />
&lt;!-- ... --&gt;<br />
&lt;servlet-mapping&gt;<br />
&lt;servlet-name&gt;BashMS&lt;/servlet-name&gt;<br />
&lt;url-pattern&gt;/*.asp&lt;/url-pattern&gt;<br />
&lt;/servlet-mapping&gt;<br />
3.3 命名JSP页面<br />
因为JSP页面要转换成sevlet，自然希望就像命名servlet一样命名JSP页面。毕竟，JSP页面可能会从初始化参数、安全设置或定制的URL中受益，正如普通的serlvet那样。虽然JSP页面的后台实际上是servlet这句话是正确的，但存在一个关键的猜疑：即，你不知道JSP页面的实际类名（因为系统自己挑选这个名字）。因此，为了命名JSP页面，可将jsp-file元素替换为servlet-calss元素，如下所示：<br />
&lt;servlet&gt;<br />
&lt;servlet-name&gt;Test&lt;/servlet-name&gt;<br />
&lt;jsp-file&gt;/TestPage.jsp&lt;/jsp-file&gt;<br />
&lt;/servlet&gt;<br />
命名JSP页面的原因与命名servlet的原因完全相同：即为了提供一个与定制设置（如，初始化参数和安全设置）一起使用的名称，并且，以便能更改激活 JSP页面的URL（比方说，以便多个URL通过相同页面得以处理，或者从URL中去掉.jsp扩展名）。但是，在设置初始化参数时，应该注意，JSP页面是利用jspInit方法，而不是init方法读取初始化参数的。<br />
例如，程序清单5-3给出一个名为TestPage.jsp的简单JSP页面，它的工作只是打印出用来激活它的URL的本地部分。TestPage.jsp放置在deployDemo应用的顶层。程序清单5-4给出了用来分配一个注册名PageName，然后将此注册名与</font><a href="http://host/webAppPrefix/UrlTest2/anything" target="_blank"><font size="2">http://host/webAppPrefix/UrlTest2/anything</font></a><font size="2"> 形式的URL相关联的web.xml文件（即，deployDemo/WEB-INF/web.xml）的一部分。<br />
<br />
程序清单5-3 TestPage.jsp<br />
&lt;!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"&gt;<br />
&lt;HTML&gt;<br />
&lt;HEAD&gt;<br />
&lt;TITLE&gt;<br />
JSP Test Page<br />
&lt;/TITLE&gt;<br />
&lt;/HEAD&gt;<br />
&lt;BODY BGCOLOR="#FDF5E6"&gt;<br />
&lt;H2&gt;URI: &lt;%= request.getRequestURI() %&gt;&lt;/H2&gt;<br />
&lt;/BODY&gt;<br />
&lt;/HTML&gt;<br />
<br />
<br />
程序清单5-4 web.xml（说明JSP页命名的摘录）<br />
&lt;?xml version="1.0" encoding="ISO-8859-1"?&gt;<br />
&lt;!DOCTYPE web-app<br />
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"<br />
"</font><a href="http://java.sun.com/dtd/web-app_2_3.dtd" target="_blank"><font size="2">http://java.sun.com/dtd/web-app_2_3.dtd</font></a><font size="2">"&gt;<br />
<br />
&lt;web-app&gt;<br />
&lt;!-- ... --&gt;<br />
&lt;servlet&gt;<br />
&lt;servlet-name&gt;PageName&lt;/servlet-name&gt;<br />
&lt;jsp-file&gt;/TestPage.jsp&lt;/jsp-file&gt;<br />
&lt;/servlet&gt;<br />
&lt;!-- ... --&gt;<br />
&lt;servlet-mapping&gt;<br />
&lt;servlet-name&gt; PageName &lt;/servlet-name&gt;<br />
&lt;url-pattern&gt;/UrlTest2/*&lt;/url-pattern&gt;<br />
&lt;/servlet-mapping&gt;<br />
&lt;!-- ... --&gt;<br />
&lt;/web-app&gt;<br />
<br />
<br />
4 禁止激活器servlet<br />
<br />
对servlet或JSP页面建立定制URL的一个原因是，这样做可以注册从 init（servlet）或jspInit（JSP页面）方法中读取得初始化参数。但是，初始化参数只在是利用定制URL模式或注册名访问 servlet或JSP页面时可以使用，用缺省URL </font><a href="http://host/webAppPrefix/servlet/ServletName" target="_blank"><font size="2">http://host/webAppPrefix/servlet/ServletName</font></a><font size="2"> 访问时不能使用。因此，你可能会希望关闭缺省URL，这样就不会有人意外地调用初始化servlet了。这个过程有时称为禁止激活器servlet，因为多数服务器具有一个用缺省的servlet URL注册的标准servlet，并激活缺省的URL应用的实际servlet。<br />
有两种禁止此缺省URL的主要方法：<br />
l 在每个Web应用中重新映射/servlet/模式。<br />
l 全局关闭激活器servlet。<br />
重要的是应该注意到，虽然重新映射每个Web应用中的/servlet/模式比彻底禁止激活servlet所做的工作更多，但重新映射可以用一种完全可移植的方式来完成。相反，全局禁止激活器servlet完全是针对具体机器的，事实上有的服务器（如ServletExec）没有这样的选择。下面的讨论对每个Web应用重新映射/servlet/ URL模式的策略。后面提供在Tomcat中全局禁止激活器servlet的详细内容。<br />
4.1 重新映射/servlet/URL模式<br />
在一个特定的Web应用中禁止以</font><a href="http://host/webAppPrefix/servlet/" target="_blank"><font size="2">http://host/webAppPrefix/servlet/</font></a><font size="2"> 开始的URL的处理非常简单。所需做的事情就是建立一个错误消息servlet，并使用前一节讨论的url-pattern元素将所有匹配请求转向该 servlet。只要简单地使用：<br />
&lt;url-pattern&gt;/servlet/*&lt;/url-pattern&gt;<br />
作为servlet-mapping元素中的模式即可。<br />
例如，程序清单5-5给出了将SorryServlet servlet（程序清单5-6）与所有以</font><a href="http://host/webAppPrefix/servlet/" target="_blank"><font size="2">http://host/webAppPrefix/servlet/</font></a><font size="2"> 开头的URL相关联的部署描述符文件的一部分。<br />
<br />
程序清单5-5 web.xml（说明JSP页命名的摘录）<br />
&lt;?xml version="1.0" encoding="ISO-8859-1"?&gt;<br />
&lt;!DOCTYPE web-app<br />
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"<br />
"</font><a href="http://java.sun.com/dtd/web-app_2_3.dtd" target="_blank"><font size="2">http://java.sun.com/dtd/web-app_2_3.dtd</font></a><font size="2">"&gt;<br />
<br />
&lt;web-app&gt;<br />
&lt;!-- ... --&gt;<br />
&lt;servlet&gt;<br />
&lt;servlet-name&gt;Sorry&lt;/servlet-name&gt;<br />
&lt;servlet-class&gt;moreservlets.SorryServlet&lt;/servlet-class&gt;<br />
&lt;/servlet&gt;<br />
&lt;!-- ... --&gt;<br />
&lt;servlet-mapping&gt;<br />
&lt;servlet-name&gt; Sorry &lt;/servlet-name&gt;<br />
&lt;url-pattern&gt;/servlet/*&lt;/url-pattern&gt;<br />
&lt;/servlet-mapping&gt;<br />
&lt;!-- ... --&gt;<br />
&lt;/web-app&gt;<br />
<br />
<br />
程序清单5-6 SorryServlet.java<br />
package moreservlets;<br />
<br />
import java.io.*;<br />
import javax.servlet.*;<br />
import javax.servlet.http.*;<br />
<br />
/** Simple servlet used to give error messages to<br />
* users who try to access default servlet URLs<br />
* (i.e., </font><a href="http://host/webAppPrefix/servlet/ServletName" target="_blank"><font size="2">http://host/webAppPrefix/servlet/ServletName</font></a><font size="2">)<br />
* in Web applications that have disabled this<br />
* behavior.<br />
* &lt;P&gt;<br />
* Taken from More Servlets and JavaServer Pages<br />
* from Prentice Hall and Sun Microsystems Press,<br />
* </font><a href="http://www.moreservlets.com/." target="_blank"><font size="2">http://www.moreservlets.com/.</font></a><br />
<font size="2">* &#169; 2002 Marty Hall; may be freely used or adapted.<br />
*/<br />
<br />
public class SorryServlet extends HttpServlet {<br />
public void doGet(HttpServletRequest request,<br />
HttpServletResponse response)<br />
throws ServletException, IOException {<br />
response.setContentType("text/html");<br />
PrintWriter out = response.getWriter();<br />
String title = "Invoker Servlet Disabled.";<br />
out.println(ServletUtilities.headWithTitle(title) +<br />
"&lt;BODY BGCOLOR=\"#FDF5E6\"&gt;\n" +<br />
"&lt;H2&gt;" + title + "&lt;/H2&gt;\n" +<br />
"Sorry, access to servlets by means of\n" +<br />
"URLs that begin with\n" +<br />
"</font><a href="http://host/webAppPrefix/servlet/" target="_blank"><font size="2">http://host/webAppPrefix/servlet/</font></a><font size="2">\n" +<br />
"has been disabled.\n" + <br />
"&lt;/BODY&gt;&lt;/HTML&gt;");<br />
}<br />
<br />
public void doPost(HttpServletRequest request,<br />
HttpServletResponse response)<br />
throws ServletException, IOException {<br />
doGet(request, response);<br />
}<br />
}<br />
<br />
<br />
4.2 全局禁止激活器：Tomcat<br />
Tomcat 4中用来关闭缺省URL的方法与Tomcat 3中所用的很不相同。下面介绍这两种方法：<br />
1．禁止激活器： Tomcat 4<br />
Tomcat 4用与前面相同的方法关闭激活器servlet，即利用web.xml中的url-mapping元素进行关闭。不同之处在于Tomcat使用了放在 install_dir/conf中的一个服务器专用的全局web.xml文件，而前面使用的是存放在每个Web应用的WEB-INF目录中的标准 web.xml文件。<br />
因此，为了在Tomcat 4中关闭激活器servlet，只需在install_dir/conf/web.xml中简单地注释出/servlet/* URL映射项即可，如下所示：<br />
&lt;!-- <br />
&lt;servlet-mapping&gt;<br />
&lt;servlet-name&gt;invoker&lt;/servlet-name&gt;<br />
&lt;url-pattern&gt;/servlet/*&lt;/url-pattern&gt;<br />
&lt;/servlet-mapping&gt;<br />
--&gt;<br />
再次提醒，应该注意这个项是位于存放在install_dir/conf的Tomcat专用的web.xml文件中的，此文件不是存放在每个Web应用的WEB-INF目录中的标准web.xml。<br />
2．禁止激活器：Tomcat3<br />
在Apache Tomcat的版本3中，通过在install_dir/conf/server.xml中注释出InvokerInterceptor项全局禁止缺省 servlet URL。例如，下面是禁止使用缺省servlet URL的server.xml文件的一部分。<br />
&lt;!-- <br />
&lt;RequsetInterceptor <br />
className="org.apache.tomcat.request.InvokerInterceptor"<br />
debug="0" prefix="/servlet/" /&gt;<br />
--&gt;<br />
<br />
5 初始化和预装载servlet与JSP页面<br />
<br />
这里讨论控制servlet和JSP页面的启动行为的方法。特别是，说明了怎样分配初始化参数以及怎样更改服务器生存期中装载servlet和JSP页面的时刻。<br />
5.1 分配servlet初始化参数<br />
利用init-param元素向servlet提供初始化参数，init-param元素具有param-name和param-value子元素。例如，在下面的例子中，如果initServlet servlet是利用它的注册名（InitTest）访问的，它将能够从其方法中调用getServletConfig(). getInitParameter("param1")获得"Value 1"，调用getServletConfig().getInitParameter("param2")获得"2"。<br />
&lt;servlet&gt;<br />
&lt;servlet-name&gt;InitTest&lt;/servlet-name&gt;<br />
&lt;servlet-class&gt;moreservlets.InitServlet&lt;/servlet-class&gt;<br />
&lt;init-param&gt;<br />
&lt;param-name&gt;param1&lt;/param-name&gt;<br />
&lt;param-value&gt;value1&lt;/param-value&gt;<br />
&lt;/init-param&gt;<br />
&lt;init-param&gt;<br />
&lt;param-name&gt;param2&lt;/param-name&gt;<br />
&lt;param-value&gt;2&lt;/param-value&gt;<br />
&lt;/init-param&gt;<br />
&lt;/servlet&gt;<br />
在涉及初始化参数时，有几点需要注意：<br />
l 返回值。GetInitParameter的返回值总是一个String。因此，在前一个例子中，可对param2使用Integer.parseInt获得一个int。<br />
l JSP中的初始化。JSP页面使用jspInit而不是init。JSP页面还需要使用jsp-file元素代替servlet-class。<br />
l 缺省URL。初始化参数只在通过它们的注册名或与它们注册名相关的定制URL模式访问Servlet时可以使用。因此，在这个例子中，param1和 param2初始化参数将能够在使用URL </font><a href="http://host/webAppPrefix/servlet/InitTest" target="_blank"><font size="2">http://host/webAppPrefix/servlet/InitTest</font></a><font size="2"> 时可用，但在使用URL </font><a href="http://host/webAppPrefix/servlet/myPackage.InitServlet" target="_blank"><font size="2">http://host/webAppPrefix/servlet/myPackage.InitServlet</font></a><font size="2"> 时不能使用。<br />
例如，程序清单5-7给出一个名为InitServlet的简单servlet，它使用init方法设置firstName和emailAddress字段。程序清单5-8给出分配名称InitTest给servlet的web.xml文件。<br />
程序清单5-7 InitServlet.java<br />
package moreservlets;<br />
<br />
import java.io.*;<br />
import javax.servlet.*;<br />
import javax.servlet.http.*;<br />
<br />
/** Simple servlet used to illustrate servlet<br />
* initialization parameters.<br />
* &lt;P&gt;<br />
* Taken from More Servlets and JavaServer Pages<br />
* from Prentice Hall and Sun Microsystems Press,<br />
* </font><a href="http://www.moreservlets.com/." target="_blank"><font size="2">http://www.moreservlets.com/.</font></a><br />
<font size="2">* &#169; 2002 Marty Hall; may be freely used or adapted.<br />
*/<br />
<br />
public class InitServlet extends HttpServlet {<br />
private String firstName, emailAddress;<br />
<br />
public void init() {<br />
ServletConfig config = getServletConfig();<br />
firstName = config.getInitParameter("firstName");<br />
emailAddress = config.getInitParameter("emailAddress");<br />
}<br />
<br />
public void doGet(HttpServletRequest request,<br />
HttpServletResponse response)<br />
throws ServletException, IOException {<br />
response.setContentType("text/html");<br />
PrintWriter out = response.getWriter();<br />
String uri = request.getRequestURI();<br />
out.println(ServletUtilities.headWithTitle("Init Servlet") +<br />
"&lt;BODY BGCOLOR=\"#FDF5E6\"&gt;\n" +<br />
"&lt;H2&gt;Init Parameters:&lt;/H2&gt;\n" +<br />
"&lt;UL&gt;\n" +<br />
"&lt;LI&gt;First name: " + firstName + "\n" +<br />
"&lt;LI&gt;Email address: " + emailAddress + "\n" +<br />
"&lt;/UL&gt;\n" + <br />
"&lt;/BODY&gt;&lt;/HTML&gt;");<br />
}<br />
}<br />
<br />
<br />
程序清单5-8 web.xml（说明初始化参数的摘录）<br />
&lt;?xml version="1.0" encoding="ISO-8859-1"?&gt;<br />
&lt;!DOCTYPE web-app<br />
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"<br />
"</font><a href="http://java.sun.com/dtd/web-app_2_3.dtd" target="_blank"><font size="2">http://java.sun.com/dtd/web-app_2_3.dtd</font></a><font size="2">"&gt;<br />
<br />
&lt;web-app&gt;<br />
&lt;!-- ... --&gt;<br />
&lt;servlet&gt;<br />
&lt;servlet-name&gt;InitTest&lt;/servlet-name&gt;<br />
&lt;servlet-class&gt;moreservlets.InitServlet&lt;/servlet-class&gt;<br />
&lt;init-param&gt;<br />
&lt;param-name&gt;firstName&lt;/param-name&gt;<br />
&lt;param-value&gt;Larry&lt;/param-value&gt;<br />
&lt;/init-param&gt;<br />
&lt;init-param&gt;<br />
&lt;param-name&gt;emailAddress&lt;/param-name&gt;<br />
&lt;param-value&gt;</font><a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#69;&#108;&#108;&#105;&#115;&#111;&#110;&#64;&#77;&#105;&#99;&#114;&#111;&#115;&#111;&#102;&#116;&#46;&#99;&#111;&#109;"><font size="2">Ellison@Microsoft.com</font></a><font size="2">&lt;/param-value&gt;<br />
&lt;/init-param&gt;<br />
&lt;/servlet&gt;<br />
&lt;!-- ... --&gt;<br />
&lt;/web-app&gt;<br />
<br />
5.2 分配JSP初始化参数<br />
给JSP页面提供初始化参数在三个方面不同于给servlet提供初始化参数。<br />
1）使用jsp-file而不是servlet-class。因此，WEB-INF/web.xml文件的servlet元素如下所示：<br />
&lt;servlet&gt;<br />
&lt;servlet-name&gt;PageName&lt;/servlet-name&gt;<br />
&lt;jsp-file&gt;/RealPage.jsp&lt;/jsp-file&gt;<br />
&lt;init-param&gt;<br />
&lt;param-name&gt;...&lt;/param-name&gt;<br />
&lt;param-value&gt;...&lt;/param-value&gt;<br />
&lt;/init-param&gt;<br />
...<br />
&lt;/servlet&gt;<br />
2) 几乎总是分配一个明确的URL模式。对servlet，一般相应地使用以</font><a href="http://host/webAppPrefix/servlet/" target="_blank"><font size="2">http://host/webAppPrefix/servlet/</font></a><font size="2"> 开始的缺省URL。只需记住，使用注册名而不是原名称即可。这对于JSP页面在技术上也是合法的。例如，在上面给出的例子中，可用URL </font><a href="http://host/webAppPrefix/servlet/PageName" target="_blank"><font size="2">http://host/webAppPrefix/servlet/PageName</font></a><font size="2"> 访问RealPage.jsp的对初始化参数具有访问权的版本。但在用于JSP页面时，许多用户似乎不喜欢应用常规的servlet的URL。此外，如果 JSP页面位于服务器为其提供了目录清单的目录中（如，一个既没有index.html也没有index.jsp文件的目录），则用户可能会连接到此 JSP页面，单击它，从而意外地激活未初始化的页面。因此，好的办法是使用url-pattern（5.3节）将JSP页面的原URL与注册的 servlet名相关联。这样，客户机可使用JSP页面的普通名称，但仍然激活定制的版本。例如，给定来自项目1的servlet定义，可使用下面的 servlet-mapping定义：<br />
&lt;servlet-mapping&gt;<br />
&lt;servlet-name&gt;PageName&lt;/servlet-name&gt;<br />
&lt;url-pattern&gt;/RealPage.jsp&lt;/url-pattern&gt;<br />
&lt;/servlet-mapping&gt;<br />
3）JSP页使用jspInit而不是init。自动从JSP页面建立的servlet或许已经使用了inti方法。因此，使用JSP声明提供一个init方法是不合法的，必须制定jspInit方法。<br />
为了说明初始化JSP页面的过程，程序清单5-9给出了一个名为InitPage.jsp的JSP页面，它包含一个jspInit方法且放置于 deployDemo Web应用层次结构的顶层。一般，</font><a href="http://host/deployDemo/InitPage.jsp" target="_blank"><font size="2">http://host/deployDemo/InitPage.jsp</font></a><font size="2"> 形式的URL将激活此页面的不具有初始化参数访问权的版本，从而将对firstName和emailAddress变量显示null。但是， web.xml文件（程序清单5-10）分配了一个注册名，然后将该注册名与URL模式/InitPage.jsp相关联。<br />
<br />
程序清单5-9 InitPage.jsp<br />
&lt;!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"&gt;<br />
&lt;HTML&gt;<br />
&lt;HEAD&gt;&lt;TITLE&gt;JSP Init Test&lt;/TITLE&gt;&lt;/HEAD&gt;<br />
&lt;BODY BGCOLOR="#FDF5E6"&gt;<br />
&lt;H2&gt;Init Parameters:&lt;/H2&gt;<br />
&lt;UL&gt;<br />
&lt;LI&gt;First name: &lt;%= firstName %&gt;<br />
&lt;LI&gt;Email address: &lt;%= emailAddress %&gt;<br />
&lt;/UL&gt;<br />
&lt;/BODY&gt;&lt;/HTML&gt;<br />
&lt;%!<br />
private String firstName, emailAddress;<br />
<br />
public void jspInit() {<br />
ServletConfig config = getServletConfig();<br />
firstName = config.getInitParameter("firstName");<br />
emailAddress = config.getInitParameter("emailAddress");<br />
}<br />
%&gt;<br />
<br />
<br />
程序清单5-10 web.xml（说明JSP页面的init参数的摘录）<br />
&lt;?xml version="1.0" encoding="ISO-8859-1"?&gt;<br />
&lt;!DOCTYPE web-app<br />
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"<br />
"</font><a href="http://java.sun.com/dtd/web-app_2_3.dtd" target="_blank"><font size="2">http://java.sun.com/dtd/web-app_2_3.dtd</font></a><font size="2">"&gt;<br />
<br />
&lt;web-app&gt;<br />
&lt;!-- ... --&gt;<br />
&lt;servlet&gt;<br />
&lt;servlet-name&gt;InitPage&lt;/servlet-name&gt;<br />
&lt;jsp-file&gt;/InitPage.jsp&lt;/jsp-file&gt;<br />
&lt;init-param&gt;<br />
&lt;param-name&gt;firstName&lt;/param-name&gt;<br />
&lt;param-value&gt;Bill&lt;/param-value&gt;<br />
&lt;/init-param&gt;<br />
&lt;init-param&gt;<br />
&lt;param-name&gt;emailAddress&lt;/param-name&gt;<br />
&lt;param-value&gt;</font><a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#103;&#97;&#116;&#101;&#115;&#64;&#111;&#114;&#97;&#99;&#108;&#101;&#46;&#99;&#111;&#109;"><font size="2">gates@oracle.com</font></a><font size="2">&lt;/param-value&gt;<br />
&lt;/init-param&gt;<br />
&lt;/servlet&gt;<br />
&lt;!-- ... --&gt; <br />
&lt;servlet-mapping&gt;<br />
&lt;servlet-name&gt; InitPage&lt;/servlet-name&gt;<br />
&lt;url-pattern&gt;/InitPage.jsp&lt;/url-pattern&gt;<br />
&lt;/servlet-mapping&gt;<br />
&lt;!-- ... --&gt;<br />
&lt;/web-app&gt;<br />
<br />
<br />
5.3 提供应用范围内的初始化参数<br />
一般，对单个地servlet或JSP页面分配初始化参数。指定的servlet或JSP页面利用ServletConfig的getInitParameter方法读取这些参数。但是，在某些情形下，希望提供可由任意servlet或JSP页面借助ServletContext的getInitParameter方法读取的系统范围内的初始化参数。<br />
可利用context-param元素声明这些系统范围内的初始化值。context-param元素应该包含param-name、param-value以及可选的description子元素，如下所示：<br />
&lt;context-param&gt;<br />
&lt;param-name&gt;support-email&lt;/param-name&gt;<br />
&lt;param-value&gt;</font><a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#98;&#108;&#97;&#99;&#107;&#104;&#111;&#108;&#101;&#64;&#109;&#121;&#99;&#111;&#109;&#112;&#97;&#110;&#121;&#46;&#99;&#111;&#109;"><font size="2">blackhole@mycompany.com</font></a><font size="2">&lt;/param-value&gt;<br />
&lt;/context-param&gt;<br />
可回忆一下，为了保证可移植性，web.xml内的元素必须以正确的次序声明。但这里应该注意，context-param元素必须出现任意与文档有关的元素（icon、display-name或description）之后及filter、filter-mapping、listener或 servlet元素之前。<br />
5.4 在服务器启动时装载servlet<br />
假如servlet或JSP页面有一个要花很长时间执行的init （servlet）或jspInit（JSP）方法。例如，假如init或jspInit方法从某个数据库或ResourceBundle查找产量。这种情况下，在第一个客户机请求时装载servlet的缺省行为将对第一个客户机产生较长时间的延迟。因此，可利用servlet的load-on- startup元素规定服务器在第一次启动时装载servlet。下面是一个例子。<br />
&lt;servlet&gt;<br />
&lt;servlet-name&gt; &#8230; &lt;/servlet-name&gt;<br />
&lt;servlet-class&gt; &#8230; &lt;/servlet-class&gt; &lt;!-- Or jsp-file --&gt;<br />
&lt;load-on-startup/&gt;<br />
&lt;/servlet&gt;<br />
可以为此元素体提供一个整数而不是使用一个空的load-on-startup。想法是服务器应该在装载较大数目的servlet或JSP页面之前装载较少数目的servlet或JSP页面。例如，下面的servlet项（放置在Web应用的WEB-INF目录下的web.xml文件中的web-app元素内）将指示服务器首先装载和初始化SearchServlet，然后装载和初始化由位于Web应用的result目录中的index.jsp文件产生的 servlet。<br />
&lt;servlet&gt;<br />
&lt;servlet-name&gt;Search&lt;/servlet-name&gt;<br />
&lt;servlet-class&gt;myPackage.SearchServlet&lt;/servlet-class&gt; &lt;!-- Or jsp-file --&gt;<br />
&lt;load-on-startup&gt;1&lt;/load-on-startup&gt;<br />
&lt;/servlet&gt;<br />
&lt;servlet&gt;<br />
&lt;servlet-name&gt;Results&lt;/servlet-name&gt;<br />
&lt;servlet-class&gt;/results/index.jsp&lt;/servlet-class&gt; &lt;!-- Or jsp-file --&gt;<br />
&lt;load-on-startup&gt;2&lt;/load-on-startup&gt;<br />
&lt;/servlet&gt;<br />
<br />
6 声明过滤器<br />
<br />
servlet版本2.3引入了过滤器的概念。虽然所有支持servlet API版本2.3的服务器都支持过滤器，但为了使用与过滤器有关的元素，必须在web.xml中使用版本2.3的DTD。<br />
过滤器可截取和修改进入一个servlet或JSP页面的请求或从一个servlet或JSP页面发出的相应。在执行一个servlet或JSP页面之前，必须执行第一个相关的过滤器的doFilter方法。在该过滤器对其FilterChain对象调用doFilter时，执行链中的下一个过滤器。如果没有其他过滤器，servlet或JSP页面被执行。过滤器具有对到来的ServletRequest对象的全部访问权，因此，它们可以查看客户机名、查找到来的cookie等。为了访问servlet或JSP页面的输出，过滤器可将响应对象包裹在一个替身对象（stand-in object）中，比方说把输出累加到一个缓冲区。在调用FilterChain对象的doFilter方法之后，过滤器可检查缓冲区，如有必要，就对它进行修改，然后传送到客户机。<br />
例如，程序清单5-11帝国难以了一个简单的过滤器，只要访问相关的servlet或JSP页面，它就截取请求并在标准输出上打印一个报告（开发过程中在桌面系统上运行时，大多数服务器都可以使用这个过滤器）。<br />
<br />
程序清单5-11 ReportFilter.java<br />
package moreservlets;<br />
<br />
import java.io.*;<br />
import javax.servlet.*;<br />
import javax.servlet.http.*;<br />
import java.util.*;<br />
<br />
/** Simple filter that prints a report on the standard output <br />
* whenever the associated servlet or JSP page is accessed.<br />
* &lt;P&gt;<br />
* Taken from More Servlets and JavaServer Pages<br />
* from Prentice Hall and Sun Microsystems Press,<br />
* </font><a href="http://www.moreservlets.com/." target="_blank"><font size="2">http://www.moreservlets.com/.</font></a><br />
<font size="2">* &#169; 2002 Marty Hall; may be freely used or adapted.<br />
*/<br />
<br />
public class ReportFilter implements Filter {<br />
public void doFilter(ServletRequest request,<br />
ServletResponse response,<br />
FilterChain chain)<br />
throws ServletException, IOException {<br />
HttpServletRequest req = (HttpServletRequest)request;<br />
System.out.println(req.getRemoteHost() +<br />
" tried to access " +<br />
req.getRequestURL() +<br />
" on " + new Date() + ".");<br />
chain.doFilter(request,response);<br />
}<br />
<br />
public void init(FilterConfig config)<br />
throws ServletException {<br />
}<br />
<br />
public void destroy() {}<br />
}<br />
<br />
一旦建立了一个过滤器，可以在web.xml中利用filter元素以及filter-name（任意名称）、file-class（完全限定的类名）和（可选的）init-params子元素声明它。请注意，元素在web.xml的web-app元素中出现的次序不是任意的；允许服务器（但不是必需的）强制所需的次序，并且实际中有些服务器也是这样做的。但这里要注意，所有filter元素必须出现在任意filter-mapping元素之前， filter-mapping元素又必须出现在所有servlet或servlet-mapping元素之前。<br />
例如，给定上述的ReportFilter类，可在web.xml中作出下面的filter声明。它把名称Reporter与实际的类ReportFilter（位于moreservlets程序包中）相关联。<br />
&lt;filter&gt;<br />
&lt;filter-name&gt;Reporter&lt;/filter-name&gt;<br />
&lt;filter-class&gt;moresevlets.ReportFilter&lt;/filter-class&gt;<br />
&lt;/filter&gt;<br />
一旦命名了一个过滤器，可利用filter-mapping元素把它与一个或多个servlet或JSP页面相关联。关于此项工作有两种选择。<br />
首先，可使用filter-name和servlet-name子元素把此过滤器与一个特定的servlet名（此servlet名必须稍后在相同的 web.xml文件中使用servlet元素声明）关联。例如，下面的程序片断指示系统只要利用一个定制的URL访问名为SomeServletName 的servlet或JSP页面，就运行名为Reporter的过滤器。<br />
&lt;filter-mapping&gt;<br />
&lt;filter-name&gt;Reporter&lt;/filter-name&gt;<br />
&lt;servlet-name&gt;SomeServletName&lt;/servlet-name&gt;<br />
&lt;/filter-mapping&gt;<br />
其次，可利用filter-name和url-pattern子元素将过滤器与一组servlet、JSP页面或静态内容相关联。例如，相面的程序片段指示系统只要访问Web应用中的任意URL，就运行名为Reporter的过滤器。<br />
&lt;filter-mapping&gt;<br />
&lt;filter-name&gt;Reporter&lt;/filter-name&gt;<br />
&lt;url-pattern&gt;/*&lt;/url-pattern&gt;<br />
&lt;/filter-mapping&gt;<br />
例如，程序清单5-12给出了将ReportFilter过滤器与名为PageName的servlet相关联的web.xml文件的一部分。名字 PageName依次又与一个名为TestPage.jsp的JSP页面以及以模式http: //host/webAppPrefix/UrlTest2/ 开头的URL相关联。TestPage.jsp的源代码已经JSP页面命名的谈论在前面的3节"分配名称和定制的URL"中给出。事实上，程序清单5- 12中的servlet和servlet-name项从该节原封不动地拿过来的。给定这些web.xml项，可看到下面的标准输出形式的调试报告（换行是为了容易阅读）。<br />
audit.irs.gov tried to access <br />
</font><a href="http://mycompany.com/deployDemo/UrlTest2/business/tax-plan.html" target="_blank"><font size="2">http://mycompany.com/deployDemo/UrlTest2/business/tax-plan.html</font></a><br />
<font size="2">on Tue Dec 25 13:12:29 EDT 2001.<br />
<br />
程序清单5-12 Web.xml（说明filter用法的摘录）<br />
&lt;?xml version="1.0" encoding="ISO-8859-1"?&gt;<br />
&lt;!DOCTYPE web-app<br />
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"<br />
"</font><a href="http://java.sun.com/dtd/web-app_2_3.dtd" target="_blank"><font size="2">http://java.sun.com/dtd/web-app_2_3.dtd</font></a><font size="2">"&gt;<br />
<br />
&lt;web-app&gt;<br />
&lt;filter&gt;<br />
&lt;filter-name&gt;Reporter&lt;/filter-name&gt;<br />
&lt;filter-class&gt;moresevlets.ReportFilter&lt;/filter-class&gt;<br />
&lt;/filter&gt;<br />
&lt;!-- ... --&gt;<br />
&lt;filter-mapping&gt;<br />
&lt;filter-name&gt;Reporter&lt;/filter-name&gt;<br />
&lt;servlet-name&gt;PageName&lt;/servlet-name&gt;<br />
&lt;/filter-mapping&gt;<br />
&lt;!-- ... --&gt;<br />
&lt;servlet&gt;<br />
&lt;servlet-name&gt;PageName&lt;/servlet-name&gt;<br />
&lt;jsp-file&gt;/RealPage.jsp&lt;/jsp-file&gt;<br />
&lt;/servlet&gt;<br />
&lt;!-- ... --&gt;<br />
&lt;servlet-mapping&gt;<br />
&lt;servlet-name&gt; PageName &lt;/servlet-name&gt;<br />
&lt;url-pattern&gt;/UrlTest2/*&lt;/url-pattern&gt;<br />
&lt;/servlet-mapping&gt;<br />
&lt;!-- ... --&gt;<br />
&lt;/web-app&gt;<br />
<br />
<br />
7 指定欢迎页<br />
<br />
假如用户提供了一个像http: //host/webAppPrefix/directoryName/ 这样的包含一个目录名但没有包含文件名的URL，会发生什么事情呢？用户能得到一个目录表？一个错误？还是标准文件的内容？如果得到标准文件内容，是 index.html、index.jsp、default.html、default.htm或别的什么东西呢？<br />
Welcome-file-list 元素及其辅助的welcome-file元素解决了这个模糊的问题。例如，下面的web.xml项指出，如果一个URL给出一个目录名但未给出文件名，服务器应该首先试用index.jsp，然后再试用index.html。如果两者都没有找到，则结果有赖于所用的服务器（如一个目录列表）。<br />
&lt;welcome-file-list&gt;<br />
&lt;welcome-file&gt;index.jsp&lt;/welcome-file&gt;<br />
&lt;welcome-file&gt;index.html&lt;/welcome-file&gt;<br />
&lt;/welcome-file-list&gt;<br />
虽然许多服务器缺省遵循这种行为，但不一定必须这样。因此，明确地使用welcom-file-list保证可移植性是一种良好的习惯。<br />
<br />
8 指定处理错误的页面<br />
<br />
现在我了解到，你在开发servlet和JSP页面时从不会犯错误，而且你的所有页面是那样的清晰，一般的程序员都不会被它们的搞糊涂。但是，是人总会犯错误的，用户可能会提供不合规定的参数，使用不正确的URL或者不能提供必需的表单字段值。除此之外，其它开发人员可能不那么细心，他们应该有些工具来克服自己的不足。<br />
error-page元素就是用来克服这些问题的。它有两个可能的子元素，分别是：error-code和exception- type。第一个子元素error-code指出在给定的HTTP错误代码出现时使用的URL。第二个子元素excpetion-type指出在出现某个给定的Java异常但未捕捉到时使用的URL。error-code和exception-type都利用location元素指出相应的URL。此 URL必须以/开始。location所指出的位置处的页面可通过查找HttpServletRequest对象的两个专门的属性来访问关于错误的信息，这两个属性分别是：javax.servlet.error.status_code和javax.servlet.error.message。<br />
可回忆一下，在web.xml内以正确的次序声明web-app的子元素很重要。这里只要记住，error-page出现在web.xml文件的末尾附近，servlet、servlet-name和welcome-file-list之后即可。<br />
<br />
8.1 error-code元素<br />
为了更好地了解error-code元素的值，可考虑一下如果不正确地输入文件名，大多数站点会作出什么反映。这样做一般会出现一个404错误信息，它表示不能找到该文件，但几乎没提供更多有用的信息。另一方面，可以试一下在</font><a href="http://www.microsoft.com/" target="_blank"><font size="2">www.microsoft.com</font></a><font size="2">、</font><a href="http://www.ibm.com/" target="_blank"><font size="2">www.ibm.com</font></a><font size="2"> 处或者特别是在</font><a href="http://www.bea.com/" target="_blank"><font size="2">www.bea.com</font></a><font size="2"> 处输出未知的文件名。这是会得出有用的消息，这些消息提供可选择的位置，以便查找感兴趣的页面。提供这样有用的错误页面对于Web应用来说是很有价值得。事实上rm-error-page子元素）。由form-login-page给出的HTML表单必须具有一个j_security_check的 ACTION属性、一个名为j_username的用户名文本字段以及一个名为j_password的口令字段。<br />
例如，程序清单5-19指示服务器使用基于表单的验证。Web应用的顶层目录中的一个名为login.jsp的页面将收集用户名和口令，并且失败的登陆将由相同目录中名为login-error.jsp的页面报告。<br />
<br />
程序清单5-19 web.xml（说明login-config的摘录）<br />
&lt;?xml version="1.0" encoding="ISO-8859-1"?&gt;<br />
&lt;!DOCTYPE web-app<br />
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"<br />
"</font><a href="http://java.sun.com/dtd/web-app_2_3.dtd" target="_blank"><font size="2">http://java.sun.com/dtd/web-app_2_3.dtd</font></a><font size="2">"&gt;<br />
<br />
&lt;web-app&gt;<br />
&lt;!-- ... --&gt;<br />
&lt;security-constraint&gt; ... &lt;/security-constraint&gt;<br />
&lt;login-config&gt;<br />
&lt;auth-method&gt; FORM &lt;/auth-method&gt;<br />
&lt;form-login-config&gt;<br />
&lt;form-login-page&gt;/login.jsp&lt;/form-login-page&gt;<br />
&lt;form-error-page&gt;/login-error.jsp&lt;/form-error-page&gt;<br />
&lt;/form-login-config&gt;<br />
&lt;/login-config&gt;<br />
&lt;!-- ... --&gt;<br />
&lt;/web-app&gt;<br />
<br />
<br />
9.2 限制对Web资源的访问<br />
现在，可以指示服务器使用何种验证方法了。"了不起，"你说道，"除非我能指定一个来收到保护的 URL，否则没有多大用处。"没错。指出这些URL并说明他们应该得到何种保护正是security-constriaint元素的用途。此元素在 web.xml中应该出现在login-config的紧前面。它包含是个可能的子元素，分别是：web-resource-collection、 auth-constraint、user-data-constraint和display-name。下面各小节对它们进行介绍。<br />
l web-resource-collection<br />
此元素确定应该保护的资源。所有security-constraint元素都必须包含至少一个web-resource-collection项。此元素由一个给出任意标识名称的web-resource-name元素、一个确定应该保护的URL的url-pattern元素、一个指出此保护所适用的 HTTP命令（GET、POST等，缺省为所有方法）的http-method元素和一个提供资料的可选description元素组成。例如，下面的 Web-resource-collection项（在security-constratint元素内）指出Web应用的proprietary目录中所有文档应该受到保护。<br />
&lt;security-constraint&gt;<br />
&lt;web-resource-coolection&gt;<br />
&lt;web-resource-name&gt;Proprietary&lt;/web-resource-name&gt;<br />
&lt;url-pattern&gt;/propritary/*&lt;/url-pattern&gt;<br />
&lt;/web-resource-coolection&gt;<br />
&lt;!-- ... --&gt;<br />
&lt;/security-constraint&gt;<br />
重要的是应该注意到，url-pattern仅适用于直接访问这些资源的客户机。特别是，它不适合于通过MVC体系结构利用 RequestDispatcher来访问的页面，或者不适合于利用类似jsp:forward的手段来访问的页面。这种不匀称如果利用得当的话很有好处。例如，servlet可利用MVC体系结构查找数据，把它放到bean中，发送请求到从bean中提取数据的JSP页面并显示它。我们希望保证决不直接访问受保护的JSP页面，而只是通过建立该页面将使用的bean的servlet来访问它。url-pattern和auth-contraint元素可通过声明不允许任何用户直接访问JSP页面来提供这种保证。但是，这种不匀称的行为可能让开发人员放松警惕，使他们偶然对应受保护的资源提供不受限制的访问。 <br />
l auth-constraint<br />
尽管web-resource-collention元素质出了哪些URL应该受到保护，但是auth-constraint元素却指出哪些用户应该具有受保护资源的访问权。此元素应该包含一个或多个标识具有访问权限的用户类别role- name元素，以及包含（可选）一个描述角色的description元素。例如，下面web.xml中的security-constraint元素部门规定只有指定为Administrator或Big Kahuna（或两者）的用户具有指定资源的访问权。<br />
&lt;security-constraint&gt;<br />
&lt;web-resource-coolection&gt; ... &lt;/web-resource-coolection&gt;<br />
&lt;auth-constraint&gt;<br />
&lt;role-name&gt;administrator&lt;/role-name&gt;<br />
&lt;role-name&gt;kahuna&lt;/role-name&gt;<br />
&lt;/auth-constraint&gt;<br />
&lt;/security-constraint&gt;<br />
重要的是认识到，到此为止，这个过程的可移植部分结束了。服务器怎样确定哪些用户处于任何角色以及它怎样存放用户的口令，完全有赖于具体的系统。<br />
例如，Tomcat使用install_dir/conf/tomcat-users.xml将用户名与角色名和口令相关联，正如下面例子中所示，它指出用户joe（口令bigshot）和jane（口令enaj）属于administrator和kahuna角色。<br />
&lt;tomcat-users&gt;<br />
&lt;user name="joe" password="bigshot" roles="administrator,kahuna" /&gt;<br />
&lt;user name="jane" password="enaj" roles="kahuna" /&gt;<br />
&lt;/tomcat-users&gt;<br />
l user-data-constraint<br />
这个可选的元素指出在访问相关资源时使用任何传输层保护。它必须包含一个transport-guarantee子元素（合法值为NONE、 INTEGRAL或CONFIDENTIAL），并且可选地包含一个description元素。transport-guarantee为NONE值将对所用的通讯协议不加限制。INTEGRAL值表示数据必须以一种防止截取它的人阅读它的方式传送。虽然原理上（并且在未来的HTTP版本中），在 INTEGRAL和CONFIDENTIAL之间可能会有差别，但在当前实践中，他们都只是简单地要求用SSL。例如，下面指示服务器只允许对相关资源做 HTTPS连接：<br />
&lt;security-constraint&gt;<br />
&lt;!-- ... --&gt;<br />
&lt;user-data-constraint&gt;<br />
&lt;transport-guarantee&gt;CONFIDENTIAL&lt;/transport-guarantee&gt;<br />
&lt;/user-data-constraint&gt;<br />
&lt;/security-constraint&gt;<br />
l display-name<br />
security-constraint的这个很少使用的子元素给予可能由GUI工具使用的安全约束项一个名称。<br />
9.3 分配角色名<br />
迄今为止，讨论已经集中到完全由容器（服务器）处理的安全问题之上了。但servlet以及JSP页面也能够处理它们自己的安全问题。<br />
例如，容器可能允许用户从bigwig或bigcheese角色访问一个显示主管人员额外紧贴的页面，但只允许bigwig用户修改此页面的参数。完成这种更细致的控制的一种常见方法是调用HttpServletRequset的isUserInRole方法，并据此修改访问。<br />
Servlet的 security-role-ref子元素提供出现在服务器专用口令文件中的安全角色名的一个别名。例如，假如编写了一个调用 request.isUserInRole（"boss"）的servlet，但后来该servlet被用在了一个其口令文件调用角色manager而不是boss的服务器中。下面的程序段使该servlet能够使用这两个名称中的任何一个。<br />
&lt;servlet&gt;<br />
&lt;!-- ... --&gt;<br />
&lt;security-role-ref&gt;<br />
&lt;role-name&gt;boss&lt;/role-name&gt; &lt;!-- New alias --&gt;<br />
&lt;role-link&gt;manager&lt;/role-link&gt; &lt;!-- Real name --&gt;<br />
&lt;/security-role-ref&gt;<br />
&lt;/servlet&gt;<br />
也可以在web-app内利用security-role元素提供将出现在role-name元素中的所有安全角色的一个全局列表。分别地生命角色使高级IDE容易处理安全信息。<br />
<br />
10 控制会话超时<br />
<br />
如果某个会话在一定的时间内未被访问，服务器可把它扔掉以节约内存。可利用HttpSession的setMaxInactiveInterval方法直接设置个别会话对象的超时值。如果不采用这种方法，则缺省的超时值由具体的服务器决定。但可利用session-config和session- timeout元素来给出一个适用于所有服务器的明确的超时值。超时值的单位为分钟，因此，下面的例子设置缺省会话超时值为三个小时（180分钟）。<br />
&lt;session-config&gt;<br />
&lt;session-timeout&gt;180&lt;/session-timeout&gt;<br />
&lt;/session-config&gt;<br />
<br />
11 Web应用的文档化<br />
<br />
越来越多的开发环境开始提供servlet和JSP的直接支持。例子有Borland Jbuilder Enterprise Edition、Macromedia UltraDev、Allaire JRun Studio（写此文时，已被Macromedia收购）以及IBM VisuaAge for Java等。<br />
大量的web.xml元素不仅是为服务器设计的，而且还是为可视开发环境设计的。它们包括icon、display-name和discription等。<br />
可回忆一下，在web.xml内以适当地次序声明web-app子元素很重要。不过，这里只要记住icon、display-name和description是web.xml的web-app元素内的前三个合法元素即可。<br />
l icon<br />
icon元素指出GUI工具可用来代表Web应用的一个和两个图像文件。可利用small-icon元素指定一幅16 x 16的GIF或JPEG图像，用large-icon元素指定一幅32 x 32的图像。下面举一个例子： <br />
&lt;icon&gt;<br />
&lt;small-icon&gt;/images/small-book.gif&lt;/small-icon&gt;<br />
&lt;large-icon&gt;/images/tome.jpg&lt;/large-icon&gt;<br />
&lt;/icon&gt;<br />
l display-name<br />
display-name元素提供GUI工具可能会用来标记此Web应用的一个名称。下面是个例子。<br />
&lt;display-name&gt;Rare Books&lt;/display-name&gt;<br />
l description<br />
description元素提供解释性文本，如下所示：<br />
&lt;description&gt;<br />
This Web application represents the store developed for<br />
rare-books.com, an online bookstore specializing in rare<br />
and limited-edition books.<br />
&lt;/description&gt;<br />
<br />
12 关联文件与MIME类型<br />
<br />
服务器一般都具有一种让Web站点管理员将文件扩展名与媒体相关联的方法。例如，将会自动给予名为mom.jpg的文件一个image/jpeg的MIME 类型。但是，假如你的Web应用具有几个不寻常的文件，你希望保证它们在发送到客户机时分配为某种MIME类型。mime-mapping元素（具有 extension和mime-type子元素）可提供这种保证。例如，下面的代码指示服务器将application/x-fubar的MIME类型分配给所有以.foo结尾的文件。<br />
&lt;mime-mapping&gt;<br />
&lt;extension&gt;foo&lt;/extension&gt;<br />
&lt;mime-type&gt;application/x-fubar&lt;/mime-type&gt;<br />
&lt;/mime-mapping&gt;<br />
或许，你的Web应用希望重载（override）标准的映射。例如，下面的代码将告诉服务器在发送到客户机时指定.ps文件作为纯文本（text/plain）而不是作为PostScript（application/postscript）。<br />
&lt;mime-mapping&gt;<br />
&lt;extension&gt;ps&lt;/extension&gt;<br />
&lt;mime-type&gt;application/postscript&lt;/mime-type&gt;<br />
&lt;/mime-mapping&gt;<br />
<br />
<br />
13 定位TLD<br />
<br />
JSP taglib元素具有一个必要的uri属性，它给出一个TLD（Tag Library Descriptor）文件相对于Web应用的根的位置。TLD文件的实际名称在发布新的标签库版本时可能会改变，但我们希望避免更改所有现有JSP页面。此外，可能还希望使用保持taglib元素的简练性的一个简短的uri。这就是部署描述符文件的taglib元素派用场的所在了。Taglib包含两个子元素：taglib-uri和taglib-location。taglib-uri元素应该与用于JSP taglib元素的uri属性的东西相匹配。Taglib-location元素给出TLD文件的实际位置。例如，假如你将文件chart-tags- 1.3beta.tld放在WebApp/WEB-INF/tlds中。现在，假如web.xml在web-app元素内包含下列内容。<br />
&lt;taglib&gt;<br />
&lt;taglib-uri&gt;/charts.tld&lt;/taglib-uri&gt;<br />
&lt;taglib-location&gt;<br />
/WEB-INF/tlds/chart-tags-1.3beta.tld<br />
&lt;/taglib-location&gt;<br />
&lt;/taglib&gt;<br />
给出这个说明后，JSP页面可通过下面的简化形式使用标签库。<br />
&lt;%@ taglib uri="/charts.tld" prefix="somePrefix" %&gt;<br />
<br />
14 指定应用事件监听程序<br />
<br />
应用事件监听器程序是建立或修改servlet环境或会话对象时通知的类。它们是servlet规范的版本2.3中的新内容。这里只简单地说明用来向Web应用注册一个监听程序的web.xml的用法。<br />
注册一个监听程序涉及在web.xml的web-app元素内放置一个listener元素。在listener元素内，listener-class元素列出监听程序的完整的限定类名，如下所示：<br />
&lt;listener&gt;<br />
&lt;listener-class&gt;package.ListenerClass&lt;/listener-class&gt;<br />
&lt;/listener&gt;<br />
虽然listener元素的结构很简单，但请不要忘记，必须正确地给出web-app元素内的子元素的次序。listener元素位于所有的servlet 元素之前以及所有filter-mapping元素之后。此外，因为应用生存期监听程序是serlvet规范的2.3版本中的新内容，所以必须使用 web.xml DTD的2.3版本，而不是2.2版本。<br />
例如，程序清单5-20给出一个名为ContextReporter的简单的监听程序，只要Web应用的Servlet-Context建立（如装载Web应用）或消除（如服务器关闭）时，它就在标准输出上显示一条消息。程序清单5-21给出此监听程序注册所需要的web.xml文件的一部分。<br />
<br />
程序清单5-20 ContextReporterjava<br />
package moreservlets;<br />
<br />
import javax.servlet.*;<br />
import java.util.*;<br />
<br />
/** Simple listener that prints a report on the standard output <br />
* when the ServletContext is created or destroyed.<br />
* &lt;P&gt;<br />
* Taken from More Servlets and JavaServer Pages<br />
* from Prentice Hall and Sun Microsystems Press,<br />
* </font><a href="http://www.moreservlets.com/." target="_blank"><font size="2">http://www.moreservlets.com/.</font></a><br />
<font size="2">* &#169; 2002 Marty Hall; may be freely used or adapted.<br />
*/<br />
<br />
public class ContextReporter implements ServletContextListener {<br />
public void contextInitialized(ServletContextEvent event) {<br />
System.out.println("Context created on " +<br />
new Date() + ".");<br />
}<br />
<br />
public void contextDestroyed(ServletContextEvent event) {<br />
System.out.println("Context destroyed on " +<br />
new Date() + ".");<br />
}<br />
}<br />
<br />
<br />
程序清单5-21 web.xml（声明一个监听程序的摘录）<br />
&lt;?xml version="1.0" encoding="ISO-8859-1"?&gt;<br />
&lt;!DOCTYPE web-app<br />
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"<br />
"</font><a href="http://java.sun.com/dtd/web-app_2_3.dtd" target="_blank"><font size="2">http://java.sun.com/dtd/web-app_2_3.dtd</font></a><font size="2">"&gt;<br />
<br />
&lt;web-app&gt;<br />
&lt;!-- ... --&gt;<br />
&lt;filter-mapping&gt; &#8230; &lt;/filter-mapping&gt;<br />
&lt;listener&gt;<br />
&lt;listener-class&gt;package.ListenerClass&lt;/listener-class&gt;<br />
&lt;/listener&gt;<br />
&lt;servlet&gt; ... &lt;/servlet&gt;<br />
&lt;!-- ... --&gt;<br />
&lt;/web-app&gt;<br />
<br />
<br />
15 J2EE元素<br />
<br />
本节描述用作J2EE环境组成部分的Web应用的web.xml元素。这里将提供一个简明的介绍，详细内容可以参阅</font><a href="http://java.sun.com/j2ee/j2ee-1_3-fr-spec.pdf" target="_blank"><font size="2">http://java.sun.com/j2ee/j2ee-1_3-fr-spec.pdf</font></a><font size="2">的Java 2 Plantform Enterprise Edition版本1.3规范的第5章。<br />
l distributable<br />
distributable 元素指出，Web应用是以这样的方式编程的：即，支持集群的服务器可安全地在多个服务器上分布Web应用。例如，一个可分布的应用必须只使用 Serializable对象作为其HttpSession对象的属性，而且必须避免用实例变量（字段）来实现持续性。distributable元素直接出现在discription元素之后，并且不包含子元素或数据，它只是一个如下的标志。<br />
&lt;distributable /&gt;<br />
l resource-env-ref<br />
resource -env-ref元素声明一个与某个资源有关的管理对象。此元素由一个可选的description元素、一个resource-env-ref- name元素（一个相对于java:comp/env环境的JNDI名）以及一个resource-env-type元素（指定资源类型的完全限定的类），如下所示：<br />
&lt;resource-env-ref&gt;<br />
&lt;resource-env-ref-name&gt;<br />
jms/StockQueue<br />
&lt;/resource-env-ref-name&gt;<br />
&lt;resource-env-ref-type&gt;<br />
javax.jms.Queue<br />
&lt;/resource-env-ref-type&gt;<br />
&lt;/resource-env-ref&gt;<br />
l env-entry<br />
env -entry元素声明Web应用的环境项。它由一个可选的description元素、一个env-entry-name元素（一个相对于java: comp/env环境JNDI名）、一个env-entry-value元素（项值）以及一个env-entry-type元素（java.lang程序包中一个类型的完全限定类名，java.lang.Boolean、java.lang.String等）组成。下面是一个例子：<br />
&lt;env-entry&gt;<br />
&lt;env-entry-name&gt;minAmout&lt;/env-entry-name&gt;<br />
&lt;env-entry-value&gt;100.00&lt;/env-entry-value&gt;<br />
&lt;env-entry-type&gt;minAmout&lt;/env-entry-type&gt;<br />
&lt;/env-entry&gt;<br />
l ejb-ref<br />
ejb -ref元素声明对一个EJB的主目录的应用。它由一个可选的description元素、一个ejb-ref-name元素（相对于java: comp/env的EJB应用）、一个ejb-ref-type元素（bean的类型，Entity或Session）、一个home元素（bean的主目录接口的完全限定名）、一个remote元素（bean的远程接口的完全限定名）以及一个可选的ejb-link元素（当前bean链接的另一个 bean的名称）组成。<br />
l ejb-local-ref<br />
ejb-local-ref元素声明一个EJB的本地主目录的引用。除了用local-home代替home外，此元素具有与ejb-ref元素相同的属性并以相同的方式使用。<br />
<br />
<br />
<br />
<br />
<br />
<br />
17:42 | 固定链接 | 评论 (0) | 引用通告 (0) | 记录它 | 计算机与 Internet <br />
<br />
<br />
固定链接 关闭 <br />
<br />
</font><a href="http://spaces.msn.com/members/tsfy/Blog/cns!1pFtRRZqZXTCdE5YlUjqVIcQ!116.entry" target="_blank"><font size="2">http://spaces.msn.com/members/tsfy/Blog/cns!1pFtRRZqZXTCdE5YlUjqVIcQ!116.entry</font></a><font size="2"> <br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
4月14日 <br />
<br />
<br />
<br />
给你的session加个监听器 <br />
<br />
<br />
今天一个学生问我怎么实现在网页里显示在线用户的名称——他已经使用了session，但是无法处理用户离开的情况，然后导致在线用户列表的无限增大。跟他说了自己在application中进行超时检查，更新application的时候就比较当前所有列表中的session是否超过自己指定的时间间隔。后来想了想，又给他提了使用给session加监听器的方法。但是提的时候自己也没有做过，所以只是说这种方式很复杂，建议他还是自己进行超时检查。刚才又看了看资料，发现实际上给session加监听器的方式很简单，不禁觉得自己有点误人子弟了，现在将方法写在这，借以告诫自己以后要严谨。<br />
首先写一个SessionBinder类,它实现了HttpSessionBindingListener接口的valueBound方法和valueUnbound方法，示例代码如下：<br />
public class SessionBinder implements HttpSessionBindingListener {<br />
&nbsp; public void valueBound(HttpSessionBindingEvent event){<br />
&nbsp; &nbsp; //you can do anything you want!this method will be called when this binder is bind with any session.<br />
&nbsp; }<br />
<br />
&nbsp; public void valueUnbound(HttpSessionBindingEvent event) {<br />
&nbsp; &nbsp; //you can do something while this session is invalidate<br />
&nbsp; }<br />
}<br />
现在写好了SessionBinder，我们现在选择在一个servlet中向session中加入这个监听器——在jsp中的代码书写与此相同<br />
//省略前面的代码，此操作可能发生在servlet的doGet方法中，也可能是doPost方法中<br />
&nbsp; HttpSession session = req.getSession(true);//首先获得需要加入监听器的session对象，req是HttpRequest对象<br />
&nbsp; SessionBinder sb = new SessionBinder();//建立一个监听器对象<br />
&nbsp; session.putValue("BinderObject",sb);//将监听器加入此session中，从此时开始执行sb的valueBound方法<br />
//省略后面的代码<br />
随后，如果整个session超时或者被用户中止之后，sb的valueUnbound自动执行<br />
呵呵，以上代码以供参考</font><br />
<img src ="http://www.blogjava.net/xinwuhen/aggbug/193043.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/xinwuhen/" target="_blank">心无痕</a> 2008-04-15 11:42 <a href="http://www.blogjava.net/xinwuhen/archive/2008/04/15/193043.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Tomcat启动分析</title><link>http://www.blogjava.net/xinwuhen/archive/2008/04/15/193030.html</link><dc:creator>心无痕</dc:creator><author>心无痕</author><pubD