﻿<?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-CONAN ZONE-文章分类-J2SE</title><link>http://www.blogjava.net/conans/category/32378.html</link><description>你越挣扎我就越兴奋</description><language>zh-cn</language><lastBuildDate>Wed, 10 Aug 2011 08:59:02 GMT</lastBuildDate><pubDate>Wed, 10 Aug 2011 08:59:02 GMT</pubDate><ttl>60</ttl><item><title>log4j详解与实战(转)</title><link>http://www.blogjava.net/conans/articles/355064.html</link><dc:creator>CONAN</dc:creator><author>CONAN</author><pubDate>Tue, 26 Jul 2011 07:03:00 GMT</pubDate><guid>http://www.blogjava.net/conans/articles/355064.html</guid><description><![CDATA[<p>log4j是一个非常强大的log记录软件，下面我们就来看看在项目中如何使log4j。</p>
<p>&nbsp;</p>
<p>首先当然是得到log4j的jar档，推荐使用1.2.X版，下载地址：</p>
<p><a href="http://logging.apache.org/log4j/1.2/download.html">http://logging.apache.org/log4j/1.2/download.html</a> </p>
<p>&nbsp;</p>
<p>我们先看一个最简单的示例：</p>
<p><strong>【示例1】</strong> </p>
<p><span style="font-size: medium; color: #0000ff">项目结构：</span> </p>
<p><img style="border-right: black 1px solid; border-top: black 1px solid; border-left: black 1px solid; border-bottom: black 1px solid" alt="" src="http://www.iteye.com/upload/attachment/99808/5429dd5f-c45b-350c-a40c-307f0a852358.png" /><br /><br />【注：<span style="color: #ff0000">由于这里的多个项目公用一个jar档，我们可以创建一个专门放置jar档的Java工程，然后将jar档放到lib目录下。在要使用的工程中按图所示进行引用</span> 】</p>
<p>&nbsp;</p>
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008080">&nbsp;1</span>&nbsp;<span style="color: #0000ff">package</span><span style="color: #000000">&nbsp;com.coderdream.log4j;<br /></span><span style="color: #008080">&nbsp;2</span>&nbsp;<span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;3</span>&nbsp;<span style="color: #000000"></span><span style="color: #0000ff">import</span><span style="color: #000000">&nbsp;org.apache.log4j.Logger;<br /></span><span style="color: #008080">&nbsp;4</span>&nbsp;<span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;5</span>&nbsp;<span style="color: #000000"></span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;HelloLog4j&nbsp;{<br /></span><span style="color: #008080">&nbsp;6</span>&nbsp;<span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;7</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">private</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">static</span><span style="color: #000000">&nbsp;Logger&nbsp;logger&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;Logger.getLogger(HelloLog4j.</span><span style="color: #0000ff">class</span><span style="color: #000000">);<br /></span><span style="color: #008080">&nbsp;8</span>&nbsp;<span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;9</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">/**</span><span style="color: #008000"><br /></span><span style="color: #008080">10</span>&nbsp;<span style="color: #008000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: #808080">@param</span><span style="color: #008000">&nbsp;args<br /></span><span style="color: #008080">11</span>&nbsp;<span style="color: #008000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">*/</span><span style="color: #000000"><br /></span><span style="color: #008080">12</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">static</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;main(String[]&nbsp;args)&nbsp;{<br /></span><span style="color: #008080">13</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;System.out.println("This&nbsp;is&nbsp;println&nbsp;message.");<br /></span><span style="color: #008080">14</span>&nbsp;<span style="color: #008000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br /></span><span style="color: #008080">15</span>&nbsp;<span style="color: #008000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;记录debug级别的信息</span><span style="color: #008000"><br /></span><span style="color: #008080">16</span>&nbsp;<span style="color: #008000"></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;logger.debug(</span><span style="color: #000000">"</span><span style="color: #000000">This&nbsp;is&nbsp;debug&nbsp;message.</span><span style="color: #000000">"</span><span style="color: #000000">);<br /></span><span style="color: #008080">17</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;记录info级别的信息</span><span style="color: #008000"><br /></span><span style="color: #008080">18</span>&nbsp;<span style="color: #008000"></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;logger.info(</span><span style="color: #000000">"</span><span style="color: #000000">This&nbsp;is&nbsp;info&nbsp;message.</span><span style="color: #000000">"</span><span style="color: #000000">);<br /></span><span style="color: #008080">19</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;记录error级别的信息</span><span style="color: #008000"><br /></span><span style="color: #008080">20</span>&nbsp;<span style="color: #008000"></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;logger.error(</span><span style="color: #000000">"</span><span style="color: #000000">This&nbsp;is&nbsp;error&nbsp;message.</span><span style="color: #000000">"</span><span style="color: #000000">);<br /></span><span style="color: #008080">21</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;}<br /></span><span style="color: #008080">22</span>&nbsp;<span style="color: #000000">}</span></div>
<p><span style="font-size: medium; color: #0000ff">&nbsp;配置文件log4j.properties:</p>
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008080">&nbsp;1</span>&nbsp;<span style="color: #000000">#可以设置级别：debug</span><span style="color: #000000">&gt;</span><span style="color: #000000">info</span><span style="color: #000000">&gt;</span><span style="color: #000000">error<br /></span><span style="color: #008080">&nbsp;2</span>&nbsp;<span style="color: #000000">#debug：显示debug、info、error<br /></span><span style="color: #008080">&nbsp;3</span>&nbsp;<span style="color: #000000">#info：显示info、error<br /></span><span style="color: #008080">&nbsp;4</span>&nbsp;<span style="color: #000000">#error：只error<br /></span><span style="color: #008080">&nbsp;5</span>&nbsp;<span style="color: #000000">log4j.rootLogger</span><span style="color: #000000">=</span><span style="color: #000000">debug,appender1<br /></span><span style="color: #008080">&nbsp;6</span>&nbsp;<span style="color: #000000">#log4j.rootLogger</span><span style="color: #000000">=</span><span style="color: #000000">info,appender1<br /></span><span style="color: #008080">&nbsp;7</span>&nbsp;<span style="color: #000000">#log4j.rootLogger</span><span style="color: #000000">=</span><span style="color: #000000">error,appender1<br /></span><span style="color: #008080">&nbsp;8</span>&nbsp;<span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;9</span>&nbsp;<span style="color: #000000">#输出到控制台<br /></span><span style="color: #008080">10</span>&nbsp;<span style="color: #000000">log4j.appender.appender1</span><span style="color: #000000">=</span><span style="color: #000000">org.apache.log4j.ConsoleAppender<br /></span><span style="color: #008080">11</span>&nbsp;<span style="color: #000000">#样式为TTCCLayout<br /></span><span style="color: #008080">12</span>&nbsp;<span style="color: #000000">log4j.appender.appender1.layout</span><span style="color: #000000">=</span><span style="color: #000000">org.apache.log4j.TTCCLayout</span></div><span style="font-size: small; color: #ff0000">输出结果：</span><br />
<p></span>&nbsp;</p>
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000">[main]&nbsp;DEBUG&nbsp;com.coderdream.log4j.HelloLog4j&nbsp;</span><span style="color: #000000">-</span><span style="color: #000000">&nbsp;This&nbsp;is&nbsp;debug&nbsp;message.<br />[main]&nbsp;INFO&nbsp;com.coderdream.log4j.HelloLog4j&nbsp;</span><span style="color: #000000">-</span><span style="color: #000000">&nbsp;This&nbsp;is&nbsp;info&nbsp;message.<br />[main]&nbsp;ERROR&nbsp;com.coderdream.log4j.HelloLog4j&nbsp;</span><span style="color: #000000">-</span><span style="color: #000000">&nbsp;This&nbsp;is&nbsp;error&nbsp;message.</span></div>
<p><br />&nbsp;</p>
<p>通过配置文件可知，我们需要配置3个方面的内容：</p>
<p>1、根目录（级别和目的地）；</p>
<p>2、目的地（控制台、文件等等）；</p>
<p>3、输出样式。</p>
<p><strong><span style="font-size: medium; color: #0000ff"><br />下面我们来看看Log4J的类图：</span> </strong></p>
<p><br /><img style="border-right: black 1px solid; border-top: black 1px solid; border-left: black 1px solid; border-bottom: black 1px solid" alt="" src="http://www.iteye.com/upload/attachment/99825/3889d0d4-9d5a-3af3-8b20-926b0a043666.png" /></p>
<p>&nbsp;</p>
<p><strong>Logger - 日志写出器，供程序员输出日志信息 </strong><br /><strong>Appender - 日志目的地，把格式化好的日志信息输出到指定的地方去 </strong><br />ConsoleAppender - 目的地为控制台的Appender <br />FileAppender - 目的地为文件的Appender <br />RollingFileAppender - 目的地为大小受限的文件的Appender <br /><strong>Layout - 日志格式化器，用来把程序员的logging request格式化成字符串</strong> <br />PatternLayout - 用指定的pattern格式化logging request的Layout </p>
<p><span lang="EN-US"><span style="font-size: medium"><strong><span style="color: #0000ff"><br /><span style="color: #000000">Log4j基本使用方法</span> </span></strong></span><br /><br />　　Log4j由三个重要的组件构成：日志信息的优先级，日志信息的输出目的地，日志信息的输出格式。日志信息的优先级从高到低有ERROR、WARN、 INFO、DEBUG，分别用来指定这条日志信息的重要程度；日志信息的输出目的地指定了日志将打印到控制台还是文件中；而输出格式则控制了日志信息的显示内容。<br /><br />　　<strong><span style="font-size: medium; color: #0000ff">一、定义配置文件</span> </strong><br /><br />　　其实您也可以完全不使用配置文件，而是在代码中配置Log4j环境。但是，使用配置文件将使您的应用程序更加灵活。Log4j支持两种配置文件格式，一种是XML格式的文件，一种是Java特性文件（键=值）。下面我们介绍使用Java特性文件做为配置文件的方法：<br /><br />　　<span style="font-size: small; color: #0000ff">1.配置根Logger，其语法为：</span> <br /><br />　　log4j.rootLogger = [ level ] , appenderName, appenderName, &#8230;<br /><br />　　其中，level 是日志记录的优先级，分为OFF、FATAL、ERROR、WARN、INFO、DEBUG、ALL或者您定义的级别。Log4j建议只使用四个级别，优先级从高到低分别是ERROR、WARN、INFO、DEBUG。通过在这里定义的级别，您可以控制到应用程序中相应级别的日志信息的开关。比如在这里定义了INFO级别，则应用程序中所有DEBUG级别的日志信息将不被打印出来。 appenderName就是指B日志信息输出到哪个地方。您可以同时指定多个输出目的地。<br /><br />　　<span style="font-size: small; color: #0000ff">2.配置日志信息输出目的地Appender，其语法为：</span> <br /><br />　　log4j.appender.appenderName = fully.qualified.name.of.appender.class<br />　　log4j.appender.appenderName.option1 = value1<br />　　&#8230;<br />　　log4j.appender.appenderName.option = valueN<br /><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 /><br />　　<span style="font-size: small; color: #0000ff">3.配置日志信息的格式（布局），其语法为：</span> <br /><br />　　log4j.appender.appenderName.layout = fully.qualified.name.of.layout.class<br />　　log4j.appender.appenderName.layout.option1 = value1<br />　　&#8230;<br />　　log4j.appender.appenderName.layout.option = valueN<br /><br />　　其中，Log4j提供的layout有以e几种：<br />　　org.apache.log4j.HTMLLayout（以HTML表格形式布局），<br />　　org.apache.log4j.PatternLayout（可以灵活地指定布局模式），<br />　　org.apache.log4j.SimpleLayout（包含日志信息的级别和信息字符串），<br />　　org.apache.log4j.TTCCLayout（包含日志产生的时间、线程、类别等等信息）<br /><br />　　Log4J采用类似C语言中的printf函数的打印格式格式化日志信息，打印参数如下： %m 输出代码中指定的消息<br /><br />　　%p 输出优先级，即DEBUG，INFO，WARN，ERROR，FATAL<br />　　%r 输出自应用启动到输出该log信息耗费的毫秒数<br />　　%c 输出所属的类目，通常就是所在类的全名<br />　　%t 输出产生该日志事件的线程名<br />　　%n 输出一个回车换行符，Windows平台为&#8220;rn&#8221;，Unix平台为&#8220;n&#8221;<br />　　%d 输出日志时间点的日期或时间，默认格式为ISO8601，也可以在其后指定格式，比如：%d{yyy MMM dd HH:mm:ss,SSS}，输出类似：2002年10月18日 22：10：28，921<br />　　%l 输出日志事件的发生位置，包括类目名、发生的线程，以及在代码中的行数。举例：Testlog4.main(TestLog4.java:10)<br /><br />　　<span style="color: #0000ff"><strong><span style="font-size: medium">二、在代码中使用Log4j</span> </strong></span><br /><br />　　<span style="font-size: medium; color: #0000ff">1.得到记录器</span> <br /><br />　　使用Log4j，第一步就是获取日志记录器，这个记录器将负责控制日志信息。其语法为：<br /><br />　　public static Logger getLogger( String name)<br /><br />　　通过指定的名字获得记录器，如果必要的话，则为这个名字创建一个新的记录器。Name一般取本类的名字，比如：<br /><br />　　static Logger logger = Logger.getLogger ( ServerWithLog4j.class.getName () )<br /><br />　　<span style="font-size: medium; color: #0000ff">2.读取配置文件</span> <br /><br />　　当获得了日志记录器之后，第二步将配置Log4j环境，其语法为：<br /><br />　　BasicConfigurator.configure ()： 自动快速地使用缺省Log4j环境。<br />　　PropertyConfigurator.configure ( String configFilename) ：读取使用Java的特性文件编写的配置文件。<br />　　DOMConfigurator.configure ( String filename ) ：读取XML形式的配置文件。<br /><br />　　<span style="font-size: medium; color: #0000ff">3.插入记录信息（格式化日志信息）</span> <br /><br />　　当上两个必要步骤执行完毕，您就可以轻松地使用不同优先级别的日志记录语句插入到您想记录日志的任何地方，其语法如下：<br /><br />　　Logger.debug ( Object message ) ;<br />　　Logger.info ( Object message ) ;<br />　　Logger.warn ( Object message ) ;<br />　　Logger.error ( Object message ) ; </span></p>
<p><br />&nbsp;</p>
<p><span style="font-size: medium"><strong>示例2～示例8</strong> </span></p>
<p>&nbsp;</p>
<p><strong>【示例2】</strong> 输出为文本文件或HTML文件</p>
<p>&nbsp;</p>
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000">#设置级别：<br />log4j.rootLogger</span><span style="color: #000000">=</span><span style="color: #000000">debug,appender1<br /><br />#输出到文件(这里默认为追加方式)<br />log4j.appender.appender1</span><span style="color: #000000">=</span><span style="color: #000000">org.apache.log4j.FileAppender<br />#设置文件输出路径<br />#【</span><span style="color: #000000">1</span><span style="color: #000000">】文本文件<br />#log4j.appender.appender1.File</span><span style="color: #000000">=</span><span style="color: #000000">c:</span><span style="color: #000000">/</span><span style="color: #000000">Log4JDemo02.log<br />#【</span><span style="color: #000000">2</span><span style="color: #000000">】HTML文件<br />log4j.appender.appender1.File</span><span style="color: #000000">=</span><span style="color: #000000">c:</span><span style="color: #000000">/</span><span style="color: #000000">Log4JDemo02.html<br />#设置文件输出样式<br />#log4j.appender.appender1.layout</span><span style="color: #000000">=</span><span style="color: #000000">org.apache.log4j.TTCCLayout<br />log4j.appender.appender1.layout</span><span style="color: #000000">=</span><span style="color: #000000">org.apache.log4j.HTMLLayout</span></div>
<p><br /><strong>【</strong> <strong>示例3】</strong> 输出为文本文件或HTML文件</p>
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000">#设置级别和多个目的地<br />log4j.rootLogger</span><span style="color: #000000">=</span><span style="color: #000000">debug,appender1,appender2<br /><br />#输出到控制台<br />log4j.appender.appender1</span><span style="color: #000000">=</span><span style="color: #000000">org.apache.log4j.ConsoleAppender<br />#设置输出样式<br />log4j.appender.appender1.layout</span><span style="color: #000000">=</span><span style="color: #000000">org.apache.log4j.TTCCLayout<br /><br />#输出到文件(这里默认为追加方式)<br />log4j.appender.appender2</span><span style="color: #000000">=</span><span style="color: #000000">org.apache.log4j.FileAppender<br />#设置文件输出路径<br />#【</span><span style="color: #000000">1</span><span style="color: #000000">】文本文件<br />#log4j.appender.appender2.File</span><span style="color: #000000">=</span><span style="color: #000000">c:</span><span style="color: #000000">/</span><span style="color: #000000">Log4JDemo02.log<br />#【</span><span style="color: #000000">2</span><span style="color: #000000">】HTML文件<br />log4j.appender.appender2.File</span><span style="color: #000000">=</span><span style="color: #000000">c:</span><span style="color: #000000">/</span><span style="color: #000000">Log4JDemo02.html<br />#设置文件输出样式<br />#log4j.appender.appender2.layout</span><span style="color: #000000">=</span><span style="color: #000000">org.apache.log4j.TTCCLayout<br />log4j.appender.appender2.layout</span><span style="color: #000000">=</span><span style="color: #000000">org.apache.log4j.HTMLLayout</span></div><strong>【示例4】</strong> SimpleLayout样式<br />
<p>&nbsp;</p>
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000">#设置级别和目的地<br />log4j.rootLogger</span><span style="color: #000000">=</span><span style="color: #000000">debug,appender1<br /><br />#输出到控制台<br />log4j.appender.appender1</span><span style="color: #000000">=</span><span style="color: #000000">org.apache.log4j.ConsoleAppender<br />#设置输出样式<br />log4j.appender.appender1.layout</span><span style="color: #000000">=</span><span style="color: #000000">org.apache.log4j.SimpleLayout</span></div>
<p><br /><strong><span style="color: #ff0000"><strong></strong>&nbsp;<span style="font-size: medium">输出结果：</p>
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000">DEBUG&nbsp;</span><span style="color: #000000">-</span><span style="color: #000000">&nbsp;This&nbsp;is&nbsp;debug&nbsp;message.<br />INFO&nbsp;</span><span style="color: #000000">-</span><span style="color: #000000">&nbsp;This&nbsp;is&nbsp;info&nbsp;message.<br />ERROR&nbsp;</span><span style="color: #000000">-</span><span style="color: #000000">&nbsp;This&nbsp;is&nbsp;error&nbsp;message.</span></div>
<p></span></span><strong>【示例5】</strong> 自定义样式</p>
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000">#设置级别和目的地<br />log4j.rootLogger</span><span style="color: #000000">=</span><span style="color: #000000">debug,appender1<br /><br />#输出到控制台<br />log4j.appender.appender1</span><span style="color: #000000">=</span><span style="color: #000000">org.apache.log4j.ConsoleAppender<br />#设置输出样式<br />log4j.appender.appender1.layout</span><span style="color: #000000">=</span><span style="color: #000000">org.apache.log4j.PatternLayout<br />#自定义样式<br />#&nbsp;</span><span style="color: #000000">%</span><span style="color: #000000">r&nbsp;时间&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000"><br />#&nbsp;</span><span style="color: #000000">%</span><span style="color: #000000">t&nbsp;方法名&nbsp;main<br />#&nbsp;</span><span style="color: #000000">%</span><span style="color: #000000">p&nbsp;优先级&nbsp;DEBUG</span><span style="color: #000000">/</span><span style="color: #000000">INFO</span><span style="color: #000000">/</span><span style="color: #000000">ERROR<br />#&nbsp;</span><span style="color: #000000">%</span><span style="color: #000000">c&nbsp;所属类的全名(包括包名)<br />#&nbsp;</span><span style="color: #000000">%</span><span style="color: #000000">l&nbsp;发生的位置，在某个类的某行<br />#&nbsp;</span><span style="color: #000000">%</span><span style="color: #000000">m&nbsp;输出代码中指定的讯息，如log(message)中的message<br />#&nbsp;</span><span style="color: #000000">%</span><span style="color: #000000">n&nbsp;输出一个换行<br /><br />log4j.appender.appender1.layout.ConversionPattern</span><span style="color: #000000">=%</span><span style="color: #000000">r&nbsp;[</span><span style="color: #000000">%</span><span style="color: #000000">t]&nbsp;[</span><span style="color: #000000">%</span><span style="color: #000000">p]&nbsp;</span><span style="color: #000000">-</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">%</span><span style="color: #000000">c&nbsp;</span><span style="color: #000000">-%</span><span style="color: #000000">l&nbsp;</span><span style="color: #000000">-%</span><span style="color: #000000">m</span><span style="color: #000000">%</span><span style="color: #000000">n</span></div>
<p><span style="font-size: medium; color: #ff0000">输出结果：</p>
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008080">1</span>&nbsp;<span style="color: #000000">0</span><span style="color: #000000">&nbsp;[main]&nbsp;[DEBUG]&nbsp;</span><span style="color: #000000">-</span><span style="color: #000000">&nbsp;com.coderdream.log4j.HelloLog4j&nbsp;<br /></span><span style="color: #008080">2</span>&nbsp;<span style="color: #000000"></span><span style="color: #000000">-</span><span style="color: #000000">com.coderdream.log4j.HelloLog4j.main(HelloLog4j.java:</span><span style="color: #000000">16</span><span style="color: #000000">)&nbsp;</span><span style="color: #000000">-</span><span style="color: #000000">This&nbsp;is&nbsp;debug&nbsp;message.<br /></span><span style="color: #008080">3</span>&nbsp;<span style="color: #000000"></span><span style="color: #000000">31</span><span style="color: #000000">&nbsp;[main]&nbsp;[INFO]&nbsp;</span><span style="color: #000000">-</span><span style="color: #000000">&nbsp;com.coderdream.log4j.HelloLog4j&nbsp;<br /></span><span style="color: #008080">4</span>&nbsp;<span style="color: #000000"></span><span style="color: #000000">-</span><span style="color: #000000">com.coderdream.log4j.HelloLog4j.main(HelloLog4j.java:</span><span style="color: #000000">18</span><span style="color: #000000">)&nbsp;</span><span style="color: #000000">-</span><span style="color: #000000">This&nbsp;is&nbsp;info&nbsp;message.<br /></span><span style="color: #008080">5</span>&nbsp;<span style="color: #000000"></span><span style="color: #000000">31</span><span style="color: #000000">&nbsp;[main]&nbsp;[ERROR]&nbsp;</span><span style="color: #000000">-</span><span style="color: #000000">&nbsp;com.coderdream.log4j.HelloLog4j&nbsp;<br /></span><span style="color: #008080">6</span>&nbsp;<span style="color: #000000"></span><span style="color: #000000">-</span><span style="color: #000000">com.coderdream.log4j.HelloLog4j.main(HelloLog4j.java:</span><span style="color: #000000">20</span><span style="color: #000000">)&nbsp;</span><span style="color: #000000">-</span><span style="color: #000000">This&nbsp;is&nbsp;error&nbsp;message.</span></div>
<p></span><strong>【示例6】</strong> 多目的地、自定义样式</p>
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /><span style="color: #000000">#设置级别和目的地<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />log4j.rootLogger</span><span style="color: #000000">=</span><span style="color: #000000">debug</span><span style="color: #000000">,</span><span style="color: #000000">appender1</span><span style="color: #000000">,</span><span style="color: #000000">appender2<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /><br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />#输出到控制台<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />log4j.appender.appender1</span><span style="color: #000000">=</span><span style="color: #000000">org.apache.log4j.ConsoleAppender<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />#设置输出样式<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />log4j.appender.appender1.layout</span><span style="color: #000000">=</span><span style="color: #000000">org.apache.log4j.PatternLayout<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />#自定义样式<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />#&nbsp;%r&nbsp;时间&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />#&nbsp;%t&nbsp;方法名&nbsp;main<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />#&nbsp;%p&nbsp;优先级&nbsp;DEBUG/INFO/ERROR<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />#&nbsp;%c&nbsp;所属类的全名(包括包名)<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />#&nbsp;%l&nbsp;发生的位置，在某个类的某行<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />#&nbsp;%m&nbsp;输出代码中指定的讯息，如log(message)中的message<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />#&nbsp;%n&nbsp;输出一个换行符号<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />log4j.appender.appender1.layout.ConversionPattern</span><span style="color: #000000">=</span><span style="font-weight: bold; color: #800000">[</span><span style="color: #800000">%d{yy/MM/dd&nbsp;HH:mm:ss:SSS}</span><span style="font-weight: bold; color: #800000">][</span><span style="color: #800000">%C-%M</span><span style="font-weight: bold; color: #800000">]</span><span style="color: #000000">&nbsp;%m%n<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /><br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />#输出到文件(这里默认为追加方式)<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />log4j.appender.appender2</span><span style="color: #000000">=</span><span style="color: #000000">org.apache.log4j.FileAppender<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />#设置文件输出路径<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />#【</span><span style="color: #000000">1</span><span style="color: #000000">】文本文件<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />log4j.appender.appender2.File</span><span style="color: #000000">=</span><span style="color: #000000">c:/Log4JDemo06.log<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />#设置文件输出样式<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />log4j.appender.appender2.layout</span><span style="color: #000000">=</span><span style="color: #000000">org.apache.log4j.PatternLayout<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />log4j.appender.appender2.layout.ConversionPattern</span><span style="color: #000000">=</span><span style="font-weight: bold; color: #800000">[</span><span style="color: #800000">%d{HH:mm:ss:SSS}</span><span style="font-weight: bold; color: #800000">][</span><span style="color: #800000">%C-%M</span><span style="font-weight: bold; color: #800000">]</span><span style="color: #000000">&nbsp;-%m%n</span></div>
<p><strong>【示例7】</strong> <span style="font-size: medium"><strong><span style="color: #0000ff">【企业应用】设置</span> <span style="color: #0000ff">特定包的级别和目的地</span> </strong></span></p>
<p>先增加一个包，新建一个类：</p>
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #0000ff">package</span><span style="color: #000000">&nbsp;com.coderdream.log4jDao;<br /><br /></span><span style="color: #0000ff">import</span><span style="color: #000000">&nbsp;org.apache.log4j.Logger;<br /><br /></span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;HelloDao&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">private</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">static</span><span style="color: #000000">&nbsp;Logger&nbsp;logger&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;Logger.getLogger(HelloDao.</span><span style="color: #0000ff">class</span><span style="color: #000000">);<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">/**</span><span style="color: #008000"><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: #808080">@param</span><span style="color: #008000">&nbsp;args<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">*/</span><span style="color: #000000"><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">static</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;main(String[]&nbsp;args)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;记录debug级别的信息</span><span style="color: #008000"><br /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;logger.debug(</span><span style="color: #000000">"</span><span style="color: #000000">This&nbsp;is&nbsp;debug&nbsp;message&nbsp;from&nbsp;Dao.</span><span style="color: #000000">"</span><span style="color: #000000">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;记录info级别的信息</span><span style="color: #008000"><br /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;logger.info(</span><span style="color: #000000">"</span><span style="color: #000000">This&nbsp;is&nbsp;info&nbsp;message&nbsp;from&nbsp;Dao.</span><span style="color: #000000">"</span><span style="color: #000000">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;记录error级别的信息</span><span style="color: #008000"><br /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;logger.error(</span><span style="color: #000000">"</span><span style="color: #000000">This&nbsp;is&nbsp;error&nbsp;message&nbsp;from&nbsp;Dao.</span><span style="color: #000000">"</span><span style="color: #000000">);<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />}</span></div>
<p><br /><span style="color: #0000ff"><strong><span style="font-size: small">如果这个类作为基类，如J2EE中的BaseDao、BaseAction、BaseService等等，则我们可以将各层的日志信息分类输出到各个文件。</p>
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000">#省略根，只设置特定包的级别和目的地<br />log4j.logger.com.coderdream.log4j</span><span style="color: #000000">=</span><span style="color: #000000">debug</span><span style="color: #000000">,</span><span style="color: #000000">appender1<br />log4j.logger.com.coderdream.log4jDao</span><span style="color: #000000">=</span><span style="color: #000000">info</span><span style="color: #000000">,</span><span style="color: #000000">appender1</span><span style="color: #000000">,</span><span style="color: #000000">appender2<br /><br />#输出到控制台<br />log4j.appender.appender1</span><span style="color: #000000">=</span><span style="color: #000000">org.apache.log4j.ConsoleAppender<br />#设置输出样式<br />log4j.appender.appender1.layout</span><span style="color: #000000">=</span><span style="color: #000000">org.apache.log4j.PatternLayout<br />#自定义样式<br />#&nbsp;%r&nbsp;时间&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000"><br />#&nbsp;%t&nbsp;方法名&nbsp;main<br />#&nbsp;%p&nbsp;优先级&nbsp;DEBUG/INFO/ERROR<br />#&nbsp;%c&nbsp;所属类的全名(包括包名)<br />#&nbsp;%l&nbsp;发生的位置，在某个类的某行<br />#&nbsp;%m&nbsp;输出代码中指定的讯息，如log(message)中的message<br />#&nbsp;%n&nbsp;输出一个换行符号<br />log4j.appender.appender1.layout.ConversionPattern</span><span style="color: #000000">=</span><span style="font-weight: bold; color: #800000">[</span><span style="color: #800000">%d{yy/MM/dd&nbsp;HH:mm:ss:SSS}</span><span style="font-weight: bold; color: #800000">][</span><span style="color: #800000">%C-%M</span><span style="font-weight: bold; color: #800000">]</span><span style="color: #000000">&nbsp;%m%n<br /><br />#输出到文件(这里默认为追加方式)<br />log4j.appender.appender2</span><span style="color: #000000">=</span><span style="color: #000000">org.apache.log4j.FileAppender<br />#设置文件输出路径<br />#【</span><span style="color: #000000">1</span><span style="color: #000000">】文本文件<br />log4j.appender.appender2.File</span><span style="color: #000000">=</span><span style="color: #000000">c:/Log4JDemo07_Dao.log<br />#设置文件输出样式<br />log4j.appender.appender2.layout</span><span style="color: #000000">=</span><span style="color: #000000">org.apache.log4j.PatternLayout<br />log4j.appender.appender2.layout.ConversionPattern</span><span style="color: #000000">=</span><span style="font-weight: bold; color: #800000">[</span><span style="color: #800000">%d{HH:mm:ss:SSS}</span><span style="font-weight: bold; color: #800000">][</span><span style="color: #800000">%C-%M</span><span style="font-weight: bold; color: #800000">]</span><span style="color: #000000">&nbsp;-%m%n</span></div><strong>【示例8】</strong> log4j.xml的配置方式<br />
<p></span></strong></span></p>
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008080">&nbsp;1</span>&nbsp;<span style="color: #0000ff">&lt;?</span><span style="color: #ff00ff">xml&nbsp;version="1.0"&nbsp;encoding="UTF-8"</span><span style="color: #0000ff">?&gt;</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;2</span>&nbsp;<span style="color: #000000"></span><span style="color: #0000ff">&lt;!</span><span style="color: #ff00ff">DOCTYPE&nbsp;log4j:configuration&nbsp;SYSTEM&nbsp;"log4j.dtd"</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;3</span>&nbsp;<span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;4</span>&nbsp;<span style="color: #000000"></span><span style="color: #0000ff">&lt;</span><span style="color: #800000">log4j:configuration&nbsp;</span><span style="color: #ff0000">xmlns:log4j</span><span style="color: #0000ff">="http://jakarta.apache.org/log4j/"</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;5</span>&nbsp;<span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;6</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">appender&nbsp;</span><span style="color: #ff0000">name</span><span style="color: #0000ff">="appender1"</span><span style="color: #ff0000"><br /></span><span style="color: #008080">&nbsp;7</span>&nbsp;<span style="color: #ff0000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;class</span><span style="color: #0000ff">="org.apache.log4j.RollingFileAppender"</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;8</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">param&nbsp;</span><span style="color: #ff0000">name</span><span style="color: #0000ff">="File"</span><span style="color: #ff0000">&nbsp;value</span><span style="color: #0000ff">="logfile08.html"</span><span style="color: #ff0000">&nbsp;</span><span style="color: #0000ff">/&gt;</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;9</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">param&nbsp;</span><span style="color: #ff0000">name</span><span style="color: #0000ff">="MaxFileSize"</span><span style="color: #ff0000">&nbsp;value</span><span style="color: #0000ff">="1MB"</span><span style="color: #ff0000">&nbsp;</span><span style="color: #0000ff">/&gt;</span><span style="color: #000000"><br /></span><span style="color: #008080">10</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">param&nbsp;</span><span style="color: #ff0000">name</span><span style="color: #0000ff">="MaxBackupIndex"</span><span style="color: #ff0000">&nbsp;value</span><span style="color: #0000ff">="5"</span><span style="color: #ff0000">&nbsp;</span><span style="color: #0000ff">/&gt;</span><span style="color: #000000"><br /></span><span style="color: #008080">11</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">layout&nbsp;</span><span style="color: #ff0000">class</span><span style="color: #0000ff">="org.apache.log4j.HTMLLayout"</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br /></span><span style="color: #008080">12</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">layout</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br /></span><span style="color: #008080">13</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">appender</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br /></span><span style="color: #008080">14</span>&nbsp;<span style="color: #000000"><br /></span><span style="color: #008080">15</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">root</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br /></span><span style="color: #008080">16</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">level&nbsp;</span><span style="color: #ff0000">value</span><span style="color: #0000ff">="debug"</span><span style="color: #ff0000">&nbsp;</span><span style="color: #0000ff">/&gt;</span><span style="color: #000000"><br /></span><span style="color: #008080">17</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">appender-ref&nbsp;</span><span style="color: #ff0000">ref</span><span style="color: #0000ff">="appender1"</span><span style="color: #ff0000">&nbsp;</span><span style="color: #0000ff">/&gt;</span><span style="color: #000000"><br /></span><span style="color: #008080">18</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">root</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br /></span><span style="color: #008080">19</span>&nbsp;<span style="color: #000000"></span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">log4j:configuration</span><span style="color: #0000ff">&gt;</span></div>
<p>为了提高效率，我们可以在写日志前增加判断：</p>
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008000">//</span><span style="color: #008000">&nbsp;记录debug级别的信息</span><span style="color: #008000"><br /></span><span style="color: #0000ff">if</span><span style="color: #000000">&nbsp;(logger.isDebugEnabled())&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;logger.debug(</span><span style="color: #000000">"</span><span style="color: #000000">This&nbsp;is&nbsp;debug&nbsp;message&nbsp;from&nbsp;Dao.</span><span style="color: #000000">"</span><span style="color: #000000">);<br />}<br /><br /></span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;记录info级别的信息</span><span style="color: #008000"><br /></span><span style="color: #0000ff">if</span><span style="color: #000000">&nbsp;(logger.isInfoEnabled())&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;logger.info(</span><span style="color: #000000">"</span><span style="color: #000000">This&nbsp;is&nbsp;info&nbsp;message&nbsp;from&nbsp;Dao.</span><span style="color: #000000">"</span><span style="color: #000000">);<br />}<br /><br /></span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;记录error级别的信息</span><span style="color: #008000"><br /></span><span style="color: #000000">logger.error(</span><span style="color: #000000">"</span><span style="color: #000000">This&nbsp;is&nbsp;error&nbsp;message&nbsp;from&nbsp;Dao.</span><span style="color: #000000">"</span><span style="color: #000000">);</span></div>
<p><br /><br /><br /><br /><br /><br /><br /></strong><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /></p><img src ="http://www.blogjava.net/conans/aggbug/355064.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/conans/" target="_blank">CONAN</a> 2011-07-26 15:03 <a href="http://www.blogjava.net/conans/articles/355064.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>log4j详解</title><link>http://www.blogjava.net/conans/articles/345084.html</link><dc:creator>CONAN</dc:creator><author>CONAN</author><pubDate>Thu, 24 Feb 2011 09:14:00 GMT</pubDate><guid>http://www.blogjava.net/conans/articles/345084.html</guid><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 日志论 在应用程序中输出日志有有三个目的：（1）监视代码中变量的变化情况，把数据周期性地记录到文件中供其他应用进行统计分析工作。 （2）跟踪代码运行进轨迹，作为日后审计的依据。 （3）担当集成开发环境中的调试器，向文件或控制台打印代码的调试信息。 Apache能用日志包（Commons Logging Package）是Apache的一个开放源代码项目，它提供了一组通用的日志接...&nbsp;&nbsp;<a href='http://www.blogjava.net/conans/articles/345084.html'>阅读全文</a><img src ="http://www.blogjava.net/conans/aggbug/345084.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/conans/" target="_blank">CONAN</a> 2011-02-24 17:14 <a href="http://www.blogjava.net/conans/articles/345084.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Log4j性能调优</title><link>http://www.blogjava.net/conans/articles/345083.html</link><dc:creator>CONAN</dc:creator><author>CONAN</author><pubDate>Thu, 24 Feb 2011 09:10:00 GMT</pubDate><guid>http://www.blogjava.net/conans/articles/345083.html</guid><description><![CDATA[不久前在系统中完成了监控的功能，监控系统的信息量很大，用户对页面的每一个点击都会产生记录，每天下来的日志量有2G多，我用log4j把这些监控记录
放在日志里，然后进行异步处理，但即使是这样，记录日志会对磁盘IO产生频繁的访问，而IO通常就是系统的瓶颈所在。于是对log4j配置进行一些调优就
成了必要。下面是我系统中的log4j配置：<br />
<div style="background-color: #eeeeee; font-size: 13px; border: 1px solid #cccccc; padding: 4px 5px 4px 4px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">log4j.rootLogger</span><span style="color: #000000;">=</span><span style="color: #000000;">ERROR</span><span style="color: #000000;">,</span><span style="color: #000000;">fileout</span><span style="color: #000000;">,</span><span style="color: #000000;">stdout<br />
<span style="color: red;"><span style="color: #000000;">log4j.logger.monitorLogger</span><span style="color: #000000;">=</span><span style="color: #000000;">INFO</span><span style="color: #000000;">,</span><span style="color: #000000;">monitorAppender<br />
log4j.additivity.monitorLogger</span><span style="color: #000000;">=</span><span style="color: #000000;">false</span></span></span><span style="color: #000000;"><br />
<br />
log4j.appender.stdout</span><span style="color: #000000;">=</span><span style="color: #000000;">org.apache.log4j.ConsoleAppender<br />
log4j.appender.stdout.layout</span><span style="color: #000000;">=</span><span style="color: #000000;">org.apache.log4j.PatternLayout<br />
log4j.appender.stdout.layout.ConversionPattern</span><span style="color: #000000;">=</span><span style="color: #000000;">%d&nbsp;(%F:%L)&nbsp;%-5p&nbsp;%c&nbsp;-&nbsp;%m%n<br />
<br />
log4j.appender.fileout</span><span style="color: #000000;">=</span><span style="color: #000000;">org.apache.log4j.DailyRollingFileAppender<br />
log4j.appender.fileout.File</span><span style="color: #000000;">=</span><span style="color: #000000;">logs/server_log.txt<br />
log4j.appender.fileout.layout</span><span style="color: #000000;">=</span><span style="color: #000000;">org.apache.log4j.PatternLayout<br />
log4j.appender.fileout.layout.ConversionPattern</span><span style="color: #000000;">=</span><span style="color: #000000;">%d&nbsp;</span><span style="color: #800000; font-weight: bold;">[</span><span style="color: #800000;">%t</span><span style="color: #800000; font-weight: bold;">]</span><span style="color: #000000;">&nbsp;(%F:%L)&nbsp;%-5p&nbsp;%c&nbsp;-&nbsp;%m%n<br />
<br />
log4j.appender.monitorAppender</span><span style="color: #000000;">=</span><span style="color: #000000;">org.apache.log4j.DailyRollingFileAppender<br />
log4j.appender.monitorAppender.File</span><span style="color: #000000;">=</span><span style="color: #000000;">mtlogs/mt_log.txt<br />
log4j.appender.monitorAppender.layout</span><span style="color: #000000;">=</span><span style="color: #000000;">org.apache.log4j.PatternLayout<br />
log4j.appender.monitorAppender.layout.ConversionPattern</span><span style="color: #000000;">=</span><span style="color: #000000;">%m%n<br />
log4j.appender.monitorAppender.DatePattern</span><span style="color: #000000;">=</span><span style="color: #000000;">'.'yyyy-MM-dd-HH<br />
log4j.appender.monitorAppender.BufferedIO</span><span style="color: #000000;">=</span><span style="color: #000000;">true<br />
#Buffer单位为字节，默认是8K<br />
<span style="color: red;"><span style="color: #000000;">log4j.appender.monitorAppender.BufferSize</span><span style="color: #000000;">=</span><span style="color: #000000;">8192</span></span></span></div>
1）<span style="color: #ff0000;">log4j.additivity.monitorLogger=false<br />
<span style="color: #000000;">这个选项用于控制监控logger的日志不会输出到rootlogger，否则无论会产生许多重复的数据，同时也会影响性能；<br />
<br />
2）</span></span><span style="color: #ff0000;">log4j.appender.monitorAppender.DatePattern='.'yyyy-MM-dd-HH<br />
<span style="color: #000000;">这个选项用于告诉</span></span>DailyRollingFileAppender每小时输出日志，而不是默认的一天输出一次，因为监控日志的数据量很巨大，如果以天为单位输出，日志文件会很大（G级），而且再处理会很耗时。<br />
其他一些输出选项还有：<br />
1)'.'yyyy-MM: 每月 <br />
2)'.'yyyy-ww: 每周 <br />
3)'.'yyyy-MM-dd: 每天 <br />
4)'.'yyyy-MM-dd-a: 每天两次 <br />
5)'.'yyyy-MM-dd-HH: 每小时 <br />
6)'.'yyyy-MM-dd-HH-mm: 每分钟 <span style="color: #ff0000;"><br />
<br />
<span style="color: #000000;">3）</span></span><span style="color: #ff0000;">log4j.appender.monitorAppender.BufferedIO=true<br />
</span><span style="color: #ff0000;">log4j.appender.monitorAppender.BufferSize=8192<br />
<span style="color: #000000;">这
个选项用于告诉log4j输出日志的时候采用缓冲的方式，而不是即时flush方式，并且设定了缓冲为8K，8K是默认值，可以根据日志输出的情况来修
改。这个选项很重要，在测试中发现，当并发访问很高，例如每一秒100个并发以上，使用缓存跟不使用缓冲差距很大。具体数字我这里就不列出来了。<br />
另外我想说的是，log4j输出缓冲日志是以8K为单位的，因为磁盘的一个block为8K，这样可以减少碎片，也就是说假设你设置缓存为18K，log4j在16K（8K*2)的时候就会输出），而不是18K。<br />
<br />
4）组装输出内容之前可对logger的输出级别先进行判断而不要完全依赖log4j控制，因为组装输出日志内容也是要损耗效率的。<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; //若log4j并未开启info级日志记录，直接返回<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if(!monitorLogger.isInfoEnabled()){<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return;<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; StringBuilder log = new StringBuilder();<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; logSql.append(logPk+" ");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ...<br />
<br />
5）使用异步输出 org.apache.log4j.AsyncAppender，异步输出必须使用xml方式配置才能支持，我把上面properties形式的配置文件用xml表达一下：<br />
</span></span>
<div style="background-color: #eeeeee; font-size: 13px; border: 1px solid #cccccc; padding: 4px 5px 4px 4px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #0000ff;">&lt;?</span><span style="color: #ff00ff;">xml&nbsp;version="1.0"&nbsp;encoding="UTF-8"</span><span style="color: #0000ff;">?&gt;</span><span style="color: #000000;"><br />
</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">log4j:configuration&nbsp;</span><span style="color: #ff0000;">debug</span><span style="color: #0000ff;">="true"</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">appender&nbsp;</span><span style="color: #ff0000;">name</span><span style="color: #0000ff;">="stdout"</span><span style="color: #ff0000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;class</span><span style="color: #0000ff;">="org.apache.log4j.ConsoleAppender"</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">layout&nbsp;</span><span style="color: #ff0000;">class</span><span style="color: #0000ff;">="org.apache.log4j.PatternLayout"</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">param&nbsp;</span><span style="color: #ff0000;">name</span><span style="color: #0000ff;">="ConversionPattern"</span><span style="color: #ff0000;">&nbsp;value</span><span style="color: #0000ff;">="%d&nbsp;(%F:%L)&nbsp;%-5p&nbsp;%c&nbsp;-&nbsp;%m%n"</span><span style="color: #ff0000;">&nbsp;</span><span style="color: #0000ff;">/&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">layout</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">appender</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">appender&nbsp;</span><span style="color: #ff0000;">name</span><span style="color: #0000ff;">="fileout"</span><span style="color: #ff0000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;class</span><span style="color: #0000ff;">="org.apache.log4j.DailyRollingFileAppender"</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">layout&nbsp;</span><span style="color: #ff0000;">class</span><span style="color: #0000ff;">="org.apache.log4j.PatternLayout"</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">param&nbsp;</span><span style="color: #ff0000;">name</span><span style="color: #0000ff;">="ConversionPattern"</span><span style="color: #ff0000;">&nbsp;value</span><span style="color: #0000ff;">="%d&nbsp;[%t]&nbsp;(%F:%L)&nbsp;%-5p&nbsp;%c&nbsp;-&nbsp;%m%n"</span><span style="color: #ff0000;">&nbsp;</span><span style="color: #0000ff;">/&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">layout</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">param&nbsp;</span><span style="color: #ff0000;">name</span><span style="color: #0000ff;">="File"</span><span style="color: #ff0000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;value</span><span style="color: #0000ff;">="logs/server_log.txt"</span><span style="color: #ff0000;">&nbsp;</span><span style="color: #0000ff;">/&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">appender</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">appender&nbsp;</span><span style="color: #ff0000;">name</span><span style="color: #0000ff;">="monitorAppender"</span><span style="color: #ff0000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;class</span><span style="color: #0000ff;">="org.apache.log4j.DailyRollingFileAppender"</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">layout&nbsp;</span><span style="color: #ff0000;">class</span><span style="color: #0000ff;">="org.apache.log4j.PatternLayout"</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">param&nbsp;</span><span style="color: #ff0000;">name</span><span style="color: #0000ff;">="ConversionPattern"</span><span style="color: #ff0000;">&nbsp;value</span><span style="color: #0000ff;">="%m%n"</span><span style="color: #ff0000;">&nbsp;</span><span style="color: #0000ff;">/&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">layout</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">param&nbsp;</span><span style="color: #ff0000;">name</span><span style="color: #0000ff;">="DatePattern"</span><span style="color: #ff0000;">&nbsp;value</span><span style="color: #0000ff;">="'.'yyyy-MM-dd-HH"</span><span style="color: #ff0000;">&nbsp;</span><span style="color: #0000ff;">/&gt;</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">param&nbsp;</span><span style="color: #ff0000;">name</span><span style="color: #0000ff;">="File"</span><span style="color: #ff0000;">&nbsp;value</span><span style="color: #0000ff;">="mtlogs/mt_log.txt"</span><span style="color: #ff0000;">&nbsp;</span><span style="color: #0000ff;">/&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">param&nbsp;</span><span style="color: #ff0000;">name</span><span style="color: #0000ff;">="BufferedIO"</span><span style="color: #ff0000;">&nbsp;value</span><span style="color: #0000ff;">="true"</span><span style="color: #ff0000;">&nbsp;</span><span style="color: #0000ff;">/&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">&lt;!--</span><span style="color: #008000;">&nbsp;8K为一个写单元&nbsp;</span><span style="color: #008000;">--&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">param&nbsp;</span><span style="color: #ff0000;">name</span><span style="color: #0000ff;">="BufferSize"</span><span style="color: #ff0000;">&nbsp;value</span><span style="color: #0000ff;">="8192"</span><span style="color: #ff0000;">&nbsp;</span><span style="color: #0000ff;">/&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">appender</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">appender&nbsp;</span><span style="color: #ff0000;">name</span><span style="color: #0000ff;">="async"</span><span style="color: #ff0000;">&nbsp;class</span><span style="color: #0000ff;">="org.apache.log4j.AsyncAppender"</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">appender-ref&nbsp;</span><span style="color: #ff0000;">ref</span><span style="color: #0000ff;">="monitorAppender"</span><span style="color: #0000ff;">/&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">appender</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">root</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">priority&nbsp;</span><span style="color: #ff0000;">value</span><span style="color: #0000ff;">="error"</span><span style="color: #ff0000;">&nbsp;</span><span style="color: #0000ff;">/&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">appender-ref&nbsp;</span><span style="color: #ff0000;">ref</span><span style="color: #0000ff;">="stdout"</span><span style="color: #ff0000;">&nbsp;</span><span style="color: #0000ff;">/&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">appender-ref&nbsp;</span><span style="color: #ff0000;">ref</span><span style="color: #0000ff;">="fileout"</span><span style="color: #ff0000;">&nbsp;</span><span style="color: #0000ff;">/&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">root</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">category&nbsp;</span><span style="color: #ff0000;">name</span><span style="color: #0000ff;">="com.danga.MemCached"</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">priority&nbsp;</span><span style="color: #ff0000;">value</span><span style="color: #0000ff;">="error"</span><span style="color: #ff0000;">&nbsp;</span><span style="color: #0000ff;">/&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">appender-ref&nbsp;</span><span style="color: #ff0000;">ref</span><span style="color: #0000ff;">="fileout"</span><span style="color: #ff0000;">&nbsp;</span><span style="color: #0000ff;">/&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">category&nbsp;</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">category&nbsp;</span><span style="color: #ff0000;">name</span><span style="color: #0000ff;">="com.opensymphony"</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">priority&nbsp;</span><span style="color: #ff0000;">value</span><span style="color: #0000ff;">="error"</span><span style="color: #ff0000;">&nbsp;</span><span style="color: #0000ff;">/&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">appender-ref&nbsp;</span><span style="color: #ff0000;">ref</span><span style="color: #0000ff;">="fileout"</span><span style="color: #ff0000;">&nbsp;</span><span style="color: #0000ff;">/&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">category&nbsp;</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">category&nbsp;</span><span style="color: #ff0000;">name</span><span style="color: #0000ff;">="monitorLogger"</span><span style="color: #ff0000;">&nbsp;additivity</span><span style="color: #0000ff;">="false"</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">priority&nbsp;</span><span style="color: #ff0000;">value</span><span style="color: #0000ff;">="info"</span><span style="color: #ff0000;">&nbsp;</span><span style="color: #0000ff;">/&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">appender-ref&nbsp;</span><span style="color: #ff0000;">ref</span><span style="color: #0000ff;">="async"</span><span style="color: #ff0000;">&nbsp;</span><span style="color: #0000ff;">/&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">category&nbsp;</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">log4j:configuration</span><span style="color: #0000ff;">&gt;</span></div>
<span style="color: #ff0000;"><span style="color: #000000;">配置中红色的部分就是用于支持异步输出的，在用jmeter测试的过程中发觉使用异步方式，工作的不是很稳定。性能的提升也不显著。所以最后并没有采用。<br />
<br />
</span></span>
<div style="background-color: #eeeeee; font-size: 13px; border: 1px solid #cccccc; padding: 4px 5px 4px 4px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">InputStream&nbsp;in</span><span style="color: #000000;">=</span><span style="color: #0000ff;">null</span><span style="color: #000000;">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">try</span><span style="color: #000000;">&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;in&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;Log4jConfigLocator.</span><span style="color: #0000ff;">class</span><span style="color: #000000;">.getResourceAsStream(fileName);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">(fileName.endsWith(</span><span style="color: #000000;">"</span><span style="color: #000000;">.xml</span><span style="color: #000000;">"</span><span style="color: #000000;">)){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">载入XML格式的配置文件</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Document&nbsp;doc&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(in);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DOMConfigurator.configure(doc.getDocumentElement());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span><span style="color: #0000ff;">else</span><span style="color: #000000;">{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">载入properties格式的配置文件</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Properties&nbsp;props&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;Properties();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;props.load(in);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PropertyConfigurator.configure(props);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<img src="http://www.blogjava.net/Images/dot.gif"  alt="" /><img src="http://www.blogjava.net/Images/dot.gif"  alt="" /></span></div>
<br />
<br />
<img src ="http://www.blogjava.net/conans/aggbug/345083.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/conans/" target="_blank">CONAN</a> 2011-02-24 17:10 <a href="http://www.blogjava.net/conans/articles/345083.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>动态非侵入拦截</title><link>http://www.blogjava.net/conans/articles/282635.html</link><dc:creator>CONAN</dc:creator><author>CONAN</author><pubDate>Tue, 16 Jun 2009 08:18:00 GMT</pubDate><guid>http://www.blogjava.net/conans/articles/282635.html</guid><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 动态非侵入拦截什么叫无侵入拦截？&nbsp;在JAVA中要拦截一个方法调用，有多种方式，最容易也是最流行的就是动态代理。动态代理方式实现起来简单，你只要提供一个接口和拦截处理的handler并在invoke中提供要拉截的方法调用时的附件操作，然后所有对需要拦截的方法所在的对象都由代理来生成就可以在运行时动态地实现对方法调进行拦截。&nbsp;事实上动态代理模式从描述上也看出了它...&nbsp;&nbsp;<a href='http://www.blogjava.net/conans/articles/282635.html'>阅读全文</a><img src ="http://www.blogjava.net/conans/aggbug/282635.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/conans/" target="_blank">CONAN</a> 2009-06-16 16:18 <a href="http://www.blogjava.net/conans/articles/282635.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Word/Excel/PDF文件转换成HTML整理</title><link>http://www.blogjava.net/conans/articles/255092.html</link><dc:creator>CONAN</dc:creator><author>CONAN</author><pubDate>Tue, 17 Feb 2009 06:57:00 GMT</pubDate><guid>http://www.blogjava.net/conans/articles/255092.html</guid><description><![CDATA[<p>项目开发过程中，需求涉及到了各种文档转换为HTML或者网页易显示格式，现在将实现方式整理如下： <br />
<strong>一、使用Jacob转换Word,Excel为HTML</strong> <br />
<br />
&#8220;JACOB一个Java-COM中间件.通过这个组件你可以在Java应用程序中调用COM组件和Win32 libraries。&#8221;<br />
<br />
<span style="text-decoration: underline">首先下载Jacob包，JDK1.5以上需要使用Jacob1.9版本（JDK1.6尚未测试），与先前的Jacob1.7差别不大</span><br />
<br />
1、将压缩包解压后，Jacob.jar添加到Libraries中；<br />
<br />
2、将Jacob.dll放至&#8220;WINDOWS\SYSTEM32&#8221;下面。<br />
<br />
需要注意的是： <br />
【使用IDE启动Web服务器时，系统读取不到Jacob.dll，例如用MyEclipse启动Tomcat，就需要将dll文件copy到MyEclipse安装目录的&#8220;jre\bin&#8221;下面。 <br />
一般系统没有加载到Jacob.dll文件时，报错信息为：&#8220;java.lang.UnsatisfiedLinkError: no jacob in java.library.path&#8221;】 <br />
<br />
新建类：</p>
<div class="dp-highlighter">
<div class="bar">
<div class="tools">Java代码 <a title="复制代码" onclick="dp.sh.Toolbar.CopyToClipboard(this);return false;" href="http://www.javaeye.com/topic/333676#"><img alt="复制代码" src="http://www.javaeye.com/images/icon_copy.gif" _counted="undefined" /></a></div>
</div>
<ol class="dp-j">
    <li><span><span class="keyword">public</span><span>&nbsp;</span><span class="keyword">class</span><span>&nbsp;JacobUtil &nbsp;&nbsp;</span></span></li>
    <li><span>{ &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">public</span><span>&nbsp;</span><span class="keyword">static</span><span>&nbsp;</span><span class="keyword">final</span><span>&nbsp;</span><span class="keyword">int</span><span>&nbsp;WORD_HTML&nbsp;=&nbsp;</span><span class="number">8</span><span>; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">public</span><span>&nbsp;</span><span class="keyword">static</span><span>&nbsp;</span><span class="keyword">final</span><span>&nbsp;</span><span class="keyword">int</span><span>&nbsp;WORD_TXT&nbsp;=&nbsp;</span><span class="number">7</span><span>; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">public</span><span>&nbsp;</span><span class="keyword">static</span><span>&nbsp;</span><span class="keyword">final</span><span>&nbsp;</span><span class="keyword">int</span><span>&nbsp;EXCEL_HTML&nbsp;=&nbsp;</span><span class="number">44</span><span>; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">/** </span>&nbsp;</span></li>
    <li><span><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;WORD转HTML </span>&nbsp;</span></li>
    <li><span><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;docfile&nbsp;WORD文件全路径 </span>&nbsp;</span></li>
    <li><span><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;htmlfile&nbsp;转换后HTML存放路径 </span>&nbsp;</span></li>
    <li><span><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">public</span><span>&nbsp;</span><span class="keyword">static</span><span>&nbsp;</span><span class="keyword">void</span><span>&nbsp;wordToHtml(String&nbsp;docfile,&nbsp;String&nbsp;htmlfile) &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ActiveXComponent&nbsp;app&nbsp;=&nbsp;</span><span class="keyword">new</span><span>&nbsp;ActiveXComponent(</span><span class="string">"Word.Application"</span><span>);&nbsp;</span><span class="comment">//&nbsp;启动word </span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">try</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;app.setProperty(</span><span class="string">"Visible"</span><span>,&nbsp;</span><span class="keyword">new</span><span>&nbsp;Variant(</span><span class="keyword">false</span><span>)); &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Dispatch&nbsp;docs&nbsp;=&nbsp;app.getProperty(</span><span class="string">"Documents"</span><span>).toDispatch(); &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Dispatch&nbsp;doc&nbsp;=&nbsp;Dispatch.invoke( &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;docs, &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="string">"Open"</span><span>, &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Dispatch.Method, &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">new</span><span>&nbsp;Object[]&nbsp;{&nbsp;docfile,&nbsp;</span><span class="keyword">new</span><span>&nbsp;Variant(</span><span class="keyword">false</span><span>), &nbsp;&nbsp;</span></span></li>
    <li><span>&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;</span><span class="keyword">new</span><span>&nbsp;Variant(</span><span class="keyword">true</span><span>)&nbsp;},&nbsp;</span><span class="keyword">new</span><span>&nbsp;</span><span class="keyword">int</span><span>[</span><span class="number">1</span><span>]).toDispatch(); &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Dispatch.invoke(doc,&nbsp;</span><span class="string">"SaveAs"</span><span>,&nbsp;Dispatch.Method,&nbsp;</span><span class="keyword">new</span><span>&nbsp;Object[]&nbsp;{ &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;htmlfile,&nbsp;</span><span class="keyword">new</span><span>&nbsp;Variant(WORD_HTML)&nbsp;},&nbsp;</span><span class="keyword">new</span><span>&nbsp;</span><span class="keyword">int</span><span>[</span><span class="number">1</span><span>]); &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Variant&nbsp;f&nbsp;=&nbsp;</span><span class="keyword">new</span><span>&nbsp;Variant(</span><span class="keyword">false</span><span>); &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Dispatch.call(doc,&nbsp;</span><span class="string">"Close"</span><span>,&nbsp;f); &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">catch</span><span>&nbsp;(Exception&nbsp;e) &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e.printStackTrace(); &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">finally</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;app.invoke(</span><span class="string">"Quit"</span><span>,&nbsp;</span><span class="keyword">new</span><span>&nbsp;Variant[]&nbsp;{}); &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">/** </span>&nbsp;</span></li>
    <li><span><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;EXCEL转HTML </span>&nbsp;</span></li>
    <li><span><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;xlsfile&nbsp;EXCEL文件全路径 </span>&nbsp;</span></li>
    <li><span><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;htmlfile&nbsp;转换后HTML存放路径 </span>&nbsp;</span></li>
    <li><span><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">public</span><span>&nbsp;</span><span class="keyword">static</span><span>&nbsp;</span><span class="keyword">void</span><span>&nbsp;excelToHtml(String&nbsp;xlsfile,&nbsp;String&nbsp;htmlfile) &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ActiveXComponent&nbsp;app&nbsp;=&nbsp;</span><span class="keyword">new</span><span>&nbsp;ActiveXComponent(</span><span class="string">"Excel.Application"</span><span>);&nbsp;</span><span class="comment">//&nbsp;启动word </span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">try</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;app.setProperty(</span><span class="string">"Visible"</span><span>,&nbsp;</span><span class="keyword">new</span><span>&nbsp;Variant(</span><span class="keyword">false</span><span>)); &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Dispatch&nbsp;excels&nbsp;=&nbsp;app.getProperty(</span><span class="string">"Workbooks"</span><span>).toDispatch(); &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Dispatch&nbsp;excel&nbsp;=&nbsp;Dispatch.invoke( &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;excels, &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="string">"Open"</span><span>, &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Dispatch.Method, &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">new</span><span>&nbsp;Object[]&nbsp;{&nbsp;xlsfile,&nbsp;</span><span class="keyword">new</span><span>&nbsp;Variant(</span><span class="keyword">false</span><span>), &nbsp;&nbsp;</span></span></li>
    <li><span>&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;</span><span class="keyword">new</span><span>&nbsp;Variant(</span><span class="keyword">true</span><span>)&nbsp;},&nbsp;</span><span class="keyword">new</span><span>&nbsp;</span><span class="keyword">int</span><span>[</span><span class="number">1</span><span>]).toDispatch(); &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Dispatch.invoke(excel,&nbsp;</span><span class="string">"SaveAs"</span><span>,&nbsp;Dispatch.Method,&nbsp;</span><span class="keyword">new</span><span>&nbsp;Object[]&nbsp;{ &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;htmlfile,&nbsp;</span><span class="keyword">new</span><span>&nbsp;Variant(EXCEL_HTML)&nbsp;},&nbsp;</span><span class="keyword">new</span><span>&nbsp;</span><span class="keyword">int</span><span>[</span><span class="number">1</span><span>]); &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Variant&nbsp;f&nbsp;=&nbsp;</span><span class="keyword">new</span><span>&nbsp;Variant(</span><span class="keyword">false</span><span>); &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Dispatch.call(excel,&nbsp;</span><span class="string">"Close"</span><span>,&nbsp;f); &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">catch</span><span>&nbsp;(Exception&nbsp;e) &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e.printStackTrace(); &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">finally</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;app.invoke(</span><span class="string">"Quit"</span><span>,&nbsp;</span><span class="keyword">new</span><span>&nbsp;Variant[]&nbsp;{}); &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;</span></li>
    <li><span>}&nbsp;&nbsp;</span></li>
</ol>
</div>
<pre class="java" style="display: none" name="code">public class JacobUtil
{
public static final int WORD_HTML = 8;
public static final int WORD_TXT = 7;
public static final int EXCEL_HTML = 44;
/**
* WORD转HTML
* @param docfile WORD文件全路径
* @param htmlfile 转换后HTML存放路径
*/
public static void wordToHtml(String docfile, String htmlfile)
{
ActiveXComponent app = new ActiveXComponent("Word.Application"); // 启动word
try
{
app.setProperty("Visible", new Variant(false));
Dispatch docs = app.getProperty("Documents").toDispatch();
Dispatch doc = Dispatch.invoke(
docs,
"Open",
Dispatch.Method,
new Object[] { docfile, new Variant(false),
new Variant(true) }, new int[1]).toDispatch();
Dispatch.invoke(doc, "SaveAs", Dispatch.Method, new Object[] {
htmlfile, new Variant(WORD_HTML) }, new int[1]);
Variant f = new Variant(false);
Dispatch.call(doc, "Close", f);
}
catch (Exception e)
{
e.printStackTrace();
}
finally
{
app.invoke("Quit", new Variant[] {});
}
}
/**
* EXCEL转HTML
* @param xlsfile EXCEL文件全路径
* @param htmlfile 转换后HTML存放路径
*/
public static void excelToHtml(String xlsfile, String htmlfile)
{
ActiveXComponent app = new ActiveXComponent("Excel.Application"); // 启动word
try
{
app.setProperty("Visible", new Variant(false));
Dispatch excels = app.getProperty("Workbooks").toDispatch();
Dispatch excel = Dispatch.invoke(
excels,
"Open",
Dispatch.Method,
new Object[] { xlsfile, new Variant(false),
new Variant(true) }, new int[1]).toDispatch();
Dispatch.invoke(excel, "SaveAs", Dispatch.Method, new Object[] {
htmlfile, new Variant(EXCEL_HTML) }, new int[1]);
Variant f = new Variant(false);
Dispatch.call(excel, "Close", f);
}
catch (Exception e)
{
e.printStackTrace();
}
finally
{
app.invoke("Quit", new Variant[] {});
}
}
}</pre>
<p>当时我在找转换控件时，发现网易也转载了一偏关于Jacob使用帮助，但其中出现了比较严重的错误：String htmlfile = "C:\\AA";</p>
<p>只指定到了文件夹一级，正确写法是String htmlfile = "C:\\AA\\xxx.html";</p>
<p>&nbsp;</p>
<p>到此WORD/EXCEL转换HTML就已经差不多了，相信大家应该很清楚了:)</p>
<p>&nbsp;</p>
<p><strong>二、使用XPDF将PDF转换为HTML</strong></p>
<p>&nbsp;</p>
<p>1、下载xpdf最新版本，地址：<a href="http://www.foolabs.com/xpdf/download.html">http://www.foolabs.com/xpdf/download.html</a></p>
<p>我下载的是<span class="Apple-style-span" style="word-spacing: 0px; text-transform: none; color: #000000; text-indent: 0px; font-family: Simsun; white-space: normal; letter-spacing: normal; border-collapse: separate; orphans: 2; widows: 2; webkit-border-horizontal-spacing: 0px; webkit-border-vertical-spacing: 0px; webkit-text-decorations-in-effect: none; webkit-text-size-adjust: auto; webkit-text-stroke-width: 0px"><span class="Apple-style-span" style="font-family: -webkit-sans-serif; webkit-border-horizontal-spacing: 4px; webkit-border-vertical-spacing: 4px"><a href="ftp://ftp.foolabs.com/pub/xpdf/xpdf-3.02pl2-win32.zip">xpdf-3.02pl2-win32.zip</a></span></span></p>
<p>&nbsp;</p>
<p>2、下载中文支持包</p>
<p>我下载的是<span class="Apple-style-span" style="word-spacing: 0px; text-transform: none; color: #000000; text-indent: 0px; font-family: Simsun; white-space: normal; letter-spacing: normal; border-collapse: separate; orphans: 2; widows: 2; webkit-border-horizontal-spacing: 0px; webkit-border-vertical-spacing: 0px; webkit-text-decorations-in-effect: none; webkit-text-size-adjust: auto; webkit-text-stroke-width: 0px"><span class="Apple-style-span" style="font-family: -webkit-sans-serif; webkit-border-horizontal-spacing: 4px; webkit-border-vertical-spacing: 4px"><a href="ftp://ftp.foolabs.com/pub/xpdf/xpdf-chinese-simplified.tar.gz">xpdf-chinese-simplified.tar.gz</a></span></span></p>
<p>&nbsp;</p>
<p>3、下载pdftohtml支持包</p>
<p>地址：<a href="http://sourceforge.net/projects/pdftohtml/">http://sourceforge.net/projects/pdftohtml/</a></p>
<p>我下载的是：<span class="Apple-style-span" style="word-spacing: 0px; text-transform: none; color: #000000; text-indent: 0px; font-family: Simsun; white-space: normal; letter-spacing: normal; border-collapse: separate; orphans: 2; widows: 2; webkit-border-horizontal-spacing: 0px; webkit-border-vertical-spacing: 0px; webkit-text-decorations-in-effect: none; webkit-text-size-adjust: auto; webkit-text-stroke-width: 0px"><span class="Apple-style-span" style="font-size: 12px; line-height: 14px; font-family: verdana; border-collapse: collapse; text-align: left"><a class="sfx_qalogger_element sfx_qalogger_clickable" id="showfiles_download_file_pkg0_1rel0_1" style="color: #0033cc; text-decoration: underline" onclick="window.location='/project/downloading.php?group_id=45839&amp;use_mirror=nchc&amp;filename=pdftohtml-0.39-win32.tar.gz&amp;'+Math.floor(Math.random()*100000000); return false;" href="http://downloads.sourceforge.net/pdftohtml/pdftohtml-0.39-win32.tar.gz?modtime=1154595549&amp;big_mirror=0">pdftohtml-0.39-win32.tar.gz</a></span></span></p>
<p>&nbsp;</p>
<p>4、解压调试</p>
<p>1) 先将xpdf-3.02pl2-win32.zip解压，解压后的内容可根据需要进行删减，如果只需要转换为txt格式，其他的exe文件可以删除，只保留pdftotext.exe，以此类推；</p>
<p>2) 然后将xpdf-chinese-simplified.tar.gz解压到刚才xpdf-3.02pl2-win32.zip的解压目录；</p>
<p>3) 将pdftohtml-0.39-win32.tar.gz解压，pdftohtml.exe解压到xpdf-3.02pl2-win32.zip的解压目录；</p>
<p>4) 目录结构：</p>
<p>&nbsp;+---[X:\xpdf]</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |-------各种转换用到的exe文件</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |-------xpdfrc</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; +------[X:\xpdf\xpdf-chinese-simplified]</p>
<p>&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;&nbsp;&nbsp; |</p>
<p>&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;&nbsp;&nbsp; |</p>
<p>&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;&nbsp;&nbsp; +-------很多转换时需要用到的字符文件</p>
<p>&nbsp;</p>
<p>xpdfrc：此文件是用来声明转换字符集对应路径的文件</p>
<p>&nbsp;</p>
<p>5) 修改xpdfrc文件(文件原名为sample-xpdfrc)</p>
<p>修改文件内容为：</p>
<p>&nbsp;</p>
<div class="dp-highlighter">
<div class="bar">
<div class="tools">Txt代码 <a title="复制代码" onclick="dp.sh.Toolbar.CopyToClipboard(this);return false;" href="http://www.javaeye.com/topic/333676#"><img alt="复制代码" src="http://www.javaeye.com/images/icon_copy.gif" _counted="undefined" /></a></div>
</div>
<ol class="dp-default">
    <li><span><span>#-----&nbsp;begin&nbsp;Chinese&nbsp;Simplified&nbsp;support&nbsp;package &nbsp;&nbsp;</span></span></li>
    <li><span>cidToUnicode&nbsp;&nbsp;&nbsp;&nbsp;Adobe-GB1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;xpdf-chinese-simplified\Adobe-GB1.cidToUnicode &nbsp;&nbsp;</span></li>
    <li><span>unicodeMap&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ISO-</span><span class="number">2022</span><span>-CN&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;xpdf-chinese-simplified\ISO-</span><span class="number">2022</span><span>-CN.unicodeMap &nbsp;&nbsp;</span></span></li>
    <li><span>unicodeMap&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;EUC-CN&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;xpdf-chinese-simplified\EUC-CN.unicodeMap &nbsp;&nbsp;</span></li>
    <li><span>unicodeMap&nbsp;&nbsp;GBK&nbsp;&nbsp;&nbsp;&nbsp;xpdf-chinese-simplified\GBK.unicodeMap &nbsp;&nbsp;</span></li>
    <li><span>cMapDir&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Adobe-GB1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;xpdf-chinese-simplified\CMap &nbsp;&nbsp;</span></li>
    <li><span>toUnicodeDir&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;xpdf-chinese-simplified\CMap &nbsp;&nbsp;</span></li>
    <li><span>fontDir&nbsp;&nbsp;C:\WINDOWS\Fonts &nbsp;&nbsp;</span></li>
    <li><span>displayCIDFontTT&nbsp;Adobe-GB1&nbsp;C:\WINDOWS\Fonts\simhei.ttf &nbsp;&nbsp;</span></li>
    <li><span>#-----&nbsp;end&nbsp;Chinese&nbsp;Simplified&nbsp;support&nbsp;package&nbsp;&nbsp;</span></li>
