ï»??xml version="1.0" encoding="utf-8" standalone="yes"?>日韩一区二区三区在线视频,性色av一区二区三区免费,久久夜精品香蕉http://www.aygfsteel.com/dybjsun/category/16010.htmlzh-cnSat, 08 Mar 2008 23:13:38 GMTSat, 08 Mar 2008 23:13:38 GMT60Tomcat启动分析http://www.aygfsteel.com/dybjsun/archive/2008/01/10/174216.htmldybjsundybjsunThu, 10 Jan 2008 03:24:00 GMThttp://www.aygfsteel.com/dybjsun/archive/2008/01/10/174216.htmlhttp://www.aygfsteel.com/dybjsun/comments/174216.htmlhttp://www.aygfsteel.com/dybjsun/archive/2008/01/10/174216.html#Feedback0http://www.aygfsteel.com/dybjsun/comments/commentRss/174216.htmlhttp://www.aygfsteel.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是这样一个集合:它由一个或者多个Connector¾l„成åQŒä»¥åŠä¸€ä¸ªEngineåQŒè´Ÿè´£å¤„理所有Connector所获得的客戯‚¯·æ±?br />

1.3 - Connector

一个Connectorž®†åœ¨æŸä¸ªæŒ‡å®šç«¯å£ä¸Šä¾¦å¬å®¢æˆ¯‚¯·æ±‚,òq¶å°†èŽ·å¾—çš„è¯·æ±‚äº¤¾l™Engine来处理,从Engineå¤„èŽ·å¾—å›žåº”åÆˆ˜q”回客户
TOMCAT有两个典型的ConnectoråQŒä¸€ä¸ªç›´æŽ¥ä¾¦å¬æ¥è‡ªbrowserçš„httpè¯äh±‚åQŒä¸€ä¸ªä¾¦å¬æ¥è‡ªå…¶å®ƒWebServer的请æ±?br />Coyote Http/1.1 Connector 在端å?080处侦听来自客户browserçš„httpè¯äh±‚
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 HoståQŒæ¯ä¸ªè™šæ‹Ÿä¸»æœºéƒ½æœ‰ä¸€ä¸ªåŸŸå?br />当Engine获得一个请求时åQŒå®ƒæŠŠè¯¥è¯äh±‚匚w…åˆ°æŸä¸ªHost上,然后把该è¯äh±‚交给该Host来处ç?br />Engine有一个默认虚拟主机,当请求无法匹配到ä»ÖM½•一个Host上的时候,ž®†äº¤¾l™è¯¥é»˜è®¤Host来处ç?br />

1.5 - Host

 

代表一个Virtual HoståQŒè™šæ‹Ÿä¸»æœºï¼Œæ¯ä¸ªè™šæ‹Ÿä¸ÀLœºå’ŒæŸä¸ªç½‘¾lœåŸŸåDomain Name相匹é…?br />每个虚拟ä¸ÀLœºä¸‹éƒ½å¯ä»¥éƒ¨çÖv(deploy)一个或者多个Web AppåQŒæ¯ä¸ªWeb App对应于一个ContextåQŒæœ‰ä¸€ä¸ª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 ApplicationåQŒä¸€ä¸ªWeb Applicationç”׃¸€ä¸ªæˆ–者多个Servlet¾l„成
Context在创建的时候将æ ÒŽ®é…ç½®æ–‡äšg$CATALINA_HOME/conf/web.xmlå’?WEBAPP_HOME/WEB-INF/web.xml载入Servlet¾c?br />当Context获得è¯äh±‚æ—Óž¼Œž®†åœ¨è‡ªå·±çš„æ˜ ž®„表(mapping table)中寻扄¡›¸åŒšw…çš„Servlet¾c?br />如果扑ֈ°åQŒåˆ™æ‰§è¡Œè¯¥ç±»åQŒèŽ·å¾—è¯·æ±‚çš„å›žåº”åQŒåƈ˜q”回

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

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

该文件描˜qîCº†å¦‚何启动Tomcat Server

 

4 - Context的部¾|²é…¾|®æ–‡ä»¶web.xml的说æ˜?

一个Context对应于一个Web AppåQŒæ¯ä¸ªWeb App是由一个或者多个servlet¾l„成çš?br />当一个Web App被初始化的时候,它将用自å·Þqš„ClassLoader对象载入“部¾|²é…¾|®æ–‡ä»¶web.xml”中定义的每个servlet¾c?br />它首先蝲入在$CATALINA_HOME/conf/web.xml中部¾|²çš„servlet¾c?br />然后载入在自å·Þqš„Web App根目录下的WEB-INF/web.xml中部¾|²çš„servlet¾c?br />web.xmlæ–‡äšg有两部分åQšservlet¾cÕd®šä¹‰å’Œservlet映射定义
每个被蝲入的servlet¾c»éƒ½æœ‰ä¸€ä¸ªåå­—,且被填入该Context的映ž®„表(mapping table)中,和某¿UURL PATTERN对应
当该Context获得è¯äh±‚æ—Óž¼Œž®†æŸ¥è¯¢mapping tableåQŒæ‰¾åˆ°è¢«è¯äh±‚çš„servletåQŒåƈ执行以获得请求回åº?br />

分析一下所有的Contextå…׃ínçš„web.xmlæ–‡äšgåQŒåœ¨å…¶ä¸­å®šä¹‰çš„servlet被所有的Web App载入

 

5 - Tomcat Server处理一个httpè¯äh±‚的过½E?

å‡è®¾æ¥è‡ªå®¢æˆ·çš„è¯·æ±‚äØ“åQ?br />http://localhost:8080/wsota/wsota_index.jsp

1) è¯äh±‚被发送到本机端口8080åQŒè¢«åœ¨é‚£é‡Œä¾¦å¬çš„Coyote HTTP/1.1 Connector获得
2) Connector把该è¯äh±‚交给它所在的Serviceçš„Engine来处理,òq¶ç­‰å¾…来自Engine的回åº?br />3) Engine获得è¯äh±‚localhost/wsota/wsota_index.jspåQŒåŒ¹é…å®ƒæ‰€æ‹¥æœ‰çš„æ‰€æœ‰è™šæ‹Ÿä¸»æœºHost
4) Engine匚w…åˆ°åä¸ºlocalhostçš„HoståQˆå³ä½¿åŒ¹é…ä¸åˆîC¹ŸæŠŠè¯·æ±‚交¾l™è¯¥Host处理åQŒå› ä¸ø™¯¥Hostè¢«å®šä¹‰äØ“è¯¥Engine的默认主机)
5) localhost Host获得è¯äh±‚/wsota/wsota_index.jspåQŒåŒ¹é…å®ƒæ‰€æ‹¥æœ‰çš„æ‰€æœ‰Context
6) Host匚w…åˆ°èµ\径䨓/wsotaçš„ContextåQˆå¦‚果匹配不到就把该è¯äh±‚äº¤ç»™è·¯å¾„åäØ“""çš„ContextåŽÕd¤„理)
7) path="/wsota"çš„Context获得è¯äh±‚/wsota_index.jspåQŒåœ¨å®ƒçš„mapping table中寻扑֯¹åº”çš„servlet
8) Context匚w…åˆ°URL PATTERNä¸?.jspçš„servletåQŒå¯¹åº”于JspServlet¾c?br />9) 构造HttpServletRequest对象和HttpServletResponse对象åQŒä½œä¸ºå‚数调用JspServletçš„doGet或doPostæ–ÒŽ³•
10)Context把执行完了之后的HttpServletResponse对象˜q”回¾l™Host
11)Host把HttpServletResponse对象˜q”回¾l™Engine
12)Engine把HttpServletResponse对象˜q”回¾l™Connector
13)Connector把HttpServletResponse对象˜q”回¾l™å®¢æˆ·browser

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


<web-app>


<!-- 概述åQ?br /> 该文件是所有的WEB APPå…Þq”¨çš„部¾|²é…¾|®æ–‡ä»Óž¼Œ
每当一个WEB APP被DEPLOYåQŒè¯¥æ–‡äšg都将先被处理åQŒç„¶åŽæ‰æ˜¯WEB APP自己çš?WEB-INF/web.xml
-->



<!-- +-------------------------+ -->
<!-- | servlet¾cÕd®šä¹‰éƒ¨åˆ? | -->
<!-- +-------------------------+ -->



