<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" version="2.0">

<channel>
	<title>时光印记</title>
	
	<link>http://www.colorfuldays.org</link>
	<description>Internet, Mac, Linux, Java, Music, Life, Travel and so on</description>
	<lastBuildDate>Thu, 12 Jan 2012 06:34:15 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/colorfuldays" /><feedburner:info xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" uri="colorfuldays" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item>
		<title>Solr Suggest实现搜索智能提示</title>
		<link>http://www.colorfuldays.org/program/solr/solr-suggest%e5%ae%9e%e7%8e%b0%e6%90%9c%e7%b4%a2%e6%99%ba%e8%83%bd%e6%8f%90%e7%a4%ba/</link>
		<comments>http://www.colorfuldays.org/program/solr/solr-suggest%e5%ae%9e%e7%8e%b0%e6%90%9c%e7%b4%a2%e6%99%ba%e8%83%bd%e6%8f%90%e7%a4%ba/#comments</comments>
		<pubDate>Thu, 12 Jan 2012 06:34:15 +0000</pubDate>
		<dc:creator>iamxhu</dc:creator>
				<category><![CDATA[solr]]></category>
		<category><![CDATA[spellchecker]]></category>
		<category><![CDATA[suggest]]></category>

		<guid isPermaLink="false">http://www.colorfuldays.org/?p=802</guid>
		<description><![CDATA[智能提示简介 搜索的智能提示目前是各大搜索的标配应用，主要作用是避免用户输入错误的搜索词，同时将用户引导到相应的关键词搜索上。 Solr Suggestion智能提示模块 作为一个应用广泛的搜索引擎系统，Solr内置了智能提示功能，它在Solr里叫做Suggest模块.该模块可选择基于提示词文本做智能提示，还支持通过针对索引的某个字段建立索引词库做智能提示。在诸多文档中都推荐使用基于索引来做智能提示，因此我们目前的实现也是采取该方案。 Solr Suggest的配置要点 Suggest字段的选择 因为现在整个平台是基于SPU的构建的，因此决定采用SPU关键属性组合及类目名称来做Suggest的索引字段。首先在schema.xml中添加存储Suggest的新字段，如下： &#60;field name="suggestion" type="string" indexed="true" stored="true" termVectors="true" multiValued="true"/&#62; 在该field的配置中，FieldType的选择非常关键，通常建议智能提示字段的FieldType不需要配置复杂的Analyzer，避免因为分词导致智能提示的词失控。 配置Suggest模块 在solrconfig.xml文件中配置Suggest模块，其中Suggest依赖于SpellChecker模块，所以这两个都需要配置。具体配置如下： &#60;searchComponent class="solr.SpellCheckComponent" name="suggest"&#62; &#60;str name="queryAnalyzerFieldType"&#62;string&#60;/str&#62; &#60;lst name="spellchecker"&#62; &#60;str name="name"&#62;suggest&#60;/str&#62; &#60;str name="classname"&#62;org.apache.solr.spelling.suggest.Suggester&#60;/str&#62; &#60;str name="lookupImpl"&#62;org.apache.solr.spelling.suggest.tst.TSTLookup&#60;/str&#62; &#60;str name="field"&#62;suggestion&#60;/str&#62; &#60;!-- the indexed field to derive &#8230;<p class="read-more"><a href="http://www.colorfuldays.org/program/solr/solr-suggest%e5%ae%9e%e7%8e%b0%e6%90%9c%e7%b4%a2%e6%99%ba%e8%83%bd%e6%8f%90%e7%a4%ba/">Read more &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<h2>智能提示简介</h2>
<p>搜索的智能提示目前是各大搜索的标配应用，主要作用是<span style="color: red;">避免用户输入错误的搜索词，同时将用户引导到相应的关键词搜索上</span>。</p>
<h2><a name="%E6%90%9C%E7%B4%A2%E6%99%BA%E8%83%BD%E6%8F%90%E7%A4%BA%E5%AE%9E%E7%8E%B0-SolrSuggestion%E6%99%BA%E8%83%BD%E6%8F%90%E7%A4%BA%E6%A8%A1%E5%9D%97"></a>Solr Suggestion智能提示模块</h2>
<p>作为一个应用广泛的搜索引擎系统，Solr内置了智能提示功能，它在Solr里叫做Suggest模块.该模块可选择基于提示词文本做智能提示，还支持通过针对索引的某个字段建立索引词库做智能提示。在诸多文档中都推荐使用基于索引来做智能提示，因此我们目前的实现也是采取该方案。</p>
<h2><a name="%E6%90%9C%E7%B4%A2%E6%99%BA%E8%83%BD%E6%8F%90%E7%A4%BA%E5%AE%9E%E7%8E%B0-SolrSuggest%E7%9A%84%E9%85%8D%E7%BD%AE%E8%A6%81%E7%82%B9"></a>Solr Suggest的配置要点</h2>
<h3><a name="%E6%90%9C%E7%B4%A2%E6%99%BA%E8%83%BD%E6%8F%90%E7%A4%BA%E5%AE%9E%E7%8E%B0-Suggest%E5%AD%97%E6%AE%B5%E7%9A%84%E9%80%89%E6%8B%A9"></a>Suggest字段的选择</h3>
<p>因为现在整个平台是基于SPU的构建的，因此决定采用SPU关键属性组合及类目名称来做Suggest的索引字段。首先在schema.xml中添加存储Suggest的新字段，如下：</p>
<div>
<div>
<pre> &lt;field name="suggestion" type="string" indexed="true" stored="true"
        termVectors="true" multiValued="true"/&gt;</pre>
</div>
</div>
<p>在该field的配置中，FieldType的选择非常关键，通常建议智能提示字段的FieldType不需要配置复杂的Analyzer，避免因为分词导致智能提示的词失控。</p>
<h3><a name="%E6%90%9C%E7%B4%A2%E6%99%BA%E8%83%BD%E6%8F%90%E7%A4%BA%E5%AE%9E%E7%8E%B0-%E9%85%8D%E7%BD%AESuggest%E6%A8%A1%E5%9D%97"></a>配置Suggest模块</h3>
<p>在solrconfig.xml文件中配置Suggest模块，其中Suggest依赖于SpellChecker模块，所以这两个都需要配置。具体配置如下：</p>
<div>
<div>
<pre> &lt;searchComponent class="solr.SpellCheckComponent" name="suggest"&gt;
        &lt;str name="queryAnalyzerFieldType"&gt;string&lt;/str&gt;
        &lt;lst name="spellchecker"&gt;
            &lt;str name="name"&gt;suggest&lt;/str&gt;
            &lt;str name="classname"&gt;org.apache.solr.spelling.suggest.Suggester&lt;/str&gt;
            &lt;str name="lookupImpl"&gt;org.apache.solr.spelling.suggest.tst.TSTLookup&lt;/str&gt;
            &lt;str name="field"&gt;suggestion&lt;/str&gt;
            &lt;!-- the indexed field to derive suggestions from --&gt;
            &lt;float name="threshold"&gt;0.0001&lt;/float&gt;
            &lt;str name="spellcheckIndexDir"&gt;spellchecker&lt;/str&gt;
            &lt;str name="comparatorClass"&gt;freq&lt;/str&gt;
            &lt;str name="buildOnOptimize"&gt;true&lt;/str&gt;

            &lt;!--&lt;str name="buildOnCommit"&gt;true&lt;/str&gt;--&gt;
        &lt;/lst&gt;
    &lt;/searchComponent&gt;
    &lt;requestHandler class="org.apache.solr.handler.component.SearchHandler"
                    name="/suggest"&gt;
        &lt;lst name="defaults"&gt;
            &lt;str name="spellcheck"&gt;true&lt;/str&gt;
            &lt;str name="spellcheck.dictionary"&gt;suggest&lt;/str&gt;
            &lt;str name="spellcheck.onlyMorePopular"&gt;true&lt;/str&gt;
            &lt;str name="spellcheck.extendedResults"&gt;false&lt;/str&gt;
            &lt;str name="spellcheck.count"&gt;10&lt;/str&gt;
            &lt;str name="spellcheck.collate"&gt;true&lt;/str&gt;
        &lt;/lst&gt;
        &lt;arr name="components"&gt;
            &lt;str&gt;suggest&lt;/str&gt;
        &lt;/arr&gt;
    &lt;/requestHandler&gt;
    &lt;queryConverter name="phraseQueryConverter"
                    class="com.hqb360.solr.suggest.PhraseQueryConverter"/&gt;</pre>
</div>
</div>
<p>上述配置的具体说明可参照solr的官方文档，下面对其中几个容易疑惑的地方做一下说明</p>
<ul>
<li>queryAnalyzerFieldType 配置参数<br />
queryAnalyzerFieldType参数指定访问suggest的SearchHandler处理查询参数的Analyzer，如果指定的Analyzer很复杂的话，会导致suggest返回的结果不符合预期。在这们项目中，我们现希望Analyzer不对查询做任何的改变，因此选择string。</li>
</ul>
<ul>
<li>spellcheck.dictionary的值必须与searchComponent中spellchecker标签下&lt;str name=&#8221;name&#8221;&gt;suggest&lt;/str&gt;配置对应。</li>
</ul>
<ul>
<li>Suggest返回结果的排序<br />
spellchecker组件中的comparatorClass参数可配置Suggest返回结果的排序，目前有如下几种可选方案：</p>
<ul>
<li>Empty – in which case the default is used.</li>
<li>score – explicitly choose the default case</li>
<li>freq – Sort by frequency first, then score.</li>
<li>A fully qualified class name – Provide a custom comparator that implements Comparator&lt;SuggestWord&gt;.<br />
可查看SuggestWordScoreComparator类了解更多细节</li>
</ul>
</li>
</ul>
<ul>
<li>QueryConverter定制<br />
上面的配置中，我们定制了自己的QueryConverter，主要原因是Solr默认的SpellQueryConvert是根据空格对查询参数做分隔，导致 &#8220;nokia e&#8221;这样的字符被当作“nokia”，“e&#8221;这样的两个字符处理，不符合我们的要求。定制的PhraseQueryConverter代码，需要打成jar包，放到Solr能访问到的目录下，在我们系统中是${solr.solr.home}/lib目录。</li>
</ul>
<h2><a name="%E6%90%9C%E7%B4%A2%E6%99%BA%E8%83%BD%E6%8F%90%E7%A4%BA%E5%AE%9E%E7%8E%B0-Suggest%E6%B5%8B%E8%AF%95"></a>Suggest测试</h2>
<p>配置完成之后，重启Solr后，访问如下链接</p>
<div>
<div>
<pre>http://192.168.100.10:8080/solr/suggest?q=motorola%20x</pre>
</div>
</div>
<p>结果如下：</p>
<div>
<div>
<pre>&lt;response&gt;
  &lt;lst name="responseHeader"&gt;
  &lt;int name="status"&gt;0&lt;/int&gt;
  &lt;int name="QTime"&gt;0&lt;/int&gt;
  &lt;/lst&gt;
  &lt;lst name="spellcheck"&gt;
    &lt;lst name="suggestions"&gt;
      &lt;lst name="motorola x"&gt;
        &lt;int name="numFound"&gt;10&lt;/int&gt;
        &lt;int name="startOffset"&gt;0&lt;/int&gt;
        &lt;int name="endOffset"&gt;10&lt;/int&gt;
        &lt;arr name="suggestion"&gt;
          &lt;str&gt;motorola xoom 3g版&lt;/str&gt;
          &lt;str&gt;motorola xt875&lt;/str&gt;
          &lt;str&gt;motorola xt300&lt;/str&gt;
          &lt;str&gt;motorola xt883&lt;/str&gt;
          &lt;str&gt;motorola xt702&lt;/str&gt;
          &lt;str&gt;motorola xt806&lt;/str&gt;
          &lt;str&gt;motorola xt800&lt;/str&gt;
          &lt;str&gt;motorola xt502&lt;/str&gt;
          &lt;str&gt;motorola xt882&lt;/str&gt;
          &lt;str&gt;motorola xt316&lt;/str&gt;
        &lt;/arr&gt;
      &lt;/lst&gt;
      &lt;str name="collation"&gt;motorola xoom 3g版&lt;/str&gt;
  &lt;/lst&gt;
&lt;/lst&gt;
&lt;/response&gt;</pre>
</div>
</div>
<h2><a name="%E6%90%9C%E7%B4%A2%E6%99%BA%E8%83%BD%E6%8F%90%E7%A4%BA%E5%AE%9E%E7%8E%B0-%E9%9C%80%E8%A6%81%E6%B3%A8%E6%84%8F%E7%9A%84%E7%82%B9"></a>需要注意的点</h2>
<ul>
<li>重启Solr后，第一次访问时需要在Suggest请求中添加spellcheck.build=true参数，用于创建spellchecker的索引。</li>
<li>通过threshold参数来限制一些不常用的词不出现在智能提示列表中，当这个值设置过大时，可能导致结果太少，需要引起注意。</li>
</ul>
<h2><a name="%E6%90%9C%E7%B4%A2%E6%99%BA%E8%83%BD%E6%8F%90%E7%A4%BA%E5%AE%9E%E7%8E%B0-%E5%AD%98%E5%9C%A8%E7%9A%84%E9%97%AE%E9%A2%98"></a>存在的问题</h2>
<p>目前主要存在的问题是使用freq排序算法，返回的结果完全基于索引中字符的出现次数，没有兼顾用户搜索词语的频率，因此无法将一些热门词排在更靠前的位置。这块可定制SuggestWordScoreComparator来实现，目前还没有着手做这件事情。</p>
<h2><a name="%E6%90%9C%E7%B4%A2%E6%99%BA%E8%83%BD%E6%8F%90%E7%A4%BA%E5%AE%9E%E7%8E%B0-%E5%8F%82%E8%80%83%E6%96%87%E6%A1%A3"></a>参考文档</h2>
<p><a href="http://wiki.apache.org/solr/SpellCheckComponent" rel="nofollow">SpellCheckComponent</a><br />
<a href="http://wiki.apache.org/solr/Suggester" rel="nofollow">Suggester</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.colorfuldays.org/program/solr/solr-suggest%e5%ae%9e%e7%8e%b0%e6%90%9c%e7%b4%a2%e6%99%ba%e8%83%bd%e6%8f%90%e7%a4%ba/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>遇到一个Jetty tmp的陷阱</title>
		<link>http://www.colorfuldays.org/program/%e9%81%87%e5%88%b0%e4%b8%80%e4%b8%aajetty-tmp%e7%9a%84%e9%99%b7%e9%98%b1/</link>
		<comments>http://www.colorfuldays.org/program/%e9%81%87%e5%88%b0%e4%b8%80%e4%b8%aajetty-tmp%e7%9a%84%e9%99%b7%e9%98%b1/#comments</comments>
		<pubDate>Wed, 11 Jan 2012 06:24:09 +0000</pubDate>
		<dc:creator>iamxhu</dc:creator>
				<category><![CDATA[program]]></category>
		<category><![CDATA[jetty]]></category>
		<category><![CDATA[tmpwatch]]></category>

		<guid isPermaLink="false">http://www.colorfuldays.org/?p=795</guid>
		<description><![CDATA[今天碰到一个古怪的问题，运行在Jetty服务器下的一个系统，忽然爆出一个“404，页面找不到”的错误，重启系统后问题就解决。之前也碰到一个类似的问题，当时也是重启后搞定，上次事件后，查找了一下原因，没有结果，这事情也就放下了。这次再次出现同样的问题，感觉问题比较严重，必须解决这个隐患了。 出现这个问题后，到服务器上看了一下，发现这个Jetty的进程还在，同样运行的其它几个服务也都正常。分析Jetty和应用日志后，也没有发现异常情况。再次回头看一下，抛出的错误信息： HTTP ERROR 404 Problem accessing /pages/index.jsp. Reason: Not Found 这个错误显示是index.jsp这个文件访问不到了。于是到Jetty部署解决war的默认目录/tmp去查看，这时其实已经于事无补了，因为刚才重启过，之前目录中的文件全部会被覆盖。 初步怀疑是war解压出的文件被删除了，问了一下SA有没有cron任务在晚上运行，会不会影响/tmp目录的文件，结果他表示没有。于是继续查看Nginx日志，发现在3点36分钟时，前一个请求返回的是200，后一个就变成404了。这时另外一个同事提醒说，系统默认的tmpwatch任务会清除/tmp目录下的文件。如下： cat /etc/cron.daily/tmpwatch #! /bin/sh flags=-umc /usr/sbin/tmpwatch &#8220;$flags&#8221; -x /tmp/.X11-unix -x /tmp/.XIM-unix \ -x /tmp/.font-unix -x /tmp/.ICE-unix -x /tmp/.Test-unix \ -X &#8216;/tmp/hsperfdata_*&#8217; 10d /tmp /usr/sbin/tmpwatch &#8220;$flags&#8221; 30d /var/tmp &#8230;<p class="read-more"><a href="http://www.colorfuldays.org/program/%e9%81%87%e5%88%b0%e4%b8%80%e4%b8%aajetty-tmp%e7%9a%84%e9%99%b7%e9%98%b1/">Read more &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<p>今天碰到一个古怪的问题，运行在Jetty服务器下的一个系统，忽然爆出一个“404，页面找不到”的错误，重启系统后问题就解决。之前也碰到一个类似的问题，当时也是重启后搞定，上次事件后，查找了一下原因，没有结果，这事情也就放下了。这次再次出现同样的问题，感觉问题比较严重，必须解决这个隐患了。</p>
<p>出现这个问题后，到服务器上看了一下，发现这个Jetty的进程还在，同样运行的其它几个服务也都正常。分析Jetty和应用日志后，也没有发现异常情况。再次回头看一下，抛出的错误信息：</p>
<blockquote><p>HTTP ERROR 404</p>
<p>Problem accessing /pages/index.jsp. Reason:</p>
<p>Not Found</p></blockquote>
<p>这个错误显示是index.jsp这个文件访问不到了。于是到Jetty部署解决war的默认目录/tmp去查看，这时其实已经于事无补了，因为刚才重启过，之前目录中的文件全部会被覆盖。</p>
<p>初步怀疑是war解压出的文件被删除了，问了一下SA有没有cron任务在晚上运行，会不会影响/tmp目录的文件，结果他表示没有。于是继续查看Nginx日志，发现在3点36分钟时，前一个请求返回的是200，后一个就变成404了。这时另外一个同事提醒说，系统默认的tmpwatch任务会清除/tmp目录下的文件。如下：</p>
<blockquote><p>cat /etc/cron.daily/tmpwatch<br />
#! /bin/sh<br />
flags=-umc<br />
/usr/sbin/tmpwatch &#8220;$flags&#8221; -x /tmp/.X11-unix -x /tmp/.XIM-unix \<br />
-x /tmp/.font-unix -x /tmp/.ICE-unix -x /tmp/.Test-unix \<br />
-X &#8216;/tmp/hsperfdata_*&#8217; 10d /tmp<br />
/usr/sbin/tmpwatch &#8220;$flags&#8221; 30d /var/tmp<br />
for d in /var/{cache/man,catman}/{cat?,X11R6/cat?,local/cat?}; do<br />
if [ -d "$d" ]; then<br />
/usr/sbin/tmpwatch &#8220;$flags&#8221; -f 30d &#8220;$d&#8221;<br />
fi<br />
done</p></blockquote>
<p>上面的脚本表示，tmpwatch分根据文件的修改(-m)/创建(-c)时间,清理/tmp下的10天前创建或修改的文件，问题就在这里了。如何解决呢？只要让Jetty解压war文件时，不放在/tmp下就能解决这个问题了。仔细查看Jetty的关于<a href="http://docs.codehaus.org/display/JETTY/Temporary+Directories">Temporary Directories</a> 的描述文档，原来只需要在${jetty.home}目录下创建一个work目录就行了。Jetty的这个Trick害死人，为什么不在Jetty发布包中就默认包含这个目录呢？</p>
<p><span style="color: #ff0000;">教训：使用开源的东西，一定要认真读一下它的文档，对于比较关键的问题，一定要非常熟悉，否则出了问题才来想办法解决，已经晚了。</span></p>
<p>参考文档：<br />
tmpwatch使用说明： <a title="tmpwatch" href="http://linux.die.net/man/8/tmpwatch" target="_blank">tmpwatch man</a><br />
jetty临时目录的说明： <a href="http://docs.codehaus.org/display/JETTY/Temporary+Directories">Temporary Directories</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.colorfuldays.org/program/%e9%81%87%e5%88%b0%e4%b8%80%e4%b8%aajetty-tmp%e7%9a%84%e9%99%b7%e9%98%b1/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>2011读书小结</title>
		<link>http://www.colorfuldays.org/life/books/2011%e8%af%bb%e4%b9%a6%e5%b0%8f%e7%bb%93/</link>
		<comments>http://www.colorfuldays.org/life/books/2011%e8%af%bb%e4%b9%a6%e5%b0%8f%e7%bb%93/#comments</comments>
		<pubDate>Tue, 03 Jan 2012 13:53:56 +0000</pubDate>
		<dc:creator>iamxhu</dc:creator>
				<category><![CDATA[Books]]></category>
		<category><![CDATA[2011]]></category>
		<category><![CDATA[读书]]></category>

		<guid isPermaLink="false">http://www.colorfuldays.org/?p=789</guid>
		<description><![CDATA[在2010年末入手了Kindle，当时暗暗下了个决心：2011年读完40本书。2011已经过去了，很可惜遗憾我未能完成这个目标。上半年读书时间很多，进入下半年后，工作，生活上都非常忙，又沉迷于微博，看书时间锐减，于至于读书少了许多。最终盘点下面，2011年度一共读过了28本书，比2010年的18本有所进步，分类总结一下。 对过去的事情总是有着强烈的好奇心，这是我喜欢读史的一个原因。“读史可以明智，知古可以鉴今”，这两年读史的过程中，深深地感受到这两句话的意义。历史是对过去事情的浓缩，而个人传记则是对个人生平的浓缩，优秀的个人传记是人生智慧的浓缩，从他人传记中学习做事的道理，同时也是学习他们所生活年代的社会的窗口。今年读过不少传记及史书，分列以下： 历史传记类： 水流云在 英若诚 / 张放 / 中信出版社 / 2009-9-1 / 32.00元 英家是真正的贵族。 这是一部英若诚自传，内容非常精彩。书中读了英若诚家族从清末发迹一直到英达的家族史。英家的家族史也是中国近代史的缩影，他们家族与教育有缘，现在好些知名大学的前身是英千里，英敛之当年捐助成立的。 巨流河 齊邦媛 / 天下遠見出版股份有限公司 / 2009-7-7 / TWD 500 齐邦媛自传，讲他父亲及她在台湾的经历。是抗日战争时期人民的生活及国民党败退台湾及台湾慢慢发展起来的一个小窗口。书中所述未必全面，然而从众多小人物的传记中，可以窥视历史的一斑。 大江大海1949 龙应台 这本是禁书，里面敏感内容较多，在豆瓣上都找不到了。里面讲述许多内战时期的事情，任何战争老百姓都是最受苦的，更悲剧的是，当年的人民都被某邪教给蛊惑，以至于至今仍在身受其害 今生今世 胡蘭成 / 三三書坊 / 1990 / 320台幣 这是胡兰成的自传，文笔着实了得，从文中可以看出这人本质并不太坏，对某党是深恶痛疾。从这本书中描述晚清及民国末年农村的贫困生活。蒋介石上台后，只关注城市及工业建设而忽视了千百年来农村的穷困农民，这才国民党失去中国的核心原因。 活着就为改变世界 [美] 杰弗里·扬 / &#8230;<p class="read-more"><a href="http://www.colorfuldays.org/life/books/2011%e8%af%bb%e4%b9%a6%e5%b0%8f%e7%bb%93/">Read more &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<p>在2010年末入手了Kindle，当时暗暗下了个决心：2011年读完40本书。2011已经过去了，很可惜遗憾我未能完成这个目标。上半年读书时间很多，进入下半年后，工作，生活上都非常忙，又沉迷于微博，看书时间锐减，于至于读书少了许多。最终盘点下面，2011年度一共读过了28本书，比2010年的18本有所进步，分类总结一下。</p>
<p>对过去的事情总是有着强烈的好奇心，这是我喜欢读史的一个原因。<em>“读史可以明智</em>，知古可以鉴今”，这两年读史的过程中，深深地感受到这两句话的意义。历史是对过去事情的浓缩，而个人传记则是对个人生平的浓缩，优秀的个人传记是人生智慧的浓缩，从他人传记中学习做事的道理，同时也是学习他们所生活年代的社会的窗口。今年读过不少传记及史书，分列以下：</p>
<h2><strong>历史传记类：</strong></h2>
<p><span class="Apple-style-span" style="line-height: 19px;"><a title="水流云在" href="http://book.douban.com/subject/3905365/"><img src="http://img1.douban.com/spic/s3959021.jpg" alt="水流云在" /></a></span></p>
<div>
<ul>
<li><a href="http://book.douban.com/subject/3905365/"><em>水流云在</em></a></li>
<li>英若诚 / 张放 / 中信出版社 / 2009-9-1 / 32.00元</li>
<li>英家是真正的贵族。 这是一部英若诚自传，内容非常精彩。书中读了英若诚家族从清末发迹一直到英达的家族史。英家的家族史也是中国近代史的缩影，他们家族与教育有缘，现在好些知名大学的前身是英千里，英敛之当年捐助成立的。</li>
</ul>
</div>
<p><span class="Apple-style-span" style="line-height: 19px;"><a title="巨流河" href="http://book.douban.com/subject/3822618/"><img src="http://img3.douban.com/spic/s6363979.jpg" alt="巨流河" /></a></span></p>
<div>
<ul>
<li><a href="http://book.douban.com/subject/3822618/"><em>巨流河</em></a></li>
<li>齊邦媛 / 天下遠見出版股份有限公司 / 2009-7-7 / TWD 500</li>
<li>齐邦媛自传，讲他父亲及她在台湾的经历。是抗日战争时期人民的生活及国民党败退台湾及台湾慢慢发展起来的一个小窗口。书中所述未必全面，然而从众多小人物的传记中，可以窥视历史的一斑。</li>
</ul>
</div>
<div>
<ul>
<li><em>大江大海1949</em></li>
<li>龙应台</li>
<li>这本是禁书，里面敏感内容较多，在豆瓣上都找不到了。里面讲述许多内战时期的事情，任何战争老百姓都是最受苦的，更悲剧的是，当年的人民都被某邪教给蛊惑，以至于至今仍在身受其害</li>
</ul>
<div>
<div><a title="今生今世" href="http://book.douban.com/subject/3251613/"><img src="http://img1.douban.com/spic/s3310112.jpg" alt="今生今世" /></a></div>
<div>
<ul>
<li><a href="http://book.douban.com/subject/3251613/"><em>今生今世</em></a></li>
<li>胡蘭成 / 三三書坊 / 1990 / 320台幣</li>
<li>这是胡兰成的自传，文笔着实了得，从文中可以看出这人本质并不太坏，对某党是深恶痛疾。从这本书中描述晚清及民国末年农村的贫困生活。蒋介石上台后，只关注城市及工业建设而忽视了千百年来农村的穷困农民，这才国民党失去中国的核心原因。</li>
</ul>
</div>
<div><a title="活着就为改变世界" href="http://book.douban.com/subject/4860552/"><img src="http://img1.douban.com/spic/s4401811.jpg" alt="活着就为改变世界" /></a></div>
<div>
<ul>
<li><a href="http://book.douban.com/subject/4860552/"><em>活着就为改变世界</em></a></li>
<li>[美] 杰弗里·扬 / 蒋永军 / 中信出版社 / 2010-6 / 39.00元</li>
<li>在老乔去世前读完的，不得不感叹乔布斯的伟大，也为硅谷无处不在的技术高手而折服。</li>
</ul>
</div>
</div>
</div>
<div><a title="乔布斯传" href="http://book.douban.com/subject/6723066/"><img src="http://img3.douban.com/spic/s6783948.jpg" alt="乔布斯传" /></a></div>
<div>
<ul>
<li><a href="http://book.douban.com/subject/6723066/"><em>乔布斯传</em></a></li>
<li>王咏刚 / 上海财经大学出版社 / 2011-8 / 39.80元</li>
<li>乔布斯去世后几天读的，书中的文字透露出来的语气让人觉得很诡异，处处要表达出作者的一种奇怪的优越感。一些作者杜撰的对话，实在是让人生厌。</li>
</ul>
</div>
<div><a title="八十年代访谈录" href="http://book.douban.com/subject/1777823/"><img src="http://img3.douban.com/spic/s1794585.jpg" alt="八十年代访谈录" /></a></div>
<div>
<ul>
<li><a href="http://book.douban.com/subject/1777823/"><em>八十年代访谈录</em></a></li>
<li>查建英 主编 / 生活·读书·新知三联书店 / 2006-5 / 38.00元</li>
<li>非常喜欢书中阿城，崔健，陈丹青的访谈。阿城的经历给我的感触是，能不被时代的喧嚣左右，独自做些自己喜欢的事情也是一件幸福的事情。</li>
</ul>
</div>
<div><a title="上学记" href="http://book.douban.com/subject/1859140/"><img src="http://img3.douban.com/spic/s1950424.jpg" alt="上学记" /></a></div>
<div>
<ul>
<li><a href="http://book.douban.com/subject/1859140/"><em>上学记</em></a></li>
<li>何兆武 口述 / 生活·读书·新知三联书店 / 2006-8 / 19.80元</li>
<li>西南联大的那一代人真了不起。那个时代中国的学者，学生们在学术上接近世界顶尖水准。可惜后来被莽夫掌权，闭关锁国，以意识形态的方式中国最优秀的一批知识份子悉数炕害。</li>
</ul>
</div>
<div><a title="万历十五年" href="http://book.douban.com/subject/1041482/"><img src="http://img1.douban.com/spic/s1755691.jpg" alt="万历十五年" /></a></div>
<div>
<ul>
<li><a href="http://book.douban.com/subject/1041482/"><em>万历十五年</em></a></li>
<li>[美] 黄仁宇 / 生活·读书·新知三联书店 / 1997-5 / 12.80元</li>
<li>重新审视这个帝国，深刻体会到体制决定了一个国家的命运…</li>
</ul>
</div>
<h2><strong>技术类书籍</strong></h2>
<div><a title="Nginx HTTP Server" href="http://book.douban.com/subject/4925996/"><img src="http://img1.douban.com/spic/s6987071.jpg" alt="Nginx HTTP Server" /></a></div>
<div>
<ul>
<li><a href="http://book.douban.com/subject/4925996/"><em>Nginx HTTP Server</em></a></li>
<li>Clément Nedelcu / Packt Publishing / 2010-7-20 / USD 44.99</li>
<li>范读了一遍，可以作为配置手册。对于一些Nginx的核心动作原理讲述太少，只是爬Wiki写的书。还是期待agentzh写的Nginx书能尽快完成出版吧。</li>
</ul>
</div>
<div><a title="High Performance Web Sites" href="http://book.douban.com/subject/2084131/"><img src="http://img3.douban.com/spic/s4527057.jpg" alt="High Performance Web Sites" /></a></div>
<div>
<ul>
<li><a href="http://book.douban.com/subject/2084131/"><em>High Performance Web Sites</em></a></li>
<li>Steve Souders / O&#8217;Reilly Media / 2007-9-18 / USD 29.99</li>
<li>以前对于那些网络优化规则只知其然，看完这本书后知其所以然了。写过书评如下：<br />
<strong><a title="Permalink to High Performance Website读书笔记" href="http://www.colorfuldays.org/internet/high-performance-website%e8%af%bb%e4%b9%a6%e7%ac%94%e8%ae%b0/">High Performance Website读书笔记</a></strong></li>
</ul>
</div>
<div><a title="Rework" href="http://book.douban.com/subject/3889178/"><img src="http://img3.douban.com/spic/s4614545.jpg" alt="Rework" /></a></div>
<div>
<ul>
<li><a href="http://book.douban.com/subject/3889178/"><em>Rework</em></a></li>
<li>Jason Fried / Crown Business / 2010-3-9 / USD 22.00</li>
<li>书中描述的环境在国内太难找到，简直是软件开发的理想国。在新的公司里尽量尝试着激励大家，让大家都能高效工作。</li>
</ul>
</div>
<div><a title="Hackers &amp; Painters" href="http://book.douban.com/subject/4912556/"><img src="http://img1.douban.com/spic/s6958980.jpg" alt="Hackers &amp; Painters" /></a></div>
<div>
<ul>
<li><a href="http://book.douban.com/subject/4912556/"><em>Hackers &amp; Painters</em></a></li>
<li>Paul Graham / O&#8217;Reilly Media / 2010-5-1 / GBP 13.99</li>
<li>其中讲的许多理念非常赞同，作者确实洞察程序员的心理。Lisp教徒热爱的人物，曾经因看了其博客上的文章，了解过Lisp基本语法。当然读SICP一书时慢慢体会到Lisp其中的魔力。</li>
</ul>
</div>
<div><a title="Groovy in Action" href="http://book.douban.com/subject/1874376/"><img src="http://img3.douban.com/spic/s4306693.jpg" alt="Groovy in Action" /></a></div>
<div>
<ul>
<li><a href="http://book.douban.com/subject/1874376/"><em>Groovy in Action</em></a></li>
<li>Dierk Koenig / Manning Publications / 2007-1-24 / USD 49.99</li>
<li>讲解Groovy最全面的书，其实这本书没有完全读完，不过最近在公司里号召同事们关注Groovy，这本书还得重读一遍。</li>
</ul>
</div>
<div><a title="Solr 1.4 Enterprise Search Server" href="http://book.douban.com/subject/4031994/"><img src="http://img3.douban.com/spic/s3976298.jpg" alt="Solr 1.4 Enterprise Search Server" /></a></div>
<div>
<ul>
<li><a href="http://book.douban.com/subject/4031994/"><em>Solr 1.4 Enterprise Search Server</em></a></li>
<li>David Smiley / Packt Publishing / 2009-08-19 / USD 44.99</li>
<li>号称学习Solr的Cookbook，之前很认同，不过现在不这么认为了。具体原因可看最近写的这篇：</li>
</ul>
</div>
<div><a title="高性能MySQL" href="http://book.douban.com/subject/3766465/"><img src="http://img1.douban.com/spic/s3897590.jpg" alt="高性能MySQL" /></a></div>
<div>
<ul>
<li><a href="http://book.douban.com/subject/3766465/"><em>高性能MySQL</em></a></li>
<li>开明出版社 / 2009-4 / 86.00元</li>
<li>非常好的一本书，讲到了MySQL的方方面面。不过由于MySQL发展太快，09年的一些论断到现在已经不适用了，不过那些基础的东西永远都不会变。</li>
</ul>
</div>
<h2> 商业相关书籍</h2>
<p>来到深圳后，慢慢体会到行业知识对个人的发展非常重要，因此读了些关于电子商务的书。</p>
<div><a title="One Billion Customers" href="http://book.douban.com/subject/2791877/"><img src="http://img3.douban.com/spic/s3031568.jpg" alt="One Billion Customers" /></a></div>
<div>
<ul>
<li><a href="http://book.douban.com/subject/2791877/"><em>One Billion Customers</em></a></li>
<li>James McGregor / Simon &amp; Schuster / October 11, 2005 / $15.00</li>
<li>又一本禁书，读得译言翻译的版本，对于了解这个社会的运作非常有帮助。其实看完这本书，对于我朝更加绝望。</li>
</ul>
<div>
<div><a title="长尾理论2.0" href="http://book.douban.com/subject/3685204/"><img src="http://img3.douban.com/spic/s3750308.jpg" alt="长尾理论2.0" /></a></div>
<div>
<ul>
<li><a href="http://book.douban.com/subject/3685204/"><em>长尾理论2.0</em></a></li>
<li>安德森 / 中信 / 2009-5 / 42.00元</li>
<li>07年就知道这本书，直到2011年才读完。收获很大，提供了另一个角度看商业的方法，对于电商意义重大。</li>
</ul>
</div>
<div><a title="轻公司" href="http://book.douban.com/subject/3793884/"><img src="http://img3.douban.com/spic/s3869506.jpg" alt="轻公司" /></a></div>
<div>
<ul>
<li><a href="http://book.douban.com/subject/3793884/"><em>轻公司</em></a></li>
<li>李黎 / 中信出版社 / 2009-7 / 39.00元</li>
<li>里面讲到的许多关于零售的变革及社会不断演进导致新的商业模式给我留下很深的印象，也明白了零售的一些基本知识。不过在看这本书时，大熊开玩笑的说，当时李黎写这本书时，京东，淘宝，凡客都还是“轻公司”，现在都变成“重公司”，开始搞物流了。</li>
</ul>
</div>
<div><a title="门后的秘密" href="http://book.douban.com/subject/5401859/"><img src="http://img1.douban.com/spic/s4568761.jpg" alt="门后的秘密" /></a></div>
<div>
<ul>
<li><a href="http://book.douban.com/subject/5401859/"><em>门后的秘密</em></a></li>
<li>[美] Johanna Rothmann, / 于梦瑄 / 人民邮电出版社 / 2011-1 / 29.00元</li>
<li>管理入门书籍。在淘宝时一心想做程序员，不愿管人，来到这边后慢慢地发现自己必须承担起带领团队的任务，于是开始看这本书。书中讲的东西都非常不错，解开了许多的疑惑，不过管理这事还是得用心去做，用心体会，不断提升。</li>
</ul>
</div>
<div><a title="决策与判断" href="http://book.douban.com/subject/1193621/"><img src="http://img3.douban.com/spic/s1614244.jpg" alt="决策与判断" /></a></div>
<div>
<ul>
<li><a href="http://book.douban.com/subject/1193621/"><em>决策与判断</em></a></li>
<li>斯科特·普劳斯 / 人民邮电出版社 / 2004-9 / 28.00元</li>
<li>了解在做决策时的一些常见误区，努力去规避。这本书看得不认真，书中内容非常不错，还得再重读一遍。</li>
</ul>
</div>
<div><a title="拆掉思维里的墙" href="http://book.douban.com/subject/4953695/"><img src="http://img3.douban.com/spic/s6907698.jpg" alt="拆掉思维里的墙" /></a></div>
<div>
<ul>
<li><a href="http://book.douban.com/subject/4953695/"><em>拆掉思维里的墙</em></a></li>
<li>古典 / 中国书店 / 2010-9 / 29.80元</li>
<li>励志书，其中没太大意思，刚好在找Kindle模式的书是发现有，就放进Kindle看了看。消磨时间还不错。</li>
</ul>
</div>
<div><a title="我是一只IT小小鸟" href="http://book.douban.com/subject/4006425/"><img src="http://img3.douban.com/spic/s3958139.jpg" alt="我是一只IT小小鸟" /></a></div>
<div>
<ul>
<li><a href="http://book.douban.com/subject/4006425/"><em>我是一只IT小小鸟</em></a></li>
<li>胡江堂 / 电子工业出版社 / 2009 / 29.80</li>
<li>对其中的一些人物比较熟悉了，一直追看他们的博客。书中更喜欢徐宥的一些观点。当然这些人的成功是没有办法复制的，走出自己的一条路才是正道。</li>
</ul>
</div>
<p>还有几本其它的杂书，没什么写的价值，不列在这里了。</p></div>
<div>2012年希望能再接再励，希望能够达到40本书的目标。不管今年会不会是世界末日，自己的计划不能被打乱。</div>
<div><span class="Apple-style-span" style="line-height: 18px;"><br />
</span></div>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.colorfuldays.org/life/books/2011%e8%af%bb%e4%b9%a6%e5%b0%8f%e7%bb%93/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>2011年终盘点</title>
		<link>http://www.colorfuldays.org/life/2011%e5%b9%b4%e7%bb%88%e7%9b%98%e7%82%b9/</link>
		<comments>http://www.colorfuldays.org/life/2011%e5%b9%b4%e7%bb%88%e7%9b%98%e7%82%b9/#comments</comments>
		<pubDate>Mon, 02 Jan 2012 15:01:44 +0000</pubDate>
		<dc:creator>iamxhu</dc:creator>
				<category><![CDATA[Life]]></category>

		<guid isPermaLink="false">http://www.colorfuldays.org/?p=786</guid>
		<description><![CDATA[转眼间2011就成为了过去，已经进入“世界末日”的年份。埋头忙碌了一年，是时候静下心来做个总结了。2011年对我来说是一个重大的转折点，去年4月份带着些许遗憾离开了淘宝，来到了深圳华强北在线，开始新的冒险。 从2009年进入淘宝后，在淘宝学到了许多的东西，也开阔了视野，近距离观察淘宝这样一个大型Java分布式系统是如何搭建的，思考过其中的各个组件的作用。但是遗憾的时，因为机遇的关系，对于这些都只能看看，而没有办法参与，于是在一位朋友的邀请下，来到深圳，加入正在创业中的华强北在线。 加入华强北在线后，才感觉到之前在淘宝很多看似平常的事情，都不简单。于是开始慢慢地组建团队，慢慢把在淘宝学到的有用的做事方法等在这边推动起来，慢慢地规划网站架构。因为新的公司技术还属于刚刚起步阶段，许多的东西都需要亲历亲为，包括很多技术选型的工作。在这段时间里，亲手搭建Nexus做Maven镜像，亲手测试MySQL Percona性能做测试，决定系统部署方案，许多Util类型的代码，亲自决定系统架构采用RESTful风格的接口，甚至还做一些SA的活，还有许多这样的决策。在做这些决策时，常常深感庆幸又小心翼翼，因为深知自己的能力，眼界有限，目前所能做的只是尽量把基础搭建好，让系统没有严重的设计失误，以便未来有大牛加入后，可以让他们快速在现有的基础下，发挥专长。 在处理这许多的细节问题时，才慢慢发现“细节是魔鬼”这句话的真实含义。在淘宝时有许多很多的基础设施平台，在这个平台上做开发工作，很多时候对于一些细节的东西理解并不深刻。来到这边后，需要对这些都非常清楚才能放心，于是发现这半年自己的成长非常大。 在这半年中团队规模一直没有壮大起来，现在看来这是个很大的失误。在深圳招聘时，发现这边的从事外包的Java开发太多，许多人的基础不好，导致招聘一直不顺。8月份把龙浩拉入伙，是今年做得最好的一件事了，其它的几个人也都还不错，在经过几个月的磨合后，整个团队的学习氛围和工作效率都很不错了。新年后还要继续招聘，希望能找到些对技术真正感兴趣的同学一起来把平台做大。 来到深圳后，还有一个最大的改变就是终于告别单身了。 2011年有许多的遗憾，不过都已经过去了。2012年肯定会是非常忙碌的一年，希望这一年能够是收获的一年。 最后欢迎有志于Java技术的朋友与我联系，加盟华强北在线。我们的Java团队非常专业，也非常有潜力。]]></description>
			<content:encoded><![CDATA[<p>转眼间2011就成为了过去，已经进入“世界末日”的年份。埋头忙碌了一年，是时候静下心来做个总结了。2011年对我来说是一个重大的转折点，去年4月份带着些许遗憾离开了淘宝，来到了深圳华强北在线，开始新的冒险。</p>
<p>从2009年进入淘宝后，在淘宝学到了许多的东西，也开阔了视野，近距离观察淘宝这样一个大型Java分布式系统是如何搭建的，思考过其中的各个组件的作用。但是遗憾的时，因为机遇的关系，对于这些都只能看看，而没有办法参与，于是在一位朋友的邀请下，来到深圳，加入正在创业中的华强北在线。</p>
<p>加入华强北在线后，才感觉到之前在淘宝很多看似平常的事情，都不简单。于是开始慢慢地组建团队，慢慢把在淘宝学到的有用的做事方法等在这边推动起来，慢慢地规划网站架构。因为新的公司技术还属于刚刚起步阶段，许多的东西都需要亲历亲为，包括很多技术选型的工作。在这段时间里，亲手搭建Nexus做Maven镜像，亲手测试MySQL Percona性能做测试，决定系统部署方案，许多Util类型的代码，亲自决定系统架构采用RESTful风格的接口，甚至还做一些SA的活，还有许多这样的决策。在做这些决策时，常常深感庆幸又小心翼翼，因为深知自己的能力，眼界有限，目前所能做的只是尽量把基础搭建好，让系统没有严重的设计失误，以便未来有大牛加入后，可以让他们快速在现有的基础下，发挥专长。</p>
<p>在处理这许多的细节问题时，才慢慢发现“细节是魔鬼”这句话的真实含义。在淘宝时有许多很多的基础设施平台，在这个平台上做开发工作，很多时候对于一些细节的东西理解并不深刻。来到这边后，需要对这些都非常清楚才能放心，于是发现这半年自己的成长非常大。</p>
<p>在这半年中团队规模一直没有壮大起来，现在看来这是个很大的失误。在深圳招聘时，发现这边的从事外包的Java开发太多，许多人的基础不好，导致招聘一直不顺。8月份把龙浩拉入伙，是今年做得最好的一件事了，其它的几个人也都还不错，在经过几个月的磨合后，整个团队的学习氛围和工作效率都很不错了。新年后还要继续招聘，希望能找到些对技术真正感兴趣的同学一起来把平台做大。</p>
<p>来到深圳后，还有一个最大的改变就是终于告别单身了。</p>
<p>2011年有许多的遗憾，不过都已经过去了。2012年肯定会是非常忙碌的一年，希望这一年能够是收获的一年。</p>
<p>最后欢迎有志于Java技术的朋友与我联系，加盟华强北在线。我们的Java团队非常专业，也非常有潜力。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.colorfuldays.org/life/2011%e5%b9%b4%e7%bb%88%e7%9b%98%e7%82%b9/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Lucene文件结构</title>
		<link>http://www.colorfuldays.org/program/lucene%e7%9a%84%e6%96%87%e4%bb%b6%e7%bb%93%e6%9e%84/</link>
		<comments>http://www.colorfuldays.org/program/lucene%e7%9a%84%e6%96%87%e4%bb%b6%e7%bb%93%e6%9e%84/#comments</comments>
		<pubDate>Sat, 31 Dec 2011 06:07:03 +0000</pubDate>
		<dc:creator>iamxhu</dc:creator>
				<category><![CDATA[lucene]]></category>
		<category><![CDATA[program]]></category>
		<category><![CDATA[solr]]></category>

		<guid isPermaLink="false">http://www.colorfuldays.org/?p=772</guid>
		<description><![CDATA[Lucene文件的组织结构 Lucene文件结构组件 索引 段 文档 域 词 具体信息 整个存储索引的文件夹，solr中即/opt/solr/spu/data 新添加文档时生成段，在索引目录下_0.*,-1.*表示两个段 对应schema中的一条记录 文档中包括的域 分词后生成的term 简短的lucene创建索引的代码 public void createIndex() { String title = "solr apache "; Document document = new Document(); Field field = new Field("title", new StringReader(title)); document.add(field); try { SimpleFSDirectory &#8230;<p class="read-more"><a href="http://www.colorfuldays.org/program/lucene%e7%9a%84%e6%96%87%e4%bb%b6%e7%bb%93%e6%9e%84/">Read more &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<p>Lucene文件的组织结构</p>
<table>
<tbody>
<tr>
<th>Lucene文件结构组件</th>
<th>索引</th>
<th>段</th>
<th>文档</th>
<th>域</th>
<th>词</th>
</tr>
<tr>
<th>具体信息</th>
<td>整个存储索引的文件夹，solr中即/opt/solr/spu/data</td>
<td>新添加文档时生成段，在索引目录下_0.*,-1.*表示两个段</td>
<td>对应schema中的一条记录</td>
<td>文档中包括的域</td>
<td>分词后生成的term</td>
</tr>
</tbody>
</table>
<p>简短的lucene创建索引的代码</p>
<div>
<div>
<div>
<pre class="java">public void createIndex() {
  String title = "solr apache ";
  Document document = new Document();
  Field field = new Field("title", new StringReader(title));
  document.add(field);

  try {
    SimpleFSDirectory directory = new SimpleFSDirectory(new File("/home/lucene"));
    IndexWriterConfig writerConfig = new IndexWriterConfig(Version.LUCENE_34, 
            new StandardAnalyzer(Version.LUCENE_34));
    IndexWriter writer = new IndexWriter(directory,writerConfig);
    writer.addDocument(document);
    writer.commit();
    writer.close();
  }catch (IOException e) {

  }
}</pre>
</div>
</div>
</div>
<p>执行两次后，生成的索引结构如下图。 第一次title是&#8221;lucene index doc&#8221;,第二次title如上代码所示。</p>
<p><img class="aligncenter size-full wp-image-783" title="lucene" src="http://www.colorfuldays.org/wp-content/uploads/2011/12/lucene.png" alt="" width="402" height="341" /></p>
<p>索引包含正向信息的文件有:</p>
<table>
<tbody>
<tr>
<th>segments_2</th>
<td>保存了此索引包含多少个段,每个段包含多少篇文档。</td>
</tr>
<tr>
<th>_0.fnm</th>
<td>保存了此段包含了多少个域,每个域的名称及索引方式。</td>
</tr>
<tr>
<th>_0.fdx,_0.fdt</th>
<td>保存了此段包含的所有文档,每篇文档包含了多少域,每个域保存了那些信息。</td>
</tr>
<tr>
<th>_0.tvx,_0.tvd,_0.tvf</th>
<td>保存了此段包含多少文档,每篇文档包含了多少域,每个域包含了多少词,每个词的字符串,位置等信息。</td>
</tr>
</tbody>
</table>
<p>所谓反向信息保存了词典到倒排表的映射:词(Term) –&gt; 文档(Document)</p>
<p>包含反向信息的文件有:</p>
<table>
<tbody>
<tr>
<th>_0.tis,_0.tii</th>
<td>保存了词典(Term Dictionary),也即此段包含的所有的词按字典顺序的排序。</td>
</tr>
<tr>
<th>_0.frq</th>
<td>保存了倒排表,也即包含每个词的文档 ID 列表。</td>
</tr>
<tr>
<th>_0.prx</th>
<td>保存了倒排表中每个词在包含此词的文档中的位置。</td>
</tr>
</tbody>
</table>
<p>我们用Linux下的strings命令分别看一下每下文档具体包含的信息。</p>
<div>
<div>
<blockquote><p>strings 可以打印出对象中所有可读取的字符</p></blockquote>
</div>
</div>
<div>
<div>
<div>
<pre>star@star:lucene$ strings _0.fnm
title</pre>
</div>
</div>
</div>
<p>上面的命令，显示可以通过strings，获取当前索引中包含的域的名称。</p>
<div>
<div>
<div>
<pre>star@star:lucene$ strings _0.tis
index
lucene</pre>
</div>
</div>
</div>
<p>上面的输出可以看出，&#8221;lucene index doc&#8221; 实际上只索引了&#8221;index,lucene&#8221;两个词，而doc被分析器过滤掉了。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.colorfuldays.org/program/lucene%e7%9a%84%e6%96%87%e4%bb%b6%e7%bb%93%e6%9e%84/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>制作maven archetype方法</title>
		<link>http://www.colorfuldays.org/program/java/%e5%88%b6%e4%bd%9cmaven-archetype%e6%96%b9%e6%b3%95/</link>
		<comments>http://www.colorfuldays.org/program/java/%e5%88%b6%e4%bd%9cmaven-archetype%e6%96%b9%e6%b3%95/#comments</comments>
		<pubDate>Wed, 28 Dec 2011 09:22:05 +0000</pubDate>
		<dc:creator>iamxhu</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[archetype]]></category>
		<category><![CDATA[maven]]></category>

		<guid isPermaLink="false">http://www.colorfuldays.org/?p=763</guid>
		<description><![CDATA[一直想生成一个archetype，节省初始化项目时间，时间让各个项目的结构及通用配置尽量保持一致。之前试过手动来做这个archetype，发现非常麻烦，很容易出错，最终生成出来的结果也不好。最近发现mvn的archetype插件提供一种从现有项目生成archetype的功能，于是今天便试了一下，果然好用。下面将具体做法记录如下： 首先进行用来做archetype项目的根目录，执行如下命令： mvn archetype:create-from-project 这样将会生成该项目类似的archetype，具体的archetype在target/generated-sources目录下，注意新生成的archetype将会包含该项目中所有的文档 为避免新生成的冗余项目文件太多，需要将新生成archetype中的冗余文档去除，并对其项目结构做一些整理。 1、修改archetype目录下pom.xml，将archetype的名称修改成你喜欢的 2、可以将以原项目名（如uic）命名的文件夹改成_rootArtifactId_，这样生成项目结构时，这个目录名称就会变成新的项目名称了。 这些都整理好了之后，可以将其发布到nexus仓库供其它同事使用了，发布的方法如下： 1、在archetype目录下的pom.xml中添加maven仓库配置: &#60;distributionManagement&#62; &#60;repository&#62; &#60;id&#62;releases&#60;/id&#62; &#60;url&#62; http://192.168.10.254:8081/nexus/content/repositories/releases &#60;/url&#62; &#60;/repository&#62; &#60;snapshotRepository&#62; &#60;id&#62;snapshots&#60;/id&#62; &#60;url&#62; http://192.168.10.254:8081/nexus/content/repositories/snapshots &#60;/url&#62; &#60;/snapshotRepository&#62; &#60;/distributionManagement&#62; 2、运行下面的命令发布archetype mvn deploy 发布成功之后就可以使用下面的命令创建新的项目了。 mvn archetype:generate -DarchetypeGroupId=com.hqb360 -DarchetypeVersion=1.0 -DarchetypeArtifactId=hqb-archetype]]></description>
			<content:encoded><![CDATA[<p>一直想生成一个archetype，节省初始化项目时间，时间让各个项目的结构及通用配置尽量保持一致。之前试过手动来做这个archetype，发现非常麻烦，很容易出错，最终生成出来的结果也不好。最近发现mvn的archetype插件提供一种从现有项目生成archetype的功能，于是今天便试了一下，果然好用。下面将具体做法记录如下：</p>
<p>首先进行用来做archetype项目的根目录，执行如下命令：</p>
<pre>mvn archetype:create-from-project</pre>
<p>这样将会生成该项目类似的archetype，具体的archetype在target/generated-sources目录下，注意新生成的archetype将会包含该项目中所有的文档</p>
<p>为避免新生成的冗余项目文件太多，需要将新生成archetype中的冗余文档去除，并对其项目结构做一些整理。<br />
1、修改archetype目录下pom.xml，将archetype的名称修改成你喜欢的<br />
2、可以将以原项目名（如uic）命名的文件夹改成_<em>rootArtifactId</em>_，这样生成项目结构时，这个目录名称就会变成新的项目名称了。</p>
<p>这些都整理好了之后，可以将其发布到nexus仓库供其它同事使用了，发布的方法如下：<br />
1、在archetype目录下的pom.xml中添加maven仓库配置:</p>
<pre>&lt;distributionManagement&gt;
&lt;repository&gt;
&lt;id&gt;releases&lt;/id&gt;
&lt;url&gt;

http://192.168.10.254:8081/nexus/content/repositories/releases

&lt;/url&gt;
&lt;/repository&gt;
&lt;snapshotRepository&gt;
&lt;id&gt;snapshots&lt;/id&gt;
&lt;url&gt;

http://192.168.10.254:8081/nexus/content/repositories/snapshots

&lt;/url&gt;
&lt;/snapshotRepository&gt;
&lt;/distributionManagement&gt;</pre>
<p>2、运行下面的命令发布archetype</p>
<div>
<pre>mvn deploy</pre>
</div>
<p>发布成功之后就可以使用下面的命令创建新的项目了。</p>
<div>
<div>
<pre>mvn archetype:generate -DarchetypeGroupId=com.hqb360 -DarchetypeVersion=1.0
-DarchetypeArtifactId=hqb-archetype</pre>
</div>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.colorfuldays.org/program/java/%e5%88%b6%e4%bd%9cmaven-archetype%e6%96%b9%e6%b3%95/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Solr的Analyzer分析</title>
		<link>http://www.colorfuldays.org/program/solr/solr%e7%9a%84analyzer%e5%88%86%e6%9e%90/</link>
		<comments>http://www.colorfuldays.org/program/solr/solr%e7%9a%84analyzer%e5%88%86%e6%9e%90/#comments</comments>
		<pubDate>Tue, 27 Dec 2011 03:11:06 +0000</pubDate>
		<dc:creator>iamxhu</dc:creator>
				<category><![CDATA[solr]]></category>
		<category><![CDATA[analyzer]]></category>
		<category><![CDATA[tokenizer]]></category>

		<guid isPermaLink="false">http://www.colorfuldays.org/?p=759</guid>
		<description><![CDATA[在使用Solr时，schema.xml中定义FieldType时可以指定其Analyzer。这个Analyzer在index和query时对该feild存储的值进行处理，生成token stream。这个Analyzer的基本结构如下： &#60;fieldType&#62; &#60;analyzer&#62; &#60;charFilter/&#62; &#60;tokenizer/&#62; &#60;filter&#62; &#60;/analyzer&#62; &#60;/fieldType&#62; Analyzer 的输入是字符串，即field中存储的值，输出是token stream. Analyzer可以是单独的一个类，如org.apache.lucene.analysis.WhitespaceAnalyzer，也可以是由一系统其它组件组成的chain，如： &#60;fieldType name="nametext" class="solr.TextField"&#62; &#60;analyzer&#62; &#60;tokenizer class="solr.StandardTokenizerFactory"/&#62; &#60;filter class="solr.StandardFilterFactory"/&#62; &#60;filter class="solr.LowerCaseFilterFactory"/&#62; &#60;filter class="solr.StopFilterFactory"/&#62; &#60;filter class="solr.EnglishPorterFilterFactory"/&#62; &#60;/analyzer&#62; &#60;/fieldType&#62; fieldType中的Analyzer在index和query两个阶段都会做处理，因此index和query两个阶段的analyzer可以不相同。如果没有指定analyzer的type，则表明index与query阶段用的是同样的analyzer。如： &#60;fieldType name="nametext" class="solr.TextField"&#62; &#60;analyzer *type="index"{*}&#62; &#60;tokenizer class="solr.StandardTokenizerFactory"/&#62; &#60;filter class="solr.LowerCaseFilterFactory"/&#62; &#60;filter &#8230;<p class="read-more"><a href="http://www.colorfuldays.org/program/solr/solr%e7%9a%84analyzer%e5%88%86%e6%9e%90/">Read more &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<p>在使用Solr时，schema.xml中定义FieldType时可以指定其Analyzer。这个Analyzer在index和query时对该feild存储的值进行处理，生成token stream。这个Analyzer的基本结构如下：</p>
<div>
<div>
<pre>&lt;fieldType&gt;
  &lt;analyzer&gt;
    &lt;charFilter/&gt;
    &lt;tokenizer/&gt;
    &lt;filter&gt;
  &lt;/analyzer&gt;
&lt;/fieldType&gt;</pre>
</div>
</div>
<p>Analyzer 的输入是字符串，即field中存储的值，输出是token stream.<br />
Analyzer可以是单独的一个类，如org.apache.lucene.analysis.WhitespaceAnalyzer，也可以是由一系统其它组件组成的chain，如：</p>
<div>
<div>
<pre>&lt;fieldType name="nametext" class="solr.TextField"&gt;
    &lt;analyzer&gt;
        &lt;tokenizer class="solr.StandardTokenizerFactory"/&gt;
        &lt;filter class="solr.StandardFilterFactory"/&gt;
        &lt;filter class="solr.LowerCaseFilterFactory"/&gt;
        &lt;filter class="solr.StopFilterFactory"/&gt;
        &lt;filter class="solr.EnglishPorterFilterFactory"/&gt;
    &lt;/analyzer&gt;
&lt;/fieldType&gt;</pre>
</div>
</div>
<p>fieldType中的Analyzer在index和query两个阶段都会做处理，因此index和query两个阶段的analyzer可以不相同。如果没有指定analyzer的type，则表明index与query阶段用的是同样的analyzer。如：</p>
<div>
<div>
<pre>&lt;fieldType name="nametext" class="solr.TextField"&gt;
    &lt;analyzer *type="index"{*}&gt;
        &lt;tokenizer class="solr.StandardTokenizerFactory"/&gt;
        &lt;filter class="solr.LowerCaseFilterFactory"/&gt;
        &lt;filter class="solr.KeepWordFilterFactory" words="keepwords.txt"/&gt;
        &lt;filter class="solr.SynonymFilterFactory" synonyms="syns.txt"/&gt;
    &lt;/analyzer&gt;
    &lt;analyzer *type="query"{*}&gt;
        &lt;tokenizer class="solr.StandardTokenizerFactory"/&gt;
        &lt;filter class="solr.LowerCaseFilterFactory"/&gt;
    &lt;/analyzer&gt;
&lt;/fieldType&gt;</pre>
</div>
</div>
<p>下面看一看组成analyzer的组件，其中一个analyzer chain中必须且只能包含一个tokenizer。tokenizer的作用是将输入的text stream 分解若干token。而filter的输入是token流，产出也是token流，因此多个filter可以组成一个filter chain。filter主要针对输入的token流进行处理，如做stem，去除stopwords等。solr本身已经提供了大量的tokenizer和filter，同时这种机制也让我们可以方便的进行定制。</p>
<p>除了tokenizer和filter之外，Solr还提供了一种CharFilterFactories，这个CharFilterFactories可以配置到analyer链中，但是必须配置在tokenizer之前。CharFilterFactories可以对于输入到tokenizer中的文本流做一些预处理。</p>
<p>solr中默认包含的analyzer,tokenizer,filter,可以到下面网址查看：<br />
<a href="http://wiki.apache.org/solr/AnalyzersTokenizersTokenFilters" rel="nofollow">http://wiki.apache.org/solr/AnalyzersTokenizersTokenFilters</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.colorfuldays.org/program/solr/solr%e7%9a%84analyzer%e5%88%86%e6%9e%90/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>top命令显示的VIRT列详解</title>
		<link>http://www.colorfuldays.org/linux/top%e5%91%bd%e4%bb%a4%e6%98%be%e7%a4%ba%e7%9a%84virt%e5%88%97%e8%af%a6%e8%a7%a3/</link>
		<comments>http://www.colorfuldays.org/linux/top%e5%91%bd%e4%bb%a4%e6%98%be%e7%a4%ba%e7%9a%84virt%e5%88%97%e8%af%a6%e8%a7%a3/#comments</comments>
		<pubDate>Mon, 26 Dec 2011 04:02:55 +0000</pubDate>
		<dc:creator>iamxhu</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[top]]></category>
		<category><![CDATA[VIRT]]></category>

		<guid isPermaLink="false">http://www.colorfuldays.org/?p=754</guid>
		<description><![CDATA[在Linux下使用top命令查看进程时，经常可以发现Java应用的虚拟内存（即VIRT这一列）占用很高，如下： PID   USER   PR   NI   VIRT     RES     SHR    S   %CPU  %MEM TIME+    COMMAND 5626  admin  20   0     9009m  496m   7072   S     1.8 &#8230;<p class="read-more"><a href="http://www.colorfuldays.org/linux/top%e5%91%bd%e4%bb%a4%e6%98%be%e7%a4%ba%e7%9a%84virt%e5%88%97%e8%af%a6%e8%a7%a3/">Read more &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<p>在Linux下使用top命令查看进程时，经常可以发现Java应用的虚拟内存（即VIRT这一列）占用很高，如下：</p>
<blockquote><p>PID   USER   PR   NI   VIRT     RES     SHR    S   %CPU  %MEM TIME+    COMMAND<br />
5626  admin  20   0     9009m  496m   7072   S     1.8        6.3        355:00.79     java</p></blockquote>
<p>这个VIRT代表啥意思呢？昨天看过StackOverFlow一条问题的解释后，这块算是彻底弄明白了。<br />
上面的几列中，RES表示进程实际使用的内存，如果这个值很大则表示使用了大量实际内存，需要引起注意。<br />
而VIRT的具体解释如下：<br />
The total amount of virtual memory used by the task. It includes all code,data and shared libraries plus pages that have been swapped out.<br />
这段解释的意思是VIRT表示进程所有使用过的代码，数据，共享库等等，这其中的许多数据或许已经从内存交换到硬盘上面，很少使用了。<br />
使用pmap pid 可以显示出这个进程曾经使用过的虚拟内存映射。rwx&#8211;表示一般的数据空间，r-x&#8211;表示常驻磁盘的数据。<br />
具体pmap的详细解释还是得翻看一下man文档。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.colorfuldays.org/linux/top%e5%91%bd%e4%bb%a4%e6%98%be%e7%a4%ba%e7%9a%84virt%e5%88%97%e8%af%a6%e8%a7%a3/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Solr学习资料</title>
		<link>http://www.colorfuldays.org/program/solr/solr%e5%ad%a6%e4%b9%a0%e8%b5%84%e6%96%99/</link>
		<comments>http://www.colorfuldays.org/program/solr/solr%e5%ad%a6%e4%b9%a0%e8%b5%84%e6%96%99/#comments</comments>
		<pubDate>Thu, 22 Dec 2011 04:02:45 +0000</pubDate>
		<dc:creator>iamxhu</dc:creator>
				<category><![CDATA[solr]]></category>

		<guid isPermaLink="false">http://www.colorfuldays.org/?p=747</guid>
		<description><![CDATA[从4月份开始学习Solr，并使用Solr搭建了一个基于搜索系统，到现在已经有半年多了。在学习及使用Solr过程中学到了许多东西，积累了一些经验。在学习Solr过程中主要通过看文档，问Google，这其中也发现一些非常好的资料。需要提醒的是，目前Solr领域有效的中文信息是比较缺少的，更多的时候都需要翻看英文文档。现在对自己这段时间的看过的文档做一个整理，方便其它同样在学习Solr的朋友快速找到好的资料。 Solr学习者最重要的文档是Solr的官方Wiki。Solr的官方文档组织得非常不错，使用过程碰到的许多的问题只要认真读读文档都能找到解决方法，特别是那些component的参数，一定需要细看。我在使用过程中发现许多功能只需要调整参数就能支持。 在书籍方面，目前专门讲Solr书有二本，《Apache Solr 3.1 cookbook》和《Solr 1.4 Enterprise Search Server》。从书名就能看出第一本比较新一点，针对Solr 3.1版本的，第二本针对的是1.4版本。这两本书都是从功能角度上解读Solr，其中《Solr 1.4 Enterprise Search Server》也讲到了Solr的基础知识，是一本不错的入门书籍。这两本书，第二本我详细的读过，收益良多。最后需要提醒的是以上两本书籍都是英文的。 lucene &#38; Solr作为一个快速发展的项目，知识的更新非常快，只看书是不行的，网上的资料更即时，也更全面。在这里就不得不提http://www.lucidimagination.com这个网站了。LucidiMagination这个企业提供Solr的商业支持，有点像MySQL社区的http://www.mysqlperformanceblog.com/。这个网站的博客上有许多很有价值的文章，不少文章比那两本书讲得要好，而且信息及时，对于Solr最新版本在功能和性能上提升都会涉及，绝对是学习Solr的同学必须订阅的博客。另外LucidMagination还提供了非常全面的Solr Refurence Turtorial。 这是我看过的最好的教程，针对的是Solr 3.4版本，非常新，这个PDF一共389页，对Solr的基础知识，包括的功能都有比较详细的介绍。如果只推荐一份文档给Solr入门者的话，我一定会推荐这份文档。 最后推荐一些非常好的入门文章：Optimizing Findability in Lucene and Solr,这篇文章讲述了用Solr搭建搜索需要注意的方方面面，从全局上来看一个搜索需要哪些功能，应当怎么做。这篇文章是用Solr搜索的人员必读的入门文档。]]></description>
			<content:encoded><![CDATA[<p>从4月份开始学习Solr，并使用Solr搭建了一个基于搜索系统，到现在已经有半年多了。在学习及使用Solr过程中学到了许多东西，积累了一些经验。在学习Solr过程中主要通过看文档，问Google，这其中也发现一些非常好的资料。需要提醒的是，目前Solr领域有效的中文信息是比较缺少的，更多的时候都需要翻看英文文档。现在对自己这段时间的看过的文档做一个整理，方便其它同样在学习Solr的朋友快速找到好的资料。<br />
Solr学习者最重要的文档是Solr的<a href="http://wiki.apache.org/solr/" target="_blank">官方Wiki</a>。Solr的官方文档组织得非常不错，使用过程碰到的许多的问题只要认真读读文档都能找到解决方法，特别是那些component的参数，一定需要细看。我在使用过程中发现许多功能只需要调整参数就能支持。<br />
在书籍方面，目前专门讲Solr书有二本，《Apache Solr 3.1 cookbook》和《Solr 1.4 Enterprise Search Server》。从书名就能看出第一本比较新一点，针对Solr 3.1版本的，第二本针对的是1.4版本。这两本书都是从功能角度上解读Solr，其中《Solr 1.4 Enterprise Search Server》也讲到了Solr的基础知识，是一本不错的入门书籍。这两本书，第二本我详细的读过，收益良多。最后需要提醒的是以上两本书籍都是英文的。</p>
<p>lucene &amp; Solr作为一个快速发展的项目，知识的更新非常快，只看书是不行的，网上的资料更即时，也更全面。在这里就不得不提<a href="http://www.lucidimagination.com" target="_blank">http://www.lucidimagination.com</a>这个网站了。LucidiMagination这个企业提供Solr的商业支持，有点像MySQL社区的<a href="http://www.mysqlperformanceblog.com/" target="_blank">http://www.mysqlperformanceblog.com/</a>。这个网站的博客上有许多很有价值的文章，不少文章比那两本书讲得要好，而且信息及时，对于Solr最新版本在功能和性能上提升都会涉及，绝对是学习Solr的同学必须订阅的博客。另外LucidMagination还提供了非常全面的<a href="http://www.lucidimagination.com/devzone/references/solr-guide" target="_blank">Solr Refurence Turtorial</a>。 这是我看过的最好的教程，针对的是Solr 3.4版本，非常新，这个PDF一共389页，对Solr的基础知识，包括的功能都有比较详细的介绍。如果只推荐一份文档给Solr入门者的话，我一定会推荐这份文档。</p>
<p>最后推荐一些非常好的入门文章：<a title="optimizing-findability-lucene-and-solr" href="http://www.lucidimagination.com/devzone/technical-articles/optimizing-findability-lucene-and-solr" target="_blank">Optimizing Findability in Lucene and Solr</a>,这篇文章讲述了用Solr搭建搜索需要注意的方方面面，从全局上来看一个搜索需要哪些功能，应当怎么做。这篇文章是用Solr搜索的人员必读的入门文档。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.colorfuldays.org/program/solr/solr%e5%ad%a6%e4%b9%a0%e8%b5%84%e6%96%99/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Groovy的性能分析</title>
		<link>http://www.colorfuldays.org/program/groovy%e7%9a%84%e6%80%a7%e8%83%bd%e5%88%86%e6%9e%90/</link>
		<comments>http://www.colorfuldays.org/program/groovy%e7%9a%84%e6%80%a7%e8%83%bd%e5%88%86%e6%9e%90/#comments</comments>
		<pubDate>Sun, 18 Dec 2011 15:25:25 +0000</pubDate>
		<dc:creator>iamxhu</dc:creator>
				<category><![CDATA[Groovy]]></category>
		<category><![CDATA[program]]></category>
		<category><![CDATA[groovy]]></category>

		<guid isPermaLink="false">http://www.colorfuldays.org/?p=734</guid>
		<description><![CDATA[最近在继续研究Groovy，同时也在团队内部推动Groovy作为大家学习的第二语言。目前能想到Groovy在应用中的作用有两点： 利用Groovy语法的简练，用它来写测试用例，减少测试的代码量。 实现一个动态执行Groovy脚本的引擎，将一些业务规则用Groovy实现，通过对Groovy脚本可动态更改来满足运营的一些需求。 其中第一点其实比较容易搞，也不会有性能问题，第二个需求则需要考虑到性能的问题。针对这个方案，上周六写了一个简单的GroovyEngine用来从数据库中加载Groovy脚本并执行，顺便对其做了一下性能测试。GroovyEngine的核心方法代码如: public Map&#60; string ,Object&#62; execute(Map&#60; string , Object&#62; context, Map&#60; string , Object&#62; params, Source source) { // Script script = scripts.get(source.getkey()); // if (script == null) { GroovyClassLoader groovyClassLoader = new GroovyClassLoader(); Class scriptClass = &#8230;<p class="read-more"><a href="http://www.colorfuldays.org/program/groovy%e7%9a%84%e6%80%a7%e8%83%bd%e5%88%86%e6%9e%90/">Read more &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<p>最近在继续研究Groovy，同时也在团队内部推动Groovy作为大家学习的第二语言。目前能想到Groovy在应用中的作用有两点：</p>
<ol>
<li>利用Groovy语法的简练，用它来写测试用例，减少测试的代码量。</li>
<li>实现一个动态执行Groovy脚本的引擎，将一些业务规则用Groovy实现，通过对Groovy脚本可动态更改来满足运营的一些需求。</li>
</ol>
<p>其中第一点其实比较容易搞，也不会有性能问题，第二个需求则需要考虑到性能的问题。针对这个方案，上周六写了一个简单的GroovyEngine用来从数据库中加载Groovy脚本并执行，顺便对其做了一下性能测试。GroovyEngine的核心方法代码如:</p>
<pre class="brush: java">public Map&lt; string ,Object&gt; execute(Map&lt; string , Object&gt; context,
       Map&lt; string , Object&gt; params, Source source) {
//  Script script = scripts.get(source.getkey());
//  if (script == null) {
      GroovyClassLoader groovyClassLoader = new GroovyClassLoader();
      Class scriptClass = groovyClassLoader.parseClass(source.getSource(),
         source.getkey());
      Script script = InvokerHelper.createScript(scriptClass,
  groovySpringApplicationContextBinding);
//    if (script != null) {
//      scripts.put(source.getkey(), script);
//    }
//}

  return (Map&lt; string , Object&gt;) script.invokeMethod("execute",
  new Object[]{context, params});
}</pre>
<p>其中Source是定义的一个包含Groovy脚本的对象，groovySpringApplicationContextBinding是Binding的一个实例，目的是将spring容器的对象可以被Groovy脚本方法。<br />
测试代码如下：</p>
<pre class="brush: java">class TestGroovyExecutor extends BaseTestCase{
    @Autowired
    GroovyExecutor groovyExecutor

    @Test
    public void test_execute() {
        def script = """def execute(Map context,Map param){
                        return ["result":"hello world"]
        }
        """
        def code = new Source(source: script,type: "new",name: "hello")
        def context = new HashMap&lt; string ,Object&gt;()
        def params = ["name":"Groovy"]
        def start = System.currentTimeMillis()
        1000.times{
            def result = groovyExecutor.execute(context, params, code)
        }
        def time = System.currentTimeMillis() - start
        System.out.println("take time: " + time)

    }
}</pre>
<p>上面的测试代码运行结果如下：</p>
<blockquote><p>take time: 23843</p></blockquote>
<p>这段很短的Groovy脚本大约每次的执行需要23ms。<br />
如果将Script加入缓存，如将第一段代码中的注释都打开,如下：</p>
<pre>public Map&lt; string ,Object&gt; execute(Map&lt; string , Object&gt; context,
       Map&lt; string , Object&gt; params, Source source) {
  Script script = scripts.get(source.getkey());
  if (script == null) {
      GroovyClassLoader groovyClassLoader = new GroovyClassLoader();
      Class scriptClass = groovyClassLoader.parseClass(source.getSource(),
         source.getkey());
      script = InvokerHelper.createScript(scriptClass,
  groovySpringApplicationContextBinding);
    if (script != null) {
      scripts.put(source.getkey(), script);
    }
  }</pre>
<pre>}</pre>
<p>这次将执行次数加大到100000次，测试执行结果如下：</p>
<blockquote>
<pre>take time: 1678</pre>
</blockquote>
<p>每一次执行时间少于0.1ms，这个执行效率已经可以接受了。</p>
<p>测试的最终结论是要利用Groovy的动态特性来实现一些需要动态变化的业务需求，如果性能上有要求的话，必须对Script做缓存。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.colorfuldays.org/program/groovy%e7%9a%84%e6%80%a7%e8%83%bd%e5%88%86%e6%9e%90/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss><!-- WP Super Cache is installed but broken. The path to wp-cache-phase1.php in wp-content/advanced-cache.php must be fixed! -->