</ol>
</div>
<pre class="TXT" style="display: none" name="code">#----- begin Chinese Simplified support package
cidToUnicode    Adobe-GB1       xpdf-chinese-simplified\Adobe-GB1.cidToUnicode
unicodeMap      ISO-2022-CN     xpdf-chinese-simplified\ISO-2022-CN.unicodeMap
unicodeMap      EUC-CN          xpdf-chinese-simplified\EUC-CN.unicodeMap
unicodeMap  GBK    xpdf-chinese-simplified\GBK.unicodeMap
cMapDir         Adobe-GB1       xpdf-chinese-simplified\CMap
toUnicodeDir                    xpdf-chinese-simplified\CMap
fontDir  C:\WINDOWS\Fonts
displayCIDFontTT Adobe-GB1 C:\WINDOWS\Fonts\simhei.ttf
#----- end Chinese Simplified support package</pre>
<p>&nbsp;</p>
<p>6) 创建bat文件pdftohtml.bat（放置的路径不能包含空格）</p>
<p>内容为：</p>
<p>&nbsp;</p>
<div class="dp-highlighter">
<div class="bar">
<div class="tools">Txt代码 <a title="复制代码" onclick="dp.sh.Toolbar.CopyToClipboard(this);return false;" href="http://www.javaeye.com/topic/333676#"><img alt="复制代码" src="http://www.javaeye.com/images/icon_copy.gif" _counted="undefined" /></a></div>
</div>
<ol class="dp-default">
    <li><span><span>@echo&nbsp;off &nbsp;&nbsp;</span></span></li>
    <li><span>set&nbsp;folderPath=%</span><span class="number">1</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>set&nbsp;filePath=%</span><span class="number">2</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>cd&nbsp;/d&nbsp;%folderPath% &nbsp;&nbsp;</span></li>
    <li><span>pdftohtml&nbsp;-enc&nbsp;GBK&nbsp;%filePath% &nbsp;&nbsp;</span></li>
    <li><span>exit&nbsp;&nbsp;</span></li>
