??xml version="1.0" encoding="utf-8" standalone="yes"?>国产成人精品曰本亚洲79ren,久久夜色精品国产噜噜噜亚洲AV ,91午夜精品亚洲一区二区三区http://www.tkk7.com/dybjsun/category/16010.htmlzh-cnSat, 08 Mar 2008 23:13:38 GMTSat, 08 Mar 2008 23:13:38 GMT60Tomcat启动分析http://www.tkk7.com/dybjsun/archive/2008/01/10/174216.htmldybjsundybjsunThu, 10 Jan 2008 03:24:00 GMThttp://www.tkk7.com/dybjsun/archive/2008/01/10/174216.htmlhttp://www.tkk7.com/dybjsun/comments/174216.htmlhttp://www.tkk7.com/dybjsun/archive/2008/01/10/174216.html#Feedback0http://www.tkk7.com/dybjsun/comments/commentRss/174216.htmlhttp://www.tkk7.com/dybjsun/services/trackbacks/174216.html1 - Tomcat Server的组成部?

1.1 - Server

A Server element represents the entire Catalina servlet container. (Singleton)

1.2 - Service

A Service element represents the combination of one or more Connector components that share a single Engine
Service是这样一个集合:(x)它由一个或者多个Connectorl成Q以?qing)一个EngineQ负责处理所有Connector所获得的客戯?br />

1.3 - Connector

一个Connector在某个指定端口上侦听客戯求,q将获得的请求交lEngine来处理,从Engine处获得回应ƈq回客户
TOMCAT有两个典型的ConnectorQ一个直接侦听来自browser的httphQ一个侦听来自其它WebServer的请?br />Coyote Http/1.1 Connector 在端?080处侦听来自客户browser的httph
Coyote JK2 Connector 在端?009处侦听来自其它WebServer(Apache)的servlet/jsp代理h

1.4 - Engine

The Engine element represents the entire request processing machinery associated with a particular Service
It receives and processes all requests from one or more Connectors
and returns the completed response to the Connector for ultimate transmission back to the client
Engine下可以配|多个虚拟主机Virtual HostQ每个虚拟主机都有一个域?br />当Engine获得一个请求时Q它把该h匚w到某个Host上,然后把该h交给该Host来处?br />Engine有一个默认虚拟主机,当请求无法匹配到M一个Host上的时候,交l该默认Host来处?br />

1.5 - Host

 

代表一个Virtual HostQ虚拟主机,每个虚拟L和某个网l域名Domain Name相匹?br />每个虚拟L下都可以部v(deploy)一个或者多个Web AppQ每个Web App对应于一个ContextQ有一个Context path
当Host获得一个请求时Q将把该h匚w到某个Context上,然后把该h交给该Context来处?br />匚w的方法是“最长匹配”,所以一个path==""的Context成Host的默认Context
所有无法和其它Context的\径名匚w的请求都最l和该默认Context匚w

1.6 - Context

一个Context对应于一个Web ApplicationQ一个Web Application׃个或者多个Servletl成
Context在创建的时候将Ҏ(gu)配置文g$CATALINA_HOME/conf/web.xml?WEBAPP_HOME/WEB-INF/web.xml载入Servletc?br />当Context获得hӞ在自己的映表(mapping table)中寻扄匚w的Servletc?br />如果扑ֈQ则执行该类Q获得请求的回应Qƈq回

2 - Tomcat Server的结构图01-startup.gif

3 - 配置文g$CATALINA_HOME/conf/server.xml的说?

该文件描qC如何启动Tomcat Server

 

4 - Context的部|配|文件web.xml的说?

一个Context对应于一个Web AppQ每个Web App是由一个或者多个servletl成?br />当一个Web App被初始化的时候,它将用自qClassLoader对象载入“部|配|文件web.xml”中定义的每个servletc?br />它首先蝲入在$CATALINA_HOME/conf/web.xml中部|的servletc?br />然后载入在自qWeb App根目录下的WEB-INF/web.xml中部|的servletc?br />web.xml文g有两部分Qservletcd义和servlet映射定义
每个被蝲入的servletc都有一个名字,且被填入该Context的映表(mapping table)中,和某UURL PATTERN对应
当该Context获得hӞ查询mapping tableQ找到被h的servletQƈ执行以获得请求回?br />

分析一下所有的Context׃n的web.xml文gQ在其中定义的servlet被所有的Web App载入

 

5 - Tomcat Server处理一个httph的过E?

假设来自客户的请求ؓ(f)Q?br />http://localhost:8080/wsota/wsota_index.jsp

1) h被发送到本机端口8080Q被在那里侦听的Coyote HTTP/1.1 Connector获得
2) Connector把该h交给它所在的Service的Engine来处理,q等待来自Engine的回?br />3) Engine获得hlocalhost/wsota/wsota_index.jspQ匹配它所拥有的所有虚拟主机Host
4) Engine匚w到名为localhost的HostQ即使匹配不C把请求交l该Host处理Q因Host被定义ؓ(f)该Engine的默认主机)(j)
5) localhost Host获得h/wsota/wsota_index.jspQ匹配它所拥有的所有Context
6) Host匚w到\径ؓ(f)/wsota的ContextQ如果匹配不到就把该h交给路径名ؓ(f)""的Contextd理)(j)
7) path="/wsota"的Context获得h/wsota_index.jspQ在它的mapping table中寻扑֯应的servlet
8) Context匚w到URL PATTERN?.jsp的servletQ对应于JspServletc?br />9) 构造HttpServletRequest对象和HttpServletResponse对象Q作为参数调用JspServlet的doGet或doPostҎ(gu)
10)Context把执行完了之后的HttpServletResponse对象q回lHost
11)Host把HttpServletResponse对象q回lEngine
12)Engine把HttpServletResponse对象q回lC(j)onnector
13)Connector把HttpServletResponse对象q回l客户browser

<!----------------------------------------------------------------------------------------------->


<web-app>


<!-- 概述Q?br /> 该文件是所有的WEB APPq的部|配|文Ӟ
每当一个WEB APP被DEPLOYQ该文g都将先被处理Q然后才是WEB APP自己?WEB-INF/web.xml
-->



<!-- +-------------------------+ -->
<!-- | servletcd义部? | -->
<!-- +-------------------------+ -->



<!-- DefaultServlet
当用L(fng)HTTPh无法匚wM一个servlet的时候,该servlet被执?br /> URL PATTERN MAPPING : /
-->

<servlet>
<servlet-name>default</servlet-name>
<servlet-class>
org.apache.catalina.servlets.DefaultServlet
</servlet-class>
<init-param>
<param-name>debug</param-name>
<param-value>0</param-value>
</init-param>
<init-param>
<param-name>listings</param-name>
<param-value>true</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>