<!-- DefaultServlet
当用æˆïLš„HTTPè¯äh±‚无法匚w…ä»ÖM½•一个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™åµé¢çš„æ—¶å€™ï¼ˆ*.jspåQ‰è¯¥servlet被调ç”?br /> 它是一个JSP¾~–译器,ž®†è¯·æ±‚çš„JSP™åµé¢¾~–è¯‘æˆäØ“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是一¾l„Connector的集å?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.1è¯äh±‚
minProcessors : 该Connector先创å»?个线½E‹ç­‰å¾…客戯‚¯·æ±‚,每个è¯äh±‚ç”׃¸€ä¸ªçº¿½E‹è´Ÿè´?br /> maxProcessors : 当现有的¾U¿ç¨‹ä¸å¤ŸæœåŠ¡å®¢æˆ·è¯äh±‚æ—Óž¼Œè‹¥çº¿½E‹æ€ÀL•°ä¸èƒö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收到的Httpè¯äh±‚
它将匚w…è¯äh±‚和自å·Þqš„虚拟ä¸ÀLœºåQŒåƈ把请求è{交给对应的Host来处ç?br /> 默认虚拟ä¸ÀLœºæ˜¯localhost
-->

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


<!-- 日志¾c»ï¼Œç›®å‰æ²¡æœ‰çœ‹åˆ°åQŒç•¥åŽÕd…ˆ -->

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

<!-- RealmåQŒç›®å‰æ²¡æœ‰çœ‹åˆŽÍ¼Œç•¥åŽ»å…?-->

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


<!-- 虚拟ä¸ÀLœºlocalhost
appBase : 该虚拟主机的根目录是webapps/
它将匚w…è¯äh±‚和自å·Þqš„Contextçš„èµ\径,ò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" .../>


<!-- ContextåQŒå¯¹åº”于一个Web App
path : 该Contextçš„èµ\径名æ˜?"åQŒæ•…该Context是该Host的默认Context
docBase : 该Context的根目录是webapps/mycontext/
-->

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


<!-- 另外一个ContextåQŒèµ\径名æ˜?wsota -->

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


</Host>

</Engine>

</Service>

</Server>


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


]]>
全文搜烦 lucene使用与优åŒ?/title><link>http://www.aygfsteel.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.aygfsteel.com/dybjsun/archive/2008/01/09/174065.html</guid><wfw:comment>http://www.aygfsteel.com/dybjsun/comments/174065.html</wfw:comment><comments>http://www.aygfsteel.com/dybjsun/archive/2008/01/09/174065.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/dybjsun/comments/commentRss/174065.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.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Œä½ ž®±å¯ä»¥å‘挥想象做ä»ÖM½•½W¦åˆ˜q™ä¸ªæ¡äšg的事情了。你可以把站内新闻都索引了,做个资料库;你可以把一个数据库表的若干个字ŒD늃¦å¼•è“v来,那就不用再担心因为â€?like%”而锁表了åQ›ä½ ä¹Ÿå¯ä»¥å†™ä¸ªè‡ªå·Þqš„æœçƒ¦å¼•擎…â€?br /><br />1.3 你该不该选择lucene<br />下面¾l™å‡ºä¸€äº›æµ‹è¯•数据,如果你觉得可以接受,那么可以选择ã€?br />‹¹‹è¯•一åQ?50万记录,300M左右文本åQŒç”Ÿæˆçƒ¦å¼?80M左右åQ?00¾U¿ç¨‹ä¸‹åã^均处理时é—?00msã€?br />‹¹‹è¯•二:37000记录åQŒçƒ¦å¼•数据库中的两个varchar字段åQŒçƒ¦å¼•æ–‡ä»?.6MåQ?00¾U¿ç¨‹ä¸‹åã^均处理时é—?.5msã€?br /><br />2 lucene的工作方å¼?br />lucene提供的服务实际包含两部分åQšä¸€å…¥ä¸€å‡ºã€‚所谓入是写入,卛_°†ä½ æä¾›çš„æºï¼ˆæœ¬è´¨æ˜¯å­—½W¦ä¸²åQ‰å†™å…¥çƒ¦å¼•或者将其从索引中删除;所谓出是读出,卛_‘用户提供全文搜烦服务åQŒè®©ç”¨æˆ·å¯ä»¥é€šè¿‡å…³é”®è¯å®šä½æºã€?br /><br />2.1写入‹¹ç¨‹<br />源字½W¦ä¸²é¦–å…ˆ¾lè¿‡analyzer处理åQŒåŒ…括:分词åQŒåˆ†æˆä¸€ä¸ªä¸ªå•词åQ›å޻除stopwordåQˆå¯é€‰ï¼‰ã€?br />ž®†æºä¸­éœ€è¦çš„信息加入Document的各个Field中,òq¶æŠŠéœ€è¦çƒ¦å¼•çš„Field索引èµäh¥åQŒæŠŠéœ€è¦å­˜å‚¨çš„Field存储èµäh¥ã€?br />ž®†çƒ¦å¼•写入存储器åQŒå­˜å‚¨å™¨å¯ä»¥æ˜¯å†…存或¼‚ç›˜ã€?br /><br />2.2è¯Õd‡º‹¹ç¨‹<br />用户提供搜烦关键词,¾lè¿‡analyzer处理ã€?br />对处理后的关键词搜烦索引扑ևºå¯¹åº”çš„Documentã€?br />用户æ ÒŽ®éœ€è¦ä»Žæ‰‘Öˆ°çš„Document中提取需要的Fieldã€?br /><br />3 一些需要知道的概念<br />lucene用到一些概念,了解它们的含义,有利于下面的讲解ã€?br /><br />3.1 analyzer<br />Analyzer 是分析器åQŒå®ƒçš„作用是把一个字½W¦ä¸²æŒ‰æŸ¿Uè§„则划分成一个个词语åQŒåƈ去除其中的无效词语,˜q™é‡Œè¯´çš„æ— æ•ˆè¯è¯­æ˜¯æŒ‡è‹±æ–‡ä¸­çš„“of”ã€?“the”,中文中的 “的”、“地”等词语åQŒè¿™äº›è¯è¯­åœ¨æ–‡ç« ä¸­å¤§é‡å‡ºçŽŽÍ¼Œä½†æ˜¯æœ¬èín不包含什么关键信息,åŽÀLŽ‰æœ‰åˆ©äºŽç¾ƒž®çƒ¦å¼•文件、提高效率、提高命中率ã€?br />分词的规则千变万化,但目的只有一个:按语义划分。这点在英文中比较容易实玎ͼŒå› äؓ英文本èínž®±æ˜¯ä»¥å•è¯äØ“å•ä½çš„ï¼Œå·²ç»ç”¨ç©ºæ ¼åˆ†å¼€åQ›è€Œä¸­æ–‡åˆ™å¿…须以某¿Uæ–¹æ³•å°†˜qžæˆä¸€ç‰‡çš„句子划分成一个个词语。具体划分方法下面再详细介绍åQŒè¿™é‡Œåªéœ€äº†è§£åˆ†æžå™¨çš„æ¦‚念卛_¯ã€?br /><br />3.2 document<br />用户提供的源是一条条记录åQŒå®ƒä»¬å¯ä»¥æ˜¯æ–‡æœ¬æ–‡äšg、字½W¦ä¸²æˆ–者数据库表的一条记录等½{‰ã€‚一条记录经˜q‡çƒ¦å¼•之后,ž®±æ˜¯ä»¥ä¸€ä¸ªDocumentçš„åŞ式存储在索引文äšg中的。用戯‚¿›è¡Œæœç´¢ï¼Œä¹Ÿæ˜¯ä»¥Document列表的åŞ式返回ã€?br /><br />3.3 field<br />一个Document可以包含多个信息域,例如一½‹‡æ–‡ç« å¯ä»¥åŒ…含“标题”、“正文”、“最后修æ”ÒŽ—¶é—´â€ç­‰ä¿¡æ¯åŸŸï¼Œ˜q™äº›ä¿¡æ¯åŸŸå°±æ˜¯é€šè¿‡Field在Document中存储的ã€?br />Field有两个属性可选:存储和烦引。通过存储属性你可以控制是否对这个Field˜q›è¡Œå­˜å‚¨åQ›é€šè¿‡ç´¢å¼•属性你可以控制是否对该Field˜q›è¡Œç´¢å¼•。这看è“v来似乎有些废话,事实上对˜q™ä¸¤ä¸ªå±žæ€§çš„æ­£ç¡®¾l„合很重要,下面举例说明åQ?br />˜q˜æ˜¯ä»¥åˆšæ‰çš„æ–‡ç« ä¸ÞZ¾‹å­ï¼Œæˆ‘们需要对标题和正文进行全文搜索,所以我们要把烦引属性设¾|®äؓ真,同时我们希望能直接从搜烦¾l“果中提取文章标题,所以我们把标题域的存储属性设¾|®äؓ真,但是ç”׃ºŽæ­£æ–‡åŸŸå¤ªå¤§äº†åQŒæˆ‘ä»¬äØ“äº†ç¾ƒž®çƒ¦å¼•文件大ž®ï¼Œž®†æ­£æ–‡åŸŸçš„存储属性设¾|®äؓ假,当需要时再直接读取文ä»Óž¼›æˆ‘们只是希望能从搜烦解果中提取最后修æ”ÒŽ—¶é—ß_¼Œä¸éœ€è¦å¯¹å®ƒè¿›è¡Œæœç´¢ï¼Œæ‰€ä»¥æˆ‘们把最后修æ”ÒŽ—¶é—´åŸŸçš„存储属性设¾|®äؓ真,索引属性设¾|®äؓ假。上面的三个域涵盖了两个属性的三种¾l„合åQŒè¿˜æœ‰ä¸€¿Uå…¨ä¸ºå‡çš„æ²¡æœ‰ç”¨åˆŽÍ¼Œäº‹å®žä¸ŠFieldä¸å…è®æ€½ é‚£ä¹ˆè®„¡½®åQŒå› ä¸ºæ—¢ä¸å­˜å‚¨åˆä¸çƒ¦å¼•的域是没有意义的ã€?br /><br />3.4 term<br />term是搜索的最ž®å•位,它表½Cºæ–‡æ¡£çš„一个词语,termç”׃¸¤éƒ¨åˆ†¾l„成åQšå®ƒè¡¨ç¤ºçš„词语和˜q™ä¸ªè¯è¯­æ‰€å‡ºçŽ°çš„fieldã€?br /><br />3.5 tocken<br />tocken是term的一‹Æ¡å‡ºçŽŽÍ¼Œå®ƒåŒ…含trem文本和相应的èµäh­¢åç§»åQŒä»¥åŠä¸€ä¸ªç±»åž‹å­—½W¦ä¸²ã€‚一句话中可以出现多‹Æ¡ç›¸åŒçš„词语åQŒå®ƒä»¬éƒ½ç”¨åŒä¸€ä¸ªterm表示åQŒä½†æ˜¯ç”¨ä¸åŒçš„tockenåQŒæ¯ä¸ªtocken标记该词语出现的地方ã€?br /><br />3.6 segment<br />æ·ÕdŠ ç´¢å¼•æ—¶åÆˆä¸æ˜¯æ¯ä¸ªdocument都马上添加到同一个烦引文ä»Óž¼Œå®ƒä»¬é¦–先被写入到不同的小文äšgåQŒç„¶åŽå†åˆåƈ成一个大索引文äšgåQŒè¿™é‡Œæ¯ä¸ªå°æ–‡äšg都是一个segmentã€?br /><br />4 lucene的结æž?br />lucene包括coreå’Œsandbox两部分,其中core是lucene½E›_®šçš„æ ¸å¿ƒéƒ¨åˆ†ï¼Œsandbox包含了一些附加功能,例如highlighter、各¿Uåˆ†æžå™¨ã€?br />Lucene core有七个包åQšanalysisåQŒdocumentåQŒindexåQŒqueryParseråQŒsearchåQŒstoreåQŒutilã€?br />4.1 analysis<br />Analysis包含一些内建的分析器,例如按空白字½W¦åˆ†è¯çš„WhitespaceAnalyzeråQŒæ·»åŠ äº†stopwrod˜q‡æ×oçš„StopAnalyzeråQŒæœ€å¸¸ç”¨çš„StandardAnalyzerã€?br />4.2 document<br />Document包含文档的数据结构,例如Document¾cÕd®šä¹‰äº†å­˜å‚¨æ–‡æ¡£çš„æ•°æ®ç»“构,Field¾cÕd®šä¹‰äº†Document的一个域ã€?br />4.3 index<br />Index 包含了烦引的è¯Õd†™¾c»ï¼Œä¾‹å¦‚对烦引文件的segment˜q›è¡Œå†™ã€åˆòq¶ã€ä¼˜åŒ–çš„IndexWriter¾cÕd’Œå¯¹çƒ¦å¼•进行读取和删除操作的Â?IndexReader¾c»ï¼Œ˜q™é‡Œè¦æ³¨æ„çš„æ˜¯ä¸è¦è¢«IndexReader˜q™ä¸ªåå­—误导åQŒä»¥ä¸ºå®ƒæ˜¯çƒ¦å¼•文件的è¯Õd–¾c»ï¼Œå®žé™…上删除烦引也是由它完成,  IndexWriter只关心如何将索引写入一个个segmentåQŒåƈž®†å®ƒä»¬åˆòq¶ä¼˜åŒ–ï¼›IndexReader则关注烦引文件中各个文档的组¾l‡åŞ式ã€?br />4.4 queryParser<br />QueryParser 包含了解析查询语句的¾c»ï¼Œlucene的查询语句和sql语句有点¾cÖM¼¼åQŒæœ‰å„种保留字,按照一定的语法可以¾l„成各种查询ã€?Lucene有很多种 Query¾c»ï¼Œå®ƒä»¬éƒ½ç‘ô承自QueryåQŒæ‰§è¡Œå„¿Uç‰¹ŒDŠçš„æŸ¥è¯¢åQŒQueryParser的作用就是解析查询语句,按顺序调用各¿U?Query¾cÀLŸ¥æ‰‘Ö‡º¾l“æžœã€?br />4.5 search<br />Search包含了从索引中搜索结果的各种¾c»ï¼Œä¾‹å¦‚刚才说的各种Query¾c»ï¼ŒåŒ…括TermQuery、BooleanQuery½{‰å°±åœ¨è¿™ä¸ªåŒ…里ã€?br />4.6 store<br />Store包含了烦引的存储¾c»ï¼Œä¾‹å¦‚Directory定义了烦引文件的存储¾l“æž„åQŒFSDirectory为存储在文äšg中的索引åQŒRAMDirectory为存储在内存中的索引åQŒMmapDirectoryä¸ÞZ‹É用内存映ž®„的索引ã€?br />4.7 util<br />Util包含一些公共工å…ïL±»åQŒä¾‹å¦‚时间和字符串之间的转换工具ã€?br /><br />5 如何建烦å¼?br />5.1 最½Ž€å•的能完成烦引的代码片断<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 />首先我们创徏了一个writeråQŒåÆˆæŒ‡å®šå­˜æ”¾ç´¢å¼•çš„ç›®å½•äØ“â€?data/index”,使用的分析器为StandardAnalyzeråQŒç¬¬ä¸‰ä¸ªå‚数说明如果已经有烦引文件在索引目录下,我们ž®†è¦†ç›–它们ã€?br />然后我们新徏一个documentã€?br />我们向documentæ·ÕdŠ ä¸€ä¸ªfieldåQŒåå­—是“title”,内容是“lucene introduction”,对它˜q›è¡Œå­˜å‚¨òq¶çƒ¦å¼•ã€?br />再添加一个名字是“content”的fieldåQŒå†…å®ÒŽ˜¯â€œlucene works well”,也是存储òq¶çƒ¦å¼•ã€?br />然后我们ž®†è¿™ä¸ªæ–‡æ¡£æ·»åŠ åˆ°ç´¢å¼•ä¸­ï¼Œå¦‚æžœæœ‰å¤šä¸ªæ–‡æ¡£ï¼Œå¯ä»¥é‡å¤ä¸Šé¢çš„æ“ä½œï¼Œåˆ›å¾documentòq¶æ·»åŠ ã€?br />æ·ÕdŠ å®Œæ‰€æœ‰documentåQŒæˆ‘们对索引˜q›è¡Œä¼˜åŒ–åQŒä¼˜åŒ–主要是ž®†å¤šä¸ªsegmentåˆåÆˆåˆîC¸€ä¸ªï¼Œæœ‰åˆ©äºŽæé«˜çƒ¦å¼•速度ã€?br />随后ž®†writer关闭åQŒè¿™ç‚¹å¾ˆé‡è¦ã€?br /><br />对,创徏索引ž®Þp¿™ä¹ˆç®€å•!<br />当然你可能修改上面的代码获得更具个性化的服务ã€?br /><br />5.2 ž®†çƒ¦å¼•直接写在内å­?br />你需要首先创å»ÞZ¸€ä¸ªRAMDirectoryåQŒåƈž®†å…¶ä¼ ç»™writeråQŒä»£ç å¦‚下:<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索引èµäh¥åQŒè€Œä¸æƒŒ™‡ªå·±å°†å®ƒä»¬è¯Õd…¥å­—符串创建fieldåQŒä½ å¯ä»¥ç”¨ä¸‹é¢çš„代码创徏fieldåQ?br /><br />Field field = new Field("content", new FileReader(file));<br /><br />˜q™é‡Œçš„filež®±æ˜¯è¯¥æ–‡æœ¬æ–‡ä»¶ã€‚该构造函数实际上是读åŽÀL–‡ä»¶å†…容,òq¶å¯¹å…¶è¿›è¡Œçƒ¦å¼•,但不存储ã€?br /><br />6 如何¾l´æŠ¤ç´¢å¼•<br />索引的维护操作都是由IndexReader¾cÀLä¾›ã€?br /><br />6.1 如何删除索引<br />lucene提供了两¿Uä»Žç´¢å¼•中删除document的方法,一¿Uæ˜¯<br /><br />void deleteDocument(int docNum)<br /><br />˜q™ç§æ–ÒŽ³•是根据document在烦引中的编åäh¥åˆ é™¤åQŒæ¯ä¸ªdocument加进索引后都会有个唯一¾~–号åQŒæ‰€ä»¥æ ¹æ®ç¼–号删除是一¿Uç²¾¼‹®åˆ é™¤ï¼Œä½†æ˜¯˜q™ä¸ª¾~–号是烦引的内部¾l“æž„åQŒä¸€èˆ¬æˆ‘们不会知道某个文件的¾~–号到底是几åQŒæ‰€ä»¥ç”¨å¤„不大。另一¿Uæ˜¯<br /><br />void deleteDocuments(Term term)<br /><br />˜q™ç§æ–ÒŽ³•实际上是首先æ ÒŽ®å‚æ•°term执行一个搜索操作,然后把搜索到的结果批量删除了。我们可以通过˜q™ä¸ªæ–ÒŽ³•提供一个严格的查询条äšgåQŒè¾¾åˆ°åˆ é™¤æŒ‡å®šdocument的目的ã€?br />下面¾l™å‡ºä¸€ä¸ªä¾‹å­ï¼š<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 />luceneòq¶æ²¡æœ‰æä¾›ä¸“门的索引更新æ–ÒŽ³•åQŒæˆ‘们需要先ž®†ç›¸åº”çš„document删除åQŒç„¶åŽå†ž®†æ–°çš„document加入索引。例如:<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 如何搜烦<br />lucene 的搜索相当强大,它提供了很多辅助查询¾c»ï¼Œæ¯ä¸ª¾c»éƒ½¾l§æ‰¿è‡ªQuery¾c»ï¼Œå„自完成一¿Uç‰¹ŒDŠçš„æŸ¥è¯¢åQŒä½ å¯ä»¥åƒæ­¿U¯æœ¨ä¸€æ ·å°†å®ƒä»¬ä»ÀL„¾l„合使用åQŒå®Œæˆä¸€äº›å¤æ‚操作;另外lucene˜q˜æä¾›äº†Sort¾cÕd¯¹¾l“æžœ˜q›è¡ŒæŽ’序åQŒæä¾›äº†Filter¾cÕd¯¹æŸ¥è¯¢æ¡äšg˜q›è¡Œé™åˆ¶ã€‚你或许会不自觉地拿它跟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š„æŸ¥è¯¢åQšâ€œåœ¨content域中包含‘lucene’的document”,那么你可以用TermQueryåQ?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”,那么你可以徏立两个TermQueryòq¶æŠŠå®ƒä»¬ç”¨BooleanQuery˜qžæŽ¥èµäh¥åQ?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 />如果你想å¯ÒŽŸå•词˜q›è¡Œé€šé…½W¦æŸ¥è¯¢ï¼Œä½ å¯ä»¥ç”¨WildcardQueryåQŒé€šé…½W¦åŒ…括â€?’匹配一个ä“Q意字½W¦å’Œâ€?’匹配零个或多个ä»ÀL„å­—符åQŒä¾‹å¦‚你搜烦’use*’,你可能找到’useful’或者’useless’:<br /><br />Query query = new WildcardQuery(new Term("content", "use*");<br /><br />7.1.4 PhraseQuery<br />你可能对中日关系比较感兴­‘£ï¼ŒæƒÏxŸ¥æ‰ä€˜ä¸­â€™å’Œâ€˜æ—¥â€™æŒ¨å¾—比较近åQ?个字的距¼›Õd†…åQ‰çš„æ–‡ç« å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Œä½ å¯ä»¥ç”¨PrefixQueryåQ?br /><br />PrefixQuery query = new PrefixQuery(new Term("content ", "ä¸?);<br /><br />7.1.6 FuzzyQuery<br />FuzzyQueryç”¨æ¥æœçƒ¦ç›æ€¼¼çš„termåQŒä‹É用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是RangeQueryåQŒä½ ä¹Ÿè®¸æƒÏxœç´¢æ—¶é—´åŸŸä»?0060101åˆ?0060130之间的documentåQŒä½ å¯ä»¥ç”¨RangeQueryåQ?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™ä¹ˆå¤šQueryåQŒä½ å¯èƒ½ä¼šé—®åQšâ€œä¸ä¼šè®©æˆ‘自å·Þq»„合各¿UQuery吧,太麻烦了åQâ€å½“然不会,lucene提供了一¿Uç±»ä¼égºŽSQL语句的查询语句,我们姑且叫它lucene语句åQŒé€šè¿‡å®ƒï¼Œä½ å¯ä»¥æŠŠå„种查询一句话搞定åQŒlucene会自动把它们查分成小块交¾l™ç›¸åº”Query执行。下面我们对应每¿U?Query演示一下:<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 stringåQŒå®Œæˆå¤æ‚操作,例如“标题或正文包括luceneåQŒåƈ且时间在20060101åˆ?0060130之间的文章”可以表½CÞZØ“åQšâ€? (title:lucene content:lucene) +time:[20060101 TO 20060130]”。代码如下:<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ä½œäØ“åˆ†æžå™¨çš„QueryParseråQŒå®ƒé»˜è®¤æœçƒ¦çš„域是contentã€?br />接着我们用QueryParser来parse查询字串åQŒç”Ÿæˆä¸€ä¸ªQueryã€?br />然后利用˜q™ä¸ªQueryåŽÀLŸ¥æ‰„¡»“果,¾l“果以Hitsçš„åŞ式返回ã€?br />˜q™ä¸ªHits对象包含一个列表,我们挨个把它的内å®ÒŽ˜¾½Cºå‡ºæ¥ã€?br /><br />7.3 Filter<br />filter 的作用就是限制只查询索引的某个子集,它的作用有点像SQL语句里的whereåQŒä½†åˆæœ‰åŒºåˆ«åQŒå®ƒä¸æ˜¯æ­£è§„查询的一部分åQŒåªæ˜¯å¯¹æ•°æ®æºè¿›è¡Œé¢„处理åQŒç„¶åŽäº¤¾l™æŸ¥è¯¢è¯­å¥ã€‚注意它执行的是预处理,而不是对查询¾l“æžœ˜q›è¡Œ˜q‡æ×oåQŒæ‰€ä»¥ä‹É用filter的代ä»äh˜¯å¾ˆå¤§çš„,它可能会使一‹Æ¡æŸ¥è¯¢è€—时提高一癑րã€?br />最常用的filter是RangeFilterå’ŒQueryFilter。RangeFilter是设定只搜烦指定范围内的索引åQ›QueryFilter是在上次查询的结果中搜烦ã€?br />Filterçš„ä‹É用非常简单,你只需创徏一个filter实例åQŒç„¶åŽæŠŠå®ƒä¼ ¾l™searcher。ç‘ô¾l­ä¸Šé¢çš„例子åQŒæŸ¥è¯¢â€œæ—¶é—´åœ¨20060101åˆ?0060130之间的文章”除了将限制写在query string中,你还可以写在RangeFilter中:<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能做刎ͼšé€šè¿‡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šÂ?StandardAnalyzeråQŒå¾ˆå¤šæƒ…况下StandardAnalyzer是个不错的选择。甚至你会发现StandardAnalyzer也能对中文进行分词ã€?br />但是我们的焦ç‚ÒŽ˜¯ä¸­æ–‡åˆ†è¯åQŒStandardAnalyzer能支持中文分词吗åQŸå®žè·µè¯æ˜Žæ˜¯å¯ä»¥çš„,但是效果òq¶ä¸å¥½ï¼Œæœçƒ¦â€œå¦‚æžœâ€?会把“牛奶不如果汁好喝”也搜烦出来åQŒè€Œä¸”索引文äšg很大。那么我们手头上˜q˜æœ‰ä»€ä¹ˆåˆ†æžå™¨å¯ä»¥ä½¿ç”¨å‘¢ï¼Ÿcore里面没有åQŒæˆ‘们可以在sandbox里面扑ֈ°ä¸¤ä¸ªåQ?ChineseAnalyzerå’ŒCJKAnalyzer。但是它们同样都有分词不准的问题。相比之下用StandardAnalyzerå’ŒÂ?ChineseAnalyzer建立索引旉™—´å·®ä¸å¤šï¼Œç´¢å¼•æ–‡äšg大小也差不多åQŒCJKAnalyzer表现会差些,索引文äšg大且耗时比较é•ѝ€?br />要解决问题,首先分析一下这三个分析器的分词方式。StandardAnalyzerå’ŒChineseAnalyzer都是把句子按单个字切分,也就是说  “牛奶不如果汁好喝”会被它们切分成“牛 å¥?ä¸?å¦?æž?æ±?å¥?喝”;而CJKAnalyzer则会切分成“牛å¥?奶不 不如 如果 果汁 æ±å¥½å¥½å–â€ã€‚è¿™ä¹Ÿå°±è§£é‡Šäº†äØ“ä»€ä¹ˆæœç´¢â€œæžœæ±â€éƒ½èƒ½åŒ¹é…è¿™ä¸ªå¥å­ã€?br />以上分词的缺点至ž®‘有两个åQšåŒ¹é…ä¸å‡†ç¡®å’Œçƒ¦å¼•文件大。我们的目标是将上面的句子分解成 “牛å¥?不如 果汁好喝”。这里的关键ž®±æ˜¯è¯­ä¹‰è¯†åˆ«åQŒæˆ‘们如何识别“牛奶”是一个词而“奶不”不是词语?我们很自然会惛_ˆ°åŸÞZºŽè¯åº“的分词法åQŒä¹Ÿž®±æ˜¯æˆ‘们先得åˆîC¸€ä¸ªè¯åº“,里面列ä‹D了大部分词语åQŒæˆ‘们把句子按某¿Uæ–¹å¼åˆ‡åˆ†ï¼Œå½“得到的词语与词库中的项匚w…æ—Óž¼Œæˆ‘们ž®Þp®¤ä¸ø™¿™¿Uåˆ‡åˆ†æ˜¯æ­£ç¡®çš„。这样切词的˜q‡ç¨‹ž®Þp{变成匚w…çš„过½E‹ï¼Œè€ŒåŒ¹é…çš„æ–¹å¼æœ€½Ž€å•的有正向最大匹配和逆向最大匹配两¿Uï¼Œè¯´ç™½äº†å°±æ˜¯ä¸€ä¸ªä»Žå¥å­å¼€å¤´å‘后进行匹配,一个从句子末尾向前˜q›è¡ŒåŒšw…ã€‚基于词库的分词词库非常重要åQŒè¯åº“的定w‡ç›´æŽ¥å½±å“æœçƒ¦¾l“æžœåQŒåœ¨ç›¸åŒè¯åº“的前提下åQŒæ®è¯´é€†å‘最大匹配优于正向最大匹配ã€?br />当然˜q˜æœ‰åˆ«çš„分词æ–ÒŽ³•åQŒè¿™æœ¬èínž®±æ˜¯ä¸€ä¸ªå­¦¿U‘,我这里也没有深入研究。回到具体应用,我们的目标是能找到成熟的、现成的分词工具åQŒé¿å…é‡æ–°å‘明èžR轮。经˜q‡ç½‘上搜索,用的比较多的是中¿U‘院çš?ICTCLAS和一个不开放源码但是免费的JE-Analysis。ICTCLAS有个问题是它是一个动态链接库åQ?java调用需要本地方法调用,不方便也有安全隐患,而且口碑也确实不大好。JE-Analysis效果˜q˜ä¸é”™ï¼Œå½“然也会有分词不准的地方åQŒç›¸æ¯”比较方便放心ã€?br /><br />9 性能优化<br />一直到˜q™é‡ŒåQŒæˆ‘们还是在讨论怎么样ä‹Éluceneè·‘è“v来,完成指定ä»ÕdŠ¡ã€‚åˆ©ç”¨å‰é¢è¯´çš„ä¹Ÿ¼‹®å®žèƒ½å®Œæˆå¤§éƒ¨åˆ†åŠŸèƒ½ã€‚ä½†æ˜¯æµ‹è¯•è¡¨æ˜Žlucene的性能òq¶ä¸æ˜¯å¾ˆå¥½ï¼Œåœ¨å¤§æ•°æ®é‡å¤§òq¶å‘的条件下甚至会有半分钟返回的情况。另外大数据量的数据初始化徏立烦引也是一个十分耗时的过½E‹ã€‚那么如何提高lucene的性能呢?下面从优化创建烦引性能和优化搜索性能两方面介¾lã€?br /><br />9.1 优化创徏索引性能<br />˜q™æ–¹é¢çš„优化途径比较有限åQŒIndexWriter提供了一些接口可以控制徏立烦引的操作åQŒå¦å¤–我们可以先ž®†çƒ¦å¼•写入RAMDirectoryåQŒå†æ‰šw‡å†™å…¥FSDirectoryåQŒä¸½Ž¡æ€Žæ ·åQŒç›®çš„都是尽量少的文件IOåQŒå› ä¸ºåˆ›å»ºçƒ¦å¼•的最大瓶颈在于磁盘IO。另外选择一个较好的分析器也能提高一些性能ã€?br /><br />9.1.1 通过讄¡½®IndexWriter的参æ•îC¼˜åŒ–烦引徏ç«?br />setMaxBufferedDocs(int maxBufferedDocs)<br />控制写入一个新的segment前内存中保存的document的数目,讄¡½®è¾ƒå¤§çš„æ•°ç›®å¯ä»¥åŠ å¿«å¾ç´¢å¼•é€Ÿåº¦åQŒé»˜è®¤äØ“10ã€?br />setMaxMergeDocs(int maxMergeDocs)<br />控制一个segment中可以保存的最大documentæ•°ç›®åQŒå€ÆD¾ƒž®æœ‰åˆ©äºŽ˜q½åŠ ç´¢å¼•çš„é€Ÿåº¦åQŒé»˜è®¤Integer.MAX_VALUEåQŒæ— éœ€ä¿®æ”¹ã€?br />setMergeFactor(int mergeFactor)<br />控制多个segmentåˆåÆˆçš„é¢‘çŽ‡ï¼Œå€ÆD¾ƒå¤§æ—¶å»ºç«‹ç´¢å¼•速度较快åQŒé»˜è®¤æ˜¯10åQŒå¯ä»¥åœ¨å»ºç«‹ç´¢å¼•时设¾|®äØ“100ã€?br /><br />9.1.2 通过RAMDirectory¾~“写提高性能<br />我们可以先把索引写入RAMDirectoryåQŒè¾¾åˆîC¸€å®šæ•°é‡æ—¶å†æ‰¹é‡å†™˜q›FSDirectoryåQŒå‡ž®‘磁盘IO‹Æ¡æ•°ã€?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ºé—´çš„优化,可以ž®†çƒ¦å¼•文件减ž®å°†˜q‘一半,相同‹¹‹è¯•数据下由600M减少åˆ?80M。但是对旉™—´òq¶æ²¡æœ‰ä»€ä¹ˆå¸®åŠ©ï¼Œç”šè‡³ä¼šéœ€è¦æ›´é•¿æ—¶é—ß_¼Œå› äؓ较好的分析器需要匹配词库,会消耗更多cpuåQŒæµ‹è¯•数据用StandardAnalyzer耗时133分钟åQ›ç”¨MMAnalyzer耗时150分钟ã€?br /><br />9.2 优化搜烦性能<br />虽然建立索引的操作非常耗时åQŒä½†æ˜¯é‚£æ¯•竟只在最初创建时才需要,òqÏx—¶åªæ˜¯ž®‘量的维护操作,更何况这些可以放åˆîC¸€ä¸ªåŽå°è¿›½E‹å¤„理,òq¶ä¸å½±å“ç”¨æˆ·æœçƒ¦ã€‚我们创建烦引的目的ž®±æ˜¯¾l™ç”¨æˆähœç´¢ï¼Œæ‰€ä»¥æœç´¢çš„æ€§èƒ½æ‰æ˜¯æˆ‘们最兛_¿ƒçš„。下面就来探讨一下如何提高搜索性能ã€?br /><br />9.2.1 ž®†çƒ¦å¼•放入内å­?br />˜q™æ˜¯ä¸€ä¸ªæœ€ç›´è§‚çš„æƒ³æ³•ï¼Œå› äØ“å†…å­˜æ¯”ç£ç›˜å¿«å¾ˆå¤šã€‚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速度差不多,当数据量很小时两者都非常快,当数据量较大æ—Óž¼ˆç´¢å¼•æ–‡äšg400MåQ‰RAMDirectory甚至比FSDirectory˜q˜è¦æ…¢ä¸€ç‚¹ï¼Œ˜q™ç¡®å®žè®©äººå‡ºä¹Žæ„æ–™ã€?br />而且lucene的搜索非常耗内存,即ä‹Éž®?00M的烦引文件蝲入内存,在运行一ŒD‰|—¶é—´åŽéƒ½ä¼šout of memoryåQŒæ‰€ä»¥ä¸ªäºø™®¤ä¸ø™²å…¥å†…存的作用òq¶ä¸å¤§ã€?br /><br />9.2.2 优化旉™—´èŒƒå›´é™åˆ¶<br />既然载入内存òq¶ä¸èƒ½æé«˜æ•ˆçŽ‡ï¼Œä¸€å®šæœ‰å…¶å®ƒç“‰™¢ˆåQŒç»˜q‡æµ‹è¯•发现最大的瓉™¢ˆå±…然是时间范围限åˆÓž¼Œé‚£ä¹ˆæˆ‘们可以怎样使时间范围限制的代ä­h最ž®å‘¢åQ?br />当需要搜索指定时间范围内的结果时åQŒå¯ä»¥ï¼š<br />1、用RangeQueryåQŒè®¾¾|®èŒƒå›ß_¼Œä½†æ˜¯RangeQuery的实现实际上是将旉™—´èŒƒå›´å†…的旉™—´ç‚¹å±•å¼€åQŒç»„成一个个BooleanClause加入刊W?BooleanQuery中查询,因此旉™—´èŒƒå›´ä¸å¯èƒ½è®¾¾|®å¤ªå¤§ï¼Œ¾læµ‹è¯•,范围­‘…过一个月ž®×ƒ¼šæŠ?BooleanQuery.TooManyClausesåQŒå¯ä»¥é€šè¿‡è®„¡½® BooleanQuery.setMaxClauseCount (int maxClauseCount)扩大åQŒä½†æ˜¯æ‰©å¤§ä¹Ÿæ˜¯æœ‰é™çš„åQŒåƈ且随着maxClauseCount扩大åQŒå ç”¨å†…存也扩大<br />2、用 RangeFilter代替RangeQueryåQŒç»‹¹‹è¯•速度不会比RangeQuery慢,但是仍然有性能瓉™¢ˆåQŒæŸ¥è¯¢çš„90%以上旉™—´è€—费在Â?RangeFilteråQŒç ”½I¶å…¶æºç å‘现RangeFilter实际上是首先遍历所有烦引,生成一个BitSetåQŒæ ‡è®°æ¯ä¸ªdocumentåQŒåœ¨æ—‰™—´èŒƒå›´å†…的标记为trueåQŒä¸åœ¨çš„æ ‡è®°ä¸ºfalseåQŒç„¶åŽå°†¾l“果传递给Searcher查找åQŒè¿™æ˜¯ååˆ†è€—æ—¶çš„ã€?br />3、进一步提高性能åQŒè¿™ä¸ªåˆæœ‰ä¸¤ä¸ªæ€èµ\åQ?br />a、缓存Filter¾l“果。既然RangeFilter的执行是在搜索之前,那么它的输入都是一定的åQŒå°±æ˜¯IndexReaderåQŒè€ŒÂ?IndexReader是由Directory军_®šçš„,所以可以认为RangeFilter的结果是ç”ÞpŒƒå›´çš„上下限决定的åQŒä¹Ÿž®±æ˜¯ç”±å…·ä½“的  RangeFilter对象军_®šåQŒæ‰€ä»¥æˆ‘们只要以RangeFilter对象为键åQŒå°†filter¾l“æžœBitSet¾~“å­˜èµäh¥å›_¯ã€‚lucene API 已经提供了一个CachingWrapperFilter¾cÕd°è£…了Filter及其¾l“æžœåQŒæ‰€ä»¥å…·ä½“实施è“v来我们可ä»?cache CachingWrapperFilter对象åQŒéœ€è¦æ³¨æ„çš„æ˜¯ï¼Œä¸è¦è¢«CachingWrapperFilter的名字及其说明误å¯û|¼ŒÂ  CachingWrapperFilter看è“v来是有缓存功能,但的¾~“存是针对同一个filter的,也就是在你用同一个filter˜q‡æ×o不同  IndexReaderæ—Óž¼Œå®ƒå¯ä»¥å¸®ä½ ç¼“存不同IndexReader的结果,而我们的需求恰恰相反,我们是用不同filter˜q‡æ×o同一个Â?IndexReaderåQŒæ‰€ä»¥åªèƒ½æŠŠå®ƒä½œä¸ÞZ¸€ä¸ªå°è£…ç±»ã€?br />b、降低时间精度。研½I¶Filter的工作原理可以看出,它每‹Æ¡å·¥ä½œéƒ½æ˜¯éåŽ†æ•´ä¸ªçƒ¦å¼•çš„åQŒæ‰€ä»¥æ—¶é—´ç²’度越大,å¯Òޝ”­‘Šå¿«åQŒæœç´¢æ—¶é—´è¶ŠçŸ­ï¼Œåœ¨ä¸å½±å“åŠŸèƒ½çš„æƒ…å†µä¸‹åQŒæ—¶é—´ç²¾åº¦è¶Šä½Žè¶Šå¥½ï¼Œæœ‰æ—¶ç”šè‡³ç‰ºç‰²ä¸€ç‚¹ç²¾åº¦ä¹Ÿå€¼å¾—åQŒå½“然最好的情况是根本不作时间限制ã€?br />下面针对上面的两个思èµ\演示一下优化结果(都采ç”?00¾U¿ç¨‹éšæœºå…³é”®è¯éšåÏx—¶é—´èŒƒå›ß_¼‰å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 />ç”׃»¥ä¸Šæ•°æ®å¯ä»¥å¾—出结论:<br />1ã€?ž®½é‡é™ä½Žæ—‰™—´¾_‘Öº¦åQŒå°†¾_‘Öº¦ç”Þq§’换成天带来的性能提高甚至比ä‹É用cache˜q˜å¥½åQŒæœ€å¥½ä¸ä½¿ç”¨filterã€?br />2ã€?在不能降低时间精度的情况下,使用cache能带äº?0倍左右的性能提高ã€?br /><br />9.2.3 使用更好的分析器<br />˜q™ä¸ªè·Ÿåˆ›å»ºçƒ¦å¼•优化道理差不多åQŒçƒ¦å¼•文件小了搜索自然会加快。当然这个提高也是有限的。较好的分析器相对于最差的分析器对性能的提升在20%以下ã€?br /><br />10 一些经éª?br /><br />10.1关键词区分大ž®å†™<br />or AND TO½{‰å…³é”®è¯æ˜¯åŒºåˆ†å¤§ž®å†™çš„,lucene只认大写的,ž®å†™çš„当做普通单词ã€?br /><br />10.2 è¯Õd†™äº’æ–¥æ€?br />同一时刻只能有一个对索引的写操作åQŒåœ¨å†™çš„同时可以˜q›è¡Œæœçƒ¦<br /><br />10.3 æ–‡äšgé”?br />在写索引的过½E‹ä¸­å¼ø™¡Œé€€å‡ºå°†åœ¨tmp目录留下一个lockæ–‡äšgåQŒä‹É以后的写操作无法˜q›è¡ŒåQŒå¯ä»¥å°†å…¶æ‰‹å·¥åˆ é™?br /><br />10.4 æ—‰™—´æ ¼å¼<br />lucene只支持一¿Uæ—¶é—´æ ¼å¼yyMMddHHmmssåQŒæ‰€ä»¥ä½ ä¼ ä¸€ä¸ªyy-MM-dd HH:mm:ss的时间给lucene它是不会当作旉™—´æ¥å¤„理的<br /><br />10.5 讄¡½®boost<br />有些时候在搜烦时某个字ŒD늚„权重需要大一些,例如你可能认为标题中出现关键词的文章比正文中出现关键词的文章更有价å€û|¼Œä½ å¯ä»¥æŠŠæ ‡é¢˜çš„boost讄¡½®çš„æ›´å¤§ï¼Œé‚£ä¹ˆæœçƒ¦¾l“果会优先显½Cºæ ‡é¢˜ä¸­å‡ºçŽ°å…³é”®è¯çš„æ–‡ç« åQˆæ²¡æœ‰ä‹É用排序的前题下)。ä‹É用方法:<br />Field. setBoost(float boost);默认值是1.0åQŒä¹Ÿž®±æ˜¯è¯´è¦å¢žåŠ æƒé‡çš„éœ€è¦è®¾¾|®å¾—æ¯?大ã€?br /><br /><img src ="http://www.aygfsteel.com/dybjsun/aggbug/174065.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/dybjsun/" target="_blank">dybjsun</a> 2008-01-09 17:17 <a href="http://www.aygfsteel.com/dybjsun/archive/2008/01/09/174065.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>log4jhttp://www.aygfsteel.com/dybjsun/archive/2007/12/24/170000.htmldybjsundybjsunMon, 24 Dec 2007 03:46:00 GMThttp://www.aygfsteel.com/dybjsun/archive/2007/12/24/170000.htmlhttp://www.aygfsteel.com/dybjsun/comments/170000.htmlhttp://www.aygfsteel.com/dybjsun/archive/2007/12/24/170000.html#Feedback0http://www.aygfsteel.com/dybjsun/comments/commentRss/170000.htmlhttp://www.aygfsteel.com/dybjsun/services/trackbacks/170000.html
Log4j是Apache的一个开放源代码™å¹ç›®åQŒé€šè¿‡ä½¿ç”¨Log4jåQŒæˆ‘们可以控制日志信息输送的目的地是控制台、文件、GUI¾l„äšg、甚è‡Ïx˜¯å¥—接口服务器、NT的事件记录器、UNIX Syslog守护˜q›ç¨‹½{‰ï¼›æˆ‘们也可以控制每一条日志的输出格式åQ›é€šè¿‡å®šä¹‰æ¯ä¸€æ¡æ—¥å¿—信息的¾U§åˆ«åQŒæˆ‘们能够更加细致地控制日志的生成过½E‹ã€‚最令äh感兴­‘£çš„ž®±æ˜¯åQŒè¿™äº›å¯ä»¥é€šè¿‡ä¸€ä¸ªé…¾|®æ–‡ä»¶æ¥ç‰|´»åœ°è¿›è¡Œé…¾|®ï¼Œè€Œä¸éœ€è¦ä¿®æ”¹åº”用的代码ã€?br />
此外åQŒé€šè¿‡Log4j其他语言接口åQŒæ‚¨å¯ä»¥åœ¨C、C++ã€?Net、PL/SQL½E‹åºä¸­ä‹É用Log4jåQŒå…¶è¯­æ³•和用法与在Java½E‹åºä¸­ä¸€æ øP¼Œä½¿å¾—多语­a€åˆ†å¸ƒå¼ç³»¾lŸå¾—åˆîC¸€ä¸ªç»Ÿä¸€ä¸€è‡´çš„æ—¥å¿—¾l„äšg模块。而且åQŒé€šè¿‡ä½¿ç”¨å„种½W¬ä¸‰æ–ÒŽ‰©å±•,您可以很方便地将Log4j集成到J2EE、JINI甚至是SNMP应用中ã€?br />
说明åQšä¸‹é¢åˆ†ä¸ÞZ¸‰éƒ¨åˆ†åQŒç¬¬ä¸€éƒ¨åˆ†è®²è§£å¦‚何配置log4jåQŒç¬¬äºŒéƒ¨åˆ†äؓ对log4j.properties配置文äšg中的各个属性的讲解åQŒç¬¬ä¸‰éƒ¨åˆ†äØ“å¯?log4j的详¾l†è®²è§£ï¼Œå¦‚果只想配置上log4jåQŒé‚£ä¹ˆåªéœ€è¦çœ‹å‰ä¸¤ä¸ªéƒ¨åˆ†å°±å¯ä»¥åQŒå¦‚果想对log4j深入了解åQŒåˆ™˜q˜éœ€çœ‹ç¬¬ä¸‰éƒ¨åˆ†ã€?br />
一、Log4j配置

½W¬ä¸€æ­¥ï¼šåŠ å…¥log4j-1.2.8.jar到lib下ã€?br />
½W¬äºŒæ­¥ï¼šåœ¨CLASSPATH下徏立log4j.properties。内容如下:

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¬ä¸‰æ­¥ï¼šç›¸åº”的修改其中属性,修改之前ž®±å¿…™åȝŸ¥é“这些都是干什么的åQŒåœ¨½W¬äºŒéƒ¨åˆ†è®²è§£ã€?br />
½W¬å››æ­¥ï¼šåœ¨è¦è¾“出日志的类中加入相兌™¯­å¥ï¼š

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

在相应的æ–ÒŽ³•中:

if (log.isDebugEnabled())

{

log.debug(“System �.�;

}

二、Log4j说明

1 log4j.rootCategory=INFO, stdout , R

此句为将½{‰çñ”为INFO的日志信息输出到stdoutå’ŒR˜q™ä¸¤ä¸ªç›®çš„地åQŒstdoutå’ŒR的定义在下面的代码,可以ä»ÀL„èµ·åã€‚ç­‰¾U§å¯åˆ†äØ“OFFã€?FATAL、ERROR、WARN、INFO、DEBUG、ALLåQŒå¦‚果配¾|®OFF则不打出ä»ÖM½•信息åQŒå¦‚果配¾|®äØ“INFO˜q™æ ·åªæ˜¾½CºINFO, WARN, ERRORçš„log信息åQŒè€ŒDEBUG信息不会被显½Cºï¼Œå…·ä½“讲解可参照第三部分定义配¾|®æ–‡ä»¶ä¸­çš„loggerã€?br />
3 log4j.appender.stdout=org.apache.log4j.ConsoleAppender

此句为定义名为stdout的输出端是哪¿Uç±»åž‹ï¼Œå¯ä»¥æ˜?br />
org.apache.log4j.ConsoleAppenderåQˆæŽ§åˆ¶å°åQ‰ï¼Œ

org.apache.log4j.FileAppenderåQˆæ–‡ä»Óž¼‰åQ?br />
org.apache.log4j.DailyRollingFileAppenderåQˆæ¯å¤©äñ”生一个日志文ä»Óž¼‰åQ?br />
org.apache.log4j.RollingFileAppenderåQˆæ–‡ä»¶å¤§ž®åˆ°è¾¾æŒ‡å®šå°ºå¯¸çš„æ—¶å€™äñ”生一个新的文ä»Óž¼‰

org.apache.log4j.WriterAppenderåQˆå°†æ—¥å¿—信息以流格式发送到ä»ÀL„æŒ‡å®šçš„地方)

具体讲解可参照第三部分定义配¾|®æ–‡ä»¶ä¸­çš„Appenderã€?br />
4 log4j.appender.stdout.layout=org.apache.log4j.PatternLayout

此句为定义名为stdout的输出端的layout是哪¿Uç±»åž‹ï¼Œå¯ä»¥æ˜?br />
org.apache.log4j.HTMLLayoutåQˆä»¥HTML表格形式布局åQ‰ï¼Œ

org.apache.log4j.PatternLayoutåQˆå¯ä»¥çµ‹zÕdœ°æŒ‡å®šå¸ƒå±€æ¨¡å¼åQ‰ï¼Œ

org.apache.log4j.SimpleLayoutåQˆåŒ…含日志信息的¾U§åˆ«å’Œä¿¡æ¯å­—½W¦ä¸²åQ‰ï¼Œ

org.apache.log4j.TTCCLayoutåQˆåŒ…含日志äñ”生的旉™—´ã€çº¿½E‹ã€ç±»åˆ«ç­‰½{‰ä¿¡æ¯ï¼‰

具体讲解可参照第三部分定义配¾|®æ–‡ä»¶ä¸­çš„Layoutã€?br />
5 log4j.appender.stdout.layout.ConversionPattern= [QC] %p [%t] %C.%M(%L) | %m%n

如果使用pattern布局ž®Þp¦æŒ‡å®šçš„æ‰“åîC¿¡æ¯çš„具体格式ConversionPatternåQŒæ‰“印参数如下:

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

%p 输出优先¾U§ï¼Œå³DEBUGåQŒINFOåQŒWARNåQŒERRORåQŒFATAL

%r 输出自应用启动到输出该log信息耗费的毫¿U’æ•°

%c 输出所属的¾cȝ›®åQŒé€šå¸¸ž®±æ˜¯æ‰€åœ¨ç±»çš„å…¨å?br />
%t 输出产生该日志事件的¾U¿ç¨‹å?br />
%n 输出一个回车换行符åQŒWindowsòq›_°ä¸ºâ€œrn”,Unixòq›_°ä¸ºâ€œnâ€?br />
%d 输出日志旉™—´ç‚¹çš„æ—¥æœŸæˆ–æ—¶é—ß_¼Œé»˜è®¤æ ¼å¼ä¸ºISO8601åQŒä¹Ÿå¯ä»¥åœ¨å…¶åŽæŒ‡å®šæ ¼å¼ï¼Œæ¯”如åQ?d{yyyy MMM dd HH:mm:ss,SSS}åQŒè¾“出类ä¼û|¼š2002òq?0æœ?8æ—?22åQ?0åQ?8åQ?21

%l 输出日志事äšg的发生位¾|®ï¼ŒåŒ…括¾cȝ›®åã€å‘生的¾U¿ç¨‹åQŒä»¥åŠåœ¨ä»£ç ä¸­çš„行数ã€?br />
[QC]是log信息的开å¤ß_¼Œå¯ä»¥ä¸ÞZ“Q意字½W¦ï¼Œä¸€èˆ¬äØ“™å¹ç›®½Ž€¿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çš„è¾“å‡ºç«¯çš„ç±»åž‹äØ“æ¯å¤©äº§ç”Ÿä¸€ä¸ªæ—¥å¿—æ–‡ä»¶ã€?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§äØ“DEBUGã€?br />
可以把com.neusoftæ”¹äØ“è‡ªå·±™å¹ç›®æ‰€ç”¨çš„包名ã€?br />
13 log4j.logger.com.opensymphony.oscache=ERROR

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

˜q™ä¸¤å¥æ˜¯æŠŠè¿™ä¸¤ä¸ªåŒ…下出现的错误的½{‰çñ”è®¾äØ“ERRORåQŒå¦‚果项目中没有配置EHCacheåQŒåˆ™ä¸éœ€è¦è¿™ä¸¤å¥ã€?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问题列表™åµé¢æ‰€ç”¨ï¼‰

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ç‰ÒŽ€§æ–‡ä»¶log4j.propertiesåQˆé”®=å€û|¼‰ã€‚下面将介绍使用log4j.propertiesæ–‡äšgä½œäØ“é…ç½®æ–‡äšg的方æ³?

①、配¾|®æ ¹Logger

Logger 负责处理日志记录的大部分操作�br />
å…¶è¯­æ³•äØ“åQ?br />
log4j.rootLogger = [ level ] , appenderName, appenderName, �br />
其中åQŒlevel 是日志记录的优先¾U§ï¼Œåˆ†äØ“OFF、FATAL、ERROR、WARN、INFO、DEBUG、ALL或者自定义的çñ”别。Log4j廸™®®åªä‹É用四个çñ”别,优先¾U§ä»Žé«˜åˆ°ä½Žåˆ†åˆ«æ˜¯ERROR、WARN、INFO、DEBUG。通过在这里定义的¾U§åˆ«åQŒæ‚¨å¯ä»¥æŽ§åˆ¶åˆ°åº”用程序中相应¾U§åˆ«çš„æ—¥å¿—信息的开兟뀂比如在˜q™é‡Œå®šä¹‰äº†INFO¾U§åˆ«åQŒåªæœ‰ç­‰äºŽåŠé«˜äºŽ˜q™ä¸ª¾U§åˆ«çš„æ‰˜q›è¡Œå¤„理åQŒåˆ™åº”用½E‹åºä¸­æ‰€æœ‰DEBUG¾U§åˆ«çš„æ—¥å¿—信息将不被打印出来。ALL:打印所有的日志åQŒOFFåQšå…³é—­æ‰€æœ‰çš„æ—¥å¿—输出ã€?appenderNamež®±æ˜¯æŒ‡å®šæ—¥å¿—信息输出到哪个地斏V€‚可同时指定多个输出目的地ã€?br />
②、配¾|®æ—¥å¿—信息输出目的地 Appender

Appender 负责控制日志记录操作的输出�br />
å…¶è¯­æ³•äØ“å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 />
其中åQŒLog4j提供的appender有以下几¿Uï¼š

org.apache.log4j.ConsoleAppenderåQˆæŽ§åˆ¶å°åQ‰ï¼Œ

org.apache.log4j.FileAppenderåQˆæ–‡ä»Óž¼‰åQ?br />
org.apache.log4j.DailyRollingFileAppenderåQˆæ¯å¤©äñ”生一个日志文ä»Óž¼‰åQ?br />
org.apache.log4j.RollingFileAppenderåQˆæ–‡ä»¶å¤§ž®åˆ°è¾¾æŒ‡å®šå°ºå¯¸çš„æ—¶å€™äñ”生一个新的文ä»Óž¼‰åQŒå¯é€šè¿‡ log4j.appender.R.MaxFileSize=100KB讄¡½®æ–‡äšg大小åQŒè¿˜å¯é€šè¿‡ log4j.appender.R.MaxBackupIndex=1讄¡½®ä¸ÞZ¿å­˜ä¸€ä¸ªå¤‡ä»½æ–‡ä»¶ã€?br />
org.apache.log4j.WriterAppenderåQˆå°†æ—¥å¿—信息以流格式发送到ä»ÀL„æŒ‡å®šçš„地方)

例如åQšlog4j.appender.stdout=org.apache.log4j.ConsoleAppender

定义一个名为stdout的输出目的地åQŒConsoleAppender为控制台ã€?br />
③、配¾|®æ—¥å¿—信息的格式åQˆå¸ƒå±€åQ‰Layout

Layout 负责格式化Appender的输出�br />
å…¶è¯­æ³•äØ“å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

其中åQŒLog4j提供的layout有以下几¿Uï¼š

org.apache.log4j.HTMLLayoutåQˆä»¥HTML表格形式布局åQ‰ï¼Œ

org.apache.log4j.PatternLayoutåQˆå¯ä»¥çµ‹zÕdœ°æŒ‡å®šå¸ƒå±€æ¨¡å¼åQ‰ï¼Œ

org.apache.log4j.SimpleLayoutåQˆåŒ…含日志信息的¾U§åˆ«å’Œä¿¡æ¯å­—½W¦ä¸²åQ‰ï¼Œ

org.apache.log4j.TTCCLayoutåQˆåŒ…含日志äñ”生的旉™—´ã€çº¿½E‹ã€ç±»åˆ«ç­‰½{‰ä¿¡æ¯ï¼‰

2、格式化日志信息

Log4J采用¾cÖM¼¼C语言中的printf函数的打印格式格式化日志信息åQŒæ‰“印参数如下:

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

%p 输出优先¾U§ï¼Œå³DEBUGåQŒINFOåQŒWARNåQŒERRORåQŒFATAL

%r 输出自应用启动到输出该log信息耗费的毫¿U’æ•°

%c 输出所属的¾cȝ›®åQŒé€šå¸¸ž®±æ˜¯æ‰€åœ¨ç±»çš„å…¨å?br />
%t 输出产生该日志事件的¾U¿ç¨‹å?br />
%n 输出一个回车换行符åQŒWindowsòq›_°ä¸ºâ€œrn”,Unixòq›_°ä¸ºâ€œnâ€?br />
%d 输出日志旉™—´ç‚¹çš„æ—¥æœŸæˆ–æ—¶é—ß_¼Œé»˜è®¤æ ¼å¼ä¸ºISO8601åQŒä¹Ÿå¯ä»¥åœ¨å…¶åŽæŒ‡å®šæ ¼å¼ï¼Œæ¯”如åQ?d{yyyy MMM dd HH:mm:ss,SSS}åQŒè¾“出类ä¼û|¼š2002òq?0æœ?8æ—?22åQ?0åQ?8åQ?21

%l 输出日志事äšg的发生位¾|®ï¼ŒåŒ…括¾cȝ›®åã€å‘生的¾U¿ç¨‹åQŒä»¥åŠåœ¨ä»£ç ä¸­çš„行数ã€?br />
3、在代码中ä‹É用Log4j

我们在需要输出日志信息的¾cÖM¸­åšå¦‚下的三个工作åQ?br />
1、导入所有需的commongs-logging¾c»ï¼š

import org.apache.commons.logging.Log;

import org.apache.commons.logging.LogFactory;

2、在自己的类中定义一个org.apache.commons.logging.Log¾cȝš„¿Uæœ‰é™æ€ç±»æˆå‘˜åQ?br />
private final Log log = LogFactory.getLog(getClass());

LogFactory.getLog()æ–ÒŽ³•的参æ•îC‹É用的是当前类的classã€?br />
3、ä‹É用org.apache.commons.logging.Log¾cÈš„æˆå‘˜æ–ÒŽ³•输出日志信息å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")

}


]]>
常见软äšg‹¹‹è¯•的技å·?/title><link>http://www.aygfsteel.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.aygfsteel.com/dybjsun/archive/2007/12/06/165716.html</guid><wfw:comment>http://www.aygfsteel.com/dybjsun/comments/165716.html</wfw:comment><comments>http://www.aygfsteel.com/dybjsun/archive/2007/12/06/165716.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/dybjsun/comments/commentRss/165716.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/dybjsun/services/trackbacks/165716.html</trackback:ping><description><![CDATA[软äšg‹¹‹è¯•虽然辛苦åQŒä½†æ˜¯æŽŒæ¡äº†ä¸€å®šçš„æŠ€å·§ä¹‹åŽå°†ä½¿ä½ äº‹åŠåŠŸå€ã€?br /><br />  (1) 边界‹¹‹è¯•åQŒæµ‹è¯•用戯‚¾“入框中的数值的最大数和最ž®æ•°åQŒä»¥åŠäØ“½Iºæ—¶çš„æƒ…å†üc€?br /><br />  (2) 非法‹¹‹è¯•åQŒä¾‹å¦‚在输入数字的地方输入字母ã€?br /><br />  (3) 跟踪‹¹‹è¯•åQŒè·Ÿítªä¸€æ¡æ•°æ®çš„‹¹ç¨‹,保证数据的正¼‹®æ€§ã€?br /><br />  (4) 在开始测试时应保证数据的正确性,然后在从¾pȝ»Ÿä¸­æ‰¾å‡ºå„¿UBUGã€?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ȝ»Ÿæ‰€å—到的媄响的情况ã€?br /><br />  (9) 在程序员刚修复Bug之后的地æ–?再找一找,往往½E‹åºå‘˜åªä¿®å¤æŠ¥å‘Šå‡ºæ¥çš„缺陯‚€Œä¸åŽ»è€ƒè™‘åˆ«çš„åŠŸèƒ½åœ¨ä¿®æ”ÒŽ—¶å¯èƒ½ä¼šé‡æ–°é€ æˆé”™è¯¯ã€?br /><br />  (10) 认真做好‹¹‹è¯•记录在做完一天的‹¹‹è¯•记录之后,½W¬äºŒå¤©å†æ ÒŽ®½W¬ä¸€å¤©çš„‹¹‹è¯•记录重复‹¹‹è¯•你会发现有未修正的错误ã€?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Œå…·ä½“说åQŒèÊY件测试是事务性的åQŒè€Œé¡¹ç›®ç®¡ç†æ˜¯½{–略性,一些策略性的东西必须在一些事务性的事务上来实现ã€?br /><br />  软äšg‹¹‹è¯•是一门新兴的行业åQŒçŽ°åœ¨èÊY件测试在我国的地位虽说还不是很高åQŒä½†˜q™å‡ òq´å´æ˜¯é€æ¸è½¬å¥½åQŒå›½å†…对软äšg‹¹‹è¯•的重视程度也慢慢高è“v来了。大家如果对IT有兴­‘£çš„è¯ï¼Œä¸çƒ¦äº†è§£ä¸€ä¸‹ï¼Œç›æ€¿¡ä¹Ÿä¼šæœ‰æ‰€æ„Ÿæ‚Ÿçš„。我ž®Þq»å¸¸åœ¨¾|‘上看一些èÊY件测试方面的文章或技巧,˜q™å¯¹æˆ‘的成长也是具大的。大家有旉™—´ä¸çƒ¦åŽÖM¸€ä¸‹åŒ—大测试的¾|‘ç«™åQŒé‚£é‡Œé¢ž®±æœ‰å¾ˆå¤šè½¯äšg‹¹‹è¯•技巧和行业新闻åQŒå¯¹æˆ‘启发很多ã€?img src ="http://www.aygfsteel.com/dybjsun/aggbug/165716.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/dybjsun/" target="_blank">dybjsun</a> 2007-12-06 09:33 <a href="http://www.aygfsteel.com/dybjsun/archive/2007/12/06/165716.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>SESSION机制http://www.aygfsteel.com/dybjsun/archive/2007/11/09/159237.htmldybjsundybjsunThu, 08 Nov 2007 17:45:00 GMThttp://www.aygfsteel.com/dybjsun/archive/2007/11/09/159237.htmlhttp://www.aygfsteel.com/dybjsun/comments/159237.htmlhttp://www.aygfsteel.com/dybjsun/archive/2007/11/09/159237.html#Feedback1http://www.aygfsteel.com/dybjsun/comments/commentRss/159237.htmlhttp://www.aygfsteel.com/dybjsun/services/trackbacks/159237.html阅读全文

]]>
印度人是怎样开发èÊYä»¶çš„http://www.aygfsteel.com/dybjsun/archive/2006/10/18/75780.htmldybjsundybjsunTue, 17 Oct 2006 17:54:00 GMThttp://www.aygfsteel.com/dybjsun/archive/2006/10/18/75780.htmlhttp://www.aygfsteel.com/dybjsun/comments/75780.htmlhttp://www.aygfsteel.com/dybjsun/archive/2006/10/18/75780.html#Feedback1http://www.aygfsteel.com/dybjsun/comments/commentRss/75780.htmlhttp://www.aygfsteel.com/dybjsun/services/trackbacks/75780.html阅读全文

]]>
�Linux 上安�PostgreSQLhttp://www.aygfsteel.com/dybjsun/archive/2006/10/13/75046.htmldybjsundybjsunFri, 13 Oct 2006 11:27:00 GMThttp://www.aygfsteel.com/dybjsun/archive/2006/10/13/75046.htmlhttp://www.aygfsteel.com/dybjsun/comments/75046.htmlhttp://www.aygfsteel.com/dybjsun/archive/2006/10/13/75046.html#Feedback0http://www.aygfsteel.com/dybjsun/comments/commentRss/75046.htmlhttp://www.aygfsteel.com/dybjsun/services/trackbacks/75046.html阅读全文

]]>
关于Java栈与堆的思è€?/title><link>http://www.aygfsteel.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.aygfsteel.com/dybjsun/archive/2006/10/10/74213.html</guid><wfw:comment>http://www.aygfsteel.com/dybjsun/comments/74213.html</wfw:comment><comments>http://www.aygfsteel.com/dybjsun/archive/2006/10/10/74213.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/dybjsun/comments/commentRss/74213.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/dybjsun/services/trackbacks/74213.html</trackback:ping><description><![CDATA[     摘要: 每一个Java应用都唯一对应一个JVM实例åQŒæ¯ä¸€ä¸ªå®žä¾‹å”¯ä¸€å¯¹åº”一个堆。应用程序在˜qè¡Œä¸­æ‰€åˆ›å¾çš„æ‰€æœ‰ç±»å®žä¾‹æˆ–æ•°¾l„都攑֜¨˜q™ä¸ªå †ä¸­,òq¶ç”±åº”用所有的¾U¿ç¨‹å…׃ín.è·ŸC/C++不同åQŒJava中分配堆内存是自动初始化的。Java中所有对象的存储½Iºé—´éƒ½æ˜¯åœ¨å †ä¸­åˆ†é…çš„åQŒä½†æ˜¯è¿™ä¸ªå¯¹è±¡çš„引用却是在堆栈中分配,也就是说在徏立一个对象时从两个地斚wƒ½åˆ†é…å†…å­˜åQŒåœ¨å †ä¸­åˆ†é…çš„内存实际徏立这个对象,而在堆栈中分配的内存只是一个指向这个堆对象的指é’?引用)而已ã€?nbsp; <a href='http://www.aygfsteel.com/dybjsun/archive/2006/10/10/74213.html'>阅读全文</a><img src ="http://www.aygfsteel.com/dybjsun/aggbug/74213.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/dybjsun/" target="_blank">dybjsun</a> 2006-10-10 09:24 <a href="http://www.aygfsteel.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"> <a href="http://www.aygfsteel.com/" title="狠狠久久亚洲欧美专区_中文字幕亚洲综合久久202_国产精品亚洲第五区在线_日本免费网站视频">狠狠久久亚洲欧美专区_中文字幕亚洲综合久久202_国产精品亚洲第五区在线_日本免费网站视频</a> </div> </footer> Ö÷Õ¾Ö©Öë³ØÄ£°å£º <a href="http://" target="_blank">½­É½ÊÐ</a>| <a href="http://" target="_blank">²ý¶¼ÏØ</a>| <a href="http://" target="_blank">¹ØÁë</a>| <a href="http://" target="_blank">´ó·½ÏØ</a>| <a href="http://" target="_blank">Ì«ºþÏØ</a>| <a href="http://" target="_blank">¸»½õÊÐ</a>| <a href="http://" target="_blank">½òÄÏÇø</a>| <a href="http://" target="_blank">ÉÛ¶«ÏØ</a>| <a href="http://" target="_blank">Ú¯°²ÏØ</a>| <a href="http://" target="_blank">Û¶ÑôÏØ</a>| <a href="http://" target="_blank">×ÊÖÐÏØ</a>| <a href="http://" target="_blank">Çຣʡ</a>| <a href="http://" target="_blank">ÌìÈ«ÏØ</a>| <a href="http://" target="_blank">ËìÄþÊÐ</a>| <a href="http://" target="_blank">Âí¹«ÊÐ</a>| <a href="http://" target="_blank">»´°²ÊÐ</a>| <a href="http://" target="_blank">ÂÐÄÏÏØ</a>| <a href="http://" target="_blank">ÑÓÊÙÏØ</a>| <a href="http://" target="_blank">ËÕÄáÌØ×óÆì</a>| <a href="http://" target="_blank">Ñ®ÒØÏØ</a>| <a href="http://" target="_blank">Îâ±¤ÏØ</a>| <a href="http://" target="_blank">ºôºÍºÆÌØÊÐ</a>| <a href="http://" target="_blank">À³Î÷ÊÐ</a>| <a href="http://" target="_blank">¸ß±®µêÊÐ</a>| <a href="http://" target="_blank">»ÔÄÏÏØ</a>| <a href="http://" target="_blank">ľÀï</a>| <a href="http://" target="_blank">ÈÙ²ýÏØ</a>| <a href="http://" target="_blank">ÐÂÃÜÊÐ</a>| <a href="http://" target="_blank">³¤ÄþÇø</a>| <a href="http://" target="_blank">¸ßÑôÏØ</a>| <a href="http://" target="_blank">ºâÑôÊÐ</a>| <a href="http://" target="_blank">³£ÖÝÊÐ</a>| <a href="http://" target="_blank">¬ÁúÏØ</a>| <a href="http://" target="_blank">ËÉÏªÏØ</a>| <a href="http://" target="_blank">ÄþÉÂÏØ</a>| <a href="http://" target="_blank">Ë·ÖÝÊÐ</a>| <a href="http://" target="_blank">½´¨ÏØ</a>| <a href="http://" target="_blank">°ÍÑåÏØ</a>| <a href="http://" target="_blank">»ÆÉ½ÊÐ</a>| <a href="http://" target="_blank">ÎÞÎªÏØ</a>| <a href="http://" target="_blank">Ì«¿µÏØ</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>