</ol>
</div>
<pre class="TXT" style="display: none" name="code">@echo off
set folderPath=%1
set filePath=%2
cd /d %folderPath%
pdftohtml -enc GBK %filePath%
exit</pre>
<p>&nbsp;</p>
<p>7) 创建类</p>
<p>&nbsp;</p>
<div class="dp-highlighter">
<div class="bar">
<div class="tools">Java代码 <a title="复制代码" onclick="dp.sh.Toolbar.CopyToClipboard(this);return false;" href="http://www.javaeye.com/topic/333676#"><img alt="复制代码" src="http://www.javaeye.com/images/icon_copy.gif" _counted="undefined" /></a></div>
</div>
<ol class="dp-j">
    <li><span><span class="keyword">public</span><span>&nbsp;</span><span class="keyword">class</span><span>&nbsp;ConvertPdf &nbsp;&nbsp;</span></span></li>
    <li><span>{ &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">private</span><span>&nbsp;</span><span class="keyword">static</span><span>&nbsp;String&nbsp;INPUT_PATH; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">private</span><span>&nbsp;</span><span class="keyword">static</span><span>&nbsp;String&nbsp;PROJECT_PATH; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">public</span><span>&nbsp;</span><span class="keyword">static</span><span>&nbsp;</span><span class="keyword">void</span><span>&nbsp;convertToHtml(String&nbsp;file,&nbsp;String&nbsp;project) &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;INPUT_PATH&nbsp;=&nbsp;file; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PROJECT_PATH&nbsp;=&nbsp;project; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">if</span><span>(checkContentType()==</span><span class="number">0</span><span>) &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;toHtml(); &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">private</span><span>&nbsp;</span><span class="keyword">static</span><span>&nbsp;</span><span class="keyword">int</span><span>&nbsp;checkContentType() &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;type&nbsp;=&nbsp;INPUT_PATH.substring(INPUT_PATH.lastIndexOf(</span><span class="string">"."</span><span>)&nbsp;+&nbsp;</span><span class="number">1</span><span>,&nbsp;INPUT_PATH.length()) &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.toLowerCase(); &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">if</span><span>&nbsp;(type.equals(</span><span class="string">"pdf"</span><span>)) &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">return</span><span>&nbsp;</span><span class="number">0</span><span>; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">else</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">return</span><span>&nbsp;</span><span class="number">9</span><span>; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">private</span><span>&nbsp;</span><span class="keyword">static</span><span>&nbsp;</span><span class="keyword">void</span><span>&nbsp;toHtml() &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">if</span><span>(</span><span class="keyword">new</span><span>&nbsp;File(INPUT_PATH).isFile()) &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">try</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;cmd&nbsp;=&nbsp;</span><span class="string">"cmd&nbsp;/c&nbsp;start&nbsp;X:\\pdftohtml.bat&nbsp;\""</span><span>&nbsp;+&nbsp;PROJECT_PATH&nbsp;+&nbsp;</span><span class="string">"\"&nbsp;\""</span><span>&nbsp;+&nbsp;INPUT_PATH&nbsp;+&nbsp;</span><span class="string">"\""</span><span>; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Runtime.getRuntime().exec(cmd); &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">catch</span><span>&nbsp;(IOException&nbsp;e) &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e.printStackTrace(); &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></li>
    <li><span>}&nbsp;&nbsp;</span></li>