<!-- InvokerServlet
处理一个WEB APP中的匿名servlet
当一个servlet被编写ƈ~译攑օ/WEB-INF/classes/中,却没有在/WEB-INF/web.xml中定义的时?br /> 该servlet被调用,把匿名servlet映射?servlet/ClassName的Ş?br /> URL PATTERN MAPPING : /servlet/*
-->

<servlet>
<servlet-name>invoker</servlet-name>
<servlet-class>
org.apache.catalina.servlets.InvokerServlet
</servlet-class>
<init-param>
<param-name>debug</param-name>
<param-value>0</param-value>
</init-param>
<load-on-startup>2</load-on-startup>
</servlet>


<!-- JspServlet
当请求的是一个JSP面的时候(*.jspQ该servlet被调?br /> 它是一个JSP~译器,请求的JSP面~译成ؓ(f)servlet再执?br /> URL PATTERN MAPPING : *.jsp
-->

<servlet>
<servlet-name>jsp</servlet-name>
<servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>
<init-param>
<param-name>logVerbosityLevel</param-name>
<param-value>WARNING</param-value>
</init-param>
<load-on-startup>3</load-on-startup>
</servlet>



<!-- +---------------------------+ -->
<!-- | servlet映射定义部分 | -->
<!-- +---------------------------+ -->


<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>

<servlet-mapping>
<servlet-name>invoker</servlet-name>
<url-pattern>/servlet/*</url-pattern>
</servlet-mapping>

<servlet-mapping>
<servlet-name>jsp</servlet-name>
<url-pattern>*.jsp</url-pattern>
</servlet-mapping>


<!-- +------------------------+ -->
<!-- | 其它部分Q略d | -->
<!-- +------------------------+ -->

... ... ... ...

</web-app>


<!----------------------------------------------------------------------------------------------->

<!----------------------------------------------------------------------------------------------->



<!-- 启动Server
在端?005处等待关闭命?br /> 如果接受?SHUTDOWN"字符串则关闭服务?br /> -->

<Server port="8005" shutdown="SHUTDOWN" debug="0">


<!-- Listener ???
目前没有看到q里
-->

<Listener className="org.apache.catalina.mbeans.ServerLifecycleListener" debug="0"/>
<Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" debug="0"/>


<!-- Global JNDI resources ???
目前没有看到q里Q先略去
-->

<GlobalNamingResources>
... ... ... ...
</GlobalNamingResources>


<!-- Tomcat的Standalone Service
Service是一lConnector的集?br /> 它们q一个Engine来处理所有Connector收到的请?br /> -->

<Service name="Tomcat-Standalone">


<!-- Coyote HTTP/1.1 Connector
className : 该Connector的实现类是org.apache.coyote.tomcat4.CoyoteConnector
port : 在端口号8080处侦听来自客户browser的HTTP1.1h
minProcessors : 该Connector先创?个线E等待客戯求,每个h׃个线E负?br /> maxProcessors : 当现有的U程不够服务客户hӞ若线EL不75个,则创建新U程来处理请?br /> acceptCount : 当现有线E已l达到最大数75Ӟ为客戯求排?br /> 当队列中h数超q?00Ӟ后来的请求返回Connection refused错误
redirectport : 当客戯求是httpsӞ把该h转发到端?443?br /> 其它属性略
-->

<Connector className="org.apache.coyote.tomcat4.CoyoteConnector"
port="8080"
minProcessors="5" maxProcessors="75" acceptCount="100"
enableLookups="true"
redirectPort="8443"
debug="0"
connectionTimeout="20000"
useURIValidationHack="false"
disableUploadTimeout="true" />


<!-- Engine用来处理Connector收到的Httph
它将匚wh和自q虚拟LQƈ把请求{交给对应的Host来处?br /> 默认虚拟L是localhost
-->

<Engine name="Standalone" defaultHost="localhost" debug="0">


<!-- 日志c,目前没有看到Q略d -->

<Logger className="org.apache.catalina.logger.FileLogger" .../>

<!-- RealmQ目前没有看刎ͼ略去?-->

<Realm className="org.apache.catalina.realm.UserDatabaseRealm" .../>


<!-- 虚拟Llocalhost
appBase : 该虚拟主机的根目录是webapps/
它将匚wh和自qContext的\径,q把h转交l对应的Context来处?br /> -->

<Host name="localhost" debug="0" appBase="webapps" unpackWARs="true" autoDeploy="true">


<!-- 日志c,目前没有看到Q略d -->

<Logger className="org.apache.catalina.logger.FileLogger" .../>


<!-- ContextQ对应于一个Web App
path : 该Context的\径名?"Q故该Context是该Host的默认Context
docBase : 该Context的根目录是webapps/mycontext/
-->

<Context path="" docBase="mycontext" debug="0"/>


<!-- 另外一个ContextQ\径名?wsota -->

<Context path="/wsota" docBase="wsotaProject" debug="0"/>


</Host>

</Engine>

</Service>

</Server>


<!----------------------------------------------------------------------------------------------->


dybjsun 2008-01-10 11:24 发表评论
]]>
全文搜烦(ch) lucene使用与优?/title><link>http://www.tkk7.com/dybjsun/archive/2008/01/09/174065.html</link><dc:creator>dybjsun</dc:creator><author>dybjsun</author><pubDate>Wed, 09 Jan 2008 09:17:00 GMT</pubDate><guid>http://www.tkk7.com/dybjsun/archive/2008/01/09/174065.html</guid><wfw:comment>http://www.tkk7.com/dybjsun/comments/174065.html</wfw:comment><comments>http://www.tkk7.com/dybjsun/archive/2008/01/09/174065.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/dybjsun/comments/commentRss/174065.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/dybjsun/services/trackbacks/174065.html</trackback:ping><description><![CDATA[1 lucene?br />1.1 什么是lucene<br />Lucene是一个全文搜索框Ӟ而不是应用品。因此它q不像www.baidu.com 或者google Desktop那么拿来p用,它只是提供了一U工兯你能实现q些产品?br /><br />1.2 lucene能做什?br />要回{这个问题,先要了解lucene的本质。实际上lucene的功能很单一Q说到底Q就是你l它若干个字W串Q然后它Z提供一个全文搜索服务,告诉你你要搜索的关键词出现在哪里。知道了q个本质Q你可以发挥想象做MW合q个条g的事情了。你可以把站内新闻都索引了,做个资料库;你可以把一个数据库表的若干个字D늃(ch)引v来,那就不用再担心因为?like%”而锁表了Q你也可以写个自q搜烦(ch)引擎…?br /><br />1.3 你该不该选择lucene<br />下面l出一些测试数据,如果你觉得可以接受,那么可以选择?br />试一Q?50万记录,300M左右文本Q生成烦(ch)?80M左右Q?00U程下^均处理时?00ms?br />试二:(x)37000记录Q烦(ch)引数据库中的两个varchar字段Q烦(ch)引文?.6MQ?00U程下^均处理时?.5ms?br /><br />2 lucene的工作方?br />lucene提供的服务实际包含两部分Q一入一出。所谓入是写入,卛_你提供的源(本质是字W串Q写入烦(ch)引或者将其从索引中删除;所谓出是读出,卛_用户提供全文搜烦(ch)服务Q让用户可以通过关键词定位源?br /><br />2.1写入程<br />源字W串首先l过analyzer处理Q包括:(x)分词Q分成一个个单词Q去除stopwordQ可选)(j)?br />源中需要的信息加入Document的各个Field中,q把需要烦(ch)引的Field索引hQ把需要存储的Field存储h?br />烦(ch)引写入存储器Q存储器可以是内存或盘?br /><br />2.2d程<br />用户提供搜烦(ch)关键词,l过analyzer处理?br />对处理后的关键词搜烦(ch)索引扑և对应的Document?br />用户Ҏ(gu)需要从扑ֈ的Document中提取需要的Field?br /><br />3 一些需要知道的概念<br />lucene用到一些概念,了解它们的含义,有利于下面的讲解?br /><br />3.1 analyzer<br />Analyzer 是分析器Q它的作用是把一个字W串按某U规则划分成一个个词语Qƈ去除其中的无效词语,q里说的无效词语是指英文中的“of”?“the”,中文中的 “的”、“地”等词语Q这些词语在文章中大量出玎ͼ但是本n不包含什么关键信息,L有利于羃?yu)?ch)引文件、提高效率、提高命中率?br />分词的规则千变万化,但目的只有一个:(x)按语义划分。这点在英文中比较容易实玎ͼ因ؓ(f)英文本n是以单词ؓ(f)单位的,已经用空格分开Q而中文则必须以某U方法将q成一片的句子划分成一个个词语。具体划分方法下面再详细介绍Q这里只需了解分析器的概念卛_?br /><br />3.2 document<br />用户提供的源是一条条记录Q它们可以是文本文g、字W串或者数据库表的一条记录等{。一条记录经q烦(ch)引之后,是以一个Document的Ş式存储在索引文g中的。用戯行搜索,也是以Document列表的Ş式返回?br /><br />3.3 field<br />一个Document可以包含多个信息域,例如一文章可以包含“标题”、“正文”、“最后修Ҏ(gu)间”等信息域,q些信息域就是通过Field在Document中存储的?br />Field有两个属性可选:(x)存储和烦(ch)引。通过存储属性你可以控制是否对这个Fieldq行存储Q通过索引属性你可以控制是否对该Fieldq行索引。这看v来似乎有些废话,事实上对q两个属性的正确l合很重要,下面举例说明Q?br />q是以刚才的文章Z子,我们需要对标题和正文进行全文搜索,所以我们要把烦(ch)引属性设|ؓ(f)真,同时我们希望能直接从搜烦(ch)l果中提取文章标题,所以我们把标题域的存储属性设|ؓ(f)真,但是׃正文域太大了Q我们ؓ(f)了羃?yu)?ch)引文件大,正文域的存储属性设|ؓ(f)假,当需要时再直接读取文Ӟ我们只是希望能从搜烦(ch)解果中提取最后修Ҏ(gu)_(d)不需要对它进行搜索,所以我们把最后修Ҏ(gu)间域的存储属性设|ؓ(f)真,索引属性设|ؓ(f)假。上面的三个域涵盖了两个属性的三种l合Q还有一U全为假的没有用刎ͼ事实上Field不允怽那么讄Q因为既不存储又不烦(ch)引的域是没有意义的?br /><br />3.4 term<br />term是搜索的最单位,它表C文档的一个词语,term׃部分l成Q它表示的词语和q个词语所出现的field?br /><br />3.5 tocken<br />tocken是term的一ơ出玎ͼ它包含trem文本和相应的h偏移Q以?qing)一个类型字W串。一句话中可以出现多ơ相同的词语Q它们都用同一个term表示Q但是用不同的tockenQ每个tocken标记该词语出现的地方?br /><br />3.6 segment<br />d索引时ƈ不是每个document都马上添加到同一个烦(ch)引文Ӟ它们首先被写入到不同的小文gQ然后再合ƈ成一个大索引文gQ这里每个小文g都是一个segment?br /><br />4 lucene的结?br />lucene包括core和sandbox两部分,其中core是luceneE_的核心部分,sandbox包含了一些附加功能,例如highlighter、各U分析器?br />Lucene core有七个包QanalysisQdocumentQindexQqueryParserQsearchQstoreQutil?br />4.1 analysis<br />Analysis包含一些内建的分析器,例如按空白字W分词的WhitespaceAnalyzerQ添加了stopwrodqo(h)的StopAnalyzerQ最常用的StandardAnalyzer?br />4.2 document<br />Document包含文档的数据结构,例如Documentcd义了存储文档的数据结构,Fieldcd义了Document的一个域?br />4.3 index<br />Index 包含了烦(ch)引的dc,例如对烦(ch)引文件的segmentq行写、合q、优化的IndexWritercd对烦(ch)引进行读取和删除操作的?IndexReaderc,q里要注意的是不要被I(xin)ndexReaderq个名字误导Q以为它是烦(ch)引文件的dc,实际上删除烦(ch)引也是由它完成,  IndexWriter只关心如何将索引写入一个个segmentQƈ它们合q优化;IndexReader则关注烦(ch)引文件中各个文档的组lŞ式?br />4.4 queryParser<br />QueryParser 包含了解析查询语句的c,lucene的查询语句和sql语句有点cMQ有各种保留字,按照一定的语法可以l成各种查询?Lucene有很多种 Queryc,它们都承自QueryQ执行各U特D的查询QQueryParser的作用就是解析查询语句,按顺序调用各U?QuerycL扑ևl果?br />4.5 search<br />Search包含了从索引中搜索结果的各种c,例如刚才说的各种Queryc,包括TermQuery、BooleanQuery{就在这个包里?br />4.6 store<br />Store包含了烦(ch)引的存储c,例如Directory定义了烦(ch)引文件的存储l构QFSDirectory为存储在文g中的索引QRAMDirectory为存储在内存中的索引QMmapDirectoryZ用内存映的索引?br />4.7 util<br />Util包含一些公共工L(fng)Q例如时间和字符串之间的转换工具?br /><br />5 如何建烦(ch)?br />5.1 最单的能完成烦(ch)引的代码片断<br /><br />IndexWriter writer = new IndexWriter(?data/index/? new StandardAnalyzer(), true);<br />Document doc = new Document();<br />doc.add(new Field("title", "lucene introduction", Field.Store.YES, Field.Index.TOKENIZED));<br />doc.add(new Field("content", "lucene works well", Field.Store.YES, Field.Index.TOKENIZED));<br />writer.addDocument(doc);<br />writer.optimize();<br />writer.close();<br /><br />下面我们分析一下这D代码?br />首先我们创徏了一个writerQƈ指定存放索引的目录ؓ(f)?data/index”,使用的分析器为StandardAnalyzerQ第三个参数说明如果已经有烦(ch)引文件在索引目录下,我们覆盖它们?br />然后我们新徏一个document?br />我们向documentd一个fieldQ名字是“title”,内容是“lucene introduction”,对它q行存储q烦(ch)引?br />再添加一个名字是“content”的fieldQ内Ҏ(gu)“lucene works well”,也是存储q烦(ch)引?br />然后我们这个文档添加到索引中,如果有多个文档,可以重复上面的操作,创徏documentq添加?br />d完所有documentQ我们对索引q行优化Q优化主要是多个segment合ƈC个,有利于提高烦(ch)引速度?br />随后writer关闭Q这点很重要?br /><br />对,创徏索引p么简单!<br />当然你可能修改上面的代码获得更具个性化的服务?br /><br />5.2 烦(ch)引直接写在内?br />你需要首先创Z个RAMDirectoryQƈ其传给writerQ代码如下:(x)<br /><br />Directory dir = new RAMDirectory();<br />IndexWriter writer = new IndexWriter(dir, new StandardAnalyzer(), true);<br />Document doc = new Document();<br />doc.add(new Field("title", "lucene introduction", Field.Store.YES, Field.Index.TOKENIZED));<br />doc.add(new Field("content", "lucene works well", Field.Store.YES, Field.Index.TOKENIZED));<br />writer.addDocument(doc);<br />writer.optimize();<br />writer.close();<br /><br />5.3 索引文本文g<br />如果你想把纯文本文g索引hQ而不惌己将它们d字符串创建fieldQ你可以用下面的代码创徏fieldQ?br /><br />Field field = new Field("content", new FileReader(file));<br /><br />q里的file是该文本文件。该构造函数实际上是读L件内容,q对其进行烦(ch)引,但不存储?br /><br />6 如何l护索引<br />索引的维护操作都是由IndexReadercL供?br /><br />6.1 如何删除索引<br />lucene提供了两U从索引中删除document的方法,一U是<br /><br />void deleteDocument(int docNum)<br /><br />q种Ҏ(gu)是根据document在烦(ch)引中的编h删除Q每个document加进索引后都?x)有个唯一~号Q所以根据编号删除是一U精删除,但是q个~号是烦(ch)引的内部l构Q一般我们不?x)知道某个文件的~号到底是几Q所以用处不大。另一U是<br /><br />void deleteDocuments(Term term)<br /><br />q种Ҏ(gu)实际上是首先Ҏ(gu)参数term执行一个搜索操作,然后把搜索到的结果批量删除了。我们可以通过q个Ҏ(gu)提供一个严格的查询条gQ达到删除指定document的目的?br />下面l出一个例子:(x)<br /><br />Directory dir = FSDirectory.getDirectory(PATH, false);<br />IndexReader reader = IndexReader.open(dir);<br />Term term = new Term(field, key);<br />reader.deleteDocuments(term);<br />reader.close();<br /><br />6.2 如何更新索引<br />luceneq没有提供专门的索引更新Ҏ(gu)Q我们需要先相应的document删除Q然后再新的document加入索引。例如:(x)<br /><br />Directory dir = FSDirectory.getDirectory(PATH, false);<br />IndexReader reader = IndexReader.open(dir);<br />Term term = new Term(“title? “lucene introduction?;<br />reader.deleteDocuments(term);<br />reader.close();<br /><br />IndexWriter writer = new IndexWriter(dir, new StandardAnalyzer(), true);<br />Document doc = new Document();<br />doc.add(new Field("title", "lucene introduction", Field.Store.YES, Field.Index.TOKENIZED));<br />doc.add(new Field("content", "lucene is funny", Field.Store.YES, Field.Index.TOKENIZED));<br />writer.addDocument(doc);<br />writer.optimize();<br />writer.close();<br /><br /><br />7 如何搜烦(ch)<br />lucene 的搜索相当强大,它提供了很多辅助查询c,每个c都l承自Queryc,各自完成一U特D的查询Q你可以像搭U木一样将它们Ll合使用Q完成一些复杂操作;另外luceneq提供了Sortcdl果q行排序Q提供了Filtercd查询条gq行限制。你或许?x)不自觉地拿它跟SQL语句q行比较Q?“lucene能执行and、or、order by、where、like ?xx%’操作吗Q”回{是Q“当然没问题Q?br /><br />7.1 各种各样的Query<br />下面我们看看lucene到底允许我们q行哪些查询操作Q?br /><br />7.1.1 TermQuery<br />首先介绍最基本的查询,如果你想执行一个这L(fng)查询Q“在content域中包含‘lucene’的document”,那么你可以用TermQueryQ?br /><br />Term t = new Term("content", " lucene";<br />Query query = new TermQuery(t);<br /><br />7.1.2 BooleanQuery<br />如果你想q么查询Q“在content域中包含java或perl的document”,那么你可以徏立两个TermQueryq把它们用BooleanQueryq接hQ?br /><br />TermQuery termQuery1 = new TermQuery(new Term("content", "java");<br />TermQuery termQuery 2 = new TermQuery(new Term("content", "perl");<br />BooleanQuery booleanQuery = new BooleanQuery();<br />booleanQuery.add(termQuery 1, BooleanClause.Occur.SHOULD);<br />booleanQuery.add(termQuery 2, BooleanClause.Occur.SHOULD);<br /><br />7.1.3 WildcardQuery<br />如果你想Ҏ(gu)单词q行通配W查询,你可以用WildcardQueryQ通配W包括?’匹配一个Q意字W和?’匹配零个或多个L字符Q例如你搜烦(ch)’use*’,你可能找到’useful’或者’useless’:(x)<br /><br />Query query = new WildcardQuery(new Term("content", "use*");<br /><br />7.1.4 PhraseQuery<br />你可能对中日关系比较感兴,x䏀中’和‘日’挨得比较近Q?个字的距dQ的文章Q超q这个距ȝ不予考虑Q你可以Q?br /><br />PhraseQuery query = new PhraseQuery();<br />query.setSlop(5);<br />query.add(new Term("content ", “中?);<br />query.add(new Term(“content? “日?);<br /><br />那么它可能搜到“中日合作……”、“中方和日方……”,但是搜不到“中国某高层领导说日本欠扁”?br /><br />7.1.5 PrefixQuery<br />如果你想搜以‘中’开头的词语Q你可以用PrefixQueryQ?br /><br />PrefixQuery query = new PrefixQuery(new Term("content ", "?);<br /><br />7.1.6 FuzzyQuery<br />FuzzyQuery用来搜烦(ch)怼的termQ用Levenshtein法。假设你x索跟‘wuzza’相似的词语Q你可以Q?br /><br />Query query = new FuzzyQuery(new Term("content", "wuzza");<br /><br />你可能得到‘fuzzy’和‘wuzzy’?br /><br />7.1.7 RangeQuery<br />另一个常用的Query是RangeQueryQ你也许x索时间域?0060101?0060130之间的documentQ你可以用RangeQueryQ?br /><br />RangeQuery query = new RangeQuery(new Term(“time? ?0060101?, new Term(“time? ?0060130?, true);<br /><br />最后的true表示用闭合区间?br /><br />7.2 QueryParser<br />看了q么多QueryQ你可能?x)问Q“不?x)让我自q合各UQuery吧,太麻?ch)了Q”当然不?x),lucene提供了一U类gSQL语句的查询语句,我们姑且叫它lucene语句Q通过它,你可以把各种查询一句话搞定Qlucene?x)自动把它们查分成小块交l相应Query执行。下面我们对应每U?Query演示一下:(x)<br />TermQuery可以用“field:key”方式,例如“content:lucene”?br />BooleanQuery中‘与’用?’,‘或’用?’,例如“content:java contenterl”?br />WildcardQuery仍然用?’和?’,例如“content:use*”?br />PhraseQuery用‘~’,例如“content:"中日"~5”?br />PrefixQuery用?’,例如“中*”?br />FuzzyQuery用‘~’,例如“content: wuzza ~”?br />RangeQuery用‘[]’或‘{}’,前者表C闭区间Q后者表C开区间Q例如“time:[20060101 TO 20060130]”,注意TO区分大小写?br />你可以Q意组合query stringQ完成复杂操作,例如“标题或正文包括luceneQƈ且时间在20060101?0060130之间的文章”可以表CZؓ(f)Q? (title:lucene content:lucene) +time:[20060101 TO 20060130]”。代码如下:(x)<br /><br />Directory dir = FSDirectory.getDirectory(PATH, false);<br />IndexSearcher is = new IndexSearcher(dir);<br />QueryParser parser = new QueryParser("content", new StandardAnalyzer());<br />Query query = parser.parse("+(title:lucene content:lucene) +time:[20060101 TO 20060130]";<br />Hits hits = is.search(query);<br />for (int i = 0; i < hits.length(); i++)<br />{<br />Document doc = hits.doc(i);<br />System.out.println(doc.get("title");<br />}<br />is.close();<br /><br />首先我们创徏一个在指定文g目录上的IndexSearcher?br />然后创徏一个用StandardAnalyzer作ؓ(f)分析器的QueryParserQ它默认搜烦(ch)的域是content?br />接着我们用QueryParser来parse查询字串Q生成一个Query?br />然后利用q个QueryL扄果,l果以Hits的Ş式返回?br />q个Hits对象包含一个列表,我们挨个把它的内Ҏ(gu)C出来?br /><br />7.3 Filter<br />filter 的作用就是限制只查询索引的某个子集,它的作用有点像SQL语句里的whereQ但又有区别Q它不是正规查询的一部分Q只是对数据源进行预处理Q然后交l查询语句。注意它执行的是预处理,而不是对查询l果q行qo(h)Q所以用filter的代h很大的,它可能会(x)使一ơ查询耗时提高一癑ր?br />最常用的filter是RangeFilter和QueryFilter。RangeFilter是设定只搜烦(ch)指定范围内的索引QQueryFilter是在上次查询的结果中搜烦(ch)?br />Filter的用非常简单,你只需创徏一个filter实例Q然后把它传lsearcher。l上面的例子Q查询“时间在20060101?0060130之间的文章”除了将限制写在query string中,你还可以写在RangeFilter中:(x)<br /><br />Directory dir = FSDirectory.getDirectory(PATH, false);<br />IndexSearcher is = new IndexSearcher(dir);<br />QueryParser parser = new QueryParser("content", new StandardAnalyzer());<br />Query query = parser.parse("title:lucene content:lucene";<br />RangeFilter filter = new RangeFilter("time", "20060101", "20060230", true, true);<br />Hits hits = is.search(query, filter);<br />for (int i = 0; i < hits.length(); i++)<br />{<br />Document doc = hits.doc(i);<br />System.out.println(doc.get("title");<br />}<br />is.close();<br /><br />7.4 Sort<br />有时你想要一个排好序的结果集Q就像SQL语句的“order by”,lucene能做刎ͼ(x)通过Sort?br />Sort sort = new Sort(“time?; //相当于SQL的“order by time?br />Sort sort = new Sort(“time? true); // 相当于SQL的“order by time desc?br />下面是一个完整的例子Q?br /><br />Directory dir = FSDirectory.getDirectory(PATH, false);<br />IndexSearcher is = new IndexSearcher(dir);<br />QueryParser parser = new QueryParser("content", new StandardAnalyzer());<br />Query query = parser.parse("title:lucene content:lucene";<br />RangeFilter filter = new RangeFilter("time", "20060101", "20060230", true, true);<br />Sort sort = new Sort(“time?;<br />Hits hits = is.search(query, filter, sort);<br />for (int i = 0; i < hits.length(); i++)<br />{<br />Document doc = hits.doc(i);<br />System.out.println(doc.get("title");<br />}<br />is.close();<br /><br />8 分析?br />在前面的概念介绍中我们已l知道了分析器的作用Q就是把句子按照语义切分成一个个词语。英文切分已l有了很成熟的分析器Q?StandardAnalyzerQ很多情况下StandardAnalyzer是个不错的选择。甚至你?x)发现StandardAnalyzer也能对中文进行分词?br />但是我们的焦Ҏ(gu)中文分词QStandardAnalyzer能支持中文分词吗Q实践证明是可以的,但是效果q不好,搜烦(ch)“如果??x)把“牛奶不如果汁好喝”也搜烦(ch)出来Q而且索引文g很大。那么我们手头上q有什么分析器可以使用呢?core里面没有Q我们可以在sandbox里面扑ֈ两个Q?ChineseAnalyzer和CJKAnalyzer。但是它们同样都有分词不准的问题。相比之下用StandardAnalyzer和?ChineseAnalyzer建立索引旉差不多,索引文g大小也差不多QCJKAnalyzer表现?x)差些,索引文g大且耗时比较ѝ?br />要解决问题,首先分析一下这三个分析器的分词方式。StandardAnalyzer和ChineseAnalyzer都是把句子按单个字切分,也就是说  “牛奶不如果汁好喝”会(x)被它们切分成“牛 ??????喝”;而CJKAnalyzer则会(x)切分成“牛?奶不 不如 如果 果汁 汁好好喝”。这也就解释了ؓ(f)什么搜索“果汁”都能匹配这个句子?br />以上分词的缺点至有两个Q匹配不准确和烦(ch)引文件大。我们的目标是将上面的句子分解成 “牛?不如 果汁好喝”。这里的关键是语义识别Q我们如何识别“牛奶”是一个词而“奶不”不是词语?我们很自然会(x)惛_Z词库的分词法Q也是我们先得C个词库,里面列D了大部分词语Q我们把句子按某U方式切分,当得到的词语与词库中的项匚wӞ我们pU切分是正确的。这样切词的q程p{变成匚w的过E,而匹配的方式最单的有正向最大匹配和逆向最大匹配两U,说白了就是一个从句子开头向后进行匹配,一个从句子末尾向前q行匚w。基于词库的分词词库非常重要Q词库的定w直接影响搜烦(ch)l果Q在相同词库的前提下Q据说逆向最大匹配优于正向最大匹配?br />当然q有别的分词Ҏ(gu)Q这本n是一个学U,我这里也没有深入研究。回到具体应用,我们的目标是能找到成熟的、现成的分词工具Q避免重新发明R轮。经q网上搜索,用的比较多的是中U院?ICTCLAS和一个不开放源码但是免费的JE-Analysis。ICTCLAS有个问题是它是一个动态链接库Q?java调用需要本地方法调用,不方便也有安全隐(zhn),而且口碑也确实不大好。JE-Analysis效果q不错,当然也会(x)有分词不准的地方Q相比比较方便放心?br /><br />9 性能优化<br />一直到q里Q我们还是在讨论怎么样lucene跑v来,完成指定d。利用前面说的也实能完成大部分功能。但是测试表明lucene的性能q不是很好,在大数据量大q发的条件下甚至?x)有半分钟返回的情况。另外大数据量的数据初始化徏立烦(ch)引也是一个十分耗时的过E。那么如何提高lucene的性能呢?下面从优化创建烦(ch)引性能和优化搜索性能两方面介l?br /><br />9.1 优化创徏索引性能<br />q方面的优化途径比较有限QIndexWriter提供了一些接口可以控制徏立烦(ch)引的操作Q另外我们可以先烦(ch)引写入RAMDirectoryQ再扚w写入FSDirectoryQ不怎样Q目的都是尽量少的文件IOQ因为创建烦(ch)引的最大瓶颈在于磁盘I(y)O。另外选择一个较好的分析器也能提高一些性能?br /><br />9.1.1 通过讄IndexWriter的参C化烦(ch)引徏?br />setMaxBufferedDocs(int maxBufferedDocs)<br />控制写入一个新的segment前内存中保存的document的数目,讄较大的数目可以加快徏索引速度Q默认ؓ(f)10?br />setMaxMergeDocs(int maxMergeDocs)<br />控制一个segment中可以保存的最大document数目QD?yu)有利于q加索引的速度Q默认Integer.MAX_VALUEQ无需修改?br />setMergeFactor(int mergeFactor)<br />控制多个segment合ƈ的频率,D大时建立索引速度较快Q默认是10Q可以在建立索引时设|ؓ(f)100?br /><br />9.1.2 通过RAMDirectory~写提高性能<br />我们可以先把索引写入RAMDirectoryQ达C定数量时再批量写qFSDirectoryQ减磁盘I(y)Oơ数?br /><br />FSDirectory fsDir = FSDirectory.getDirectory("/data/index", true);<br />RAMDirectory ramDir = new RAMDirectory();<br />IndexWriter fsWriter = new IndexWriter(fsDir, new StandardAnalyzer(), true);<br />IndexWriter ramWriter = new IndexWriter(ramDir, new StandardAnalyzer(), true);<br />while (there are documents to index)<br />{<br />... create Document ...<br />ramWriter.addDocument(doc);<br />if (condition for flushing memory to disk has been met)<br />{<br />fsWriter.addIndexes(new Directory[] { ramDir });<br />ramWriter.close();<br />ramWriter = new IndexWriter(ramDir, new StandardAnalyzer(), true);<br />}<br />}<br /><br />9.1.3 选择较好的分析器<br />q个优化主要是对盘I间的优化,可以烦(ch)引文件减将q一半,相同试数据下由600M减少?80M。但是对旉q没有什么帮助,甚至?x)需要更长时_(d)因ؓ(f)较好的分析器需要匹配词库,?x)消耗更多cpuQ测试数据用StandardAnalyzer耗时133分钟Q用MMAnalyzer耗时150分钟?br /><br />9.2 优化搜烦(ch)性能<br />虽然建立索引的操作非常耗时Q但是那毕竟只在最初创建时才需要,qx只是量的维护操作,更何况这些可以放C个后台进E处理,q不影响用户搜烦(ch)。我们创建烦(ch)引的目的是l用h索,所以搜索的性能才是我们最兛_的。下面就来探讨一下如何提高搜索性能?br /><br />9.2.1 烦(ch)引放入内?br />q是一个最直观的想法,因ؓ(f)内存比磁盘快很多。Lucene提供了RAMDirectory可以在内存中容纳索引Q?br /><br />Directory fsDir = FSDirectory.getDirectory(?data/index/? false);<br />Directory ramDir = new RAMDirectory(fsDir);<br />Searcher searcher = new IndexSearcher(ramDir);<br /><br />但是实践证明RAMDirectory和FSDirectory速度差不多,当数据量很小时两者都非常快,当数据量较大Ӟ索引文g400MQRAMDirectory甚至比FSDirectoryq要慢一点,q确实让人出乎意料?br />而且lucene的搜索非常耗内存,即ɞ?00M的烦(ch)引文件蝲入内存,在运行一D|间后都会(x)out of memoryQ所以个入内存的作用q不大?br /><br />9.2.2 优化旉范围限制<br />既然载入内存q不能提高效率,一定有其它瓉Q经q测试发现最大的瓉居然是时间范围限Ӟ那么我们可以怎样使时间范围限制的代h(hun)最呢Q?br />当需要搜索指定时间范围内的结果时Q可以:(x)<br />1、用RangeQueryQ设|范_(d)但是RangeQuery的实现实际上是将旉范围内的旉点展开Q组成一个个BooleanClause加入刊W?BooleanQuery中查询,因此旉范围不可能设|太大,l测试,范围过一个月׃(x)?BooleanQuery.TooManyClausesQ可以通过讄 BooleanQuery.setMaxClauseCount (int maxClauseCount)扩大Q但是扩大也是有限的Qƈ且随着maxClauseCount扩大Q占用内存也扩大<br />2、用 RangeFilter代替RangeQueryQ经试速度不会(x)比RangeQuery慢,但是仍然有性能瓉Q查询的90%以上旉耗费在?RangeFilterQ研I其源码发现RangeFilter实际上是首先遍历所有烦(ch)引,生成一个BitSetQ标记每个documentQ在旉范围内的标记为trueQ不在的标记为falseQ然后将l果传递给Searcher查找Q这是十分耗时的?br />3、进一步提高性能Q这个又有两个思\Q?br />a、缓存Filterl果。既然RangeFilter的执行是在搜索之前,那么它的输入都是一定的Q就是IndexReaderQ而?IndexReader是由Directory军_的,所以可以认为RangeFilter的结果是p围的上下限决定的Q也是由具体的  RangeFilter对象军_Q所以我们只要以RangeFilter对象为键Q将filterl果BitSet~存h卛_。lucene API 已经提供了一个CachingWrapperFiltercd装了Filter?qing)其l果Q所以具体实施v来我们可?cache CachingWrapperFilter对象Q需要注意的是,不要被CachingWrapperFilter的名字及(qing)其说明误|  CachingWrapperFilter看v来是有缓存功能,但的~存是针对同一个filter的,也就是在你用同一个filterqo(h)不同  IndexReaderӞ它可以帮你缓存不同IndexReader的结果,而我们的需求恰恰相反,我们是用不同filterqo(h)同一个?IndexReaderQ所以只能把它作Z个封装类?br />b、降低时间精度。研IFilter的工作原理可以看出,它每ơ工作都是遍历整个烦(ch)引的Q所以时间粒度越大,Ҏ(gu)快Q搜索时间越短,在不影响功能的情况下Q时间精度越低越好,有时甚至牺牲一点精度也值得Q当然最好的情况是根本不作时间限制?br />下面针对上面的两个思\演示一下优化结果(都采?00U程随机关键词随x间范_(d)(j)Q?br />W一l,旉_ֺ为秒Q?br />方式 直接用RangeFilter 使用cache 不用filter<br />q_每个U程耗时 10s 1s 300ms<br /><br />W二l,旉_ֺ为天<br />方式 直接用RangeFilter 使用cache 不用filter<br />q_每个U程耗时 900ms 360ms 300ms<br /><br />׃上数据可以得出结论:(x)<br />1?量降低旉_ֺQ将_ֺq换成天带来的性能提高甚至比用cacheq好Q最好不使用filter?br />2?在不能降低时间精度的情况下,使用cache能带?0倍左右的性能提高?br /><br />9.2.3 使用更好的分析器<br />q个跟创建烦(ch)引优化道理差不多Q烦(ch)引文件小了搜索自然会(x)加快。当然这个提高也是有限的。较好的分析器相对于最差的分析器对性能的提升在20%以下?br /><br />10 一些经?br /><br />10.1关键词区分大写<br />or AND TO{关键词是区分大写的,lucene只认大写的,写的当做普通单词?br /><br />10.2 d互斥?br />同一时刻只能有一个对索引的写操作Q在写的同时可以q行搜烦(ch)<br /><br />10.3 文g?br />在写索引的过E中退出将在tmp目录留下一个lock文gQ以后的写操作无法q行Q可以将其手工删?br /><br />10.4 旉格式<br />lucene只支持一U时间格式yyMMddHHmmssQ所以你传一个yy-MM-dd HH:mm:ss的时间给lucene它是不会(x)当作旉来处理的<br /><br />10.5 讄boost<br />有些时候在搜烦(ch)时某个字D늚权重需要大一些,例如你可能认为标题中出现关键词的文章比正文中出现关键词的文章更有价|你可以把标题的boost讄的更大,那么搜烦(ch)l果?x)优先显C标题中出现关键词的文章Q没有用排序的前题下)(j)。用方法:(x)<br />Field. setBoost(float boost);默认值是1.0Q也是说要增加权重的需要设|得?大?br /><br /><img src ="http://www.tkk7.com/dybjsun/aggbug/174065.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/dybjsun/" target="_blank">dybjsun</a> 2008-01-09 17:17 <a href="http://www.tkk7.com/dybjsun/archive/2008/01/09/174065.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>log4jhttp://www.tkk7.com/dybjsun/archive/2007/12/24/170000.htmldybjsundybjsunMon, 24 Dec 2007 03:46:00 GMThttp://www.tkk7.com/dybjsun/archive/2007/12/24/170000.htmlhttp://www.tkk7.com/dybjsun/comments/170000.htmlhttp://www.tkk7.com/dybjsun/archive/2007/12/24/170000.html#Feedback0http://www.tkk7.com/dybjsun/comments/commentRss/170000.htmlhttp://www.tkk7.com/dybjsun/services/trackbacks/170000.html
Log4j是Apache的一个开放源代码目Q通过使用Log4jQ我们可以控制日志信息输送的目的地是控制台、文件、GUIlg、甚x套接口服务器、NT的事件记录器、UNIX Syslog守护q程{;我们也可以控制每一条日志的输出格式Q通过定义每一条日志信息的U别Q我们能够更加细致地控制日志的生成过E。最令h感兴的是Q这些可以通过一个配|文件来灉|地进行配|,而不需要修改应用的代码?br />
此外Q通过Log4j其他语言接口Q?zhn)可以在C、C++?Net、PL/SQLE序中用Log4jQ其语法和用法与在JavaE序中一P使得多语a分布式系l得C个统一一致的日志lg模块。而且Q通过使用各种W三Ҏ(gu)展,(zhn)可以很方便地将Log4j集成到J2EE、JINI甚至是SNMP应用中?br />
说明Q下面分Z部分Q第一部分讲解如何配置log4jQ第二部分ؓ(f)对log4j.properties配置文g中的各个属性的讲解Q第三部分ؓ(f)?log4j的详l讲解,如果只想配置上log4jQ那么只需要看前两个部分就可以Q如果想对log4j深入了解Q则q需看第三部分?br />
一、Log4j配置

W一步:(x)加入log4j-1.2.8.jar到l(f)ib下?br />
W二步:(x)在CLASSPATH下徏立log4j.properties。内容如下:(x)

1 log4j.rootCategory=INFO, stdout , R

2

3 log4j.appender.stdout=org.apache.log4j.ConsoleAppender

4 log4j.appender.stdout.layout=org.apache.log4j.PatternLayout

5 log4j.appender.stdout.layout.ConversionPattern=[QC] %p [%t] %C.%M(%L) | %m%n

6

7 log4j.appender.R=org.apache.log4j.DailyRollingFileAppender

8 log4j.appender.R.File=D:\\Tomcat 5.5\\logs\\qc.log

9 log4j.appender.R.layout=org.apache.log4j.PatternLayout

10 log4j.appender.R.layout.ConversionPattern=%d-[TS] %p %t %c - %m%n

11

12 log4j.logger.com.neusoft=DEBUG

13 log4j.logger.com.opensymphony.oscache=ERROR

14 log4j.logger.net.sf.navigator=ERROR

15 log4j.logger.org.apache.commons=ERROR

16 log4j.logger.org.apache.struts=WARN

17 log4j.logger.org.displaytag=ERROR

18 log4j.logger.org.springframework=DEBUG

19 log4j.logger.com.ibatis.db=WARN

20 log4j.logger.org.apache.velocity=FATAL

21

22 log4j.logger.com.canoo.webtest=WARN

23

24 log4j.logger.org.hibernate.ps.PreparedStatementCache=WARN

25 log4j.logger.org.hibernate=DEBUG

26 log4j.logger.org.logicalcobwebs=WARN

W三步:(x)相应的修改其中属性,修改之前必ȝ道这些都是干什么的Q在W二部分讲解?br />
W四步:(x)在要输出日志的类中加入相兌句:(x)

定义属性:(x)protected final Log log = LogFactory.getLog(getClass());

在相应的Ҏ(gu)中:(x)

if (log.isDebugEnabled())

{

log.debug(“System ?.?;

}

二、Log4j说明

1 log4j.rootCategory=INFO, stdout , R

此句为将{为INFO的日志信息输出到stdout和Rq两个目的地Qstdout和R的定义在下面的代码,可以L起名。等U可分ؓ(f)OFF?FATAL、ERROR、WARN、INFO、DEBUG、ALLQ如果配|OFF则不打出M信息Q如果配|ؓ(f)INFOq样只显CINFO, WARN, ERROR的log信息Q而DEBUG信息不会(x)被显C,具体讲解可参照第三部分定义配|文件中的logger?br />
3 log4j.appender.stdout=org.apache.log4j.ConsoleAppender

此句为定义名为stdout的输出端是哪U类型,可以?br />
org.apache.log4j.ConsoleAppenderQ控制台Q,

org.apache.log4j.FileAppenderQ文Ӟ(j)Q?br />
org.apache.log4j.DailyRollingFileAppenderQ每天生一个日志文Ӟ(j)Q?br />
org.apache.log4j.RollingFileAppenderQ文件大到达指定尺寸的时候生一个新的文Ӟ(j)

org.apache.log4j.WriterAppenderQ将日志信息以流格式发送到L指定的地方)(j)

具体讲解可参照第三部分定义配|文件中的Appender?br />
4 log4j.appender.stdout.layout=org.apache.log4j.PatternLayout

此句为定义名为stdout的输出端的layout是哪U类型,可以?br />
org.apache.log4j.HTMLLayoutQ以HTML表格形式布局Q,

org.apache.log4j.PatternLayoutQ可以灵zd指定布局模式Q,

org.apache.log4j.SimpleLayoutQ包含日志信息的U别和信息字W串Q,

org.apache.log4j.TTCCLayoutQ包含日志生的旉、线E、类别等{信息)(j)

具体讲解可参照第三部分定义配|文件中的Layout?br />
5 log4j.appender.stdout.layout.ConversionPattern= [QC] %p [%t] %C.%M(%L) | %m%n

如果使用pattern布局p指定的打C息的具体格式ConversionPatternQ打印参数如下:(x)

%m 输出代码中指定的消息

%p 输出优先U,即DEBUGQINFOQW(xu)ARNQERRORQFATAL

%r 输出自应用启动到输出该log信息耗费的毫U数

%c 输出所属的cȝQ通常是所在类的全?br />
%t 输出产生该日志事件的U程?br />
%n 输出一个回车换行符QW(xu)indowsq_为“rn”,Unixq_为“n?br />
%d 输出日志旉点的日期或时_(d)默认格式为ISO8601Q也可以在其后指定格式,比如Q?d{yyyy MMM dd HH:mm:ss,SSS}Q输出类|(x)2002q?0?8?22Q?0Q?8Q?21

%l 输出日志事g的发生位|,包括cȝ名、发生的U程Q以?qing)在代码中的行数?br />
[QC]是log信息的开_(d)可以ZQ意字W,一般ؓ(f)目U?br />
输出的信?br />
[TS] DEBUG [main] AbstractBeanFactory.getBean(189) | Returning cached instance of singleton bean 'MyAutoProxy'

具体讲解可参照第三部分定义配|文件中的格式化日志信息?br />
7 log4j.appender.R=org.apache.log4j.DailyRollingFileAppender

此句与第3行一栗定义名为R的输出端的类型ؓ(f)每天产生一个日志文件?br />
8 log4j.appender.R.File=D:\\Tomcat 5.5\\logs\\qc.log

此句为定义名为R的输出端的文件名为D:\\Tomcat 5.5\\logs\\qc.log

可以自行修改?br />
9 log4j.appender.R.layout=org.apache.log4j.PatternLayout

与第4行相同?br />
10 log4j.appender.R.layout.ConversionPattern=%d-[TS] %p %t %c - %m%n

与第5行相同?br />
12 log4j.logger.com. neusoft =DEBUG

指定com.neusoft包下的所有类的等Uؓ(f)DEBUG?br />
可以把com.neusoft改ؓ(f)自己目所用的包名?br />
13 log4j.logger.com.opensymphony.oscache=ERROR

14 log4j.logger.net.sf.navigator=ERROR

q两句是把这两个包下出现的错误的{设ؓ(f)ERRORQ如果项目中没有配置EHCacheQ则不需要这两句?br />
15 log4j.logger.org.apache.commons=ERROR

16 log4j.logger.org.apache.struts=WARN

q两句是struts的包?br />
17 log4j.logger.org.displaytag=ERROR

q句是displaytag的包。(QC问题列表面所用)(j)

18 log4j.logger.org.springframework=DEBUG

此句为Spring的包?br />
24 log4j.logger.org.hibernate.ps.PreparedStatementCache=WARN

25 log4j.logger.org.hibernate=DEBUG

此两句是hibernate的包?br />
以上q些包的讄可根据项目的实际情况而自行定制?br />
三、log4j详解

1、定义配|文?br />
Log4j支持两种配置文g格式Q一U是XML格式的文Ӟ一U是JavaҎ(gu)文件log4j.propertiesQ键=|(j)。下面将介绍使用log4j.properties文g作ؓ(f)配置文g的方?

①、配|根Logger

Logger 负责处理日志记录的大部分操作?br />
其语法ؓ(f)Q?br />
log4j.rootLogger = [ level ] , appenderName, appenderName, ?br />
其中Qlevel 是日志记录的优先U,分ؓ(f)OFF、FATAL、ERROR、WARN、INFO、DEBUG、ALL或者自定义的别。Log4j只用四个别,优先U从高到低分别是ERROR、WARN、INFO、DEBUG。通过在这里定义的U别Q?zhn)可以控制到应用程序中相应U别的日志信息的开兟뀂比如在q里定义了INFOU别Q只有等于及(qing)高于q个U别的才q行处理Q则应用E序中所有DEBUGU别的日志信息将不被打印出来。ALL:打印所有的日志QOFFQ关闭所有的日志输出?appenderName是指定日志信息输出到哪个地斏V可同时指定多个输出目的地?br />
②、配|日志信息输出目的地 Appender

Appender 负责控制日志记录操作的输出?br />
其语法ؓ(f)Q?br />
log4j.appender.appenderName = fully.qualified.name.of.appender.class

log4j.appender.appenderName.option1 = value1

?br />
log4j.appender.appenderName.optionN = valueN

q里的appenderName为在①里定义的,可Q意v名?br />
其中QLog4j提供的appender有以下几U:(x)

org.apache.log4j.ConsoleAppenderQ控制台Q,

org.apache.log4j.FileAppenderQ文Ӟ(j)Q?br />
org.apache.log4j.DailyRollingFileAppenderQ每天生一个日志文Ӟ(j)Q?br />
org.apache.log4j.RollingFileAppenderQ文件大到达指定尺寸的时候生一个新的文Ӟ(j)Q可通过 log4j.appender.R.MaxFileSize=100KB讄文g大小Q还可通过 log4j.appender.R.MaxBackupIndex=1讄Z存一个备份文件?br />
org.apache.log4j.WriterAppenderQ将日志信息以流格式发送到L指定的地方)(j)

例如Qlog4j.appender.stdout=org.apache.log4j.ConsoleAppender

定义一个名为stdout的输出目的地QConsoleAppender为控制台?br />
③、配|日志信息的格式Q布局QLayout

Layout 负责格式化Appender的输出?br />
其语法ؓ(f)Q?br />
log4j.appender.appenderName.layout = fully.qualified.name.of.layout.class

log4j.appender.appenderName.layout.option1 = value1

?br />
log4j.appender.appenderName.layout.optionN = valueN

其中QLog4j提供的layout有以下几U:(x)

org.apache.log4j.HTMLLayoutQ以HTML表格形式布局Q,

org.apache.log4j.PatternLayoutQ可以灵zd指定布局模式Q,

org.apache.log4j.SimpleLayoutQ包含日志信息的U别和信息字W串Q,

org.apache.log4j.TTCCLayoutQ包含日志生的旉、线E、类别等{信息)(j)

2、格式化日志信息

Log4J采用cMC语言中的printf函数的打印格式格式化日志信息Q打印参数如下:(x)

%m 输出代码中指定的消息

%p 输出优先U,即DEBUGQINFOQW(xu)ARNQERRORQFATAL

%r 输出自应用启动到输出该log信息耗费的毫U数

%c 输出所属的cȝQ通常是所在类的全?br />
%t 输出产生该日志事件的U程?br />
%n 输出一个回车换行符QW(xu)indowsq_为“rn”,Unixq_为“n?br />
%d 输出日志旉点的日期或时_(d)默认格式为ISO8601Q也可以在其后指定格式,比如Q?d{yyyy MMM dd HH:mm:ss,SSS}Q输出类|(x)2002q?0?8?22Q?0Q?8Q?21

%l 输出日志事g的发生位|,包括cȝ名、发生的U程Q以?qing)在代码中的行数?br />
3、在代码中用Log4j

我们在需要输出日志信息的cM做如下的三个工作Q?br />
1、导入所有需的commongs-loggingc:(x)

import org.apache.commons.logging.Log;

import org.apache.commons.logging.LogFactory;

2、在自己的类中定义一个org.apache.commons.logging.LogcȝU有静态类成员Q?br />
private final Log log = LogFactory.getLog(getClass());

LogFactory.getLog()Ҏ(gu)的参C用的是当前类的class?br />
3、用org.apache.commons.logging.Logcȝ成员Ҏ(gu)输出日志信息Q?br />
if (log.isDebugEnabled())

{

log.debug("111");

}

if (log.isInfoEnabled())

{

log.info("222");

}

if (log.isWarnEnabled())

{

log.warn("333");

}

if (log.isErrorEnabled())

{

log.error("444");

}

if (log.isFatalEnabled())

{

log.fatal("555")

}


dybjsun 2007-12-24 11:46 发表评论
]]>
常见软g试的技?/title><link>http://www.tkk7.com/dybjsun/archive/2007/12/06/165716.html</link><dc:creator>dybjsun</dc:creator><author>dybjsun</author><pubDate>Thu, 06 Dec 2007 01:33:00 GMT</pubDate><guid>http://www.tkk7.com/dybjsun/archive/2007/12/06/165716.html</guid><wfw:comment>http://www.tkk7.com/dybjsun/comments/165716.html</wfw:comment><comments>http://www.tkk7.com/dybjsun/archive/2007/12/06/165716.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/dybjsun/comments/commentRss/165716.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/dybjsun/services/trackbacks/165716.html</trackback:ping><description><![CDATA[软g试虽然辛苦Q但是掌握了一定的技巧之后将使你事半功倍?br /><br />  (1) 边界试Q测试用戯入框中的数值的最大数和最数Q以?qing)?f)I时的情c(din)?br /><br />  (2) 非法试Q例如在输入数字的地方输入字母?br /><br />  (3) 跟踪试Q跟t一条数据的程,保证数据的正性?br /><br />  (4) 在开始测试时应保证数据的正确性,然后在从pȝ中找出各UBUG?br /><br />  (5) 接口试Q程序往往在接口的地方很容易发生错误,要在此模块测试勿掉以d?br /><br />  (6) 代码重用试Q在开发过E中有些模块功能几乎相同Q程序员在重用代码时可能忘记在原有代码上修改或修改不全面Q而造成的错误?br /><br />  (7) H发事g试Q服务器上可能发生意外情늚试?br /><br />  (8) 外界环境试Q有些系l在开发时依赖于另外一个系l?当另外一个系l发生错误时, q个pȝ所受到的媄(jing)响的情况?br /><br />  (9) 在程序员刚修复Bug之后的地?再找一找,往往E序员只修复报告出来的缺陯(g)不去考虑别的功能在修Ҏ(gu)可能?x)重新造成错误?br /><br />  (10) 认真做好试记录在做完一天的试记录之后,W二天再Ҏ(gu)W一天的试记录重复试你会(x)发现有未修正的错误?br /><br />  (11) 文字试Q如果在pȝ中有用词不当的地方,我想q是不应该的?br /><br />  (12) pȝ兼容试Q例如有些程序在IE6能运行正常,到IE5下不能运行。有些程序在WIN2000下能q行Q而到WIN98却不能运行。像一些很特别的用户去使用pȝQ你很有可能发现BUG?br /><br />  (13) 用户的易用性测试,往往用户的需求是不断的变化的Q而其中的一部䆾变化的原因,是有用户操作上不方便引v的?br /><br />  软g试是Y件开发中的重中之重,没有一点可以马虎的Q在目理q程Q我的是每个q程的每一个环节都要进行测试,保证pȝ在每个阶D可以控制。因Y件测试中考虑的问题基本上是项目管理中考虑的问题?br /><br />  我认为在目理中考虑的一些问题应该是在Y件测试时有些体现Q体现的内容是Y件测试的一些侧重点Q具体说QY件测试是事务性的Q而项目管理是{略性,一些策略性的东西必须在一些事务性的事务上来实现?br /><br />  软g试是一门新兴的行业Q现在Y件测试在我国的地位虽说还不是很高Q但q几q却是逐渐转好Q国内对软g试的重视程度也慢慢高v来了。大家如果对IT有兴的话,不烦(ch)了解一下,怿也会(x)有所感?zhn)的。我q常在|上看一些Y件测试方面的文章或技巧,q对我的成长也是具大的。大家有旉不烦(ch)M下北大测试的|站Q那里面有很多软g试技巧和行业新闻Q对我启发很多?img src ="http://www.tkk7.com/dybjsun/aggbug/165716.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/dybjsun/" target="_blank">dybjsun</a> 2007-12-06 09:33 <a href="http://www.tkk7.com/dybjsun/archive/2007/12/06/165716.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>SESSION机制http://www.tkk7.com/dybjsun/archive/2007/11/09/159237.htmldybjsundybjsunThu, 08 Nov 2007 17:45:00 GMThttp://www.tkk7.com/dybjsun/archive/2007/11/09/159237.htmlhttp://www.tkk7.com/dybjsun/comments/159237.htmlhttp://www.tkk7.com/dybjsun/archive/2007/11/09/159237.html#Feedback1http://www.tkk7.com/dybjsun/comments/commentRss/159237.htmlhttp://www.tkk7.com/dybjsun/services/trackbacks/159237.html阅读全文

dybjsun 2007-11-09 01:45 发表评论
]]>
印度人是怎样开发Y件的http://www.tkk7.com/dybjsun/archive/2006/10/18/75780.htmldybjsundybjsunTue, 17 Oct 2006 17:54:00 GMThttp://www.tkk7.com/dybjsun/archive/2006/10/18/75780.htmlhttp://www.tkk7.com/dybjsun/comments/75780.htmlhttp://www.tkk7.com/dybjsun/archive/2006/10/18/75780.html#Feedback1http://www.tkk7.com/dybjsun/comments/commentRss/75780.htmlhttp://www.tkk7.com/dybjsun/services/trackbacks/75780.html阅读全文

dybjsun 2006-10-18 01:54 发表评论
]]>
?Linux 上安?PostgreSQLhttp://www.tkk7.com/dybjsun/archive/2006/10/13/75046.htmldybjsundybjsunFri, 13 Oct 2006 11:27:00 GMThttp://www.tkk7.com/dybjsun/archive/2006/10/13/75046.htmlhttp://www.tkk7.com/dybjsun/comments/75046.htmlhttp://www.tkk7.com/dybjsun/archive/2006/10/13/75046.html#Feedback0http://www.tkk7.com/dybjsun/comments/commentRss/75046.htmlhttp://www.tkk7.com/dybjsun/services/trackbacks/75046.html阅读全文

dybjsun 2006-10-13 19:27 发表评论
]]>
关于Java栈与堆的思?/title><link>http://www.tkk7.com/dybjsun/archive/2006/10/10/74213.html</link><dc:creator>dybjsun</dc:creator><author>dybjsun</author><pubDate>Tue, 10 Oct 2006 01:24:00 GMT</pubDate><guid>http://www.tkk7.com/dybjsun/archive/2006/10/10/74213.html</guid><wfw:comment>http://www.tkk7.com/dybjsun/comments/74213.html</wfw:comment><comments>http://www.tkk7.com/dybjsun/archive/2006/10/10/74213.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/dybjsun/comments/commentRss/74213.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/dybjsun/services/trackbacks/74213.html</trackback:ping><description><![CDATA[     摘要: 每一个Java应用都唯一对应一个JVM实例Q每一个实例唯一对应一个堆。应用程序在q行中所创徏的所有类实例或数l都攑֜q个堆中,q由应用所有的U程׃n.跟C/C++不同QJava中分配堆内存是自动初始化的。Java中所有对象的存储I间都是在堆中分配的Q但是这个对象的引用却是在堆栈中分配,也就是说在徏立一个对象时从两个地斚w分配内存Q在堆中分配的内存实际徏立这个对象,而在堆栈中分配的内存只是一个指向这个堆对象的指?引用)而已?nbsp; <a href='http://www.tkk7.com/dybjsun/archive/2006/10/10/74213.html'>阅读全文</a><img src ="http://www.tkk7.com/dybjsun/aggbug/74213.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/dybjsun/" target="_blank">dybjsun</a> 2006-10-10 09:24 <a href="http://www.tkk7.com/dybjsun/archive/2006/10/10/74213.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss> <footer> <div class="friendship-link"> <p>лǵվܻԴȤ</p> <a href="http://www.tkk7.com/" title="亚洲av成人片在线观看">亚洲av成人片在线观看</a> <div class="friend-links"> </div> </div> </footer> վ֩ģ壺 <a href="http://ystchem.com" target="_blank">2021ƷƵѲ</a>| <a href="http://sdsupuchem.com" target="_blank">޾ƷƵ</a>| <a href="http://yy7699.com" target="_blank">Ʒרһ</a>| <a href="http://ttvv77.com" target="_blank">޾ƷƵѹۿ</a>| <a href="http://400209.com" target="_blank">þþþþëƬѲ</a>| <a href="http://77110524.com" target="_blank">˳δʮ˽վ</a>| <a href="http://1992zyzp.com" target="_blank">պޱ̬</a>| <a href="http://mtspvip.com" target="_blank">վ߹ۿ</a>| <a href="http://35469642.com" target="_blank">ѹۿƵ</a>| <a href="http://www-ttyx.com" target="_blank">AVһ</a>| <a href="http://323799.com" target="_blank">AVվ</a>| <a href="http://kan63.com" target="_blank">뾫Ʒþþþ </a>| <a href="http://lfhuanxin.com" target="_blank">100018Ƶ</a>| <a href="http://51a88.com" target="_blank">һ</a>| <a href="http://yy6090qpgdy.com" target="_blank">þþþAVվ</a>| <a href="http://jogador1.com" target="_blank">99re6ƵƷѹۿ</a>| <a href="http://24aabb.com" target="_blank">þþƷŮav鶹</a>| <a href="http://35419470.com" target="_blank">þ޹Ƶ</a>| <a href="http://spvec.com" target="_blank">޳AƬ77777</a>| <a href="http://cc45987.com" target="_blank">91߹ۿ</a>| <a href="http://jisuanq.com" target="_blank">Ʒþþþþ</a>| <a href="http://wxyz2.com" target="_blank">޹߹ۿ </a>| <a href="http://phlinhng.com" target="_blank">޵һƵ߹ۿ</a>| <a href="http://thegaybdsm.com" target="_blank">Ƶ</a>| <a href="http://www48646.com" target="_blank">ձվ</a>| <a href="http://hndsfwl.com" target="_blank">պɫպƵվ</a>| <a href="http://mangshigas.com" target="_blank">޺ݺݺһ</a>| <a href="http://fense1.com" target="_blank">޵Ӱ߹ۿ</a>| <a href="http://468862.com" target="_blank">þ޹</a>| <a href="http://tom-erc20.com" target="_blank">ޢva</a>| <a href="http://xyzch.com" target="_blank">޹Ʒþþþվ</a>| <a href="http://avxyz.com" target="_blank">av乾</a>| <a href="http://wwwyy763.com" target="_blank">avƬ߹ۿ</a>| <a href="http://tc116.com" target="_blank">͵͵߶̬ͼ</a>| <a href="http://xuexilo.com" target="_blank">ҹ޾ƷƬ </a>| <a href="http://dasheng178.com" target="_blank">޾Ʒþò</a>| <a href="http://www97544.com" target="_blank"> ר</a>| <a href="http://4husese.com" target="_blank">va߹ۿ</a>| <a href="http://yzxjk.com" target="_blank">ɫһɫһ</a>| <a href="http://xxxxnii.com" target="_blank">Ʒһ߲</a>| <a href="http://usagaa.com" target="_blank">þþþþAŷAV</a>| <script> (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })(); </script> </body>