</ol>
</div>
<pre class="java" style="display: none" name="code">public class ConvertPdf
{
private static String INPUT_PATH;
private static String PROJECT_PATH;
public static void convertToHtml(String file, String project)
{
INPUT_PATH = file;
PROJECT_PATH = project;
if(checkContentType()==0)
{
toHtml();
}
}
private static int checkContentType()
{
String type = INPUT_PATH.substring(INPUT_PATH.lastIndexOf(".") + 1, INPUT_PATH.length())
.toLowerCase();
if (type.equals("pdf"))
return 0;
else
return 9;
}
private static void toHtml()
{
if(new File(INPUT_PATH).isFile())
{
try
{
String cmd = "cmd /c start X:\\pdftohtml.bat \"" + PROJECT_PATH + "\" \"" + INPUT_PATH + "\"";
Runtime.getRuntime().exec(cmd);
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
}</pre>
<p>String cmd = "....";此处代码是调用创建的bat文件进行转换&nbsp;</p>
<p>&nbsp;</p>
<p>8) 测试转换</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<div class="dp-highlighter">
<div class="bar">
<div class="tools">Java代码 <a title="复制代码" onclick="dp.sh.Toolbar.CopyToClipboard(this);return false;" href="http://www.javaeye.com/topic/333676#"><img alt="复制代码" src="http://www.javaeye.com/images/icon_copy.gif" _counted="undefined" /></a></div>
</div>
<ol class="dp-j">
    <li><span><span class="keyword">public</span><span>&nbsp;</span><span class="keyword">static</span><span>&nbsp;</span><span class="keyword">void</span><span>&nbsp;main(String[]&nbsp;args) &nbsp;&nbsp;</span></span></li>
    <li><span>{ &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;ConvertPdf.convertToHtml(</span><span class="string">"C:\\test.pdf"</span><span>,&nbsp;</span><span class="string">"X:\\xpdf"</span><span>); &nbsp;&nbsp;</span></span></li>
    <li><span>}&nbsp;&nbsp;</span></li>
</ol>
</div>
<pre class="java" style="display: none" name="code">public static void main(String[] args)
{
ConvertPdf.convertToHtml("C:\\test.pdf", "X:\\xpdf");
}</pre>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>以上就是整理的内容，后续还会添加视频转换为FLV格式，如果需要的话:)</p>
<p>说的不是很详细，碰到问题的朋友可以自己努力解决一下:)</p>
 <img src ="http://www.blogjava.net/conans/aggbug/255092.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/conans/" target="_blank">CONAN</a> 2009-02-17 14:57 <a href="http://www.blogjava.net/conans/articles/255092.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java程序类加载完全揭密</title><link>http://www.blogjava.net/conans/articles/251110.html</link><dc:creator>CONAN</dc:creator><author>CONAN</author><pubDate>Tue, 13 Jan 2009 05:00:00 GMT</pubDate><guid>http://www.blogjava.net/conans/articles/251110.html</guid><description><![CDATA[<p>类加载是java语言提供的最强大的机制之一。尽管类加载并不是讨论的热点话题，但所有的编程人员都应该了解其工作机制，明白如何做才能让其满足我们的需要。这能有效节省我们的编码时间，从不断调试ClassNotFoundException,
ClassCastException的工作中解脱出来。
<br />
<br />
这篇文章从基础讲起，比如代码与数据的不同之处是什么，他们是如何构成一个实例或对象的。然后深入探讨java虚拟机（JVM）是如何利用类加载器读取代码，以及java中类加载器的主要类型。接着用一个类加载的基本算法看一下类加载器如何加载一个内部类。本文的下一节演示一段代码来说明扩展和开发属于自己的类加载器的必要性。紧接着解释如何使用定制的类加载器来完成一个一般意义上的任务，使其可以加载任意远端客户的代码，在JVM中定义，实例化并执行它。本文包括了J2EE关于类加载的规范——事实上这已经成为了J2EE的标准之一。<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;&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;&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 />
<strong>类与数据</strong><br />
<br />
一个类代表要执行的代码，而数据则表示其相关状态。状态时常改变，而代码则不会。当我们将一个特定的状态与一个类相对应起来，也就意味着将一个类事例化。尽管相同的类对应的实例其状态千差万别，但其本质都对应着同一段代码。在JAVA中，一个类通常有着一个.class文件，但也有例外。在JAVA的运行时环境中（Java
runtime），每一个类都有一个以第一类(first-class)的Java对象所表现出现的代码，其是java.lang.Class的实例。我们编译一个JAVA文件，编译器都会嵌入一个public,
static,
final修饰的类型为java.lang.Class，名称为class的域变量在其字节码文件中。因为使用了public修饰，我们可以采用如下的形式对其访问：<br />
<br />
</p>
<table width="90%" align="center" bgcolor="#e3e3e3" border="1" bordercolor="#cccccc">
    <tbody>
        <tr>
            <td>java.lang.Class klass =
            Myclass.class;</td>
        </tr>
    </tbody>
</table>
<br />
一旦一个类被载入JVM中，同一个类就不会被再次载入了（切记，同一个类）。这里存在一个问题就是什么是&#8220;同一个类&#8221;？正如一个对象有一个具体的状态，即标识，一个对象始终和其代码(类)相关联。同理，载入JVM的类也有一个具体的标识，我们接下来看。<br />
<br />
在Java中，一个类用其完全匹配类名(fully
qualified class
name)作为标识，这里指的完全匹配类名包括包名和类名。但在JVM中一个类用其全名和一个加载类ClassLoader的实例作为唯一标识。因此，如果一个名为Pg的包中，有一个名为Cl的类，被类加载器KlassLoader的一个实例kl1加载，Cl的实例，即C1.class在JVM中表示为(Cl,
Pg, kl1)。这意味着两个类加载器的实例(Cl, Pg, kl1) 和 (Cl, Pg,
kl2)是不同的，被它们所加载的类也因此完全不同，互不兼容的。那么在JVM中到底有多少种类加载器的实例？下一节我们揭示答案。<br />
<br />
<strong>类加载器</strong><br />
<br />
在JVM中，每一个类都被java.lang.ClassLoader的一些实例来加载.类ClassLoader是在包中java.lang里，开发者可以自由地继承它并添加自己的功能来加载类。<br />
<br />
无论何时我们键入java
MyMainClass来开始运行一个新的JVM，&#8220;引导类加载器(bootstrap class
loader)&#8221;负责将一些关键的Java类，如java.lang.Object和其他一些运行时代码先加载进内存中。运行时的类在JRE\lib\rt.jar包文件中。因为这属于系统底层执行动作，我们无法在JAVA文档中找到引导类加载器的工作细节。基于同样的原因，引导类加载器的行为在各JVM之间也是大相径庭。<br />
同理，如果我们按照如下方式：<br />
<br />
<table width="90%" align="center" bgcolor="#e3e3e3" border="1" bordercolor="#cccccc">
    <tbody>
        <tr>
            <td>log(java.lang.String.class.getClassLoader());</td>
        </tr>
    </tbody>
</table>
<p><br />
来获取java的核心运行时类的加载器，就会得到null。<br />
<br />
接下来介绍java的扩展类加载器。扩展库提供比java运行代码更多的特性，我们可以把扩展库保存在由java.ext.dirs属性提供的路径中。<br />
<br />
(编辑注：java.ext.dirs属性指的是系统属性下的一个key，所有的系统属性可以通过System.getProperties()方法获得。在编者的系统中，java.ext.dirs的value是&#8221;
C:\Program
Files\Java\jdk1.5.0_04\jre\lib\ext&#8221;。下面将要谈到的如java.class.path也同属系统属性的一个key。)<br />
<br />
类ExtClassLoader专门用来加载所有java.ext.dirs下的.jar文件。开发者可以通过把自己的.jar文件或库文件加入到扩展目录的classpath，使其可以被扩展类加载器读取。<br />
<br />
从开发者的角度，第三种同样也是最重要的一种类加载器是AppClassLoader。这种类加载器用来读取所有的对应在java.class.path系统属性的路径下的类。<br />
<br />
Sun的java指南中，文章&#8220;理解扩展类加载&#8221;（Understanding
Extension Class
Loading）对以上三个类加载器路径有更详尽的解释，这是其他几个JDK中的类加载器<br />
<br />
●java.net.URLClassLoader
<br />
<br />
●java.security.SecureClassLoader
<br />
<br />
●java.rmi.server.RMIClassLoader
<br />
<br />
●sun.applet.AppletClassLoader <br />
<br />
java.lang.Thread，包含了public
ClassLoader
getContextClassLoader()方法，这一方法返回针对一具体线程的上下文环境类加载器。此类加载器由线程的创建者提供，以供此线程中运行的代码在需要加载类或资源时使用。如果此加载器未被建立，缺省是其父线程的上下文类加载器。原始的类加载器一般由读取应用程序的类加载器建立。</p>
<p>&nbsp;</p>
<p align="center">&nbsp;&nbsp;&nbsp;&nbsp;&lt;二&gt;</p>
<p align="center"><strong>类加载器如何工作？<br />
<br />
</strong>　　除了引导类加载器，所有的类加载器都有一个父类加载器，不仅如此，所有的类加载器也都是java.lang.ClassLoader类型。以上两种类加载器是不同的，而且对于开发者自订制的类加载器的正常运行也至关重要。最重要的方面是正确设置父类加载器。任何类加载器，其父类加载器是加载该类加载器的类加载器实例。（记住，类加载器本身也是一个类！）<br />
<br />
使用loadClass()方法可以从类加载器中获得该类。我们可以通过java.lang.ClassLoader的源代码来了解该方法工作的细节，如下：<br />
<br />
<table width="90%" align="center" bgcolor="#e3e3e3" border="1" bordercolor="#cccccc">
    <tbody>
        <tr>
            <td>protected synchronized Class&lt;?&gt; loadClass (String name, boolean
            resolve) throws ClassNotFoundException<br />
            {<br />
            // First check if the class is
            already loaded <br />
            Class c = findLoadedClass(name); <br />
            if (c == null)
            <br />
            {<br />
            try <br />
            {<br />
            if (parent != null)<br />
            {<br />
            c =
            parent.loadClass(name, false);<br />
            } else {<br />
            c =
            findBootstrapClass0(name);<br />
            }<br />
            } catch (ClassNotFoundException e) {
            <br />
            // If still not found, then invoke // findClass to find the class.
            <br />
            c = findClass(name);<br />
            }<br />
            }<br />
            if (resolve)
            <br />
            {<br />
            resolveClass(c);<br />
            }<br />
            return
            c;<br />
            }</td>
        </tr>
    </tbody>
</table>
<br />
我们可以使用ClassLoader的两种构造方法来设置父类加载器：<br />
<br />
<table width="90%" align="center" bgcolor="#e3e3e3" border="1" bordercolor="#cccccc">
    <tbody>
        <tr>
            <td>public class MyClassLoader extends ClassLoader<br />
            {<br />
            public
            MyClassLoader()<br />
            {<br />
            super(MyClassLoader.class.getClassLoader());<br />
            }<br />
            }</td>
        </tr>
    </tbody>
</table>
<br />
或<br />
<br />
<table width="90%" align="center" bgcolor="#e3e3e3" border="1" bordercolor="#cccccc">
    <tbody>
        <tr>
            <td>public class MyClassLoader extends ClassLoader<br />
            {<br />
            public
            MyClassLoader()<br />
            {<br />
            super(getClass().getClassLoader());<br />
            }<br />
            }</td>
        </tr>
    </tbody>
</table>
<br />
第一种方式较为常用，因为通常不建议在构造方法里调用getClass()方法，因为对象的初始化只是在构造方法的出口处才完全完成。因此，如果父类加载器被正确建立，当要示从一个类加载器的实例获得一个类时，如果它不能找到这个类，它应该首先去访问其父类。如果父类不能找到它(即其父类也不能找不这个类，等等)，而且如果findBootstrapClass0()方法也失败了，则调用findClass()方法。findClass()方法的缺省实现会抛出ClassNotFoundException，当它们继承java.lang.ClassLoader来订制类加载器时开发者需要实现这个方法。findClass()的缺省实现方式如下：<br />
<br />
<table width="90%" align="center" bgcolor="#e3e3e3" border="1" bordercolor="#cccccc">
    <tbody>
        <tr>
            <td>protected Class&lt;?&gt; findClass(String name) throws
            ClassNotFoundException { throw new ClassNotFoundException(name);
            }</td>
        </tr>
    </tbody>
</table>
<br />
在findClass()方法内部，类加载器需要获取任意来源的字节码。来源可以是文件系统，URL，数据库，可以产生字节码的另一个应用程序，及其他类似的可以产生java规范的字节码的来源。你甚至可以使用BCEL
(Byte Code Engineering
Library：字节码工程库)，它提供了运行时创建类的捷径。BCEL已经被成功地使用在以下方面：编译器，优化器，混淆器，代码产生器及其他分析工具。一旦字节码被检索，此方法就会调用defineClass()方法，此行为对不同的类加载实例是有差异的。因此，如果两个类加载实例从同一个来源定义一个类，所定义的结果是不同的。<br />
<br />
JAVA语言规范（Java
language
specification）详细解释了JAVA执行引擎中的类或接口的加载（loading），链接（linking）或初始化（initialization）过程。<br />
<br />
图一显示了一个主类称为MyMainClass的应用程序。依照之前的阐述，MyMainClass.class会被AppClassLoader加载。
MyMainClass创建了两个类加载器的实例：CustomClassLoader1 和
CustomClassLoader2,他们可以从某数据源（比如网络）获取名为Target的字节码。这表示类Target的类定义不在应用程序类路径或扩展类路径。在这种情况下，如果MyMainClass想要用自定义的类加载器加载Target类，CustomClassLoader1和CustomClassLoader2会分别独立地加载并定义Target.class类。这在java中有重要的意义。如果Target类有一些静态的初始化代码，并且假设我们只希望这些代码在JVM中只执行一次，而这些代码在我们目前的步骤中会执行两次——分别被不同的CustomClassLoaders加载并执行。如果类Target被两个CustomClassLoaders加载并创建两个实例Target1和Target2，如图一显示，它们不是类型兼容的。换句话说，在JVM中无法执行以下代码：<br />
<br />
<table width="90%" align="center" bgcolor="#e3e3e3" border="1" bordercolor="#cccccc">
    <tbody>
        <tr>
            <td>Target target3 = (Target)
            target2;</td>
        </tr>
    </tbody>
</table>
<br />
以上代码会抛出一个ClassCastException。这是因为JVM把他们视为分别不同的类，因为他们被不同的类加载器所定义。这种情况当我们不是使用两个不同的类加载器CustomClassLoader1
和
CustomClassLoader2，而是使用同一个类加载器CustomClassLoader的不同实例时，也会出现同样的错误。这些会在本文后边用具体代码说明。<br />
<br />
<table width="90%" align="center" border="0">
    <tbody>
        <tr>
            <td>
            <div align="center"><img alt="" src="http://dev.yesky.com/imagelist/05/10/364n0268z3zb.JPG" width="449" height="566" /><br />
            <br />
            图1. 在同一个JVM中多个类加载器加载同一个目标类</div>
            </td>
        </tr>
    </tbody>
</table>
</p>
<p align="center">&nbsp;</p>
<p align="center">&lt;三&gt;<br />
<strong>为什么我们需要我们自己的类加载器<br />
<br />
</strong>　　原因之一为开发者写自己的类加载器来控制JVM中的类加载行为，java中的类靠其包名和类名来标识，对于实现了java.io.Serializable接口的类，serialVersionUID扮演了一个标识类版本的重要角色。这个唯一标识是一个类名、接口名、成员方法及属性等组成的一个64位的哈希字段，而且也没有其他快捷的方式来标识一个类的版本。严格说来，如果以上的都匹配，那么则属于同一个类。<br />
<br />
但是让我们思考如下情况：我们需要开发一个通用的执行引擎。可以执行实现某一特定接口的任何任务。当任务被提交到这个引擎，首先需要加载这个任务的代码。假设不同的客户对此引擎提交了不同的任务，凑巧，这些所有的任务都有一个相同的类名和包名。现在面临的问题就是这个引擎是否可以针对不同的用户所提交的信息而做出不同的反应。这一情况在下文的参考一节有可供下载的代码样例，samepath
和 differentversions，这两个目录分别演示了这一概念。 图2 显示了文件目录结构，有三个子目录samepath,
differentversions, 和 differentversionspush，里边是例子：<br />
<br />
<table width="90%" align="center" border="0">
    <tbody>
        <tr>
            <td>
            <div align="center"><img alt="" src="http://dev.yesky.com/imagelist/05/10/9l33653u08js.JPG" width="446" height="461" /><br />
            图2.
            文件夹结构组织示例</div>
            </td>
        </tr>
    </tbody>
</table>
<br />
在samepath
中，类version.Version保存在v1和v2两个子目录里，两个类具有同样的类名和包名，唯一不同的是下边这行：<br />
<br />
<table width="90%" align="center" bgcolor="#e3e3e3" border="1" bordercolor="#cccccc">
    <tbody>
        <tr>
            <td>public void fx(){ log("this = " + this + "; Version.fx(1).");
            }</td>
        </tr>
    </tbody>
</table>
<br />
V1中，日志记录中有Version.fx(1)，而在v2中则是Version.fx(2)。把这个两个存在细微不同的类放在一个classpath下，然后运行Test类：<br />
<br />
<table width="90%" align="center" bgcolor="#e3e3e3" border="1" bordercolor="#cccccc">
    <tbody>
        <tr>
            <td>set CLASSPATH=.;%CURRENT_ROOT%\v1;%CURRENT_ROOT%\v2<br />
            %JAVA_HOME%\bin\java
            Test</td>
        </tr>
    </tbody>
</table>
<br />
图3显示了控制台输出。我们可以看到对应着Version.fx(1)的代码被执行了，因为类加载器在classpath首先看到此版本的代码。<br />
<br />
<table width="90%" align="center" border="0">
    <tbody>
        <tr>
            <td>
            <div align="center"><img alt="" src="http://dev.yesky.com/imagelist/05/10/spb0js0651u8.JPG" width="428" height="193" /><br />
            图3.
            在类路径中samepath测试排在最前面的version
            1</div>
            </td>
        </tr>
    </tbody>
</table>
<br />
再次运行，类路径做如下微小改动。 <br />
<br />
<table width="90%" align="center" bgcolor="#e3e3e3" border="1" bordercolor="#cccccc">
    <tbody>
        <tr>
            <td>set CLASSPATH=.;%CURRENT_ROOT%\v2;%CURRENT_ROOT%\v1<br />
            %JAVA_HOME%\bin\java
            Test</td>
        </tr>
    </tbody>
</table>
<br />
控制台的输出变为图4。对应着Version.fx(2)的代码被加载，因为类加载器在classpath中首先找到它的路径。<br />
<br />
<table width="90%" align="center" border="0">
    <tbody>
        <tr>
            <td>
            <div align="center"><img alt="" src="http://dev.yesky.com/imagelist/05/10/wb8py2r57509.JPG" width="428" height="192" /><br />
            图4.
            在类路径中samepath测试排在最前面的version
            2</div>
            </td>
        </tr>
    </tbody>
</table>
<br />
根据以上例子可以很明显地看出，类加载器加载在类路径中被首先找到的元素。如果我们在v1和v2中删除了version.Version，做一个非version.Version形式的.jar文件，如myextension.jar，把它放到对应java.ext.dirs的路径下，再次执行后看到version.Version不再被AppClassLoader加载，而是被扩展类加载器加载。如图5所示。<br />
<br />
<table width="90%" align="center" border="0">
    <tbody>
        <tr>
            <td>
            <div align="center"><img alt="" src="http://dev.yesky.com/imagelist/05/10/rm118409yo66.JPG" width="429" height="158" /><br />
            图5.
            AppClassLoader及ExtClassLoader</div>
            </td>
        </tr>
    </tbody>
</table>
<br />
继续这个例子，文件夹differentversions包含了一个RMI执行引擎，客户端可以提供给执行引擎任何实现了common.TaskIntf接口的任务。子文件夹client1
和 client2包含了类client.TaskImpl有个细微不同的两个版本。两个类的区别在以下几行：<br />
<br />
<table width="90%" align="center" bgcolor="#e3e3e3" border="1" bordercolor="#cccccc">
    <tbody>
        <tr>
            <td>static<br />
            {<br />
            log("client.TaskImpl.class.getClassLoader (v1) : " +
            TaskImpl.class.getClassLoader());<br />
            }<br />
            <br />
            public void execute(){ log("this =
            " + this + "; execute(1)");
            }</td>
        </tr>
    </tbody>
</table>
<br />
在client1和client2里分别有getClassLoader(v1) 与
execute(1)和getClassLoader(v2) 与
execute(2)的的log语句。并且，在开始执行引擎RMI服务器的代码中，我们随意地将client2的任务实现放在类路径的前面。<br />
<br />
<table width="90%" align="center" bgcolor="#e3e3e3" border="1" bordercolor="#cccccc">
    <tbody>
        <tr>
            <td>CLASSPATH=%CURRENT_ROOT%\common;%CURRENT_ROOT%\server;<br />
            %CURRENT_ROOT%\client2;%CURRENT_ROOT%\client1<br />
            %JAVA_HOME%\bin\java
            server.Server</td>
        </tr>
    </tbody>
</table>
<br />
如图6，7，8的屏幕截图，在客户端VM，各自的client.TaskImpl类被加载、实例化，并发送到服务端的VM来执行。从服务端的控制台，可以明显看到client.TaskImpl代码只被服务端的VM执行一次，这个单一的代码版本在服务端多次生成了许多实例，并执行任务。<br />
<br />
<table width="90%" align="center" border="0">
    <tbody>
        <tr>
            <td>
            <div align="center"><img alt="" src="http://dev.yesky.com/imagelist/05/10/511b346uj8rr.JPG" width="429" height="252" /><br />
            图6.
            执行引擎服务器控制台</div>
            </td>
        </tr>
    </tbody>
</table>
<br />
图6显示了服务端的控制台，加载并执行两个不同的客户端的请求，如图7、8所示。需要注意的是，代码只被加载了一次（从静态初始化块的日志中也可以明显看出），但对于客户端的调用这个方法被执行了两次。<br />
<br />
<table width="90%" align="center" border="0">
    <tbody>
        <tr>
            <td>
            <div align="center"><img alt="" src="http://dev.yesky.com/imagelist/05/10/806698qpznjf.JPG" width="429" height="169" /><br />
            图7.
            执行引擎客户端
            1控制台　</div>
            </td>
        </tr>
    </tbody>
</table>
<br />
图7中，客户端VM加载了含有client.TaskImpl.class.getClassLoader(v1)的日志内容的类TaskImpl的代码，并提供给服务端的执行引擎。图8的客户端VM加载了另一个TaskImpl的代码，并发送给服务端。<br />
<br />
<table width="90%" align="center" border="0">
    <tbody>
        <tr>
            <td>
            <div align="center"><img alt="" src="http://dev.yesky.com/imagelist/05/10/75d4v3u7sq8y.JPG" width="428" height="169" /><br />
            图8.
            执行引擎客户端
            2控制台　</div>
            </td>
        </tr>
    </tbody>
</table>
<br />
在客户端的VM中，类client.TaskImpl被分别加载，初始化，并发送到服务端执行。图6还揭示了client.TaskImpl的代码只在服务端的VM中加载了一次，但这&#8220;唯一的一次&#8221;却在服务端创造了许多实例并执行。或许客户端1该不高兴了因为并不是它的client.TaskImpl(v1)的方法调用被服务端执行了，而是其他的一些代码。如何解决这一问题？答案就是实现定制的类加载器。<br />
</p>
<p align="center">&lt;四&gt;</p>
<p align="center"><strong>定制类加载器<br />
<br />
</strong>　　要较好地控制类的加载，就要实现定制的类加载器。所有自定义的类加载器都应继承自java.lang.ClassLoader。而且在构造方法中，我们也应该设置父类加载器。然后重写findClass()方法。differentversionspush文件夹包含了一个叫做FileSystemClassLoader的自订制的类加载器。其结构如图9所示。<br />
<br />
<table width="90%" align="center" border="0">
    <tbody>
        <tr>
            <td>
            <div align="center"><img alt="" src="http://dev.yesky.com/imagelist/05/10/r5ji48er1w43.JPG" width="400" height="630" /><br />
            图9.
            定制类加载器关系</div>
            </td>
        </tr>
    </tbody>
</table>
<br />
以下是在common.FileSystemClassLoader实现的主方法：<br />
<br />
<table width="90%" align="center" bgcolor="#e3e3e3" border="1" bordercolor="#cccccc">
    <tbody>
        <tr>
            <td>public byte[] findClassBytes(String
            className)<br />
            {<br />
            try<br />
            {<br />
            String pathName = currentRoot +
            File.separatorChar + className. replace(&#8217;.&#8217;, File.separatorChar) +
            ".class";<br />
            FileInputStream inFile = new FileInputStream(pathName);
            <br />
            byte[] classBytes = new
            byte[inFile.available()];<br />
            inFile.read(classBytes); <br />
            return classBytes;
            <br />
            }<br />
            catch (java.io.IOException ioEx)<br />
            {<br />
            return null;
            <br />
            }<br />
            }<br />
            <br />
            public Class findClass(String name)throws
            ClassNotFoundException<br />
            {<br />
            byte[] classBytes = findClassBytes(name);
            <br />
            if (classBytes==null)<br />
            {<br />
            throw new ClassNotFoundException();<br />
            }
            else{<br />
            return defineClass(name, classBytes, 0,
            classBytes.length);<br />
            }<br />
            }<br />
            <br />
            public Class findClass(String name, byte[]
            classBytes)throws ClassNotFoundException<br />
            {<br />
            if
            (classBytes==null)<br />
            {<br />
            throw new ClassNotFoundException(
            "(classBytes==null)"); <br />
            } else{<br />
            return defineClass(name, classBytes, 0,
            classBytes.length);<br />
            }<br />
            }<br />
            <br />
            public void execute(String codeName,
            byte[] code)<br />
            {<br />
            Class klass = null;<br />
            try<br />
            {<br />
            klass =
            findClass(codeName, code);<br />
            TaskIntf task = (TaskIntf)
            klass.newInstance();<br />
            task.execute();<br />
            } catch(Exception
            exception){<br />
            exception.printStackTrace();<br />
            }<br />
            }</td>
        </tr>
    </tbody>
</table>
<br />
这个类供客户端把client.TaskImpl(v1)转换成字节数组，之后此字节数组被发送到RMI服务端。在服务端，一个同样的类用来把字节数组的内容转换回代码。客户端代码如下：<br />
<br />
<table width="90%" align="center" bgcolor="#e3e3e3" border="1" bordercolor="#cccccc">
    <tbody>
        <tr>
            <td>public class Client<br />
            {<br />
            public static void main (String[]
            args)<br />
            {<br />
            try{ byte[] code = getClassDefinition ("client.TaskImpl");
            <br />
            serverIntf.execute("client.TaskImpl",
            code);<br />
            }<br />
            catch(RemoteException
            remoteException)<br />
            {<br />
            remoteException.printStackTrace();<br />
            }<br />
            }<br />
            <br />
            private
            static byte[] getClassDefinition (String codeName)<br />
            {<br />
            String userDir =
            System.getProperties(). getProperty("BytePath");<br />
            FileSystemClassLoader fscl1
            = null; <br />
            try<br />
            {<br />
            fscl1 = new FileSystemClassLoader
            (userDir);<br />
            }<br />
            catch(FileNotFoundException
            fileNotFoundException)<br />
            {<br />
            fileNotFoundException.printStackTrace();
            <br />
            }<br />
            return
            fscl1.findClassBytes(codeName);<br />
            }<br />
            }</td>
        </tr>
    </tbody>
</table>
<br />
在执行引擎中，从客户端收到的代码被送到定制的类加载器中。定制的类加载器把其从字节数组定义成类，实例化并执行。需要指出的是，对每一个客户请求，我们用类FileSystemClassLoader的不同实例来定义客户端提交的client.TaskImpl。而且，client.TaskImpl并不在服务端的类路径中。这也就意味着当我们在FileSystemClassLoader调用findClass()方法时，findClass()调用内在的defineClass()方法。类client.TaskImpl被特定的类加载器实例所定义。因此，当FileSystemClassLoader的一个新的实例被使用，类又被重新定义为字节数组。因此，对每个客户端请求类client.TaskImpl被多次定义，我们就可以在相同执行引擎JVM中执行不同的client.TaskImpl的代码。<br />
<br />
<table width="90%" align="center" bgcolor="#e3e3e3" border="1" bordercolor="#cccccc">
    <tbody>
        <tr>
            <td>public void execute(String codeName, byte[] code)throws
            RemoteException<br />
            {<br />
            FileSystemClassLoader fileSystemClassLoader =
            null;<br />
            try<br />
            {<br />
            fileSystemClassLoader = new
            FileSystemClassLoader();<br />
            fileSystemClassLoader.execute(codeName,
            code);<br />
            }<br />
            catch(Exception exception)<br />
            {<br />
            throw new
            RemoteException(exception.getMessage());
            <br />
            }<br />
            }</td>
        </tr>
    </tbody>
</table>
<br />
示例在differentversionspush文件夹下。服务端和客户端的控制台界面分别如图10，11，12所示：<br />
<br />
<table width="90%" align="center" border="0">
    <tbody>
        <tr>
            <td>
            <div align="center"><img alt="" src="http://dev.yesky.com/imagelist/05/10/xt7zup25eyzk.JPG" width="428" height="251" /><br />
            图10.
            定制类加载器执行引擎</div>
            </td>
        </tr>
    </tbody>
</table>
<br />
图10显示的是定制的类加载器控制台。我们可以看到client.TaskImpl的代码被多次加载。实际上针对每一个客户端，类都被加载并初始化。<br />
<br />
<table width="90%" align="center" border="0">
    <tbody>
        <tr>
            <td>
            <div align="center"><img alt="" src="http://dev.yesky.com/imagelist/05/10/qjuwm77a3l70.JPG" width="429" height="183" /><br />
            图11.
            定制类加载器，客户端1</div>
            </td>
        </tr>
    </tbody>
</table>
<br />
图11中，含有client.TaskImpl.class.getClassLoader(v1)的日志记录的类TaskImpl的代码被客户端的VM加载，然后送到服务端。图12
另一个客户端把包含有client.TaskImpl.class.getClassLoader(v1)的类代码加载并送往服务端。<br />
<br />
<table width="90%" align="center">
    <tbody>
        <tr>
            <td>
            <div align="center"><img alt="" src="http://dev.yesky.com/imagelist/05/10/1dpn2sj8pu1l.JPG" width="427" height="181" /><br />
            图12.
            定制类加载器，客户端1</div>
            </td>
        </tr>
    </tbody>
</table>
<br />
这段代码演示了我们如何利用不同的类加载器实例来在同一个VM上执行不同版本的代码。<br />
<br />
<strong>J2EE的类加载器</strong><br />
<br />
J2EE的服务器倾向于以一定间隔频率，丢弃原有的类并重新载入新的类。在某些情况下会这样执行，而有些情况则不。同样，对于一个web服务器如果要丢弃一个servlet实例，可能是服务器管理员的手动操作，也可能是此实例长时间未相应。当一个JSP页面被首次请求，容器会把此JSP页面翻译成一个具有特定形式的servlet代码。一旦servlet代码被创建，容器就会把这个servlet翻译成class文件等待被使用。对于提交给容器的每次请求，容器都会首先检查这个JSP文件是否刚被修改过。是的话就重新翻译此文件，这可以确保每次的请求都是及时更新的。企业级的部署方案以.ear,
.war,
.rar等形式的文件，同样需要重复加载，可能是随意的也可能是依照某种配置方案定期执行。对所有的这些情况——类的加载、卸载、重新加载&#8230;&#8230;全部都是建立在我们控制应用服务器的类加载机制的基础上的。实现这些需要扩展的类加载器，它可以执行由其自身所定义的类。Brett
Peterson已经在他的文章 Understanding J2EE Application Server Class Loading
Architectures给出了J2EE应用服务器的类加载方案的详细说明，详见网站TheServerSide.com。<br />
<br />
<strong>结束语</strong><br />
<br />
本文探讨了类载入到虚拟机是如何进行唯一标识的，以及类如果存在同样的类名和包名时所产生的问题。因为没有一个直接可用的类版本管理机制，所以如果我们要按自己的意愿来加载类时，需要自己订制类加载器来扩展其行为。我们可以利用许多J2EE服务器所提供的&#8220;热部署&#8221;功能来重新加载一个新版本的类，而不改动服务器的VM。即使不涉及应用服务器，我们也可以利用定制类加载器来控制java应用程序载入类时的具体行为。Ted
Neward的书Server-Based Java Programming中详细阐述java的类加载，J2EE的API以及使用他们的最佳途径。<br />
</p>
<img src ="http://www.blogjava.net/conans/aggbug/251110.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/conans/" target="_blank">CONAN</a> 2009-01-13 13:00 <a href="http://www.blogjava.net/conans/articles/251110.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ThreadLocal 的使用</title><link>http://www.blogjava.net/conans/articles/251108.html</link><dc:creator>CONAN</dc:creator><author>CONAN</author><pubDate>Tue, 13 Jan 2009 04:58:00 GMT</pubDate><guid>http://www.blogjava.net/conans/articles/251108.html</guid><description><![CDATA[<p>EasyDBO的数据库连接部分，为了给每个连接提供上下文，程序用到了一个关键的类——ThreadLocal。</p>
<p><strong>什么是ThreadLocal？</strong></p>
<p>顾名思义它是local
variable（线程局部变量）。它的功用非常简单，就是为每一个使用该变量的线程都提供一个变量值的副本，是每一个线程都可以独立地改变自己的副本，而不会和其它线程的副本冲突。从线程的角度看，就好像每一个线程都完全拥有该变量。</p>
<p>使用场景</p>
<ol>
    <li><strong>To keep state with a thread (user-id, transaction-id,
    logging-id)</strong>
    </li>
    <li><strong>To cache objects which you need frequently</strong></li>
</ol>
<p><strong>ThreadLocal类</strong></p>
<p>它主要由四个方法组成initialValue()，get()，set(T)，remove()，其中值得注意的是initialValue()，该方法是一个protected的方法，显然是为了子类重写而特意实现的。该方法返回当前线程在该线程局部变量的初始值，这个方法是一个延迟调用方法，在一个线程第1次调用get()或者set(Object)时才执行，并且仅执行1次。ThreadLocal中的确实实现直接返回一个null：</p>
<p>ThreadLocal的原理</p>
<p>ThreadLocal是如何做到为每一个线程维护变量的副本的呢？其实实现的思路很简单，在ThreadLocal类中有一个Map，用于存储每一个线程的变量的副本。比如下面的示例实现：</p>
<p>public class ThreadLocal<br />
{<br />
private Map values =
Collections.synchronizedMap(new HashMap());<br />
public Object
get()<br />
{<br />
Thread curThread = Thread.currentThread(); <br />
Object o =
values.get(curThread); <br />
if (o == null &amp;&amp;
!values.containsKey(curThread))<br />
{<br />
o =
initialValue();<br />
values.put(curThread, o); <br />
}<br />
return o;
<br />
}</p>
<p>　public void set(Object
newValue)<br />
{<br />
values.put(Thread.currentThread(), newValue);<br />
}</p>
<p>　public Object initialValue()<br />
{<br />
return null; <br />
}<br />
} </p>
<p><strong>ThreadLocal 的使用</strong></p>
<p>使用方法一：</p>
<p>Hibernate的文档时看到了关于使ThreadLocal管理多线程访问的部分。具体代码如下 <br />
<br />
1.&nbsp;&nbsp;public static
final ThreadLocal session = new ThreadLocal(); <br />
2.&nbsp;&nbsp;public static Session
currentSession() { <br />
3.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Session s = (Session)session.get();
<br />
4.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//open a new session,if this session has none <br />
5.&nbsp;&nbsp; if(s ==
null){ <br />
6.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;s = sessionFactory.openSession(); <br />
7.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;session.set(s);
<br />
8.&nbsp;&nbsp; } <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return s; <br />
9. } <br />
<br />
我们逐行分析 <br />
1。
初始化一个ThreadLocal对象，ThreadLocal有三个成员方法 get()、set()、initialvalue()。
<br />
&nbsp;&nbsp;&nbsp;&nbsp;如果不初始化initialvalue，则initialvalue返回null。
<br />
3。session的get根据当前线程返回其对应的线程内部变量，也就是我们需要的net.sf.hibernate.Session（相当于对应每个数据库连接）.多线程情况下共享数据库链接是不安全的。ThreadLocal保证了每个线程都有自己的s（数据库连接）。
<br />
5。如果是该线程初次访问，自然，s（数据库连接）会是null，接着创建一个Session，具体就是行6。 <br />
6。创建一个数据库连接实例 s
<br />
7。保存该数据库连接s到ThreadLocal中。
<br />
8。如果当前线程已经访问过数据库了，则从session中get()就可以获取该线程上次获取过的连接实例。 </p>
<p>使用方法二</p>
<p>当要给线程初始化一个特殊值时，需要自己实现ThreadLocal的子类并重写该方法，通常使用一个内部匿名类对ThreadLocal进行子类化，EasyDBO中创建jdbc连接上下文就是这样做的：</p>
<p>public class JDBCContext{<br />
&nbsp;private static Logger logger =
Logger.getLogger(JDBCContext.class);<br />
&nbsp;private DataSource ds;<br />
&nbsp;protected
Connection connection;<br />
&nbsp;private boolean isValid = true;<br />
&nbsp;private static
ThreadLocal jdbcContext;<br />
&nbsp;<br />
&nbsp;private JDBCContext(DataSource
ds){<br />
&nbsp;&nbsp;this.ds = ds;<br />
&nbsp;&nbsp;createConnection();&nbsp;&nbsp;<br />
&nbsp;}<br />
&nbsp;public static
JDBCContext getJdbcContext(javax.sql.DataSource
ds)<br />
&nbsp;{&nbsp;&nbsp;<br />
&nbsp;&nbsp;if(jdbcContext==null)jdbcContext=new
JDBCContextThreadLocal(ds);<br />
&nbsp;&nbsp;JDBCContext context = (JDBCContext)
jdbcContext.get();<br />
&nbsp;&nbsp;if (context == null) {<br />
&nbsp;&nbsp;&nbsp;context = new
JDBCContext(ds);<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;return context;<br />
&nbsp;}</p>
<p>&nbsp;private static class JDBCContextThreadLocal extends ThreadLocal
{<br />
&nbsp;&nbsp;public javax.sql.DataSource ds;<br />
&nbsp;&nbsp;public
JDBCContextThreadLocal(javax.sql.DataSource
ds)<br />
&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;this.ds=ds;<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;protected synchronized Object
initialValue() {<br />
&nbsp;&nbsp;&nbsp;return new JDBCContext(ds);<br />
&nbsp;&nbsp;}<br />
&nbsp;}<br />
}</p>
<p>使用单例模式，不同的线程调用getJdbcContext()获得自己的jdbcContext，都是通过JDBCContextThreadLocal
内置子类来获得JDBCContext对象的线程局部变量，这个变量是该线程所独有的。</p>
<img src ="http://www.blogjava.net/conans/aggbug/251108.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/conans/" target="_blank">CONAN</a> 2009-01-13 12:58 <a href="http://www.blogjava.net/conans/articles/251108.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Classloader 基础</title><link>http://www.blogjava.net/conans/articles/251107.html</link><dc:creator>CONAN</dc:creator><author>CONAN</author><pubDate>Tue, 13 Jan 2009 04:56:00 GMT</pubDate><guid>http://www.blogjava.net/conans/articles/251107.html</guid><description><![CDATA[<p><strong><font face="Verdana">什么是ClassLoader</font></strong></p>
<p>ClassLoader是一个抽象类，我们用它的实例对象来装载类，<font face="宋体">它负责将</font> <span lang="EN-US">Java</span> <span style="font-family: 宋体;">字节码装载到</span>
<span lang="EN-US">JVM</span> <span style="font-family: 宋体;">中，</span>
<span style="font-family: 宋体;">并使其成为</span>
<span lang="EN-US">JVM</span> <span style="font-family: 宋体;">一部分。</span>
<span lang="EN-US">JVM</span> <span style="font-family: 宋体;">的类动态装载技术能够在运行时刻动态地加载或者替换系统的某些功能模块，</span><span style="font-family: 宋体;">而不影响系统其他功能模块的正常运行。</span>一般是通过类名读入一个class文件来装载这个类，（其它加载形式暂时没有研究过）。</p>
<p><strong><font face="Verdana">ClassLoader装载过程</font></strong></p>
<p class="WordPro" style="margin: 5.25pt 0cm 0pt; text-indent: 24pt;"><span style="font-family: 宋体;">类装载就是寻找一个类或是一个接口的字节码文件并通过解析该字节码来构造代表这个类或是这个接口的</span>
<span lang="EN-US">class</span> <span style="font-family: 宋体;">对象的过程。在</span>
<span lang="EN-US">Java</span> <span style="font-family: 宋体;">中，类装载器把一个类装入</span>
<span lang="EN-US">Java</span> <span style="font-family: 宋体;">虚拟机中，要经过三个步骤来完成：装载、链接和初始化，其中链接又可以分成校验、准备和解析三步，除了解析外，其它步骤是严格按照顺序完成的，各个步骤的主要工作如下：</span>
</p>
<p class="WordPro" style="margin: 5.25pt 0cm 0pt 69pt; text-indent: -21pt;"><span lang="EN-US"><span>1.<span style="font-family: 'Times New Roman'; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal; -x-system-font: none;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span></span></span><span style="font-family: 宋体;">装载：查找和导入类或接口的字节码；</span>
</p>
<p class="WordPro" style="margin: 5.25pt 0cm 0pt 69pt; text-indent: -21pt;"><span lang="EN-US"><span>2.<span style="font-family: 'Times New Roman'; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal; -x-system-font: none;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span></span></span><span style="font-family: 宋体;">链接：执行下面的校验、准备和解析步骤，其中解析步骤是可以选择的；</span>
</p>
<p class="WordPro" style="margin: 5.25pt 0cm 0pt 90pt; text-indent: -21pt;"><span style="font-family: Wingdings;" lang="EN-US"><span>l<span style="font-family: 'Times New Roman'; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal; -x-system-font: none;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span></span></span><span style="font-family: 宋体;">校验：检查导入类或接口的二进制数据的正确性；</span>
</p>
<p class="WordPro" style="margin: 5.25pt 0cm 0pt 90pt; text-indent: -21pt;"><span style="font-family: Wingdings;" lang="EN-US"><span>l<span style="font-family: 'Times New Roman'; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal; -x-system-font: none;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span></span></span><span style="font-family: 宋体;">准备：给类的静态变量分配并初始化存储空间；</span>
</p>
<p class="WordPro" style="margin: 5.25pt 0cm 0pt 90pt; text-indent: -21pt;"><span style="font-family: Wingdings;" lang="EN-US"><span>l<span style="font-family: 'Times New Roman'; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal; -x-system-font: none;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span></span></span><span style="font-family: 宋体;">解析：将符号引用转成直接引用；</span>
</p>
<p class="WordPro" style="margin: 5.25pt 0cm 0pt 69pt; text-indent: -21pt;"><span lang="EN-US"><span>3.<span style="font-family: 'Times New Roman'; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal; -x-system-font: none;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span></span></span><span style="font-family: 宋体;">初始化：激活类的静态变量的初始化</span>
<span lang="EN-US">Java</span> <span style="font-family: 宋体;">代码和静态</span>
<span lang="EN-US">Java</span> <span style="font-family: 宋体;">代码块。</span></p>
<p><strong><font face="Verdana">装载的实现</font></strong></p>
<p class="WordPro" style="margin: 5.25pt 0cm 0pt; text-indent: 24pt;"><span lang="EN-US">JVM</span> <span style="font-family: 宋体;">中类的装载是由</span>
<span lang="EN-US">ClassLoader</span> <span style="font-family: 宋体;">和它的子类来实现的。</span>
<span lang="EN-US">Java ClassLoader </span><span style="font-family: 宋体;">是一个重要的</span>
<span lang="EN-US">Java</span> <span style="font-family: 宋体;">运行时系统组件，它负责在运行时查找和装入</span>
<span lang="EN-US">Java</span> <span style="font-family: 宋体;">字节码。</span>
</p>
<p class="WordPro" style="margin: 5.25pt 0cm 0pt; text-indent: 24pt;"><span style="font-family: 宋体;">在</span>
<span lang="EN-US">Java</span> <span style="font-family: 宋体;">中，</span>
<span lang="EN-US">ClassLoader</span> <span style="font-family: 宋体;">是一个抽象类，它在包</span>
<span lang="EN-US">java.lang</span> <span style="font-family: 宋体;">中。可以这样说，只要了解了</span>
<span lang="EN-US">ClassLoader</span> <span style="font-family: 宋体;">中的一些重要的方法，再结合上面所介绍的</span>
<span lang="EN-US">JVM</span> <span style="font-family: 宋体;">中类装载的具体的过程，对动态装载类这项技术就有了一个比较大概的掌握，这些重要的方法包括以下几个：</span>
</p>
<p class="WordPro" style="margin: 5.25pt 0cm 0pt 45pt; text-indent: -21pt;"><span lang="EN-US"><span>1.<span style="font-family: 'Times New Roman'; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal; -x-system-font: none;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span></span></span><span lang="EN-US">loadCass</span> <span style="font-family: 宋体;">方法：</span>
<span lang="EN-US">loadClass(String name ,boolean resolve)</span> <span style="font-family: 宋体;">其中</span>
<span lang="EN-US">name</span> <span style="font-family: 宋体;">参数指定了</span>
<span lang="EN-US">JVM</span> <span style="font-family: 宋体;">需要的类的名称</span>
<span lang="EN-US">,</span> <span style="font-family: 宋体;">该名称以类的全限定名表示，如</span>
<span lang="EN-US">Java.lang.Object</span> <span style="font-family: 宋体;">；</span>
<span lang="EN-US">resolve</span> <span style="font-family: 宋体;">参数告诉方法是否需要解析类，在初始化类之前，应考虑类解析，并不是所有的类都需要解析，如果</span>
<span lang="EN-US">JVM</span> <span style="font-family: 宋体;">只需要知道该类是否存在或找出该类的超类，那么就不需要解析。这个方法是</span>
<span lang="EN-US">ClassLoader </span><span style="font-family: 宋体;">的入口点。</span>
</p>
<p class="WordPro" style="margin: 5.25pt 0cm 0pt 45pt; text-indent: -21pt;"><span lang="EN-US"><span>2.<span style="font-family: 'Times New Roman'; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal; -x-system-font: none;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span></span></span><span lang="EN-US">defineClass</span> <span style="font-family: 宋体;">方法</span>
<span lang="EN-US"><span>&nbsp; </span></span><span style="font-family: 宋体;">这个方法接受类文件的字节数组并把它转换成</span>
<span lang="EN-US">Class</span> <span style="font-family: 宋体;">对象。字节数组可以是从本地文件系统或网络装入的数据。它把字节码分析成运行时数据结构、校验有效性等等。</span>
</p>
<p class="WordPro" style="margin: 5.25pt 0cm 0pt 45pt; text-indent: -21pt;"><span lang="EN-US"><span>3.<span style="font-family: 'Times New Roman'; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal; -x-system-font: none;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span></span></span><span lang="EN-US">findSystemClass</span> <span style="font-family: 宋体;">方法</span>
<span lang="EN-US"><span>&nbsp; </span>findSystemClass</span>
<span style="font-family: 宋体;">方法从本地文件系统装入</span>
<span lang="EN-US">Java</span> <span style="font-family: 宋体;">字节码。它在本地文件系统中寻找类文件，如果存在，就使用</span>
<span lang="EN-US">defineClass</span> <span style="font-family: 宋体;">将字节数组转换成</span>
<span lang="EN-US">Class</span> <span style="font-family: 宋体;">对象。当运行</span>
<span lang="EN-US">Java</span> <span style="font-family: 宋体;">应用程序时</span>
<span lang="EN-US">,</span> <span style="font-family: 宋体;">这是</span>
<span lang="EN-US">JVM </span><span style="font-family: 宋体;">正常装入类的缺省机制。</span>
</p>
<p class="WordPro" style="margin: 5.25pt 0cm 0pt 45pt; text-indent: -21pt;"><span lang="EN-US"><span>4.<span style="font-family: 'Times New Roman'; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal; -x-system-font: none;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span></span></span><span lang="EN-US">resolveClass</span> <span style="font-family: 宋体;">方法</span>
<span lang="EN-US">resolveClass(Class c)</span> <span style="font-family: 宋体;">方法解析装入的类，如果该类已经被解析过那么将不做处理。当调用</span>
<span lang="EN-US">loadClass</span> <span style="font-family: 宋体;">方法时</span>
<span lang="EN-US">,</span> <span style="font-family: 宋体;">通过它的</span>
<span lang="EN-US">resolve </span><span style="font-family: 宋体;">参数决定是否要进行解析。</span>
</p>
<p class="WordPro" style="margin: 5.25pt 0cm 0pt 45pt; text-indent: -21pt;"><span lang="EN-US"><span>5.<span style="font-family: 'Times New Roman'; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal; -x-system-font: none;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span></span></span><span lang="EN-US">findLoadedClass</span> <span style="font-family: 宋体;">方法</span>
<span lang="EN-US"><span>&nbsp; </span></span><span style="font-family: 宋体;">当调用</span>
<span lang="EN-US">loadClass</span> <span style="font-family: 宋体;">方法装入类时</span>
<span lang="EN-US">,</span> <span style="font-family: 宋体;">调用</span>
<span lang="EN-US">findLoadedClass </span><span style="font-family: 宋体;">方法来查看</span>
<span lang="EN-US">ClassLoader</span> <span style="font-family: 宋体;">是否已装入这个类</span>
<span lang="EN-US">,</span> <span style="font-family: 宋体;">如果已装入</span>
<span lang="EN-US">,</span> <span style="font-family: 宋体;">那么返回</span>
<span lang="EN-US">Class</span> <span style="font-family: 宋体;">对象</span>
<span lang="EN-US">,</span> <span style="font-family: 宋体;">否则返回</span>
<span lang="EN-US">NULL</span> <span style="font-family: 宋体;">。如果强行装载已存在的类</span>
<span lang="EN-US">,</span> <span style="font-family: 宋体;">将会抛出链接错误。</span>
</p>
<p><strong><font face="Verdana">java.lang.Class类</font></strong></p>
<p>某个类的所有实例内部都有一个引用，指向该类对应的Class的实例的位置，每个java类对应的Class实例可以当作是类在内存中的代理人。所以当要获得类的信息(如有哪些类变量,有哪些方法)时，都可以让类对应的Class的实例代劳.java的Reflection机制就大量的使用这种方法来实现。但是Class类无法手工实例化，当载入任意类的时候自动创建一个该类对应的Class的实例。每个java类都是由某个classLoader(ClassLoader的实例)来载入的，因此Class类别的实例中都会他的ClassLoader的实例的引用。可以通过getClass.getClassLoader()得到CLassLoader的实例。</p>
<p><strong><font face="Verdana">java动态载入class的两种方式:</font></strong>
<br />
1)implicit隐式,即利用实例化才载入的特性来动态载入class <br />
2)explicit显式方式,又分两种方式:
<br />
a)java.lang.Class的forName()方法 <br />
b)java.lang.ClassLoader的loadClass()方法</p>
<p><strong><font face="Verdana">各种java类由哪些classLoader加载?</font></strong> </p>
<p>1)java类可以通过实例.getClass.getClassLoader()得到<br />
2)接口由AppClassLoader(SystemClassLoader)载入
，SystemClassLoader：可以由ClassLoader.getSystemClassLoader()获得实例<br />
3)ClassLoader类由bootstrap
loader载入</p>
<p><strong><font face="Verdana">ClassLoader hierachy:</font></strong> </p>
<p>1)jvm初始化产生bootstrap loader。并设定它的父ClassLoader为null</p>
<p>2)bootstrap loader建立AppClassLoader,载入 运行java.exe时
的-cp或-classpath中的类（每个运行中的线程都有一个成员contextClassLoader，用来在运行时动态地载入其它类系统默认的contextClassLoader是systemClassLoader）</p>
<p><shape id="_x0000_i1026" style="width: 331.5pt; height: 148.5pt;" type="#_x0000_t75"><imagedata src="file:///C:%5CDOCUME%7E1%5CADMINI%7E1%5CLOCALS%7E1%5CTemp%5Cmsohtml1%3C%21--%20%7E%20Value_txtContent%20%7E%20--%3E3%5Cclip_image003.gif" o:href="http://www.yesky.com/image20010518/159569.gif"><img src="http://www.yesky.com/image20010518/159569.gif"  alt="" /> </imagedata></shape></p>
<p class="a" style="margin: 5.25pt 0cm 0pt;" align="center"><span lang="EN-US">Java</span> <span style="font-family: 宋体;">类装载的代理结构</span>
</p>
<p class="WordPro" style="margin: 5.25pt 0cm 0pt; text-indent: 24pt;"><span style="font-family: 宋体;">根</span>
<span lang="EN-US">(Bootstrap) </span><span style="font-family: 宋体;">装载器：该装载器没有父装载器，它是</span>
<span lang="EN-US">JVM</span> <span style="font-family: 宋体;">实现的一部分，从</span>
<span lang="EN-US">sun.boot.class.path</span> <span style="font-family: 宋体;">装载运行时库的核心代码。</span>
</p>
<p>
</p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
</p>
<p>
</p>
<p class="WordPro" style="margin: 5.25pt 0cm 0pt; text-indent: 24pt;"><span style="font-family: 宋体;">扩展</span>
<span lang="EN-US">(Extension) </span><span style="font-family: 宋体;">装载器：继承的父装载器为根装载器，不像根装载器可能与运行时的操作系统有关，这个类装载器是用纯</span>
<span lang="EN-US">Java</span> <span style="font-family: 宋体;">代码实现的，它从</span>
<span lang="EN-US">java.ext.dirs (</span> <span style="font-family: 宋体;">扩展目录</span>
<span lang="EN-US">)</span> <span style="font-family: 宋体;">中装载代码。</span>
</p>
<p>
</p>
<p class="WordPro" style="margin: 5.25pt 0cm 0pt; text-indent: 24pt;"><span style="font-family: 宋体;">系统</span>
<span lang="EN-US">(System or Application) </span><span style="font-family: 宋体;">装载器：装载器为扩展装载器，我们都知道在安装</span>
<span lang="EN-US">JDK</span> <span style="font-family: 宋体;">的时候要设置环境变量</span>
<span lang="EN-US">(CLASSPATH )</span> <span style="font-family: 宋体;">，这个类装载器就是从</span>
<span lang="EN-US">java.class.path(CLASSPATH </span><span style="font-family: 宋体;">环境变量</span>
<span lang="EN-US">)</span> <span style="font-family: 宋体;">中装载代码的，它也是用纯</span>
<span lang="EN-US">Java</span> <span style="font-family: 宋体;">代码实现的，同时还是用户自定义类装载器的缺省父装载器。</span>
</p>
<p class="WordPro" style="margin: 5.25pt 0cm 0pt; text-indent: 24pt;"><span style="font-family: 宋体;">小应用程序</span>
<span lang="EN-US">(Applet) </span><span style="font-family: 宋体;">装载器：父装载器为系统装载器，它从用户指定的网络上的特定目录装载小应用程序代码。</span>
</p>
<p class="WordPro" style="margin: 5.25pt 0cm 0pt; text-indent: 24pt;">java中的<font face="宋体">代理结构</font>是自上而下查找类的，这与很多web装载器不同。</p>
<p>
</p>
<p><strong><font face="Verdana">tomcat中的实现的子ClassLoader的结构</font></strong></p>
<p>Tomcat Server在启动的时候将构造一个ClassLoader树，以保证模块的类库是私有的 <br />
Tomcat
Server的ClassLoader结构如下： <br />
<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<img style="vertical-align: middle;" src="http://www.yculblog.com/images/emotions/010.gif" border="0"  alt="" />---------------------------+ <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;| &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Bootstrap &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&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;| <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;| &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&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;| <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Common &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&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;|
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;| &nbsp;&nbsp;&nbsp;&nbsp;Catalina &nbsp;Shared &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&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;| <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;| &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;WebApp1 &nbsp;WebApp2 &nbsp;&nbsp;| <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<img style="vertical-align: middle;" src="http://www.yculblog.com/images/emotions/010.gif" border="0"  alt="" />---------------------------+ <br />
<br />
其中： <br />
- Bootstrap -
载入JVM自带的类和$JAVA_HOME/jre/lib/ext/*.jar <br />
- System - 载入$CLASSPATH/*.class <br />
-
Common - 载入$CATALINA_HOME/common/...，它们对TOMCAT和所有的WEB APP都可见 <br />
- Catalina -
载入$CATALINA_HOME/server/...，它们仅对TOMCAT可见，对所有的WEB APP都不可见 <br />
- Shared -
载入$CATALINA_HOME/shared/...，它们仅对所有WEB APP可见，对TOMCAT不可见（也不必见） <br />
- WebApp? -
载入ContextBase?/WEB-INF/...，它们仅对该WEB APP可见 </p>
<p>ClassLoader被组织成树形，一般的工作原理是： <br />
1) 线程需要用到某个类，于是contextClassLoader被请求来载入该类
<br />
2) contextClassLoader请求它的父ClassLoader来完成该载入请求 <br />
3)
如果父ClassLoader无法载入类，则contextClassLoader试图自己来载入
<br />
<br />
<br />
注意：WebApp?ClassLoader的工作原理和上述有少许不同：
<br />
它先试图自己载入类（在ContextBase?/WEB-INF/...中载入类），如果无法载入，再请求父ClassLoader完成 </p>
<img src ="http://www.blogjava.net/conans/aggbug/251107.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/conans/" target="_blank">CONAN</a> 2009-01-13 12:56 <a href="http://www.blogjava.net/conans/articles/251107.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title> JAVA操作大型文本文件</title><link>http://www.blogjava.net/conans/articles/213757.html</link><dc:creator>CONAN</dc:creator><author>CONAN</author><pubDate>Wed, 09 Jul 2008 11:14:00 GMT</pubDate><guid>http://www.blogjava.net/conans/articles/213757.html</guid><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: &nbsp;在前面的废话不想看的可以skip-----由于工作需要，经常需要打开和查询250M左右的文本文件（总行数超过250万行）分析日志，公司发的笔记本内存才512M，地球人都知道，这样的电脑根本不能胜任。不知道有没有人和我一样倒霉，面对这么庞大的文件，曾经让我很无奈，很彷徨。从寻找优秀的类似notepad这样的文本工具，企图通过工具来提高下速度，其中JIURL这个记事本工具，我个人觉得很好，...&nbsp;&nbsp;<a href='http://www.blogjava.net/conans/articles/213757.html'>阅读全文</a><img src ="http://www.blogjava.net/conans/aggbug/213757.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/conans/" target="_blank">CONAN</a> 2008-07-09 19:14 <a href="http://www.blogjava.net/conans/articles/213757.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>一次Java垃圾收集调优实战</title><link>http://www.blogjava.net/conans/articles/213752.html</link><dc:creator>CONAN</dc:creator><author>CONAN</author><pubDate>Wed, 09 Jul 2008 11:07:00 GMT</pubDate><guid>http://www.blogjava.net/conans/articles/213752.html</guid><description><![CDATA[<h3>1 资料</h3>
<ul>
    <li><span class="nobr"><a title="Visit page outside Confluence" href="http://calvin.javaeye.com/blog/91905" rel="nofollow" mce_href="http://calvin.javaeye.com/blog/91905" linktype="raw" linktext="JDK5.0垃圾收集优化之--Don't Pause(花钱的年华)|http://calvin.javaeye.com/blog/91905">JDK5.0垃圾收集优化之--Don't Pause(花钱的年华)<sup><img class="rendericon" height="7" alt="" src="http://wiki.springside.org.cn/images/icons/linkext7.gif" width="7" align="absMiddle" border="0" mce_src="http://www.blogjava.net/images/icons/linkext7.gif" /></sup></a></span>&#8201;
    <li><span class="nobr"><a title="Visit page outside Confluence" href="http://calvin.javaeye.com/blog/91903" rel="nofollow" mce_href="http://calvin.javaeye.com/blog/91903" linktype="raw" linktext="编写对GC友好，又不泄漏的代码(花钱的年华)|http://calvin.javaeye.com/blog/91903">编写对GC友好，又不泄漏的代码(花钱的年华)<sup><img class="rendericon" height="7" alt="" src="http://wiki.springside.org.cn/images/icons/linkext7.gif" width="7" align="absMiddle" border="0" mce_src="http://www.blogjava.net/images/icons/linkext7.gif" /></sup></a></span>&#8201;
    <li><span class="nobr"><a title="Visit page outside Confluence" href="http://pengjiaheng.spaces.live.com/blog/cns%212DAA368B386E6AEA%21770.entry" rel="nofollow" mce_href="http://pengjiaheng.spaces.live.com/blog/cns%212DAA368B386E6AEA%21770.entry" linktype="raw" linktext="JVM调优总结|http://pengjiaheng.spaces.live.com/blog/cns!2DAA368B386E6AEA!770.entry">JVM调优总结<sup><img class="rendericon" height="7" alt="" src="http://wiki.springside.org.cn/images/icons/linkext7.gif" width="7" align="absMiddle" border="0" mce_src="http://www.blogjava.net/images/icons/linkext7.gif" /></sup></a></span>&#8201;
    <li><span class="nobr"><a title="Visit page outside Confluence" href="http://www.md.pp.ru/%7Eeu/jdk6options.html" rel="nofollow" mce_href="http://www.md.pp.ru/%7Eeu/jdk6options.html" linktype="raw" linktext="JDK 6所有选项及默认值|http://www.md.pp.ru/~eu/jdk6options.html">JDK 6所有选项及默认值<sup><img class="rendericon" height="7" alt="" src="http://wiki.springside.org.cn/images/icons/linkext7.gif" width="7" align="absMiddle" border="0" mce_src="http://www.blogjava.net/images/icons/linkext7.gif" /></sup></a></span>&#8201; </li>
</ul>
<h3>2 GC日志打印</h3>
<p>&nbsp; GC调优是个很实验很伽利略的活儿，GC日志是先决的数据参考和最终验证：</p>
<div class="macro" macrotext="{code}" command="code">
<div class="code">
<div class="codeContent">
<pre class="code-java">-XX:+PrintGCDetails -XX:+PrintGCTimeStamps(GC发生的时间) -XX:+PrintGCApplicationStoppedTime(GC消耗了多少时间) -XX:+PrintGCApplicationConcurrentTime(GC之间运行了多少时间)</pre>
</div>
</div>
</div>
<p>&#8201;</p>
<h3><a class="" style="background-image: url(/CuteSoft_Client/CuteEditor/Load.ashx?type=image&file=anchor.gif); width: 20px; text-indent: 20px; background-repeat: no-repeat; height: 20px" name="JavaPerformance-1.3收集器选择"></a>3 收集器选择</h3>
<h4><a class="" style="background-image: url(/CuteSoft_Client/CuteEditor/Load.ashx?type=image&file=anchor.gif); width: 20px; text-indent: 20px; background-repeat: no-repeat; height: 20px" name="JavaPerformance-CMS收集器：暂停时间优先"></a>CMS收集器：暂停时间优先</h4>
<p>&nbsp;&nbsp; 配置参数：-XX:+UseConcMarkSweepGC<br />
&nbsp;&nbsp; 已默认无需配置的参数：-XX:+UseParNewGC(Parallel收集新生代) -XX:+CMSPermGenSweepingEnabled(CMS收集持久代) -XX:UseCMSCompactAtFullCollection(FullGC时压缩年老代)</p>
<p>&nbsp;&nbsp; 初始效果：1G堆内存的新生代约60m，minor gc约5-20毫秒，full gc约130毫秒。</p>
<h4><a class="" style="background-image: url(/CuteSoft_Client/CuteEditor/Load.ashx?type=image&file=anchor.gif); width: 20px; text-indent: 20px; background-repeat: no-repeat; height: 20px" name="JavaPerformance-Parallel收集器：吞吐量优先"></a>Parallel收集器：吞吐量优先</h4>
<p>&nbsp;&nbsp;&nbsp; 配置参数： -XX:+UseParallelGC -XX:+UseParallelOldGC(Parallel收集年老代，从JDK6.0开始支持)</p>
<p>&nbsp;&nbsp;&nbsp; 已默认无需配置的参数： -XX:+UseAdaptiveSizePolicy(动态调整新生代大小)</p>
<p>&nbsp;&nbsp;&nbsp; 初始效果：1G堆内存的新生代约90-110m(动态调整)，minor gc约5-20毫秒，full gc没有UseParallelOldGC 参数约 1.3秒，有UseParallelOldGC参数约1.06秒，差别不大。</p>
<p>&nbsp;&nbsp;&nbsp; 另外-XX:MaxGCPauseMillis=100 设置期望minor gc的最大时间，JVM会以此来调整新生代的大小，但在此测试环境中对象死的太快，此参数作用不大。</p>
<h3><a class="" style="background-image: url(/CuteSoft_Client/CuteEditor/Load.ashx?type=image&file=anchor.gif); width: 20px; text-indent: 20px; background-repeat: no-repeat; height: 20px" name="JavaPerformance-1.4调优实战"></a>4 调优实战</h3>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Parallel收集高达1秒的暂停时间基本不可忍受，所以选择CMS收集器。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 不知为何在被压的Mule 2.0应用里，每秒都有大约400M的海量短命对象产生：</p>
<ol>
    <li>因为默认60M的新生代太小了，频繁发生minor gc，大约0.2秒就进行一次。
    <li>因为CMS收集器中MaxTenuringThreshold(生代对象撑过过多少次minor gc才进入年老代的设置)默认0，存活的临时对象不经过Survivor区直接进入年老代，不久就占满年老代发生full gc。 </li>
</ol>
<p>&nbsp; &nbsp;&nbsp; 对这两个参数进行调优，既要改善上面两种情况，又要避免新生代过大，复制次数过多造成minor gc的暂停时间过长。</p>
<ol>
    <li>使用-Xmn调到1/3 总内存。比较后设置-Xmn500m，新生代实际约460m。(-XX:NewRatio参数无效)。
    <li>添加-XX:+PrintTenuringDistribution 参数观察各个Age的对象总大小，观察后设置-XX:MaxTenuringThreshold=5。 </li>
</ol>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 优化后，大约1.1秒才发生一次minor GC，同时年老代的增长速度大大减缓，预计几个小时才会发生一次GC，而minor gc速度依然保持在15-20ms之间。</p>
<p>&nbsp; &nbsp; &nbsp; 参数定稿：</p>
<div class="macro" macrotext="{code}" command="code">
<div class="code">
<div class="codeContent">
<pre class="code-java">&nbsp;-Xms1024m -Xmx1024m -Xmn500m -XX:+UseConcMarkSweepGC&nbsp;  -XX:MaxTenuringThreshold=5&nbsp; -XX:+ExplicitGCInvokesConcurrent</pre>
</div>
</div>
</div>
<p>&#8201;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 最后服务处理速度从1180 tps 上升到1380 tps，调整两个参数提升17%的性能还是笔很划算的买卖。</p>
<img src ="http://www.blogjava.net/conans/aggbug/213752.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/conans/" target="_blank">CONAN</a> 2008-07-09 19:07 <a href="http://www.blogjava.net/conans/articles/213752.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Effective Java读书笔记 </title><link>http://www.blogjava.net/conans/articles/212422.html</link><dc:creator>CONAN</dc:creator><author>CONAN</author><pubDate>Thu, 03 Jul 2008 12:36:00 GMT</pubDate><guid>http://www.blogjava.net/conans/articles/212422.html</guid><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 终于翻开这本James都称赞的java经典书籍了，发现比一般的英语书籍要难懂一些。但是里面的Item都是非常实用的，是java程序员应该理解的。Creating and Destroying ObjectItem 1:考虑用静态工厂方法替代构造器例如：public static Boolean valueOf(boolean b)&nbsp;&nbsp;&nbsp;&nbsp;&n...&nbsp;&nbsp;<a href='http://www.blogjava.net/conans/articles/212422.html'>阅读全文</a><img src ="http://www.blogjava.net/conans/aggbug/212422.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/conans/" target="_blank">CONAN</a> 2008-07-03 20:36 <a href="http://www.blogjava.net/conans/articles/212422.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java中类型与类的区别 </title><link>http://www.blogjava.net/conans/articles/212197.html</link><dc:creator>CONAN</dc:creator><author>CONAN</author><pubDate>Wed, 02 Jul 2008 12:35:00 GMT</pubDate><guid>http://www.blogjava.net/conans/articles/212197.html</guid><description><![CDATA[在Java中，数据类型包括以下两类：<br />
<br />
(1)基本数据类型：包括byte,short,int,long,float,double,char,boolean等八种类型，在Java中，基本数据类型的数据都是有符号数，没有无符号类型数据，这是不同于C++的一个地方。<br />
<br />
(2)复合数据类型：包括数组和类两种。其中类包括Integer,BigInteger等，参见Java类库java.lang.Number的所有子类；数组就是将数字与保存的数据对象联系起来的容器，可以是多维的，可以保存基本数据类型的数据，也可以保存类类型的数据。<br />
<br />
请看下例：<br />
(1) int i=10;<br />
(2) Integer i = new Integer(10);<br />
<br />
在上例中，变量i的值都是整型值10，但是在第一个方法中，变量i是一个int类型变量，属于一个基本数据类型；在第二个方法中，变量i是一个类的实例对象，属于一个复合类型Integer类的一个实例变量，更确切地说，i是一个指向Integer类实例对象的引用，在&#8220;=&#8221;右边是构造一个新分配的Integer类型的变量，该对象表示整型值10，而&#8220;=&#8221;左边是定义一个指向Integer类型对象的引用(对象句柄)，使得该对象引用指向新分配的对象。<br />
<br />
小结：类是一种特殊的数据类型，这就是类型与类的区别:) 
<img src ="http://www.blogjava.net/conans/aggbug/212197.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/conans/" target="_blank">CONAN</a> 2008-07-02 20:35 <a href="http://www.blogjava.net/conans/articles/212197.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java标准类库提供的容器总结 </title><link>http://www.blogjava.net/conans/articles/212196.html</link><dc:creator>CONAN</dc:creator><author>CONAN</author><pubDate>Wed, 02 Jul 2008 12:35:00 GMT</pubDate><guid>http://www.blogjava.net/conans/articles/212196.html</guid><description><![CDATA[<p>在Java中，容器主要包括：数组(Array)、集合(Collection)和映射(Map)三种。<br />
<br />
(1)数组Array：将数字与元素联系起来，其中的元素都具有相同的数据类型，只能通过下标来访问其元素；数组可以是一维的，也可以是多维的；数组一旦生成，其容量就不能改变。数组是一种复合数据类型，在Java中，除了可以像&#8220;int[] array;&#8221;来声明和表示一个数组，还可以用Array类来表示一个数组，同样地，JDK类库还提供了Arrays类类操作数组，该类定义了对数组进行操作的各种方法(赋值、排序、搜索、比较、查找元素等)。<br />
<br />
(2)集合Collection：是一个接口类，包括List、Set、Queue等子接口，其具体的实现类可以用来保存多个元素。这里只讨论常用的子接口List和Set的常用实现类。常用的List实现类有ArrayList、Vector和LinkedList等，常用的Set实现类有HashSet、LinkedHashSet和TreeSet等。需要注意的是，List和Set有着很大的不同，主要包括是否允许元素重复和是否维护元素的次序。<br />
<br />
(3)映射Map：保存相关联的键值对。其具体的实现类可以将键映射到值，根据键得到值，因此，一个映射不能包含重复的键，但是允许有重复的值，每个键最多只能映射到一个值。 常见的Map实现类有HashMap、Hashtable、LinkedHashMap和TreeMap等。<br />
<br />
为了讨论的方便，下面以Array，List、Set、Map为分类来讨论这几种容器的使用特点。<br />
<br />
(1)Array：<br />
<br />
<span style="background-color: #ffffff">&nbsp;&nbsp;&nbsp;&nbsp;数组的使用很直接，主要是根据下表来获取其元素。其特点就是一旦生成，其容量不能改变，并且每个元素之间不允许有&#8220;空隙&#8221;。其使用实例可以参考电子工业出版社&#8220;宝典&#8221;系列之《Java JDK 实例宝典》(夏先波 编著)，个人感觉这本书写得不错，给出了许多JDK类库的具体使用实例，代码的注释也比较详细，很适合初学者入门学习使用，如果看Java Doc 还是有不明白的地方，也可以参考此书:)<br />
<br />
(2)List：可用来存放多个元素，能够自动扩充容量，能够维护元素的次序，并且允许元素重复。<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;(2.1)ArrayList类：最常用的List实现类，内部是通过数组实现的，它允许对元素进行快速的随机访问，但是要从ArrayList的中间位置插入或者删除&nbsp;&nbsp;&nbsp;&nbsp;元素时，需要对数组进行复制、移动，代价比较高，因此，ArrayList适合随机查找和遍历，不适合插入和删除。<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;(2.2)Vector类：同ArrayList一样，其内部也是通过数组实现的，不同的是，Vector支持线程的同步，能够避免多线程同时写而引起的不一致，但是实现线程的同步需要很高的代价，因此访问Vector比ArrayList慢。<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;(2.3)LinkedList类：见其名，该类与链表肯定有关系:)该类的内部是通过链表来实现的，很适合数据的动态插入和删除，但是随即访问和遍历的速度比较慢。此外，该类还提供了List接口中没有定义的方法，专门用于操作表头和表尾元素，可以当作堆栈、队列和双向队列使用。</span><br />
<br />
(3)Set：可用来存放多个元素，但是不允许元素重复(即不保存重复元素)，也不能够维护元素的次序。很直观，联想一下数学中的集合的概念就很好理解了。此外，需要注意的是，加入Set的元素必须定义equals()方法以确保对象的唯一性，如String对象。<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;(3.1) HashSet类：采用散列函数对元素进行排序，是专门为快速查询而设计的存入HashSet的对象必须定义hashCode()方法。<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;(3.2)TreeSet类：采用红黑树的数据结构进行排序元素，使用它可以从Set中提取有序的序列。<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;(3.3) LinkedHashSet类：内部使用散列以加快查询速度，同时使用链表维护元素的插入次序，在使用迭代器遍历时，会按插入次序显示结果。<br />
<br />
<br />
(4)Map：可以用来存放相关联的键值对，根据键得到值。常见的Map实现类有HashMap、Hashtable、LinkedHashMap和TreeMap。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;(4.1)HashMap类：一个最常用的Map，它根据键的hashCode值存储数据，根据键可以直接获取它的值，具有很快的访问速度，但不支持线程同步。HashMap最多允许一条记录的键为null，但是允许多条记录的值为null。<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;(4.2)Hashtable类：与HashMap类似，但是它不允许记录的键或者值为null，支持线程同步，因而Hashtable在写入数据时会很慢。<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;(4.3)LinkedHashMap类：保存了记录的插入顺序，在用Iterator遍历它时，先得到的记录肯定时先插入的，在遍历的时候比HashMap慢。<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;(4.4)TreeMap类：能够把它保存的记录根据键排序，默认为升序排列。当用Iterator遍历它时，得到的记录是排过序的记录。</p>
<img src ="http://www.blogjava.net/conans/aggbug/212196.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/conans/" target="_blank">CONAN</a> 2008-07-02 20:35 <a href="http://www.blogjava.net/conans/articles/212196.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>常用java date 方法集合</title><link>http://www.blogjava.net/conans/articles/211309.html</link><dc:creator>CONAN</dc:creator><author>CONAN</author><pubDate>Sat, 28 Jun 2008 06:48:00 GMT</pubDate><guid>http://www.blogjava.net/conans/articles/211309.html</guid><description><![CDATA[计算某一月份的最大天数<br />
<br />
Calendar time=Calendar.getInstance();<br />
time.clear();<br />
time.set(Calendar.YEAR,year); //year 为 int <br />
time.set(Calendar.MONTH,i-1);//注意,Calendar对象默认一月为0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
int day=time.getActualMaximum(Calendar.DAY_OF_MONTH);//本月份的天数<br />
注：在使用set方法之前，必须先clear一下，否则很多信息会继承自系统当前时间<br />
<br />
2.Calendar和Date的转化<br />
<br />
(1) Calendar转化为Date<br />
Calendar cal=Calendar.getInstance();<br />
Date date=cal.getTime();<br />
<br />
(2) Date转化为Calendar<br />
Date date=new Date();<br />
Calendar cal=Calendar.getInstance();<br />
cal.setTime(date);<br />
<br />
3.格式化输出日期时间 （这个用的比较多）<br />
<br />
Date date=new Date();<br />
SimpleDateFormat df=new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");<br />
String time=df.format(date);<br />
System.out.println(time);<br />
<br />
4.计算一年中的第几星期<br />
<br />
(1)计算某一天是一年中的第几星期<br />
Calendar cal=Calendar.getInstance();<br />
cal.set(Calendar.YEAR, 2006);<br />
cal.set(Calendar.MONTH, 8);<br />
cal.set(Calendar.DAY_OF_MONTH, 3);<br />
int weekno=cal.get(Calendar.WEEK_OF_YEAR);<br />
<br />
(2)计算一年中的第几星期是几号<br />
SimpleDateFormat df=new SimpleDateFormat("yyyy-MM-dd");<br />
Calendar cal=Calendar.getInstance();<br />
cal.set(Calendar.YEAR, 2006);<br />
cal.set(Calendar.WEEK_OF_YEAR, 1);<br />
cal.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);<br />
System.out.println(df.format(cal.getTime()));<br />
输出:<br />
2006-01-02<br />
<br />
5.add()和roll()的用法(不太常用)<br />
<br />
(1)add()方法<br />
SimpleDateFormat df=new SimpleDateFormat("yyyy-MM-dd");<br />
Calendar cal=Calendar.getInstance();<br />
cal.set(Calendar.YEAR, 2006);<br />
cal.set(Calendar.MONTH, 8);<br />
cal.set(Calendar.DAY_OF_MONTH, 3);<br />
cal.add(Calendar.DATE, -4);<br />
Date date=cal.getTime();<br />
System.out.println(df.format(date));<br />
cal.add(Calendar.DATE, 4);<br />
date=cal.getTime();<br />
System.out.println(df.format(date));<br />
输出：<br />
&nbsp;&nbsp;&nbsp; 2006-08-30<br />
&nbsp;&nbsp;&nbsp; 2006-09-03<br />
(2)roll方法<br />
cal.set(Calendar.YEAR, 2006);<br />
cal.set(Calendar.MONTH, 8);<br />
cal.set(Calendar.DAY_OF_MONTH, 3);<br />
cal.roll(Calendar.DATE, -4);<br />
date=cal.getTime();<br />
System.out.println(df.format(date));<br />
cal.roll(Calendar.DATE, 4);<br />
date=cal.getTime();<br />
System.out.println(df.format(date));<br />
输出：<br />
&nbsp;&nbsp;&nbsp; 2006-09-29<br />
&nbsp;&nbsp;&nbsp; 2006-09-03<br />
可见，roll()方法在本月内循环，一般使用add()方法；<br />
<br />
6.计算两个任意时间中间的间隔天数（这个比较常用）<br />
(1)传进Calendar对象<br />
&nbsp;&nbsp;&nbsp; public int getIntervalDays(Calendar startday,Calendar endday)...{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(startday.after(endday))...{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Calendar cal=startday;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; startday=endday;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; endday=cal;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; long sl=startday.getTimeInMillis();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; long el=endday.getTimeInMillis();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; long ei=el-sl;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return (int)(ei/(1000*60*60*24));<br />
&nbsp;&nbsp;&nbsp; }<br />
(2)传进Date对象<br />
<br />
&nbsp;&nbsp;&nbsp; public int getIntervalDays(Date startday,Date endday)...{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(startday.after(endday))...{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Date cal=startday;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; startday=endday;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; endday=cal;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; long sl=startday.getTime();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; long el=endday.getTime();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; long ei=el-sl;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return (int)(ei/(1000*60*60*24));<br />
&nbsp;&nbsp;&nbsp; }<br />
(3)改进精确计算相隔天数的方法<br />
&nbsp;&nbsp;&nbsp; public int getDaysBetween (Calendar d1, Calendar d2) ...{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (d1.after(d2)) ...{ <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; java.util.Calendar swap = d1;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; d1 = d2;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; d2 = swap;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int days = d2.get(Calendar.DAY_OF_YEAR) - d1.get(Calendar.DAY_OF_YEAR);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int y2 = d2.get(Calendar.YEAR);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (d1.get(Calendar.YEAR) != y2) ...{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; d1 = (Calendar) d1.clone();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; do ...{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; days += d1.getActualMaximum(Calendar.DAY_OF_YEAR);//得到当年的实际天数<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; d1.add(Calendar.YEAR, 1);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } while (d1.get(Calendar.YEAR) != y2);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return days;<br />
&nbsp;&nbsp;&nbsp; }<br />
注意：通过上面的方法可以衍生出求任何时间，如要查出邮箱三周之内收到的邮件（得到当前系统时间－再得到三周前时间）用收件的时间去匹配 最好装化成 long去比较<br />
如：1年前日期（注意毫秒的转换）<br />
&nbsp;&nbsp; java.util.Date myDate=new java.util.Date();<br />
&nbsp;&nbsp; long myTime=(myDate.getTime()/1000)-60*60*24*365;<br />
&nbsp;&nbsp; myDate.setTime(myTime*1000);<br />
&nbsp;&nbsp; String mDate=formatter.format(myDate);<br />
<br />
7. String 和 Date ，Long 之间相互转换 （最常用）<br />
<br />
字符串转化成时间类型（字符串可以是任意类型，只要和SimpleDateFormat中的格式一致即可）<br />
通常我们取时间跨度的时候，会substring出具体时间－－long－比较<br />
<br />
java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat("M/dd/yyyy hh:mm:ss a",java.util.Locale.US);<br />
java.util.Date d = sdf.parse("5/13/2003 10:31:37 AM");<br />
long dvalue=d.getTime();<br />
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");<br />
String mDateTime1=formatter.format(d);<br />
<br />
8. 通过时间求时间<br />
<br />
年月周求日期<br />
SimpleDateFormat formatter2 = new SimpleDateFormat("yyyy-MM F E");<br />
java.util.Date date2= formatter2.parse("2003-05 5 星期五");<br />
SimpleDateFormat formatter3 = new SimpleDateFormat("yyyy-MM-dd");<br />
String mydate2=formatter3.format(date2);<br />
<br />
求是星期几<br />
mydate= myFormatter.parse("2001-1-1");<br />
SimpleDateFormat formatter4 = new SimpleDateFormat("E");<br />
String mydate3=formatter4.format(mydate);<br />
<br />
9. java 和 具体的数据库结合<br />
<br />
在开发web应用中，针对不同的数据库日期类型，我们需要在我们的程序中对日期类型做各种不同的转换。若对应数据库数据是oracle的Date类型，即只需要年月日的，可以选择使用java.sql.Date类型，若对应的是MSsqlserver 数据库的DateTime类型，即需要年月日时分秒的，选择java.sql.Timestamp类型<br />
你可以使用dateFormat定义时间日期的格式，转一个字符串即可<br />
<br />
class Datetest{<br />
*method 将字符串类型的日期转换为一个timestamp（时间戳记java.sql.Timestamp）<br />
*@param dateString 需要转换为timestamp的字符串<br />
*@return dataTime timestamp<br />
<br />
public final static java.sql.Timestamp string2Time(String dateString)<br />
throws java.text.ParseException {<br />
DateFormat dateFormat;<br />
dateFormat = new SimpleDateFormat("yyyy-MM-dd kk:mm:ss.SSS", Locale.ENGLISH);//设定格式<br />
//dateFormat = new SimpleDateFormat("yyyy-MM-dd kk:mm:ss", Locale.ENGLISH);<br />
dateFormat.setLenient(false);<br />
java.util.Date timeDate = dateFormat.parse(dateString);//util类型<br />
java.sql.Timestamp dateTime = new java.sql.Timestamp(timeDate.getTime());//Timestamp类型,timeDate.getTime()返回一个long型<br />
return dateTime;<br />
}<br />
<br />
*method 将字符串类型的日期转换为一个Date（java.sql.Date）<br />
*@param dateString 需要转换为Date的字符串<br />
*@return dataTime Date<br />
<br />
public final static java.sql.Date string2Date(String dateString)<br />
throws java.lang.Exception {<br />
DateFormat dateFormat;<br />
dateFormat = new SimpleDateFormat("yyyy-MM-dd", Locale.ENGLISH);<br />
dateFormat.setLenient(false);<br />
java.util.Date timeDate = dateFormat.parse(dateString);//util类型<br />
java.sql.Date dateTime = new java.sql.Date(timeDate.getTime());//sql类型<br />
return dateTime;<br />
}<br />
<br />
public static void main(String[] args){<br />
Date da = new Date();<br />
注意：这个地方da.getTime()得到的是一个long型的值<br />
System.out.println(da.getTime());<br />
<br />
由日期date转换为timestamp<br />
<br />
第一种方法：使用new Timestamp(long)<br />
Timestamp t = new Timestamp(new Date().getTime());<br />
System.out.println(t);<br />
<br />
第二种方法：使用Timestamp(int year,int month,int date,int hour,int minute,int second,int nano)<br />
Timestamp tt = new Timestamp(Calendar.getInstance().get(<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Calendar.YEAR) - 1900, Calendar.getInstance().get(<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Calendar.MONTH), Calendar.getInstance().get(<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Calendar.DATE), Calendar.getInstance().get(<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Calendar.HOUR), Calendar.getInstance().get(<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Calendar.MINUTE), Calendar.getInstance().get(<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Calendar.SECOND), 0);<br />
System.out.println(tt);<br />
<br />
try {<br />
String sToDate = "2005-8-18";//用于转换成java.sql.Date的字符串<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String sToTimestamp = "2005-8-18 14:21:12.123";//用于转换成java.sql.Timestamp的字符串<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Date date1 = string2Date(sToDate);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Timestamp date2 = string2Time(sToTimestamp);<br />
System.out.println("Date:"+date1.toString());//结果显示<br />
System.out.println("Timestamp:"+date2.toString());//结果显示<br />
}catch(Exception e) {<br />
e.printStackTrace();<br />
}<br />
}<br />
}&nbsp;<br />
<img src ="http://www.blogjava.net/conans/aggbug/211309.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/conans/" target="_blank">CONAN</a> 2008-06-28 14:48 <a href="http://www.blogjava.net/conans/articles/211309.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title> Java正则表达式详解</title><link>http://www.blogjava.net/conans/articles/209562.html</link><dc:creator>CONAN</dc:creator><author>CONAN</author><pubDate>Fri, 20 Jun 2008 14:44:00 GMT</pubDate><guid>http://www.blogjava.net/conans/articles/209562.html</guid><description><![CDATA[<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true">如果你曾经用过Perl或任何其他内建正则表达式支持的语言，你一定知道用正则表达式处理文本和匹配模式是多么简单。如果你不熟悉这个术语，那么&#8220;正则表达式&#8221;（Regular Expression）就是一个字符构成的串，它定义了一个用来搜索匹配字符串的模式。</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true">许多语言，包括Perl、PHP、Python、JavaScript和JScript，都支持用正则表达式处理文本，一些文本编辑器用正则表达式实现高级&#8220;搜索-替换&#8221;功能。那么Java又怎样呢？本文写作时，一个包含了用正则表达式进行文本处理的Java规范需求（Specification Request）已经得到认可，你可以期待在JDK的下一版本中看到它。</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true">然而，如果现在就需要使用正则表达式，又该怎么办呢？你可以从Apache.org下载源代码开放的Jakarta-ORO库。本文接下来的内容先简要地介绍正则表达式的入门知识，然后以Jakarta-ORO API为例介绍如何使用正则表达式。</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true"><strong _extended="true"><font size="4" _extended="true">一、正则表达式基础知识</font></strong></td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true">我们先从简单的开始。假设你要搜索一个包含字符&#8220;cat&#8221;的字符串，搜索用的正则表达式就是&#8220;cat&#8221;。如果搜索对大小写不敏感，单词&#8220;catalog&#8221;、&#8220;Catherine&#8221;、&#8220;sophisticated&#8221;都可以匹配。也就是说：</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true"><img alt="" src="http://www.ccw.com.cn/htm/app/aprog/01_7_31_4_a.jpg" border="0" _extended="true" /></td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true"><strong _extended="true">1.1 句点符号</strong></td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true">假设你在玩英文拼字游戏，想要找出三个字母的单词，而且这些单词必须以&#8220;t&#8221;字母开头，以&#8220;n&#8221;字母结束。另外，假设有一本英文字典，你可以用正则表达式搜索它的全部内容。要构造出这个正则表达式，你可以使用一个通配符——句点符号&#8220;.&#8221;。这样，完整的表达式就是&#8220;t.n&#8221;，它匹配&#8220;tan&#8221;、&#8220;ten&#8221;、&#8220;tin&#8221;和&#8220;ton&#8221;，还匹配&#8220;t#n&#8221;、&#8220;tpn&#8221;甚至&#8220;t n&#8221;，还有其他许多无意义的组合。这是因为句点符号匹配所有字符，包括空格、Tab字符甚至换行符：</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true"><img alt="" src="http://www.ccw.com.cn/htm/app/aprog/01_7_31_4_b.jpg" border="0" _extended="true" /></td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true"><strong _extended="true">1.2 方括号符号</strong></td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true">为了解决句点符号匹配范围过于广泛这一问题，你可以在方括号（&#8220;[]&#8221;）里面指定看来有意义的字符。此时，只有方括号里面指定的字符才参与匹配。也就是说，正则表达式&#8220;t[aeio]n&#8221;只匹配&#8220;tan&#8221;、&#8220;Ten&#8221;、&#8220;tin&#8221;和&#8220;ton&#8221;。但&#8220;Toon&#8221;不匹配，因为在方括号之内你只能匹配单个字符：</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true"><img alt="" src="http://www.ccw.com.cn/htm/app/aprog/01_7_31_4_c.jpg" border="0" _extended="true" /></td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true"><strong _extended="true">1.3 &#8220;或&#8221;符号</strong></td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true">如果除了上面匹配的所有单词之外，你还想要匹配&#8220;toon&#8221;，那么，你可以使用&#8220;|&#8221;操作符。&#8220;|&#8221;操作符的基本意义就是&#8220;或&#8221;运算。要匹配&#8220;toon&#8221;，使用&#8220;t(a|e|i|o|oo)n&#8221;正则表达式。这里不能使用方扩号，因为方括号只允许匹配单个字符；这里必须使用圆括号&#8220;()&#8221;。圆括号还可以用来分组，具体请参见后面介绍。</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true"><img alt="" src="http://www.ccw.com.cn/htm/app/aprog/01_7_31_4_d.jpg" border="0" _extended="true" /></td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true"><strong _extended="true">1.4 表示匹配次数的符号</strong></td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true">表一显示了表示匹配次数的符号，这些符号用来确定紧靠该符号左边的符号出现的次数：</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true">
            <p align="center" _extended="true"><img alt="" src="http://www.ccw.com.cn/htm/app/aprog/01_7_31_4n.jpg" border="0" _extended="true" /></p>
            </td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true">假设我们要在文本文件中搜索美国的社会安全号码。这个号码的格式是999-99-9999。用来匹配它的正则表达式如图一所示。在正则表达式中，连字符（&#8220;-&#8221;）有着特殊的意义，它表示一个范围，比如从0到9。因此，匹配社会安全号码中的连字符号时，它的前面要加上一个转义字符&#8220;\&#8221;。</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true">
            <p align="center" _extended="true"><img alt="" src="http://www.ccw.com.cn/htm/app/aprog/01_7_31_4a.gif" border="0" _extended="true" /></p>
            </td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true">
            <p align="center" _extended="true">图一：匹配所有123-12-1234形式的社会安全号码</p>
            </td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true">假设进行搜索的时候，你希望连字符号可以出现，也可以不出现——即，999-99-9999和999999999都属于正确的格式。这时，你可以在连字符号后面加上&#8220;？&#8221;数量限定符号，如图二所示：</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true">
            <p align="center" _extended="true"><img style="width: 500px; height: 90px" alt="" src="http://www.ccw.com.cn/htm/app/aprog/01_7_31_4b.gif" border="0" _extended="true" /></p>
            </td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true">
            <p align="center" _extended="true">图二：匹配所有123-12-1234和123121234形式的社会安全号码</p>
            </td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true">下面我们再来看另外一个例子。美国汽车牌照的一种格式是四个数字加上二个字母。它的正则表达式前面是数字部分&#8220;[0-9]{4}&#8221;，再加上字母部分&#8220;[A-Z]{2}&#8221;。图三显示了完整的正则表达式。</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true">
            <p align="center" _extended="true"><img alt="" src="http://www.ccw.com.cn/htm/app/aprog/01_7_31_4c.gif" border="0" _extended="true" /></p>
            </td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true">
            <p align="center" _extended="true">图三：匹配典型的美国汽车牌照号码，如8836KV</p>
            </td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true">1.5 &#8220;否&#8221;符号</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true">&#8220;^&#8221;符号称为&#8220;否&#8221;符号。如果用在方括号内，&#8220;^&#8221;表示不想要匹配的字符。例如，图四的正则表达式匹配所有单词，但以&#8220;X&#8221;字母开头的单词除外。</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true">
            <p align="center" _extended="true"><img alt="" src="http://www.ccw.com.cn/htm/app/aprog/01_7_31_4d.gif" border="0" _extended="true" /></p>
            </td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true">
            <p align="center" _extended="true">图四：匹配所有单词，但&#8220;X&#8221;开头的除外</p>
            </td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true">1.6 圆括号和空白符号</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true">假设要从格式为&#8220;June 26, 1951&#8221;的生日日期中提取出月份部分，用来匹配该日期的正则表达式可以如图五所示：</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true">
            <p align="center" _extended="true"><img style="width: 500px; height: 107px" alt="" src="http://www.ccw.com.cn/htm/app/aprog/01_7_31_4e.gif" border="0" _extended="true" /></p>
            </td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true">
            <p align="center" _extended="true">图五：匹配所有Moth DD,YYYY格式的日期</p>
            </td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true">新出现的&#8220;\s&#8221;符号是空白符号，匹配所有的空白字符，包括Tab字符。如果字符串正确匹配，接下来如何提取出月份部分呢？只需在月份周围加上一个圆括号创建一个组，然后用ORO API（本文后面详细讨论）提取出它的值。修改后的正则表达式如图六所示：</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true">
            <p align="center" _extended="true"><img style="width: 500px; height: 118px" alt="" src="http://www.ccw.com.cn/htm/app/aprog/01_7_31_4f.gif" border="0" _extended="true" /></p>
            </td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true">
            <p align="center" _extended="true">图六：匹配所有Month DD,YYYY格式的日期，定义月份值为第一个组</p>
            </td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true"><strong _extended="true">1.7 其它符号</strong></td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true">为简便起见，你可以使用一些为常见正则表达式创建的快捷符号。如表二所示：</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true">表二：常用符号</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true">
            <p align="center" _extended="true"><img alt="" src="http://www.ccw.com.cn/htm/app/aprog/01_7_31_4o.jpg" border="0" _extended="true" /></p>
            </td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true">例如，在前面社会安全号码的例子中，所有出现&#8220;[0-9]&#8221;的地方我们都可以使用&#8220;\d&#8221;。修改后的正则表达式如图七所示：</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true">
            <p align="center" _extended="true"><img alt="" src="http://www.ccw.com.cn/htm/app/aprog/01_7_31_4g.gif" border="0" _extended="true" /></p>
            </td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true">
            <p align="center" _extended="true">图七：匹配所有123-12-1234格式的社会安全号码</p>
            </td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true"><strong _extended="true"><font size="4" _extended="true">二、Jakarta-ORO库</font></strong></td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true">有许多源代码开放的正则表达式库可供Java程序员使用，而且它们中的许多支持Perl 5兼容的正则表达式语法。我在这里选用的是Jakarta-ORO正则表达式库，它是最全面的正则表达式API之一，而且它与Perl 5正则表达式完全兼容。另外，它也是优化得最好的API之一。</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true">Jakarta-ORO库以前叫做OROMatcher，Daniel Savarese大方地把它赠送给了Jakarta Project。你可以按照本文最后参考资源的说明下载它。</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true">我首先将简要介绍使用Jakarta-ORO库时你必须创建和访问的对象，然后介绍如何使用Jakarta-ORO API。</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true"><strong _extended="true">▲ PatternCompiler对象</strong></td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true">首先，创建一个Perl5Compiler类的实例，并把它赋值给PatternCompiler接口对象。Perl5Compiler是PatternCompiler接口的一个实现，允许你把正则表达式编译成用来匹配的Pattern对象。</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true"><img alt="" src="http://www.ccw.com.cn/htm/app/aprog/01_7_31_4_e.jpg" border="0" _extended="true" /></td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true"><strong _extended="true">▲ Pattern对象</strong></td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true">要把正则表达式编译成Pattern对象，调用compiler对象的compile()方法，并在调用参数中指定正则表达式。例如，你可以按照下面这种方式编译正则表达式&#8220;t[aeio]n&#8221;：</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true"><img alt="" src="http://www.ccw.com.cn/htm/app/aprog/01_7_31_4_f.jpg" border="0" _extended="true" /></td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true">默认情况下，编译器创建一个大小写敏感的模式（pattern）。因此，上面代码编译得到的模式只匹配&#8220;tin&#8221;、&#8220;tan&#8221;、 &#8220;ten&#8221;和&#8220;ton&#8221;，但不匹配&#8220;Tin&#8221;和&#8220;taN&#8221;。要创建一个大小写不敏感的模式，你应该在调用编译器的时候指定一个额外的参数：</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true"><img alt="" src="http://www.ccw.com.cn/htm/app/aprog/01_7_31_4_g.jpg" border="0" _extended="true" /></td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true">创建好Pattern对象之后，你就可以通过PatternMatcher类用该Pattern对象进行模式匹配。</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true"><strong _extended="true">▲ PatternMatcher对象</strong></td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true">PatternMatcher对象根据Pattern对象和字符串进行匹配检查。你要实例化一个Perl5Matcher类并把结果赋值给PatternMatcher接口。Perl5Matcher类是PatternMatcher接口的一个实现，它根据Perl 5正则表达式语法进行模式匹配：</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true"><img alt="" src="http://www.ccw.com.cn/htm/app/aprog/01_7_31_4_h.jpg" border="0" _extended="true" /></td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true">使用PatternMatcher对象，你可以用多个方法进行匹配操作，这些方法的第一个参数都是需要根据正则表达式进行匹配的字符串：</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true">&#183; boolean matches(String input, Pattern pattern)：当输入字符串和正则表达式要精确匹配时使用。换句话说，正则表达式必须完整地描述输入字符串。</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true">&#183; boolean matchesPrefix(String input, Pattern pattern)：当正则表达式匹配输入字符串起始部分时使用。</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true">&#183; boolean contains(String input, Pattern pattern)：当正则表达式要匹配输入字符串的一部分时使用（即，它必须是一个子串）。</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true">另外，在上面三个方法调用中，你还可以用PatternMatcherInput对象作为参数替代String对象；这时，你可以从字符串中最后一次匹配的位置开始继续进行匹配。当字符串可能有多个子串匹配给定的正则表达式时，用PatternMatcherInput对象作为参数就很有用了。用PatternMatcherInput对象作为参数替代String时，上述三个方法的语法如下：</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true">&#183; boolean matches(PatternMatcherInput input, Pattern pattern)</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true">&#183; boolean matchesPrefix(PatternMatcherInput input, Pattern pattern)</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true">&#183; boolean contains(PatternMatcherInput input, Pattern pattern)</td>
        </tr>
    </tbody>
</table>
<p>&nbsp;
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true"><strong _extended="true"><font size="4" _extended="true">三、应用实例</font></strong></td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true">下面我们来看看Jakarta-ORO库的一些应用实例。</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true"><strong _extended="true">3.1 日志文件处理</strong></td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true">任务：分析一个Web服务器日志文件，确定每一个用户花在网站上的时间。在典型的BEA WebLogic日志文件中，日志记录的格式如下：</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true"><img alt="" src="http://www.ccw.com.cn/htm/app/aprog/01_7_31_4_i.jpg" border="0" _extended="true" /></td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true">分析这个日志记录，可以发现，要从这个日志文件提取的内容有两项：IP地址和页面访问时间。你可以用分组符号（圆括号）从日志记录提取出IP地址和时间标记。</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true">首先我们来看看IP地址。IP地址有4个字节构成，每一个字节的值在0到255之间，各个字节通过一个句点分隔。因此，IP地址中的每一个字节有至少一个、最多三个数字。图八显示了为IP地址编写的正则表达式：</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true">
            <p align="center" _extended="true"><img style="width: 500px; height: 118px" alt="" src="http://www.ccw.com.cn/htm/app/aprog/01_7_31_4h.gif" border="0" _extended="true" /></p>
            </td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true">
            <p align="center" _extended="true">图八：匹配IP地址</p>
            </td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true">IP地址中的句点字符必须进行转义处理（前面加上&#8220;\&#8221;），因为IP地址中的句点具有它本来的含义，而不是采用正则表达式语法中的特殊含义。句点在正则表达式中的特殊含义本文前面已经介绍。</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true">日志记录的时间部分由一对方括号包围。你可以按照如下思路提取出方括号里面的所有内容：首先搜索起始方括号字符（&#8220;[&#8221;），提取出所有不超过结束方括号字符（&#8220;]&#8221;）的内容，向前寻找直至找到结束方括号字符。图九显示了这部分的正则表达式。</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true">
            <p align="center" _extended="true"><img alt="" src="http://www.ccw.com.cn/htm/app/aprog/01_7_31_4i.gif" border="0" _extended="true" /></p>
            </td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true">
            <p align="center" _extended="true">图九：匹配至少一个字符，直至找到&#8220;]&#8221;</p>
            </td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true">现在，把上述两个正则表达式加上分组符号（圆括号）后合并成单个表达式，这样就可以从日志记录提取出IP地址和时间。注意，为了匹配&#8220;- -&#8221;（但不提取它），正则表达式中间加入了&#8220;\s-\s-\s&#8221;。完整的正则表达式如图十所示。</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true">
            <p align="center" _extended="true"><img style="width: 500px; height: 73px" alt="" src="http://www.ccw.com.cn/htm/app/aprog/01_7_31_4j.gif" border="0" _extended="true" /></p>
            </td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true">
            <p align="center" _extended="true">图十：匹配IP地址和时间标记</p>
            </td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true">现在正则表达式已经编写完毕，接下来可以编写使用正则表达式库的Java代码了。</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true">为使用Jakarta-ORO库，首先创建正则表达式字符串和待分析的日志记录字符串：</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true"><img alt="" src="http://www.ccw.com.cn/htm/app/aprog/01_7_31_4_j.jpg" border="0" _extended="true" /></td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true">这里使用的正则表达式与图十的正则表达式差不多完全相同，但有一点例外：在Java中，你必须对每一个向前的斜杠（&#8220;\&#8221;）进行转义处理。图十不是Java的表示形式，所以我们要在每个&#8220;\&#8221;前面加上一个&#8220;\&#8221;以免出现编译错误。遗憾的是，转义处理过程很容易出现错误，所以应该小心谨慎。你可以首先输入未经转义处理的正则表达式，然后从左到右依次把每一个&#8220;\&#8221;替换成&#8220;\\&#8221;。如果要复检，你可以试着把它输出到屏幕上。</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true">初始化字符串之后，实例化PatternCompiler对象，用PatternCompiler编译正则表达式创建一个Pattern对象：</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true"><img alt="" src="http://www.ccw.com.cn/htm/app/aprog/01_7_31_4_k.jpg" border="0" _extended="true" /></td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true">现在，创建PatternMatcher对象，调用PatternMatcher接口的contain()方法检查匹配情况：</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true"><img alt="" src="http://www.ccw.com.cn/htm/app/aprog/01_7_31_4_l.jpg" border="0" _extended="true" /></td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true">接下来，利用PatternMatcher接口返回的MatchResult对象，输出匹配的组。由于logEntry字符串包含匹配的内容，你可以看到类如下面的输出：</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true"><img alt="" src="http://www.ccw.com.cn/htm/app/aprog/01_7_31_4_m.jpg" border="0" _extended="true" /></td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true"><strong _extended="true">3.2 HTML处理实例一</strong></td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true">下面一个任务是分析HTML页面内FONT标记的所有属性。HTML页面内典型的FONT标记如下所示：</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true"><img alt="" src="http://www.ccw.com.cn/htm/app/aprog/01_7_31_4_n.jpg" border="0" _extended="true" /></td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true">程序将按照如下形式，输出每一个FONT标记的属性：</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true"><img alt="" src="http://www.ccw.com.cn/htm/app/aprog/01_7_31_4_o.jpg" border="0" _extended="true" /></td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true">在这种情况下，我建议你使用两个正则表达式。第一个如图十一所示，它从字体标记提取出&#8220;"face="Arial, Serif" size="+2" color="red"&#8221;。</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true">
            <p align="center" _extended="true"><img style="width: 500px; height: 91px" alt="" src="http://www.ccw.com.cn/htm/app/aprog/01_7_31_4k.gif" border="0" _extended="true" /></p>
            </td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true">
            <p align="center" _extended="true">图十一：匹配FONT标记的所有属性</p>
            </td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true">第二个正则表达式如图十二所示，它把各个属性分割成名字-值对。</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true">
            <p align="center" _extended="true"><img style="width: 500px; height: 140px" alt="" src="http://www.ccw.com.cn/htm/app/aprog/01_7_31_4l.gif" border="0" _extended="true" /></p>
            </td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true">
            <p align="center" _extended="true">图十二：匹配单个属性，并把它分割成名字-值对</p>
            </td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true">分割结果为：</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true"><img alt="" src="http://www.ccw.com.cn/htm/app/aprog/01_7_31_4_p.jpg" border="0" _extended="true" /></td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true">现在我们来看看完成这个任务的Java代码。首先创建两个正则表达式字符串，用Perl5Compiler把它们编译成Pattern对象。编译正则表达式的时候，指定Perl5Compiler.CASE_INSENSITIVE_MASK选项，使得匹配操作不区分大小写。</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true">接下来，创建一个执行匹配操作的Perl5Matcher对象。</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true"><img alt="" src="http://www.ccw.com.cn/htm/app/aprog/01_7_31_4_q.jpg" border="0" _extended="true" /></td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true">假设有一个String类型的变量html，它代表了HTML文件中的一行内容。如果html字符串包含FONT标记，匹配器将返回true。此时，你可以用匹配器对象返回的MatchResult对象获得第一个组，它包含了FONT的所有属性：</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true"><img alt="" src="http://www.ccw.com.cn/htm/app/aprog/01_7_31_4_r.jpg" border="0" _extended="true" /></td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true">接下来创建一个PatternMatcherInput对象。这个对象允许你从最后一次匹配的位置开始继续进行匹配操作，因此，它很适合于提取FONT标记内属性的名字-值对。创建PatternMatcherInput对象，以参数形式传入待匹配的字符串。然后，用匹配器实例提取出每一个FONT的属性。这通过指定PatternMatcherInput对象（而不是字符串对象）为参数，反复地调用PatternMatcher对象的contains()方法完成。PatternMatcherInput对象之中的每一次迭代将把它内部的指针向前移动，下一次检测将从前一次匹配位置的后面开始。</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true">本例的输出结果如下：</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true"><img alt="" src="http://www.ccw.com.cn/htm/app/aprog/01_7_31_4_s.jpg" border="0" _extended="true" /></td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true"><strong _extended="true">3.3 HTML处理实例二</strong></td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true">下面我们来看看另一个处理HTML的例子。这一次，我们假定Web服务器从widgets.acme.com移到了newserver.acme.com。现在你要修改一些页面中的链接：</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true"><img alt="" src="http://www.ccw.com.cn/htm/app/aprog/01_7_31_4_t.jpg" border="0" _extended="true" /></td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true">执行这个搜索的正则表达式如图十三所示：</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true">
            <p align="center" _extended="true"><img style="width: 500px; height: 108px" alt="" src="http://www.ccw.com.cn/htm/app/aprog/01_7_31_4m.gif" border="0" _extended="true" /></p>
            </td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true">
            <p align="center" _extended="true">图十三：匹配修改前的链接</p>
            </td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true">如果能够匹配这个正则表达式，你可以用下面的内容替换图十三的链接：</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true"><a href="http://newserver.acme.com/interface.html#$1" _extended="true"></a><img alt="" src="http://www.ccw.com.cn/htm/app/aprog/01_7_31_4_u.jpg" border="0" _extended="true" /></td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true">注意#字符的后面加上了$1。Perl正则表达式语法用$1、$2等表示已经匹配且提取出来的组。图十三的表达式把所有作为一个组匹配和提取出来的内容附加到链接的后面。</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true">现在，返回Java。就象前面我们所做的那样，你必须创建测试字符串，创建把正则表达式编译到Pattern对象所必需的对象，以及创建一个PatternMatcher对象：<img style="width: 500px; height: 181px" alt="" src="http://www.ccw.com.cn/htm/app/aprog/01_7_31_4_v.jpg" border="0" _extended="true" /></td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true">接下来，用com.oroinc.text.regex包Util类的substitute()静态方法进行替换，输出结果字符串：</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true"><img alt="" src="http://www.ccw.com.cn/htm/app/aprog/01_7_31_4_w.jpg" border="0" _extended="true" /></td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true">Util.substitute()方法的语法如下：</td>
        </tr>
    </tbody>
</table>
<table height="17" width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" height="13" _extended="true"><img alt="" src="http://www.ccw.com.cn/htm/app/aprog/01_7_31_4_x.jpg" border="0" _extended="true" /></td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true">这个调用的前两个参数是以前创建的PatternMatcher和Pattern对象。第三个参数是一个Substiution对象，它决定了替换操作如何进行。本例使用的是Perl5Substitution对象，它能够进行Perl5风格的替换。第四个参数是想要进行替换操作的字符串，最后一个参数允许指定是否替换模式的所有匹配子串（Util.SUBSTITUTE_ALL），或只替换指定的次数。</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center" _extended="true">
    <tbody _extended="true">
        <tr _extended="true">
            <td class="a14" _extended="true"><strong _extended="true">【结束语】</strong>在这篇文章中，我为你介绍了正则表达式的强大功能。只要正确运用，正则表达式能够在字符串提取和文本修改中起到很大的作用。另外，我还介绍了如何在Java程序中通过Jakarta-ORO库利用正则表达式。至于最终采用老式的字符串处理方式（使用StringTokenizer，charAt，和substring），还是采用正则表达式，这就有待你自己决定了。</td>
        </tr>
    </tbody>
</table>
</p>
<img src ="http://www.blogjava.net/conans/aggbug/209562.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/conans/" target="_blank">CONAN</a> 2008-06-20 22:44 <a href="http://www.blogjava.net/conans/articles/209562.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>