<?xml version="1.0" encoding="GBK" ?>
<rss version="2.0" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:dcterms="http://purl.org/dc/terms/">
 <channel>
  	  <title><![CDATA[疯狂的阶梯]]></title>
	  <link>http://xiecc.blog.163.com</link>
	  <description><![CDATA[It&apos;s a wonderful life 将八卦进行到底]]></description>
	  <language>zh-CN</language>
	  <pubDate>Fri, 23 Oct 2009 20:36:19 +0800</pubDate>
	  <lastBuildDate>Fri, 23 Oct 2009 20:36:19 +0800</lastBuildDate>
	  <docs>http://blogs.law.harvard.edu/tech/rss</docs>
	  <generator><![CDATA[NetEase Space]]></generator>
	  <managingEditor><![CDATA[xiecc]]></managingEditor>
	  <webMaster><![CDATA[圈圈套圈圈]]></webMaster>
		  <ttl>120</ttl>
	  <image>
	  	<title><![CDATA[疯狂的阶梯]]></title>
	  	<url>http://ava.bimg.126.net/photo/c5jDHZcQ6SFZ9C1snnxe4Q==/171699735795392049.jpg</url>
	  	<link>http://xiecc.blog.163.com</link>
	  </image>
  <item>
  	<title><![CDATA[10 Must-Know Topics For Software Architects In 2009 ]]></title>	
    <link>http://xiecc.blog.163.com/blog/static/1403220092220104143</link>
    <description><![CDATA[<div><p style="text-indent: 2em;">&nbsp;</p>
<p style="text-indent: 2em;">&nbsp;这篇文章很赞， 收藏</p>
<p style="text-indent: 2em;"><a href="http://hinchcliffe.org/archive/2009/03/17/16712.aspx">http://hinchcliffe.org/archive/2009/03/17/16712.aspx</a></p>
<p style="text-indent: 2em;"><img title="10 Must-Know Topics For Software Architects In 2009  - 圈圈套圈圈 - 疯狂的阶梯" alt="10 Must-Know Topics For Software Architects In 2009  - 圈圈套圈圈 - 疯狂的阶梯" src="http://hinchcliffe.org/img/software_architecture_2009.png" border="0">In the last year or so, after quite a lull, the software architecture business has gotten rather exciting again. We're finally seeing major new topics emerging into the early mainstream that are potential game-changers, while at the same time a few innovations that have been hovering in the margins of the industry are starting to break out in a big way. </p>
<p style="text-indent: 2em;">The big changes: The hegemony of traditional <a href="http://en.wikipedia.org/wiki/Multitier_architecture">3 and 4-tier application models</a>, heavyweight run-time platforms, and classical service-oriented architecture that has dominated for about a decade is now literally being torn asunder by a raft of new approaches for designing and architecting applications.</p>
<p style="text-indent: 2em;">These might sound like incautious words but major changes are in the air and architects are reaching out for new solutions as they encounter novel new challenges in the field. As a consequence, these new advances either address increasingly well-understood shortcomings of existing approaches or add new capabilities that we haven't generally focused on before but are becoming increasingly important. A few examples of the latter include creating reusable platforms out of applications from the outset (the <a href="http://blogs.zdnet.com/Hinchcliffe/?p=215">open API story</a>) or cost-effectively creating architectures that can instantly support global distribution, hundreds of terabytes of data, and tens of millions of users. There are others that we'll explore throughout this post.</p>
<p style="text-indent: 2em;">These innovations are hallmarks particularly of the largest systems being built today (which are running into unique challenges due to scale, performance, or feature set) though these software advances are also moving across the spectrum of software from everyday corporate systems and Internet applications to new mobile devices and beyond, such as the emerging space of social networking applications.</p>
<p style="text-indent: 2em;">Mainstays of application architecture such as the relational database model, monolithic run-times, and even deterministic behavior are being challenged by non-relational systems, cloud computing, and new pull-based systems where consistency and even data integrity sometimes take a backseat to uptime and performance.</p>
<p style="text-indent: 2em;">Let's also not forget about Web 2.0 approaches and design patterns which are becoming ever more established in online applications and enterprise architecture both. Social architectures, crowdsourcing, and open supply chains are becoming the norm in the latest software systems faster than expected in many cases. Unfortunately, as a result, the architectural expertise needed to effectively leverage these ideas is often far from abundant. </p>
<p style="text-indent: 2em;">To try to get a handle on what's happening and to explore these emerging topics, I've been doing conference talks lately about the transformation of software architecture that we're beginning to see in so many quarters these days and generally finding consensus that the exciting days of architecture are back, if they ever left. Now it's up to us to begin the lengthy process of taking many of these ideas into our organizations and integrating them into our thought processes and architectural frameworks and bringing them to bear to solve problems and provide value. As one software architect came up and asked me recently, "How do I get my organization to understand what's happening out there?" This is an attempt at addressing that question.</p>
<p style="text-indent: 2em;">Here's a list of the most important new areas that software architects should be conversant in and looking at in 2009:</p>
<p style="text-indent: 2em;">10 Must-Know Topics for Software Architects in 2009</p>
<p style="text-indent: 2em;">
</p><ol>
<li>Cloud Computing. This one is easy to cite given the amount of attention we're seeing in the blogosphere and at conferences, never mind the (considerable) number of actual users of popular cloud services such as <a href="http://aws.amazon.com/ec2/">Amazon EC2</a>. While the term doesn't have an exact definition, it covers the gamut of utility hosting to <a href="http://www.flickr.com/photos/dionh/2604129489/">Platform-as-a-service (PaaS)</a>. I've <a href="http://blogs.zdnet.com/Hinchcliffe/?p=191">covered cloud computing on ZDNet</a> <a href="http://blogs.zdnet.com/Hinchcliffe/?p=194">in detail before</a> and <a href="http://blogs.zdnet.com/Hinchcliffe/?p=261">broken down the vendor space</a> recently as well. While the economics of cloud computing can be extremely compelling and there is undoubtedly a model that will fit your particular needs, cloud computing is also ground zero for the next generation of the famous OS platform wars. Walk carefully and prototype often to get early competency in an architectural advance that will almost certainly change a great deal about the software business in the near future. 
</li><li>Non-relational databases. Tony Bain over at Read/Write Web recently asked "<a href="http://www.readwriteweb.com/archives/is_the_relational_database_doomed.php">Is The Relational Database Doomed?</a>" While it's far too soon to declare the demise of the workhorse relational database that's the bedrock of so many application stacks, there a large number of promising alternatives emerging. Why get rid of the traditional relational database? Certain application designs can greatly benefit from the advantages of document or resource-centric storage approaches. Performance in particular can be much higher with non-relational databases; there are often surprisingly low ceilings to the scale of relational databases, even with clustering and grid computing. And then there is <a href="http://hinchcliffe.org/archive/2005/09/22/2233.aspx">abstraction impedance</a>, which not only can create a lot more overhead when programming but also hurts run-time performance by maintaining several different representations of the data at one time during a service request. Promising non-relational solutions include <a href="http://couchdb.apache.org/">CouchDB</a>, which I'm starting to see in more and more products, as well as <a href="http://aws.amazon.com/simpledb/">Amazon SimpleDB</a>, <a href="https://launchpad.net/drizzle">Drizzle</a> (from the MySql folks), <a href="http://www.mongodb.org/">Mongo</a>, and <a href="http://code.google.com/p/scalaris/">Scalaris</a>. While many applications will continue to get along just fine with relational databases and object-relational mapping, this is the first time that mainstream database alternatives are readily available for those that are increasingly in need of them. 
</li><li>Next-generation distributed computing. An <a href="http://www.nytimes.com/2009/03/17/technology/business-computing/17cloud.html">excellent story today in the New York Times</a> about <a href="http://hadoop.com/">Hadoop</a> provides a good backdrop on this subject: New distributed computing models are moving from the lab and becoming indispensable for providing otherwise difficult to harness computing power when connected to previously unthinkable quantities of data. While traditional request-response models that are the mainstay of network-oriented computing are important, so increasingly are effective ways to process the huge amount of data that are now common in modern software systems. Watch this <a href="http://developer.yahoo.net/blogs/hadoop/2009/03/using_hadoop_to_fight_spam_-_part_1.html">video interview with Mark Risher and Jay Pujara</a> at Yahoo that discusses how Hadoop "enables them to slice through billions of messages to isolate patterns and identify spammers. They can now create new queries and get results within minutes, for problems that took hours or were considered impossible with their previous approach." While Hadoop has considerable momentum, other similar offerings include the commercial <a href="http://www.gridgain.com/">GridGain</a> and open source <a href="http://discoproject.org/">Disco</a> and there are many others. 
</li><li>Web-Oriented Architecture (WOA). <img title="10 Must-Know Topics For Software Architects In 2009  - 圈圈套圈圈 - 疯狂的阶梯" alt="10 Must-Know Topics For Software Architects In 2009  - 圈圈套圈圈 - 疯狂的阶梯" src="http://hinchcliffe.org/img/woa_app_stack.png" border="0">I've discussed Web-Oriented Architecture on this blog now for several years and my most <a href="http://hinchcliffe.org/archive/2008/02/27/16617.aspx">complete write-up is here</a>. In short, the premise is that RESTful architectures (and the architecture stack above and around it including data representation, security, integration, composition, and distribution) are a more natural, productive, and effective way to build increasingly open and federated network-based applications. The <a href="http://blogs.zdnet.com/service-oriented/?p=1169">WOA debate</a> has raged for a while now since it became a hot topic last year but the largest network on the world has cast its vote and WOA is the way that the Web is going by and large; WOA-based applications just align better to the way the network itself inherently works. In my opinion, it is a much better way to create service-oriented architecture for almost all requirements, resulting in more supple and resilient software that is less difficult and expensive to build and maintain. For enterprises considering the move to WOA, here is <a href="http://blogs.zdnet.com/Hinchcliffe/?p=168">good overview I did a short while back</a> about the issues and the evolution of SOA. 
</li><li>Mashups. David Linthicum <a href="http://weblog.infoworld.com/realworldsoa/archives/2009/03/why_did_mashups.html?source=rss">wondered today in Infoworld</a> where the <a href="http://blogs.zdnet.com/Hinchcliffe/?p=81">mashups</a> have gone, clarifying that he believed they had become integral to SOA and for delivering value in enterprise architecture. In reality, while mashups are extremely common in the consumer space, to the point that it's just an every day application development activity, the tools and concepts are just now ready for prime-time in business. I've previously called mashups one of the <a href="http://blogs.zdnet.com/Hinchcliffe/?p=106">next major new application development models</a> and that's just what's happened. Mashups were also prominent in my <a href="http://blogs.zdnet.com/Hinchcliffe/?p=221">Enterprise Web 2.0 Predictions for 2009</a> (item #7). If you're not studying mashup techniques, Michael Ogrinz's <a href="http://www.mashuppatterns.com/">Mashup Patterns</a> is an excellent place to start studying how they impact software architecture . 
</li><li>Open Supply Chains via APIs. I find the term open APIs, which an increasing <a href="http://web2.socialcomputingmagazine.com/the_growth_of_open_apis_more_evidence_that_web_services_dri.htm">body of evidence</a> shows are an extremely powerful model for cross-organization SOAs, to be confusing to the layperson so I've begun calling them "open supply chains." Opening up your business in a scalable, cost-effective manner as a platform for partners to build up on is one of the most powerful business models of the 21st century. However, there seems to be a large divide between native-Web DNA companies and traditional organizations in understanding how important this is (it's increasingly mandatory in order to compete online). All evidence so far points to this as one of the most important, though potentially difficult, things to get right in your architecture. Security, governance, scalability, and ease-of-consumption are all major subject areas and our enterprise architetures and SOAs must be ready for this business strategy as more and more organizations open up. Here's my recent <a href="http://blogs.zdnet.com/Hinchcliffe/?p=215">"state of the union"</a> on open APIs. 
</li><li>Dynamic Languages. Though dynamic languages have been popular on the Web since Javascript and Perl first arrived on the scene, it's only been recently that it's become acceptable to develop "real" software with them. .NET and <a href="http://java.sun.com/">Java</a> are still extremely compelling (and common) platforms for writing and running application code but it's dynamic languages like Ruby, Python, PHP, and now <a href="http://erlang.org/">Erlang</a> that are getting all the attention these days. Why is this? As I explored in a <a href="http://hinchcliffe.org/archive/2008/01/10/16613.aspx#issues_and_motivations">detailed comparison</a> a while back, a trade-off in run-time performance has generally been found to enable a large boost in productivity by virtue of what this lets dynamic languages accomplish. It also doesn't hurt that a lot of work has gone into newer dynamic languages to make them extremely Web-friendly, which is now one of the most common use cases for any programming language. Dynamic languages have architectural trade-offs of course, like any technology, though increasingly frameworks like <a href="http://rubyonrails.org/">Rails</a>, <a href="/hhtp://cakephp.org/">CakePHP</a>, and <a href="http://grails.org/">Grails</a> are built on top of them which bring the latest best practices and design patterns, something that is not happening as frequently with older platforms. The tipping point has arrived however, and dynamic languages are beginning to take the center stage in a significant percentage of new projects. Software architects should be prepared. 
</li><li>Social computing. Developers and software architects are often uncomfortable with <a href="http://web2.socialcomputingmagazine.com/the_webpowered_control_shift_social_computing.htm">social computing</a> aspect of software systems today but <a href="http://en.wikipedia.org/wiki/Reed%27s_law">Reed's Law</a> has unequivocally demonstrated that the value of social systems is generally much higher than non-social systems. Or you could just look at the many popular applications out there that are driven by their social behavior and derive their (often enormous) value from the participation it entails. Whether this is YouTube, Facebook, Twitter, or thousands of other social applications (business and consumer both), the lesson is clear: Social architecture is an important new layer in the application stack and it I've since made it two entire quadrants <a href="http://blogs.zdnet.com/Hinchcliffe/?p=130">of my view of Web 2.0 in the enterprise</a> as a consequence. A List Apart has a great introduction to <a href="http://www.alistapart.com/articles/theelementsofsocialarchitecture">The Elements of Social Architecture</a> and I've identified some of the core patterns for this in my Enterprise 2.0 mnemonic, <a href="http://blogs.zdnet.com/Hinchcliffe/?p=186">FLATNESSES</a>. Fnding a high-value place for social computing in our enterprise architectures will be essential for modern software efforts. 
</li><li>Crowdsourcing and peer production architectures. Increasingly, the public network (the Web) has been used to enable potent <a href="http://blogs.zdnet.com/Hinchcliffe/?p=218">open business models</a> that are beginning to change the way we run our businesses and institutions. This started with open source software and has since moved to media and is now encroaching on a wide variety of industries. The models for doing this online require software architectures that can support this including architectural models for harnessing collective intelligence, moderating it, aggregating it, and protecting it and the users that provide it. As I wrote a couple of months ago in <a href="http://web2.socialcomputingmagazine.com/50_essential_strategies_for_creating_a_successful_web_20_pr.htm">50 Essential Strategies for Creating a Successful Web 2.0 Product</a>, these architectures of participation create most of the value in the software systems that employ them. If you're not sure this is a software architecture issue, just look at Amazon's <a href="http://mturk.com/">Mechanical Turk</a> or <a href="http://www.crowdsound.com/">CrowdSound</a>, that latter which is a widget that allows even end-users to dynamically include crowdsourcing into their applications. You can also read John Tropea's <a href="http://libraryclips.blogsome.com/2009/03/15/crowdsource-as-a-way-to-create-a-community/">new exploration of this topic</a> for an application layer viewpoint. 
</li><li>New Application Models. The Semantic Web seems to be on the rise again and I've already covered Platform-as-a-service and mashups here, but in addition to these we are seeing entirely new application models cropping up in scale online. Whether these are Facebook applications, next-generation mobile apps (iPhone, Android, RIM, etc), OpenSocial or just the increasing prevalence of widgets and gadgets, the trend in the atomization of software (which was done still perhaps the best and most effectively so far in Unix) is reminding us that we still have new discoveries ahead of us. While these often seem trivial, aka applications as a feature, it's also increasingly clear that these are going to be here to stay and can provide considerable point value when they're designed correctly. Certainly for next-generation intranets and portals as well as the online "desktop", micro-applications which have to contend both with scale and with being useful and secure while embedded in other applications is increasingly on the radar. Know how they work, why they are so popular (there are tens upon tens of thousands of Facebook and <a href="http://web2.socialcomputingmagazine.com/the_6_essential_things_you_need_to_know_about_googles_opens.htm">OpenSocial applications</a> alone) and learn how they can be used to provide real utility and every day value. </li></ol></div>]]></description>
	    <author><![CDATA[圈圈套圈圈]]></author>
	    <comments>http://xiecc.blog.163.com/blog/static/1403220092220104143</comments>
    <slash:comments>5</slash:comments>
    <guid isPermaLink="true">http://xiecc.blog.163.com/blog/static/1403220092220104143</guid>
    <pubDate>Sun, 22 Mar 2009 12:10:04 +0800</pubDate>
    <dcterms:modified>2009-03-25T16:21:46+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[Opensocial出客户端开发工具了]]></title>	
    <link>http://xiecc.blog.163.com/blog/static/140322009222115745210</link>
    <description><![CDATA[<div><P>又是eclipse插件， 还是小日本写的，不过总比在web上方便了。</P>
<P>只是开发时要在本地起个shindig server， 所有数据都是本地模拟的，碰到容器自己扩展的API或不兼容的地方就麻烦了。不过既然是开源的&nbsp;，可以边玩边写办法。&nbsp;</P>
<P><A href="http://blog.opensocial.org/2009/03/introducing-opensocial-development.html">http://blog.opensocial.org/2009/03/introducing-opensocial-development.html</A></P>
<P><A href="http://code.google.com/p/opensocial-development-environment/">http://code.google.com/p/opensocial-development-environment/</A></P>
<P>&nbsp;</P>
<P style="TEXT-INDENT: 2em">With the <A href="http://code.google.com/p/opensocial-development-environment/">OpenSocial Development Environment (OSDE)</A>, you no longer need an online OpenSocial container environment to build your applications. OSDE is a new <A href="http://www.eclipse.org/">Eclipse</A> plugin that lets you develop either OpenSocial JavaScript (gadget) client applications or OpenSocial Java client applications using OpenSocial 0.8's REST/RPC protocols, entirely within the Eclipse development environment.</P>
<P style="TEXT-INDENT: 2em">OSDE is the creation of <A href="http://www.opensocial.org/profile/YoichiroTanaka">Yoichiro Tanaka</A>, an expert software developer and leading pioneer in OpenSocial development from Japan. Yoichiro has also published a <A href="http://gihyo.jp/book/2009/978-4-7741-3748-3">book on OpenSocial development</A> in Japan.</P>
<P style="TEXT-INDENT: 2em">Installing the OSDE plugin onto Eclipse 3.4.1 (or later) takes only minutes, and you can be up and running with a fully self-contained OpenSocial development environment. OSDE provides a complete social network environment in a single plugin, along with the necessary tools to easily manage your environment's social data. Additionally, you won't need to create multiple accounts on a social network for testing your applications. This can come in handy if you happen to feel inspired to create a new OpenSocial app while on a plane! </P>
<P style="TEXT-INDENT: 2em"><EMBED allowScriptAccess="never" allowNetworking="internal" src=http://www.youtube.com/v/Hh8r7A3o42g&amp;hl=en&amp;fs=1 width=480 height=295 type=application/x-shockwave-flash allowfullscreen="true" ></EMBED></P>
<P style="TEXT-INDENT: 2em">Architectural Highlights</P>
<P style="TEXT-INDENT: 2em">OSDE is able to provide a complete, standalone development environment because it bundles the same code running on many OpenSocial containers today into a single Eclipse plug-in: for serving gadgets and OpenSocial data, <A href="http://incubator.apache.org/shindig/">Apache Shindig</A> is bundled along with a compact <A href="http://www.h2database.com/">Java H2 database</A>, allowing for social data persistence. OSDE also uses <A href="http://www.hibernate.org/">Hibernate</A> for Java Object Relational mapping of the OpenSocial data entities: people, activities, and data. Plus, OSDE bundles the <A href="http://code.google.com/p/opensocial-java-client/">OpenSocial Java client library</A> so its wizards can quickly generate runnable Java client applications that use OpenSocial's REST/RPC protocols.</P>
<P style="TEXT-INDENT: 2em">Feature Highlights</P>
<P style="TEXT-INDENT: 2em">OSDE also includes development features that greatly enhance OpenSocial development:</P>
<P style="TEXT-INDENT: 2em">
</P><UL>
<LI>OpenSocial project creator wizards for both JavaScript/gadget client apps, as well as Java client applications that use the REST/RPC protocols. 
</LI><LI>A re-entrant gadget specification editor that enables efficient editing of OpenSocial gadget properties, views, locale settings, user preferences as well as gadget and spec/JavaScript source code. 
</LI><LI>An OpenSocial console view that shows the console output of the local Shindig/H2 social engine, as well as tabbed views for directly managing the onboard People, Activities and AppData persisted social data. 
<UL>
<LI>OSDE users can use the social database console to edit their own custom social data (such as people, friend relationships, activities etc.), or they can simply load the sample social data that comes with Apache Shindig's 'Sample Container' application.
<P></P>
<P style="TEXT-INDENT: 2em"></P></LI></UL></LI></UL>
<P>For more information on how to use OSDE, checkout the <A href="http://wiki.opensocial.org/index.php?title=OSDE_Tutorial">OSDE tutorial</A> (which includes a <A href="http://www.youtube.com/watch?v=Hh8r7A3o42g">screencast</A>) and visit the <A href="http://code.google.com/p/opensocial-development-environment/">OSDE homepage</A>.</P>
<P></P>
<P style="TEXT-INDENT: 2em">Posted by Chris Schalk, Google Developer Advocate</P></div>]]></description>
	    <author><![CDATA[圈圈套圈圈]]></author>
	    <comments>http://xiecc.blog.163.com/blog/static/140322009222115745210</comments>
    <slash:comments>0</slash:comments>
    <guid isPermaLink="true">http://xiecc.blog.163.com/blog/static/140322009222115745210</guid>
    <pubDate>Sun, 22 Mar 2009 11:57:45 +0800</pubDate>
    <dcterms:modified>2009-03-22T11:57:45+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[引用 【看图学2.0】Web 2.0应用解析，一目了然]]></title>	
    <link>http://xiecc.blog.163.com/blog/static/140322009222113044866</link>
    <description><![CDATA[<div><P>&nbsp;</P>
<P>太喜欢Dion Hinchcliffe画的图了</P>
<P><EM>引用</EM></P>
<BLOCKQUOTE><A href="http://fxd163tech.blog.163.com/" target=_blank>方兴东</A> 的 <A href="http://fxd163tech.blog.163.com/blog/static/242854132009281240290" target=_blank>【看图学2.0】Web 2.0应用解析，一目了然</A><BR>
<P style="TEXT-INDENT: 2em"></P>
<P style="TEXT-INDENT: 2em">如今，Web 2.0已经臭大街了，人人都厌倦了。不过，我还是很喜欢看<A href="http://blogs.zdnet.com/Hinchcliffe/">Dion Hinchcliffe</A>的博客，而且都是只看图片不看文字。因为，看他的图片比看他的文字更一目了然。仿佛回到了小学时候的看图说话了。转贴几张，与大家欣赏。感谢<A href="http://blogs.zdnet.com/Hinchcliffe/">Dion Hinchcliffe</A>。</P>
<P style="TEXT-INDENT: 2em"><IMG title="【看图学2.0】Web 2.0应用解析，一目了然 - 方兴东 - 方兴东的博客" alt="【看图学2.0】Web 2.0应用解析，一目了然 - 方兴东 - 方兴东的博客" src="http://i.zdnet.com/blogs/strategic_web2_business.png" border=0></P>
<P style="TEXT-INDENT: 2em"><IMG title="【看图学2.0】Web 2.0应用解析，一目了然 - 方兴东 - 方兴东的博客" alt="【看图学2.0】Web 2.0应用解析，一目了然 - 方兴东 - 方兴东的博客" src="http://i.zdnet.com/blogs/cloud_computing_landscape.jpg" border=0></P>
<P style="TEXT-INDENT: 2em"><IMG title="【看图学2.0】Web 2.0应用解析，一目了然 - 方兴东 - 方兴东的博客" alt="【看图学2.0】Web 2.0应用解析，一目了然 - 方兴东 - 方兴东的博客" src="http://i.zdnet.com/blogs/ew2_outlook_2009.png" border=0></P>
<P style="TEXT-INDENT: 2em"><IMG title="【看图学2.0】Web 2.0应用解析，一目了然 - 方兴东 - 方兴东的博客" alt="【看图学2.0】Web 2.0应用解析，一目了然 - 方兴东 - 方兴东的博客" src="http://i.zdnet.com/blogs/open_business_strategies.png" border=0></P>
<P style="TEXT-INDENT: 2em"><IMG title="【看图学2.0】Web 2.0应用解析，一目了然 - 方兴东 - 方兴东的博客" alt="【看图学2.0】Web 2.0应用解析，一目了然 - 方兴东 - 方兴东的博客" src="http://i.zdnet.com/blogs/apis_web_distribution.png" border=0></P>
<P style="TEXT-INDENT: 2em"><IMG title="【看图学2.0】Web 2.0应用解析，一目了然 - 方兴东 - 方兴东的博客" alt="【看图学2.0】Web 2.0应用解析，一目了然 - 方兴东 - 方兴东的博客" src="http://i.zdnet.com/blogs/woa_and_soa_focus_small1.jpg" border=0></P>
<P style="TEXT-INDENT: 2em"><IMG title="【看图学2.0】Web 2.0应用解析，一目了然 - 方兴东 - 方兴东的博客" alt="【看图学2.0】Web 2.0应用解析，一目了然 - 方兴东 - 方兴东的博客" src="http://i.zdnet.com/blogs/community_membership_lifecycle.jpg" border=0></P>
<P style="TEXT-INDENT: 2em"></P></BLOCKQUOTE></div>]]></description>
	    <author><![CDATA[圈圈套圈圈]]></author>
	    <comments>http://xiecc.blog.163.com/blog/static/140322009222113044866</comments>
    <slash:comments>1</slash:comments>
    <guid isPermaLink="true">http://xiecc.blog.163.com/blog/static/140322009222113044866</guid>
    <pubDate>Sun, 22 Mar 2009 11:30:44 +0800</pubDate>
    <dcterms:modified>2009-03-22T11:30:44+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[校内网许朝军：开放平台让校内拥有无限的生产力]]></title>	
    <link>http://xiecc.blog.163.com/blog/static/14032200921155717749</link>
    <description><![CDATA[<div><span style="border-collapse: separate; color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 24px; orphans: 2; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px;"><p style="margin: 0px 0px 24px;">　消息称3月11日千橡副总裁、校内、开心网负责人许朝军在参加媒体活动时，笑称做开放平台就像做超市，并表示开放平台让校内拥有无限的生产力，将在未来两年内资产翻倍增长。</p><p style="margin: 0px 0px 24px;">　　此前有媒体报道校内开放平台已经开始盈利，具体方式是第三方App通过校内豆充值系统进行游戏道具收费。目前互联网上最火热的应用之一“开心农场”，于去年年底就已正式在校内盈利，“我们公布一个数字，开心农场每天的收入差不多5万块钱，按比例分成后，他每天可以2.5万，一个月75万，扣除成本，收入已经很可观。”许朝军介绍到：“但这个产品的对收费的深度挖掘还远远不够，还有至少四到五倍的增长潜力，有机会成长成月入千万的游戏应用。”</p><p style="margin: 0px 0px 24px;">　　许朝军表示开放平台不仅让校内从封闭的<a href="http://web2.iresearch.cn/58" target="_blank" style="text-decoration: none; color: red;">社区</a>转变成一个开放的平台，更为校内带来了无限的生产力、无限的创造力和无限的商业价值。“校内现在的工程师只有150名，但是开放平台上却已经有1000个应用，这都是得益于第三方公司的创作。而校内的开放平台则是相当于一个大超市，我们为第三方开发者提供技术接口、优质的用户等资源。”许朝军说道：“同时我们会和第三方一起探索好的商业模式，目前已经证明通过向个人用户收费，可以让第三方公司的收入大于成本，并实现盈利。”</p><p style="margin: 0px 0px 24px;">　　之后校内相关负责人正式介绍了开放平台的“Golden Partners”计划，与优秀的第三方开发团队建立“互助”、“互惠”的合作关系。并表示校内将用丰富的推广资源、技术资源等为第三方提供最好的创作和经营App的环境。</p><p style="margin: 0px 0px 24px;"><a href="http://news.iresearch.cn/0200/20090311/91759.shtml">转自： http://news.iresearch.cn/0200/20090311/91759.shtm</a></p></span></div>]]></description>
	    <author><![CDATA[圈圈套圈圈]]></author>
	    <comments>http://xiecc.blog.163.com/blog/static/14032200921155717749</comments>
    <slash:comments>0</slash:comments>
    <guid isPermaLink="true">http://xiecc.blog.163.com/blog/static/14032200921155717749</guid>
    <pubDate>Wed, 11 Mar 2009 17:57:17 +0800</pubDate>
    <dcterms:modified>2009-03-11T17:57:58+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[广州出差小记2]]></title>	
    <link>http://xiecc.blog.163.com/blog/static/1403220092784820876</link>
    <description><![CDATA[<div><P><BR>不要流水帐了， 直接进入总结：</P>
<P>看到最搞的广告：数码港酒店的电梯里两个大液晶屏的广告竟然是广州热线的停车位游戏， 拿到第一名的可奖一吨汽油。</P>
<P>泛泛地介绍技术比深入到某个点要难。</P>
<P>如果可以在笔记本演示一些东西可以讲得更清楚， 可惜笔记本是借的，只装了个office。</P>
<P>广州邮件组的人很热情，认识了很多人。</P>
<P>咱们测试组开发的东西很牛B，让人刮目相看。</P>
<P>有空一定要认真看看Mapreduce的paper。</P>
<P>最大的希望：能开发出让自己觉得很有底气的产品。</P>
<P>&nbsp;</P>
<P><BR><BR>&nbsp;</P></div>]]></description>
	    <author><![CDATA[圈圈套圈圈]]></author>
	    <comments>http://xiecc.blog.163.com/blog/static/1403220092784820876</comments>
    <slash:comments>0</slash:comments>
    <guid isPermaLink="true">http://xiecc.blog.163.com/blog/static/1403220092784820876</guid>
    <pubDate>Sat, 7 Mar 2009 20:56:27 +0800</pubDate>
    <dcterms:modified>2009-03-07T20:56:27+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[广州出差小记]]></title>	
    <link>http://xiecc.blog.163.com/blog/static/1403220092743953821</link>
    <description><![CDATA[<div>这回出门可真惨，本来是坐飞机直达广州。结果深圳、东莞、广州一路转悠了一天。不过收获也有一些。<br>周四早上九点的飞机，于是六点半起了个大早 ，一出门就赶上大暴雨，幸好打的还比较顺利。但是上了高架后出租车的雨刮器居然坏了，视线一片模糊，司机居然说不碍事，把我吓的，赶快叫他下了高架另外叫了俩，幸好时间还来得及。<br>上午11点眼看到广州了， 结果被告知广州雷雨，要到深圳迫降，这下大家都晕了，不过更晕的还在后面。11点半在深圳着陆后，只得在飞机上死等，一个小时后深圳开始下大雨，又累、又闷、又饿，但是机长就不开飞机门放我们出去，说是叫不到摆渡车。于是乎在飞机上狂等了3小时，终于等来了摆渡车。<br>眼看起飞无望，我们决定改坐汽车，在国道上拦了一辆大巴继续上路。可惜这是我生平见过最慢的大巴了，走走停停本来2小时的路， 结果花了5小时终于到了广州，真是不容易啊。<br><br>呵呵，全是流水帐， 下次再写点实质性的<br><br></div>]]></description>
	    <author><![CDATA[圈圈套圈圈]]></author>
	    <comments>http://xiecc.blog.163.com/blog/static/1403220092743953821</comments>
    <slash:comments>2</slash:comments>
    <guid isPermaLink="true">http://xiecc.blog.163.com/blog/static/1403220092743953821</guid>
    <pubDate>Sat, 7 Mar 2009 16:39:53 +0800</pubDate>
    <dcterms:modified>2009-03-07T16:39:53+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[中国开放平台年度奖项评选]]></title>	
    <link>http://xiecc.blog.163.com/blog/static/14032200912675112479</link>
    <description><![CDATA[<div><p>好久没写了，所以先灌篇水， 引自 http://oplatform.org/archives/66 。<br></p><p>今年确实是中国的开放平台之年，虽然这个开放还是犹抱琵琶半遮面。</p>
<p>快过年了，咱们也来整体看看，评评奖。</p>
<p><strong>最公正的开放平台——聚友（myspace中国）</strong></p>
<p>从开放思想和对待开发者的角度来看，聚友是最为公正的真正从构建完善生态系统角度着手的平台，不过其用户量太少，即使好心也没太多的玩头。但是，这种精神我们是要大大的提倡和鼓励的！</p>
<p><strong>最让人迷惑的开放平台——校内</strong></p>
<p>校内的开放是让开发者真正兴奋起来的开放，那可是实实在在的大量用户啊。不过早期的协议争论和在维护开发者关系上的经验缺乏，让校内的开放魅力打折
了许多。我一直想问校内的一个问题，就是校内通过开放获得了什么好处没？这些好处与自己做相对比，哪个更大一些。在中国干长期的事情没有眼前的利益是干不
成的。期待平台也通过开放获得了切切实实的好处，这样，开放的事情才能长期搞下去。</p>
<p>千橡集团最近也做了个开心，这个开心要开不开的，这种思路会影响到校内未来的开发策略的走向吗？迷惑之。</p>
<p><strong>最扯淡的开放平台——51</strong></p>
<p>从用户数来说，51本是目前最值得期待的开放SNS平台，其开放平台的运营者也一直很得开发者的信任，其发言人对于开放平台的讨论文章也非常值得一看。不过到后面出尔反尔、杀鸡取卵，与开发者争眼前利益，说的比做的好多了，所以封之为最扯淡的开放平台，具体的事例可参见《<a href="http://oplatform.org/archives/62">扯淡的51开放平台</a>》。<strong><br>
</strong></p>
<p><strong>最“坏”的“开放”平台——开心网（kaixin001.com）</strong></p>
<p>开心网凭借APP运营的方式，快速的占领了白领市场，整个架构也是采用开放的架构模式，不过一直不开放，近期也看不到开放的苗头。开发者一方面在模
仿开心的做法，另一方面也非常期待开心开放。从开放的事业的角度，开心还带了个坏头，让很多搞开放平台的人看到通过自己做和运营APP去获得短期利益的美
景，我们确实是只管抓眼前的老鼠的事情的。</p>
<p><strong>最有“钱途”的开放平台——移动139社区</strong></p>
<p>移动139社区（将来不一定叫这个名字）即将推出，据信也是采用开放的架构模式，被内部誉为移动梦网2.0。跟着它玩的能够成为SP2.0吗？小额
支付的便利性和前端收费的可能性（向用户收钱）是让开发者所期盼的。不过如何发展并留住用户是移动最需要解决的问题。这个平台不起来，跟它玩的人自然没饭
吃。</p>
<p><strong>最憋屈的开放平台——一起网</strong></p>
<p>我丝毫不怀疑谢文老师对于开放的思想境界，一起网也化了很大的努力去搭建开放平台的架构。不过无可奈何花落去，谢文老师的离开，让我看不到一起网的开放的未来。当然一起网还有很多很多问题，最让人憋屈的是一起本希望与开发者一起将一起做大，但是蛋和鸡的故事又在这里重演。</p>
<p><strong>声音最小的开放平台——海内</strong></p>
<p>海内的开放就这么开了，同王兴一样，不怎么说话。还好，很多开发者都是海内的用户，连其他开放平台也要在这上面开群组召集开发者，所以圈子里都是知道的，但是好像没多少开发者跟它玩，哎！</p>
<p><strong>传说中目前最赚钱的开放平台——淘宝</strong></p>
<p>在宣传资料里面看到有开发者在上面赚了几十万了，其他平台有人赚个几千块都跳到天上去了。能向商家收费，这个是个很爽的事情，不过不过出了宣传那
个，还有谁赚了很多钱吗？另外，就我所知，目前基本上给SNS开发的那群人基本上都不太跟淘宝玩，跟淘宝玩的人也基本不跟SNS玩，泾渭分明啊。马云说要
给优秀的开发者投很多很多钱，这个是不是会成为一个马大炮，俺也不晓得。“开放、协同、繁荣”是阿里集团的战略，目前来看，这个战略落地得还不够好，不是
所有的阿里人都有马总的境界的，下面的人还需教育教育再教育。</p>
<p><strong>最快淡出视野的开放平台——搜狐blog</strong></p>
<p>搜狐blog开得最早，不过走得个人门户的老路，采用的netvibes的标准，早期确实让人兴奋了一段时间，现在都没太多人兴奋了，慢慢的淡出了人们的视野，让我们谈起开放平台都不怎么想得起它了。</p>
<p><strong>链条最长的开放平台——manyou（康盛油菜花相关）</strong></p>
<p>其他开发者都是直接给平台开发应用然后给用户用，直面用户，manyou中间有个站长。你的站能运营多少个应用？你会去买应用吗？你会给康盛分钱吗？你会将你的用户和数据开放给康盛吗？链条虽然只增加了一个点，这工作难度可就是增长很多了。难啊！</p>
<p><strong>最忽悠的“开放”平台——天际</strong></p>
<p>灌水一篇，不过这篇文章确实很赞， 引自 &nbsp; http://oplatform.org/archives/66</p><p><br></p><p>最早加入Open Social联盟的中国网站是天际，在很多地方都看到它跟开放扯到一起，到现在还没看到它的开放，或者它就没想过开放，只是想借用开放，让它的名字出现下，好让我们还能看到它，别遗忘了。</p>
<p>在开放的事业中，有很多实干家，也有些忽悠的，需要听其言观其行。既然它喜欢忽悠，为了快遗忘的回忆，咱们再帮它忽悠下。</p>
<p><strong>死得最快的开放平台——雅虎NCP</strong></p>
<p>NCP是什么玩意，你听说过吗？是农产品的简称吗？匆匆出来，然后匆匆的消逝，不带走一片云彩。“农产品”生命如此的短暂，却不能如流星，闪耀一下，可怜的多少人的心血，就如此的没冒泡就消逝了。</p>
<p>好大喜功，不懂互联网的发展规律，忽视用户需求，老想一炮就把这江山打下，注定是要失败的。NCP再次证明了一条规律，这个互联网的世界里要扬名立万虽然没钱和人不行，但是只有钱和人也是扯淡的事情，特别是说不缺钱和人。</p>
<p>以上奖项请联系开放平台实验室，奖品：奖状一张！</p>
<p>PS：本次评选限于中国境内平台，不包括最有前途的facebook。另外，移动互联网那边还有些开放平台很值得跟的。还有些即将开放，比如新浪那边。</p></div>]]></description>
	    <author><![CDATA[圈圈套圈圈]]></author>
	    <comments>http://xiecc.blog.163.com/blog/static/14032200912675112479</comments>
    <slash:comments>0</slash:comments>
    <guid isPermaLink="true">http://xiecc.blog.163.com/blog/static/14032200912675112479</guid>
    <pubDate>Thu, 26 Feb 2009 19:51:12 +0800</pubDate>
    <dcterms:modified>2009-02-26T19:52:42+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[&quot;明朝的那些事儿&quot; 感悟]]></title>	
    <link>http://xiecc.blog.163.com/blog/static/1403220091492021459</link>
    <description><![CDATA[<div>&nbsp;一、忠臣与奸臣最重要的区别不在于贪不贪、是不是拉帮结派、拍马屁、娶几个老婆，关键是能给老百姓做事。<BR>这跟以前电视里的形象是反差可太大了。徐玠，张居正这样的大忠臣照样也收礼、贪财、摆架子，戚继光、胡宗宪这样的照样要跟上面拍马屁、送礼、拉帮结伙，<BR>只有象海瑞这样少根筋的才清廉，可惜这样的不可能成大事，一不小心变成了别人政治斗争的工具。<BR>而象严嵩这样的模范丈夫，因为不给老百姓干活，最后被万千人唾骂。<BR><BR>二、小时候看到的一些很风光的人物历史上其实很惨<BR>象唐寅这样的其实这辈子过得都挺郁闷、只能去妓院里解闷，哪有电视电影里那么风光。 徐渭那样的就更惨了，跟小时候看的徐文长的动画片出入也太大了。<BR><BR><BR>三、有些神人因为某些原因现在名气不大了，而有有些却被捧得巨响亮<BR>王守仁这样有无数传奇、且与孔孟朱并驾的圣贤级人物（远比这几人能打仗，经历更传奇），因为他的心学是唯心主义，因为是蒋介石的偶像，<BR>我们只能在做政治选择题的时候看到王阳明同志的心学作为反例出现。而于谦、海瑞（这两位我也敬佩的）作为爱国主义和清正廉明的典型自然是名声巨响。<BR><BR><BR>四、政治斗争太恐怖了<BR>这个谁都知道。不过想着这些人防住了对手几十招，结果只漏了一招就命丧黄泉，还是蛮吓人的，于谦、夏言这种玩政治的高手最后还是挂了，严嵩老儿支撑到86岁最后还是给坑了，象海瑞这样的最后居然能善终那得多少人品啊。<BR><BR></div>]]></description>
	    <author><![CDATA[圈圈套圈圈]]></author>
	    <comments>http://xiecc.blog.163.com/blog/static/1403220091492021459</comments>
    <slash:comments>3</slash:comments>
    <guid isPermaLink="true">http://xiecc.blog.163.com/blog/static/1403220091492021459</guid>
    <pubDate>Wed, 4 Feb 2009 21:20:21 +0800</pubDate>
    <dcterms:modified>2009-02-04T21:32:21+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[读明朝的那些事儿]]></title>	
    <link>http://xiecc.blog.163.com/blog/static/14032200903195912543</link>
    <description><![CDATA[<div><P>一问周围的人，竟然发现一大半都读过明朝的那些事儿，我真是落后分子，趁着看春晚无聊就在电脑上看书补课了，没想到一看就被吸引，一口气看了一大半。幽默、诙谐、悬疑，再加上时不时出来个著名人物，而且还能了解很多不为人知的历史，夫是太爽了。</P>
<P>后来看了作者介绍，一个海关的公务员，三年如一日，每天晚上花6个小时写作，这是什么支撑的他？应该是兴趣，有时兴趣远远比毅力或信念更重要。</P>
<P>忽然想起了国外的那些开源软件作者，白天写程序，晚上回到家继续开发自己喜欢的开源项目，没有外界的压力、没有功利心、甚至在第一个版本前没有任务反馈，只是因为喜欢，这是多么爽的事，又是多么高的境界。 Guido van Rossum用了9年时间在工作之余开发python， 这样的神人我只能仰慕。</P>
<P>这辈子我都不会达到这种境界，现在我只能想着把工作做好，混口饭吃，但这些神人是我的榜样和动力。</P>
<P>&nbsp;</P>
<P>&nbsp;</P></div>]]></description>
	    <author><![CDATA[圈圈套圈圈]]></author>
	    <comments>http://xiecc.blog.163.com/blog/static/14032200903195912543</comments>
    <slash:comments>4</slash:comments>
    <guid isPermaLink="true">http://xiecc.blog.163.com/blog/static/14032200903195912543</guid>
    <pubDate>Sat, 31 Jan 2009 21:59:12 +0800</pubDate>
    <dcterms:modified>2009-01-31T21:59:12+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[以后要好好写博了]]></title>	
    <link>http://xiecc.blog.163.com/blog/static/14032200902754551605</link>
    <description><![CDATA[<div>博客都荒废两年了， 实在是太懒了，以后要改邪归正。<br>2009的干活的口诀是： 少写几行代码，多做一些设计，不要拘泥细节，角度要站得高些，目标要放得远些<br></div>]]></description>
	    <author><![CDATA[圈圈套圈圈]]></author>
	    <comments>http://xiecc.blog.163.com/blog/static/14032200902754551605</comments>
    <slash:comments>1</slash:comments>
    <guid isPermaLink="true">http://xiecc.blog.163.com/blog/static/14032200902754551605</guid>
    <pubDate>Tue, 27 Jan 2009 17:45:51 +0800</pubDate>
    <dcterms:modified>2009-01-27T17:45:51+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[引用 【原创教程】博客圈子管理帮助［图解］]]></title>	
    <link>http://xiecc.blog.163.com/blog/static/1403220061039725808</link>
    <description><![CDATA[<div><p>一朵微笑帮我们写的圈子帮助, 真好&nbsp;</p><p><em>引用</em></p><blockquote><a href="http://blog.163.com/muyangnv-mile" target="_blank">一朵微笑</a> 的 <a href="/muyangnv-mile/blog/static/48096320061019114699" target="_blank">【原创教程】博客圈子管理帮助［图解］</a><br><p>　　前言：如果你是位博客圈子高手，这篇日志可以不用看了<img src="http://mimg.163.com/popo/smile14.gif">。</p>
<p>　　博客圈子，你我都是新手。这两天微笑仔细研究了一下，把我所了解的博客圈子管理方式打出来，与各位管理员共同学习。</p>
<p>　　<font color="#cc0066">一：登录圈子管理页面</font></p>
<p>　　打开博客圈子（本教程以一朵微笑圈子为例。一朵微笑圈子地址：<a href="http://q.163.com/asmile">http://q.163.com/asmile</a>），点击右上角的“登录”按钮，弹出登录对话框，输入登录帐号和密码，点击“登录”按钮。如图１、</p>
<p align="center"><a href="http://img699.photo.163.com/muyangnv-mile/103449313/2343268599.jpg" target="_blank"><img alt="2343268599.jpg" src="http://img699.photo.163.com/muyangnv-mile/103449313/2343268599.jpg" height="333" width="500"></a></p>
<p align="center">图１</p>
<p align="left">　　登录以后，如果你是本圈子的管理员，你将会看到在页面的右上角有个“编辑我的圈子”按钮（如图２）。</p>
<p align="center"><a href="http://img699.photo.163.com/muyangnv-mile/103449313/2343344495.jpg" target="_blank"><img alt="2343344495.jpg" src="http://img699.photo.163.com/muyangnv-mile/103449313/2343344495.jpg" height="303" width="423"></a></p>
<p align="center">图２</p>
<p align="left">　　点击此按钮进入圈子管理页面（有时叫管理后台），其实它和普通浏览没多大区别。如果仔细看，你会发现页面上各个模块下有个管理按钮。如图３</p>
<p align="center"><a href="http://img699.photo.163.com/muyangnv-mile/103449313/2343445096.jpg" target="_blank"><img alt="2343445096.jpg" src="http://img699.photo.163.com/muyangnv-mile/103449313/2343445096.jpg" height="302" width="444"></a></p>
<p align="center">图３</p>
<p align="center">&nbsp;</p>
<p>　　右上，也多了“排版”“设置”两个按钮。如图４。</p>
<p align="center"><a href="http://img699.photo.163.com/muyangnv-mile/103449313/2343491782.jpg" target="_blank"><img alt="2343491782.jpg" src="http://img699.photo.163.com/muyangnv-mile/103449313/2343491782.jpg" height="275" width="423"></a></p>
<p align="center">图４</p>
<p>　　<font color="#cc0066">二：日志管理（即圈友推送过来的日志管理）</font></p>
<p>　　点击“日志”按钮，进入日志管理页面。如果你的圈子是从网易部落移过来的，可以重新对各分类修改管理。如果你的圈子还没添加过分类，那么就先添加几个分类吧。注：系统默认有两个分类，即“最新日志”和“推荐日志”。添加分类，虽然增加了管理员的工作量，但可以增加日志在圈子首页的显示篇数和延长停留时间，从而增加首页日志的点击浏览量。如果你是个懒人，就当我没说<img src="http://mimg.163.com/popo/smile24.gif"></p>
<p>　　<font color="#0000cc">１、添加分类</font></p>
<p>　　点击“管理分类”按钮，打开分类管理页面。点击“添加分类”，在分类名称下的框中填入各分类的名称。点击右侧的“确定”。如果不满意，还可以修改哦～～<img src="http://mimg.163.com/popo/smile36.gif">如图５</p>
<p align="center"><a href="http://img699.photo.163.com/muyangnv-mile/103449313/2343579659.jpg" target="_blank"><img alt="2343579659.jpg" src="http://img699.photo.163.com/muyangnv-mile/103449313/2343579659.jpg" height="317" width="434"></a></p>
<p align="center">图５</p>
<p align="left"><font color="#0000cc">　　２、显示分类模块</font></p>
<p align="left">　　点击图４中的“排版”按钮，出现一个黄色的横条，上有“模块”和“版式”两个按钮，如图６所示。点击“模块”按钮，点击刚才新添加的分类模块，将其由灰色变为彩色，灰色方块变成小眼睛<img src="http://mimg.163.com/popo/smile28.gif">。如果模块为灰色，则其为隐藏状态，不能在圈子首页上显示<img src="http://mimg.163.com/popo/smile12.gif">。</p>
<p align="center"><a href="http://img699.photo.163.com/muyangnv-mile/103449313/2348598414.jpg" target="_blank"><img alt="2348598414.jpg" src="http://img699.photo.163.com/muyangnv-mile/103449313/2348598414.jpg" height="280" width="441"></a></p>
<p align="center">图６</p>
<p><font color="#0000cc">　　３、移动日志到分类</font></p>
<p>　　添加完分类，我们就去管理日志吧<img src="http://mimg.163.com/popo/smile32.gif">。把日志移到各个分类，是圈子日常管理的一个大项<img src="http://mimg.163.com/popo/smile39.gif">。</p>
<p>　　点击“管理分类”上边的“所有日志”（图５中的②所示），打开圈子里的所有日志列表。新推送过来的日志，都被设为“默认分类”，即“最新日志”类。点击日志标题后边分类下的小铅笔图标按钮。弹出一个小对话框，在对话框中选择相应的分类，点击“确定”。如图７</p>
<p align="center"><a href="http://img699.photo.163.com/muyangnv-mile/103449313/2347381359.jpg" target="_blank"></a></p>
<p align="center"><a href="http://img699.photo.163.com/muyangnv-mile/103449313/2348598670.jpg" target="_blank"><img alt="2348598670.jpg" src="http://img699.photo.163.com/muyangnv-mile/103449313/2348598670.jpg" height="283" width="434"></a></p>
<p align="center">图７</p>
<p align="left">　　<font color="#0000cc">４、推荐日志</font></p>
<p align="left">　　图７中在小铅笔的右边，有一排小星星，在这里可以设置日志的级别。管理员通过日志级别的设置，来推荐和引导网友阅读。</p>
<p align="left">　　从左到右，可以设置五个等级。鼠标左键点击星星即可<img src="http://mimg.163.com/popo/smile18.gif">。如果一篇日志被设为五个星，那么它自动成为被圈子推荐的日志，即移入“推荐日志”<img src="http://mimg.163.com/popo/smile16.gif">。</p>
<p align="left">　　如果一篇日志被移动到某个类别，同时又被设为五星推荐，那么这篇文章一定时间内会在圈子的三个分类同时出现。即在“最新日志”、“推荐日志”和“某分类”同时出现<img src="http://mimg.163.com/popo/smile29.gif">。避免或利用这一现象，依各个圈子的管理方法而定。如图８</p>
<p align="center"><a href="http://img699.photo.163.com/muyangnv-mile/103449313/2347655772.jpg" target="_blank"></a></p>
<p align="center"><a href="http://img699.photo.163.com/muyangnv-mile/103449313/2348598933.jpg" target="_blank"><img alt="2348598933.jpg" src="http://img699.photo.163.com/muyangnv-mile/103449313/2348598933.jpg" height="272" width="444"></a></p>
<p align="center">图８</p>
<p align="left"><font color="#cc0066">　　三、圈友管理</font></p>
<p align="left"><font color="#0000cc">　　１、审核圈友</font></p>
<p align="left">　　点击“圈友”，进入圈友管理页面。点击“圈友审核”，打开待审核的圈友名单。“同意”和“拒绝”两个审核按钮，管理员看着办啦～～<img src="http://mimg.163.com/popo/smile28.gif">　如图９</p>
<p align="center"><a href="http://img699.photo.163.com/muyangnv-mile/103449313/2347951063.jpg" target="_blank"></a></p>
<p align="center"><a href="http://img699.photo.163.com/muyangnv-mile/103449313/2348599247.jpg" target="_blank"><img alt="2348599247.jpg" src="http://img699.photo.163.com/muyangnv-mile/103449313/2348599247.jpg" height="289" width="436"></a></p>
<p align="center">图９</p>
<p align="left">　<font color="#0000cc">　２、圈友推荐和设置圈子管理员</font></p>
<p align="left">　　在推荐圈友之前，请先确认图６中的“推荐圈友”模块为显示状态，否则推荐了也不能在圈子首页显示<img src="http://mimg.163.com/popo/smile10.gif">。</p>
<p align="left">　　点击图９中的“所有圈友”按钮，找到需要推荐或设为管理员的圈友。点击小铅笔图标，弹出个小对话框，如图１０。点击②所示的下拉菜单，将其设为本圈子“管理员”，或者不动，保留其“普通圈友”身份。点击“推荐圈友”前的小方框，将其显示为选中状态。点击“确定”按钮，设置完毕<img src="http://mimg.163.com/popo/smile32.gif">。</p>
<p align="center"><a href="http://img699.photo.163.com/muyangnv-mile/103449313/2348597618.jpg" target="_blank"><img alt="2348597618.jpg" src="http://img699.photo.163.com/muyangnv-mile/103449313/2348597618.jpg" height="265" width="449"></a></p>
<p align="center">图１０</p>
<p align="left"><font color="#cc0066">　　四：上传圈子形象秀</font></p>
<p align="left">　　点击图９中的“关于我们”按钮，进入圈子信息个页面。</p>
<p align="left">　　将“不显示形象”前的对钩去掉<img src="http://mimg.163.com/popo/smile39.gif">。点击“浏览”按钮，弹出对话框。在对话框中找到已经做好的圈子形象图片，将其选中，点击“打开”按钮（有的电脑上显示是“确定”或“好”等）。最后别忘了点击“提交”哦～～<img src="http://mimg.163.com/popo/smile32.gif">　如图１１。我上传的是ＧＩＦ小动画，但圈子“关于我们”页面它不动<img src="http://mimg.163.com/popo/smile35.gif">。呵呵～博客圈子还不完善<img src="http://mimg.163.com/popo/smile40.gif">。</p>
<p align="center"><a href="http://img699.photo.163.com/muyangnv-mile/103449313/2348598120.jpg" target="_blank"><img alt="2348598120.jpg" src="http://img699.photo.163.com/muyangnv-mile/103449313/2348598120.jpg" height="301" width="500"></a></p>
<p align="center">图１１</p>
<p align="left">　　圈子的板式和圈子信息设置，比较简单。我见有的圈子首页模块添加了自定义模块，做了背景音乐和图片等。目前网易博客圈子还不是很稳定，一朵微笑圈子还没有自定义模块的添加通道。等以后博客圈子功能更完善了，我再编写新博客圈子教程，我们再共同学习。谢谢！<img src="http://mimg.163.com/popo/smile03.gif"></p></blockquote></div>]]></description>
	    <author><![CDATA[圈圈套圈圈]]></author>
	    <comments>http://xiecc.blog.163.com/blog/static/1403220061039725808</comments>
    <slash:comments>14</slash:comments>
    <guid isPermaLink="true">http://xiecc.blog.163.com/blog/static/1403220061039725808</guid>
    <pubDate>Fri, 3 Nov 2006 09:07:25 +0800</pubDate>
    <dcterms:modified>2006-11-03T09:09:37+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[博客圈子终于上线]]></title>	
    <link>http://xiecc.blog.163.com/blog/static/1403220069318409789</link>
    <description><![CDATA[<div><P>通宵回来, 累.</P>
<P>经过了三个月的奋战, 网易的博客圈子终于正式上线了, 心里又充满欣慰。</P>
<P>尽管现在的功能还不是太完善， 但是我相信网易的圈子会越来越好的!</P></div>]]></description>
	    <author><![CDATA[圈圈套圈圈]]></author>
	    <comments>http://xiecc.blog.163.com/blog/static/1403220069318409789</comments>
    <slash:comments>6</slash:comments>
    <guid isPermaLink="true">http://xiecc.blog.163.com/blog/static/1403220069318409789</guid>
    <pubDate>Tue, 31 Oct 2006 08:40:09 +0800</pubDate>
    <dcterms:modified>2006-10-31T08:40:10+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[国庆前更新一把]]></title>	
    <link>http://xiecc.blog.163.com/blog/static/1403220068290421800</link>
    <description><![CDATA[<div>好久没更新了， 国庆前随便写几句吧。最近很忙， 很累， 但是也很开心， 我们开发的产品低调上线了。 尽管还有很多问题， 但是毕竟松了一口气...<BR></div>]]></description>
	    <author><![CDATA[圈圈套圈圈]]></author>
	    <comments>http://xiecc.blog.163.com/blog/static/1403220068290421800</comments>
    <slash:comments>9</slash:comments>
    <guid isPermaLink="true">http://xiecc.blog.163.com/blog/static/1403220068290421800</guid>
    <pubDate>Fri, 29 Sep 2006 12:04:21 +0800</pubDate>
    <dcterms:modified>2006-10-30T17:22:33+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[Spring MVC framework深入分析之一--总体分析 ]]></title>	
    <link>http://xiecc.blog.163.com/blog/static/1403220068333538188</link>
    <description><![CDATA[<div><P>再发文章凑数. xiecc于2005年7月11日</P>
<P>&nbsp;</P>
<P>在当今的MVC framework里，似乎Webwork2逐渐成为主流， Webwork2+SpringFramework的组合变得越来越流行。这似乎意味着Spring自带的MVC framework远比Webwork2差，所以大家纷纷用Webwork2来代替。确实，Spring的MVC framework不算是整个Spring的核心部件，但它的威力却超过了很多人的想象。很多人包括xiecc认为Spring的MVC framework是非常优秀的，甚至比Webwork2更优秀。<BR>下面列举一下Spring的MVC framework在设计时做出的一些重要的决定，并将之和相关的MVC framework如Webwork2或struts进行对比：<BR>
</P><P><BR>一、 Spring的整个MVC配置是基于IOC容器的<BR>与struts或webwork2相比，这是一个ms有点奇怪的决定，看一下Spring MVC的配置文件，最先看到的不是action或者form，而是一些有着特定名字的bean，Bean下面的配置是一些简单或有点复杂的属性。我们看到的是机器更容易的数据结构，而不是人更容易理解的元素。<BR>但是这恰恰是Spring的MVC强大的根源！因为它的配置就是Spring的核心IOC容器的配置，这意味着所有IOC容器的威力都可以在这里展现，我们可以为所欲为地对Spring MVC进行扩展和增强，我们可以完成在其它MVC framwork中很多难以想象的任务。想扩展新的URL映射方式吗？要换一个themeResolver或LocalReolver的实现吗?想在页面中显示新类型的View（比如说RDF，呵呵，一个小秘密：xiecc是研究语义网的，虽然成天不务正业，不写论文，只写八卦）？甚至想直接在Controller里定义AOP吗？这些对Spring的MVC来说都是小菜一碟。<BR>我没有仔细研究过Webwork2的扩展机制，我知道通过Webwork2的interceptor机制，可以进行很多的扩展，甚至有一个简单简单的IOC容器。但不管它有多强大，提供了多少扩展点。它的威力都很难和真正的IOC容器相比。而struts的plugin功能则是出名的滥，虽然它也提供了plugin机制。<BR>Spring采用IOC配置的另一个原因是使Spring的MVC与Spring的IOC容器的整合变得非常的容易。Spring提供了与struts与webwork2的整合，但是这样整合都需要在进行间接的包装，感觉总不是很自然。而且还会导致一个概念多个配置，webwork2就需要在Spring里配置bean，再配置自己的xwork文件。想象一下吧，我们的bean直接就是一个controller,直接可以完成MVC的所有任务,这是多少爽的感觉。<BR>Rod Johnson采用IOC容器来实现的另一个原因是这会减少好多开发工作量。看一下urlMapping吧，它提供的property本身就是一个HashMap，只有配置完成，我们的bean里的数据就自然存在了，哈哈，好爽吧。不用象struts那样解析XML，再把它的内容一项一项地读到HashMap里。<BR>虽然这样的配置会有点怪异，但假如我们对Spring的IOC容器非常熟悉的话，会发现它非常的亲切，也非常的简单。<BR>最后是一个简单的小秘密，Spring怎么知道某个bean的配置就是urlMapping？另一个bean的配置就是viewResolver？其实很简单，把所有的bean全部读到内存里，然后通过bean的名字或类型去找就行了。通过名字去找就是简单的getBean方法，通过类型去找则使用了BeanFactoryUtils.beansOfTypeIncludingAncestors的静态方法。</P>
<P>二、 Spring提供了明确的Model, View概念和相应的数据结构<BR>在Spring里有一个有趣的数据类型叫做ModelAndView，它只是简单地把要显示的数据和显示的结果封装在一个类里。但是它却提供了明确的MVC概念，尤其是model概念的强化，使程序的逻辑变得更清晰了。<BR>记得以前在Struts里写程序里的时候，为了显示数据经常自己把东西放到HttpSession或HttpServletRequest里（或set到form里，虽然不太有用），这造成了model概念的模糊，而且也导致了struts与JSP页面的紧耦合。假如我们要替换成Veloctiy,就得另外加一个plugin,因为在velocity里数据是不需要不放到request里的。<BR>Webwork2里强调的是与Web framework解耦和它的command模式的简单性，因此在它的action里只有简单的get或set方法，假如返回数据，也只是简单地返回一个String。当然这样的实现有它的好处，但是它淡化了model和view的概念。Rod Johnson认为Webwork2里的Action同时包含了Action和Model的职责，这样一个类的职责太多，不是一个很好的设计。当然Jason Carreira不太认同这种观点，因为Action里的model对象完成可以delege给其它对象。但不管怎样，这种争论的根源在于Webwork2里淡化了model, view甚至web的概念。仁者见仁，智者见智，最后的结果还是看个人喜欢好吧。</P>
<P>三、 Spring的Controller是Singleton的，或者是线程不安全的<BR>和Struts一样，Spring的Controller是Singleton的，这意味着每个request过来，系统都会用原有的instance去处理，这样导致了两个结果：我们不用每次创建Controller，减少了对象创建和垃圾收集的时间；由于只有一个Controller的instance，当多个线程调用它的时候，它里面的instance变量不是线程安全的。<BR>这也是Webwork2吹嘘的地方，它的每个Action都是线程安全的。因为每过来一个request，它就创建一个Action对象。由于现代JDK垃圾收集功能的效率已经不成问题，所以这种创建完一个对象就扔掉的模式也得到了好多人的认可。Rod Johnson甚至以此为例证明J2EE提供的object pool功能是没多大价值的。<BR>但是当人们在吹嘘线程安全怎么怎么重要的时候，我想请问有多少人在多少情况下需要考虑线程安全？Rod Johnson在分析EJB的时候也提出过其它问题，并不是没有了EJB的线程安全魔法，世界就会灭亡的，大多数情况下，我们根本不需要考虑线程安全的问题，也不考虑object pool。因为我们大多数情况下不需要保持instance状态。<BR>至少我写了那么多的struts Action，写了那么多的Spring Controller，几乎没有碰到需要在instance变量保持状态的问题。当然也许是我写的代码不够多，Struts的设计者Craig R. McClanahan曾经说当时他设计struts时有两个条件不成熟：当时没有测试驱动开发的概念；当时JVM的垃圾收集性能太次。假如现在重新设计的话，他也会采用每个request生成一个新对象的设计方法，这样可以解决掉线程安全的问题了。</P>
<P>四、 Spring不象Webwork2或tapestry那样去隐藏Servlet相关的元素如HttpServletRequest或HttpServletResponse<BR>这又是一个重要的设计决定。在Webwork2里我们没有HttpServletRequest或者HttpServletResponse，只有getter, setter或ActionContext里数据，这样的结果导致一个干净的Action，一个与Web完全无关的Action，一个可以在任何环境下独立运行的bean。那么Webwork2的这样一个基于Command模式的Action究竟给我们带来了什么?我想主要有两点：<BR>1、 它使我们的Action可以非常容易地被测试。<BR>2、 用户可以在Action里添加业务逻辑，并被其它类重用。<BR>然而仔细跟Spring比较一下，我们就会发现这两点功能所带来的好处其实并不象我们想象的那么显著。Spring的Controller类也可以非常轻松被测试，看一下spring-mock下面的包吧，它提供的MockHttpServletRequest, MockHttpServletResponse还有其它一些类让测试Controller变得异常轻松。再看一下Action里的业务逻辑吧，Jason Carreira曾经说我们可以尽情地在Webwork2的Action里加业务逻辑，因为Action是不依赖于Web的。但是有多少人真正往Action里加业务逻辑的？大多数人都会业务逻辑delegate给另一个Service类或Manager类。因为我们很清楚，往Action里加业务逻辑会使整个体系的分层架构变得不清晰，不管怎样，Web层就是Web层，业务层就是业务层，两者的逻辑混在一起总会带来问题的。而且往Action里加业务逻辑会使用这个Action类变得庞大，Webwork2的Action是每个request都创建实例的，尽管带来的性能影响不太大，但并不表示每次都要把业务逻辑再new出来，业务逻辑在大多数的情况下应该是单例的。<BR>不把request和response展现给用户当然还会带来功能上的损失，也许一般的场合，用用webwork2提供的接口已经足够了，但有时我们必须要知道request和response才能发挥出更大的威力。比如我以前的一个项目里有一个通过递归动态生成的树状结构的页面，在jsp页面上显示递归是痛苦或不可能的，因此我用response直接write出页面，这在spring里很easy，但在webwork里可能比较难了（偶不敢肯定，偶研究得不够深，也许高手是有办法的）。</P>
<P>五、 Spring提供了不错但不够充分的interceptor机制<BR>回头看一下struts，它在架构里甚至没有给我们提供hook point的机会，我们没有任何机会加入自己的interceptor。我们只能通过重载struts的RequestProcessor类来进行一点有限的扩展。<BR>到了Webwork2，似乎interceptor一下子成了整个Framework的核心，除了Action的核心部件，其它所有的东西都是interceptor。它的超强的interceptor功能使们扩展整个架构变得非常方便。有人称这种interceptor为AOP，Jason Carreira则自豪地宣称这个叫做pragamtic AOP。我不认同这是AOP，它只是简单的interceptor机制。但不管如何，它的interceptor确实有强大的功能。<BR>Spring也提供了它的interceptor机制，它的HandlerInterceptor三个interceptor方法：peHandle, postHandle, afterCompletion。分别对应Controller执行前，Controller执行后和page render之后。虽然大多数情况下已经够用，但是从功能上来说显然它没有Webwork2强大。从AOP的角度来看，它没有提供around interceptor，而只有before与after interceptor。这意味着我们无法在interceptor前后保持状态，最简单的情况假如我们要计算一个Controller的执行时间，我们必须在执行完before后把begintime这个状态保持住，再在after里把它调出来，但是显然这个状态保持会是个问题，我们不能把它放到instance变量里，因为interceptor不是线程安全的。也许通过ThreadLocal可以解决这个问题，但是如此简单的功能要用到这样的方法来处理，显然这个Interceptor本身设计上还是有点问题的。<BR>六、 Spring提供了MultiActionController，使它可以在一个类里包含多个Action<BR>这个设计和struts的DispatchAction有点类似，只不过提供了更灵活的机制。当我们的项目变大的时候，把功能类似的方法放到同一个Action里完全值得的！Webwork2缺少这样的机制。假如看一下Spring的源代码，会发现其实实现MultiActionController的工作量相当的少，只不过是用反射机制把解析出来的方法名执行一下就完事了。其实Webwork2也完全可以提供这样的机制。虽然从设计上来说确实不是很优雅，但是它确实很有用。</P>
<P>七、 Spring提供了更多的选择方式<BR>看看Spring里提供的Controller吧，它提供了好多不同的Controller类。要生成Wizard吗？要专门用于提交form的Controller吗?要执多个方法的类吗?Spring提供了丰富的子类来扩展这些选择。当然我们还可以很轻松地自己扩展这些功能。<BR>再看看Spring的ViewResolver吧， 它提供了无数不同类型的ViewResolver。更重要的是我们自定义我们的页面映射方式。看看strtus，看看webwork2，都会存在页面与forward name的一层间接转换，我们必须在配置文件里配置好某个字符串（典型的是success）对应的是那个页面。但是Spring里我们有了更大的自由度，我们可以采用webwork2的策略，也可以采用更简单的策略，如将JSP文件名去掉扩展名的映射方法。也许有人认为这种映射方式很幼稚，但是我觉得它是非常有用的方式，即使在大项目里。<BR>还有新的扩展吗？看看Spring Web Flow吧，它是SpringFramework的子项目。它为一长串的基于页面流的Wizard页面提供了可配置的实现方式。在Spring 1.3里，它将是SpringFramework的一部分。</P>
<P>八、 Spring的tag<BR>尽管Spring的tag数量上少得可怜，但它却是精心设计的。它的目标很简单：让美工可以轻松地编辑页面。因为在Spring的页面里Text仍然是Text，checkbox仍然是CheckBox，而不象在struts或webwork2中的Tag。它只是用Springbind对输入内容进行了一下包装。所以尽管页面显示代码上会比Webwork2多，但这绝对是有价值的。</P>
<P>在接下来的几章里，我会分析一下Spring是如何让我们的Web应用不需要知道ApplicationContext就能够访问IOC容器的，然后会对Spring的设计和执行过程进行简单的源码分析，然后给出几个扩展Spring MVC的方法。</P>
<P>&nbsp;</P></div>]]></description>
	    <author><![CDATA[圈圈套圈圈]]></author>
	    <comments>http://xiecc.blog.163.com/blog/static/1403220068333538188</comments>
    <slash:comments>7</slash:comments>
    <guid isPermaLink="true">http://xiecc.blog.163.com/blog/static/1403220068333538188</guid>
    <pubDate>Sun, 3 Sep 2006 15:35:38 +0800</pubDate>
    <dcterms:modified>2006-09-03T15:35:38+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[大家都爱上开会]]></title>	
    <link>http://xiecc.blog.163.com/blog/static/140322006817226872</link>
    <description><![CDATA[<div><P>开会也许是我这这辈子最痛恨的事情之一, 尤其是想起昔日有一阵子的马拉松式(连开八小时的会议, 每周N次)会议更是心有余悸。<BR>所以当初听说每天开scrum会议的时候心里也暗怕, 没想到一个多月下来,大家都爱上了开会，每天大家都嚷嚷着去开会，<BR>想想真是有意思。<BR>为什么大家爱开会？<BR>1、工作太紧张的时候，开会可以放松一下。<BR>2、大家坐下来交流一下，瞎乱聊一通挺好玩。有时大家互相启发一下也挺有收获。<BR>3、没有领导，每个人都感觉很轻松，大家都平等的感觉，没有任何压力。<BR>4、时间短，一般15分钟解决， 长一点20分钟， 大家都不会觉得烦。<BR></P></div>]]></description>
	    <author><![CDATA[圈圈套圈圈]]></author>
	    <comments>http://xiecc.blog.163.com/blog/static/140322006817226872</comments>
    <slash:comments>4</slash:comments>
    <guid isPermaLink="true">http://xiecc.blog.163.com/blog/static/140322006817226872</guid>
    <pubDate>Fri, 1 Sep 2006 19:22:06 +0800</pubDate>
    <dcterms:modified>2006-09-01T19:22:06+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[身体是革命的本钱]]></title>	
    <link>http://xiecc.blog.163.com/blog/static/14032200672812624221</link>
    <description><![CDATA[<div>最近写程序累, 身体也一直不好, 胃老是不舒服, 弄得我一直没心情鼓弄blog。<br>得胃病真讨厌， 一顿饭都不能饿着，不能喝酒，空调一对着吹就容易拉肚子，真是羡慕精力过剩从不喊累的B.E.啊。<br>以后下午要吃点东西填肚子，然后多锻炼身体，毕竟身体是革命的本钱啊。<br><br><br></div>]]></description>
	    <author><![CDATA[圈圈套圈圈]]></author>
	    <comments>http://xiecc.blog.163.com/blog/static/14032200672812624221</comments>
    <slash:comments>6</slash:comments>
    <guid isPermaLink="true">http://xiecc.blog.163.com/blog/static/14032200672812624221</guid>
    <pubDate>Mon, 28 Aug 2006 13:26:24 +0800</pubDate>
    <dcterms:modified>2006-08-28T13:26:24+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[解析Acegi Security System for Spring]]></title>	
    <link>http://xiecc.blog.163.com/blog/static/14032200671773359760</link>
    <description><![CDATA[<div><P>最近写程序狂累， 先找一篇以前写的blog蒙混一下啦，反正最近刚要用Acegi。</P>
<P>xiecc于2005-11-19</P>
<P><SPAN style="FONT-FAMILY: 宋体">偶对</SPAN><SPAN lang=EN-US>Acegi Security System</SPAN><SPAN style="FONT-FAMILY: 宋体">景仰已久，它利用了</SPAN><SPAN lang=EN-US>Spring</SPAN><SPAN style="FONT-FAMILY: 宋体">提供的</SPAN><SPAN lang=EN-US>IOC</SPAN><SPAN style="FONT-FAMILY: 宋体">和</SPAN><SPAN lang=EN-US>AOP</SPAN><SPAN style="FONT-FAMILY: 宋体">的机制，实现了一个安全架构，让我们的业务逻辑和安全检查逻辑完全解耦，所有的安全逻辑只要通过</SPAN><SPAN lang=EN-US>Spring</SPAN><SPAN style="FONT-FAMILY: 宋体">的标准配置文件的定义就可实现了。不过说得简单，真的每次拿起</SPAN><SPAN lang=EN-US>Acegi Security System</SPAN><SPAN style="FONT-FAMILY: 宋体">来看的时候，感觉就象云里雾里，如果不仔细看它的文档，再深入研究的话，根本就看不出头绪。某种程度上来说，学习</SPAN><SPAN lang=EN-US>Acegi Security System</SPAN><SPAN style="FONT-FAMILY: 宋体">似乎比学习</SPAN><SPAN lang=EN-US>Spring</SPAN><SPAN style="FONT-FAMILY: 宋体">还要难。</SPAN></P>
<P><BR>&nbsp;</P>
<P><SPAN style="FONT-FAMILY: 宋体">最近偶沉下心来，花了好多时间，看了文档和主要的源代码，终于摸出了点头绪。为什么</SPAN><SPAN lang=EN-US>Acegi Security System</SPAN><SPAN style="FONT-FAMILY: 宋体">会这么难？我觉得原因有以下几个：</SPAN></P>
<P>
</P><P><SPAN style="FONT-FAMILY: 宋体">一、</SPAN><SPAN lang=EN-US>Acegi Security System</SPAN><SPAN style="FONT-FAMILY: 宋体">的配置文件是用的是</SPAN><SPAN lang=EN-US>Spring</SPAN><SPAN style="FONT-FAMILY: 宋体">的标准配置。某种程度上，它的配置是针对</SPAN><SPAN lang=EN-US>Acegi</SPAN><SPAN style="FONT-FAMILY: 宋体">的设计和实现都很了解的人，而不是针对最终用户的。配置文件里那么多的类，那么复杂的对象关联，如果没有对</SPAN><SPAN lang=EN-US>Acegi</SPAN><SPAN style="FONT-FAMILY: 宋体">的设计有深入了解，只能看得云里雾里。也许我们能在</SPAN><SPAN lang=EN-US>Acegi Security</SPAN><SPAN style="FONT-FAMILY: 宋体">上包一层，定义自己的配置文件来简化</SPAN><SPAN lang=EN-US>Acegi Security</SPAN><SPAN style="FONT-FAMILY: 宋体">。但是仔细想想，</SPAN><SPAN lang=EN-US>Acegi Security</SPAN><SPAN style="FONT-FAMILY: 宋体">的设计是有道理的，</SPAN><SPAN lang=EN-US>Security</SPAN><SPAN style="FONT-FAMILY: 宋体">本来就不是一件简单的事，我们不能指望一个新手来完成所有</SPAN><SPAN lang=EN-US>Security</SPAN><SPAN style="FONT-FAMILY: 宋体">的配置。而利用</SPAN><SPAN lang=EN-US>Spring</SPAN><SPAN style="FONT-FAMILY: 宋体">的配置文件却能达到最大的灵活性，利用</SPAN><SPAN lang=EN-US>Spring</SPAN><SPAN style="FONT-FAMILY: 宋体">的</SPAN><SPAN lang=EN-US>IOC</SPAN><SPAN style="FONT-FAMILY: 宋体">机制，所有的配置都可以提供我们的自定义的实现。一旦当我们对</SPAN><SPAN lang=EN-US>Acegi</SPAN><SPAN style="FONT-FAMILY: 宋体">有了深入了解之后，所有的这些配置就会变得很自然了。</SPAN></P>
<P>
</P><P><SPAN style="FONT-FAMILY: 宋体">二、</SPAN><SPAN lang=EN-US>Acegi</SPAN><SPAN style="FONT-FAMILY: 宋体">的文档相当的好，它将</SPAN><SPAN lang=EN-US>Acegi</SPAN><SPAN style="FONT-FAMILY: 宋体">的内部实现、类之间的关联，实现的目标进行了很深入的分析。但是却忽略了一点，它的整个文档是从设计出发，而不是从需求出发的，整个文档似乎更关注于</SPAN><SPAN lang=EN-US>Acegi Security</SPAN><SPAN style="FONT-FAMILY: 宋体">是怎么设计的，而不是怎么用的。当然我承认如果要深入了解</SPAN><SPAN lang=EN-US>Acegi</SPAN><SPAN style="FONT-FAMILY: 宋体">，我们必须要知道它的设计和实现，但是对于一个新手来说，假如我们能马上知道</SPAN><SPAN lang=EN-US>Acegi</SPAN><SPAN style="FONT-FAMILY: 宋体">的安全认证执行流程是怎么样的，再通过个认证流程展开说明</SPAN><SPAN lang=EN-US>authentication</SPAN><SPAN style="FONT-FAMILY: 宋体">和</SPAN><SPAN lang=EN-US>authorization</SPAN><SPAN style="FONT-FAMILY: 宋体">所涉及到的东西岂不更好？</SPAN></P>
<P>
</P><P><SPAN style="FONT-FAMILY: 宋体">今天先写到这里啦，过两天再写一下</SPAN><SPAN lang=EN-US>Acegi Security</SPAN><SPAN style="FONT-FAMILY: 宋体">的认证流程吧，还是蛮好玩的，虽然写起来可能会有点累。</SPAN></P>
<P><SPAN style="FONT-FAMILY: 宋体"></SPAN>&nbsp;</P><SPAN style="FONT-FAMILY: 宋体">
<P><SPAN style="FONT-FAMILY: 宋体">我发现我给自己设了个陷阱，对于</SPAN><SPAN lang=EN-US>Acegi Security System</SPAN><SPAN style="FONT-FAMILY: 宋体">的解析并不是光写个安全认证的流程就能说清楚的。虽然看起来</SPAN><SPAN lang=EN-US>Acegi</SPAN><SPAN style="FONT-FAMILY: 宋体">的文档确实挺累，但是当我动笔写时却发现要写得比这个文档更好还是挺难的。毕竟我们不能让本来很难的事情一下子就变得很简单了，我也是昨天重要看了一遍了</SPAN><SPAN lang=EN-US>Acegi Security System</SPAN><SPAN style="FONT-FAMILY: 宋体">的源代码，才发现我自己有明白了好多不明白的东西。但是我仍然希望我写的东西能够帮助那些正在学习和研究</SPAN><SPAN lang=EN-US>Acegi Security System</SPAN><SPAN style="FONT-FAMILY: 宋体">的人们，所以我又开始动笔了，呵呵！</SPAN></P>
<P><BR>&nbsp;</P>
<P><SPAN style="FONT-FAMILY: 宋体">虽然我不想介绍太多与安全认证流程无关的东西，但是有些东西的讲解却是必不可少的，因为没有这些基本的概念和类，后面的东西就没法说清了。不过对于具体的类、类图和它们之间的关联，我还是推荐去看</SPAN><SPAN lang=EN-US>Professional Java Development with the Spring Framework</SPAN><SPAN style="FONT-FAMILY: 宋体">里关于</SPAN><SPAN lang=EN-US>Acegi</SPAN><SPAN style="FONT-FAMILY: 宋体">的那一章，对于想读</SPAN><SPAN lang=EN-US>Acegi</SPAN><SPAN style="FONT-FAMILY: 宋体">的源代码和了解</SPAN><SPAN lang=EN-US>Acegi</SPAN><SPAN style="FONT-FAMILY: 宋体">内部设计的人来说，这一章真是太有用了。</SPAN></P>
<P><IMG hspace=0 src="http://blog.itpub.net/resserver.php?blogId=1476&amp;resource=acegi1.gif&amp;mode=medium" align=baseline border=0></P>
<P></P>
<P><SPAN style="FONT-FAMILY: 宋体">本来不想贴这幅类图的，毕竟有盗版的嫌疑，但是发现有些东西不贴出来又说不清楚。整个认证功能的核心是</SPAN><SPAN lang=EN-US>Authentication</SPAN><SPAN style="FONT-FAMILY: 宋体">接口，我们只把</SPAN><SPAN lang=EN-US>Authentication</SPAN><SPAN style="FONT-FAMILY: 宋体">想象成一个包含用户基本信息的类就行了，它里面放了用户名、密码、这个用户的具体权限有哪些（当然具体的东西是由它的子类</SPAN><SPAN lang=EN-US>UsernamePasswordAuthenticationToken</SPAN><SPAN style="FONT-FAMILY: 宋体">实现的，其它类的存放的信息稍有不同，毕竟验证的方式还是多种多样的，我这里描述的所有东西</SPAN><SPAN lang=EN-US>Acegi</SPAN><SPAN style="FONT-FAMILY: 宋体">最常用的实现方式，而不考虑其它的东西，否则只会分散注意力，看了之后一头雾水）。</SPAN><SPAN lang=EN-US>Authentication</SPAN><SPAN style="FONT-FAMILY: 宋体">里还包含了一个</SPAN><SPAN lang=EN-US>GrantedAuthority</SPAN><SPAN style="FONT-FAMILY: 宋体">接口，今天暂且不讨论</SPAN><SPAN lang=EN-US>Authorization</SPAN><SPAN style="FONT-FAMILY: 宋体">的问题了，毕竟它与验证的流程是不相关的，而具体的细节又极复杂。</SPAN></P>
<P></P>
<P><SPAN style="FONT-FAMILY: 宋体">我们通过</SPAN><SPAN lang=EN-US>AuthenticationManager</SPAN><SPAN style="FONT-FAMILY: 宋体">这个接口来验证这个</SPAN><SPAN lang=EN-US>Authtication</SPAN><SPAN style="FONT-FAMILY: 宋体">对象的合法性，真正的验证过程看上去很悬，其实最后的实现无非是去数据库搜索一下是否存在这个用户，密码是否匹配（说的仍然是最常用的实现方式，呵呵），只是它设计的时候对象的关联比较巧妙，类图看熟了就会觉得没什么，真正查数据库的那个类是</SPAN><SPAN lang=EN-US>DaoAuthenticationProvider</SPAN><SPAN style="FONT-FAMILY: 宋体">。这个接口真正巧妙的地方是它执行后返回的结果是一个</SPAN><SPAN lang=EN-US>Authentication</SPAN><SPAN style="FONT-FAMILY: 宋体">，而不是用一个布尔值来表示验证成功或失败。</SPAN><SPAN lang=EN-US>Why? </SPAN><SPAN style="FONT-FAMILY: 宋体">记得当年在</SPAN><SPAN lang=EN-US>JavaEye</SPAN><SPAN style="FONT-FAMILY: 宋体">上有个讨论</SPAN><SPAN lang=EN-US>Exception</SPAN><SPAN style="FONT-FAMILY: 宋体">的贴子，</SPAN><SPAN lang=EN-US>robbin</SPAN><SPAN style="FONT-FAMILY: 宋体">认为用户安全认证应该用</SPAN><SPAN lang=EN-US>Checked Exception</SPAN><SPAN style="FONT-FAMILY: 宋体">来控制流程，更多的人认为密码错误是正常的事件流，返回布尔值更为恰当，这里不讨论这两种观点的对错，毕竟每个人站的角度不同，具体的情况也不同。</SPAN></P>
<P></P>
<P><SPAN style="FONT-FAMILY: 宋体">但是如果要实现认证的透明性，我们要用到的却是</SPAN><SPAN lang=EN-US>unchecked exception</SPAN><SPAN style="FONT-FAMILY: 宋体">，这个</SPAN><SPAN lang=EN-US>Exception</SPAN><SPAN style="FONT-FAMILY: 宋体">叫做</SPAN><SPAN lang=EN-US>AuthenticationException</SPAN><SPAN style="FONT-FAMILY: 宋体">（如果是</SPAN><SPAN lang=EN-US>authorization</SPAN><SPAN style="FONT-FAMILY: 宋体">会抛出</SPAN><SPAN lang=EN-US>AccessDeniedException,</SPAN><SPAN style="FONT-FAMILY: 宋体">不过道理类似），这真是奇妙的事，因为</SPAN><SPAN lang=EN-US>Exeception</SPAN><SPAN style="FONT-FAMILY: 宋体">是可以传递的，如果在本类里面处理不了这个</SPAN><SPAN lang=EN-US>Exception</SPAN><SPAN style="FONT-FAMILY: 宋体">，我们就会将这个</SPAN><SPAN lang=EN-US>Exception</SPAN><SPAN style="FONT-FAMILY: 宋体">抛给调用这个类的类，如此循环，直到有一个类可以处理它为止（对于</SPAN><SPAN lang=EN-US>Web</SPAN><SPAN style="FONT-FAMILY: 宋体">来说应该是在页面上提示登录出错信息）。没想到</SPAN><SPAN lang=EN-US>Exception</SPAN><SPAN style="FONT-FAMILY: 宋体">的这个种特性用在安全认证里如此的合适，权限不够？用户密码不对？我才不管呢，只要抛出个异常，最后会有人把它接住处理掉的。当然这里的另一个条件是</SPAN><SPAN lang=EN-US>Unchecked</SPAN><SPAN style="FONT-FAMILY: 宋体">，只有</SPAN><SPAN lang=EN-US>unchecked</SPAN><SPAN style="FONT-FAMILY: 宋体">才不会导致接口的污染，才能达到完全的透明性。</SPAN></P>
<P></P>
<P><SPAN style="FONT-FAMILY: 宋体">有了前面的基础接口，我们要提出下一个问题了，这个</SPAN><SPAN lang=EN-US>Authentication</SPAN><SPAN style="FONT-FAMILY: 宋体">对象应该存放在哪里？几乎每个做过</SPAN><SPAN lang=EN-US>Web</SPAN><SPAN style="FONT-FAMILY: 宋体">应用的人告诉我：</SPAN><SPAN lang=EN-US>HttpSession</SPAN><SPAN style="FONT-FAMILY: 宋体">。</SPAN><SPAN lang=EN-US>Acegi</SPAN><SPAN style="FONT-FAMILY: 宋体">也不例外，虽然还有其它的存放地点（要跟具体的</SPAN><SPAN lang=EN-US>Web</SPAN><SPAN style="FONT-FAMILY: 宋体">容器结合，会导致不兼容性，一般不提倡用）。但是我们马上会问下一个问题：我们怎么得到</SPAN><SPAN lang=EN-US>Authentication</SPAN><SPAN style="FONT-FAMILY: 宋体">对象？当然我们可以去</SPAN><SPAN lang=EN-US>HttpSession</SPAN><SPAN style="FONT-FAMILY: 宋体">里去取，但是很多时候我们在验证的是与</SPAN><SPAN lang=EN-US>Web</SPAN><SPAN style="FONT-FAMILY: 宋体">层无关的（比如要用户调用</SPAN><SPAN lang=EN-US>Service</SPAN><SPAN style="FONT-FAMILY: 宋体">层的权限或</SPAN><SPAN lang=EN-US>Domain Object</SPAN><SPAN style="FONT-FAMILY: 宋体">的权限）。我们必须用与</SPAN><SPAN lang=EN-US>Web</SPAN><SPAN style="FONT-FAMILY: 宋体">无关的</SPAN><SPAN lang=EN-US>API</SPAN><SPAN style="FONT-FAMILY: 宋体">来获取</SPAN><SPAN lang=EN-US>Authentication</SPAN><SPAN style="FONT-FAMILY: 宋体">。这让我们想起了什么？对，是</SPAN><SPAN lang=EN-US>Webwork</SPAN><SPAN style="FONT-FAMILY: 宋体">，</SPAN><SPAN lang=EN-US>Webwork</SPAN><SPAN style="FONT-FAMILY: 宋体">的</SPAN><SPAN lang=EN-US>Action</SPAN><SPAN style="FONT-FAMILY: 宋体">是完全与</SPAN><SPAN lang=EN-US>Web API</SPAN><SPAN style="FONT-FAMILY: 宋体">无关的，它的</SPAN><SPAN lang=EN-US>Request</SPAN><SPAN style="FONT-FAMILY: 宋体">里的参数自动</SPAN><SPAN lang=EN-US>populate</SPAN><SPAN style="FONT-FAMILY: 宋体">成了</SPAN><SPAN lang=EN-US>Action</SPAN><SPAN style="FONT-FAMILY: 宋体">的属性，但是我们仍然可以通过</SPAN><SPAN lang=EN-US>ActionContext</SPAN><SPAN style="FONT-FAMILY: 宋体">来获取这些信息。它是怎么做到的？是</SPAN><SPAN lang=EN-US>Threadlocal</SPAN><SPAN style="FONT-FAMILY: 宋体">，因为每个</SPAN><SPAN lang=EN-US>Web Request</SPAN><SPAN style="FONT-FAMILY: 宋体">都会使</SPAN><SPAN lang=EN-US>Web</SPAN><SPAN style="FONT-FAMILY: 宋体">容器生成一个新的线程来处理它的这个特性使我们可以将这些</SPAN><SPAN lang=EN-US>Web</SPAN><SPAN style="FONT-FAMILY: 宋体">的数据一股脑塞给</SPAN><SPAN lang=EN-US>Threadlocal</SPAN><SPAN style="FONT-FAMILY: 宋体">。这个存放</SPAN><SPAN lang=EN-US>Authentication</SPAN><SPAN style="FONT-FAMILY: 宋体">的对象叫做</SPAN><SPAN lang=EN-US>SecurityContext</SPAN><SPAN style="FONT-FAMILY: 宋体">，而把</SPAN><SPAN lang=EN-US>SecurityContext</SPAN><SPAN style="FONT-FAMILY: 宋体">放入</SPAN><SPAN lang=EN-US>Threadloal</SPAN><SPAN style="FONT-FAMILY: 宋体">或取出的则是</SPAN><SPAN lang=EN-US>SecurityContextHolder</SPAN><SPAN style="FONT-FAMILY: 宋体">，下面就是它的类图：</SPAN></P>
<P><IMG hspace=0 src="http://blog.itpub.net/resserver.php?blogId=1476&amp;resource=acegi2.gif&amp;mode=medium" align=baseline border=0></P>
<P></P>
<P><SPAN style="FONT-FAMILY: 宋体">讲完这些基础设施，我们就可以看具体的认证流程啦，真正的认证是一串的</SPAN><SPAN lang=EN-US>Filter</SPAN><SPAN style="FONT-FAMILY: 宋体">（对</SPAN><SPAN lang=EN-US>Servlet</SPAN><SPAN style="FONT-FAMILY: 宋体">容器熟悉的人应该都不要解释了）。只不过</SPAN><SPAN lang=EN-US>Acegi</SPAN><SPAN style="FONT-FAMILY: 宋体">在这些</SPAN><SPAN lang=EN-US>Filter</SPAN><SPAN style="FONT-FAMILY: 宋体">上稍微玩的点花招，因为一般的</SPAN><SPAN lang=EN-US>Filter</SPAN><SPAN style="FONT-FAMILY: 宋体">是不能定义在</SPAN><SPAN lang=EN-US>Spring</SPAN><SPAN style="FONT-FAMILY: 宋体">的</SPAN><SPAN lang=EN-US>ApplicationContext</SPAN><SPAN style="FONT-FAMILY: 宋体">里的，所以这用了一个代理的</SPAN><SPAN lang=EN-US>Filter</SPAN><SPAN style="FONT-FAMILY: 宋体">对象</SPAN><SPAN lang=EN-US>FilterToBeanProxy</SPAN><SPAN style="FONT-FAMILY: 宋体">将</SPAN><SPAN lang=EN-US>Filter</SPAN><SPAN style="FONT-FAMILY: 宋体">操作</SPAN><SPAN lang=EN-US>Delegate</SPAN><SPAN style="FONT-FAMILY: 宋体">给定义在</SPAN><SPAN lang=EN-US>ApplicationContext</SPAN><SPAN style="FONT-FAMILY: 宋体">里的</SPAN><SPAN lang=EN-US>Filter</SPAN><SPAN style="FONT-FAMILY: 宋体">。这个似乎跟主题无关，不过如果以后真有类似的需求的话，这倒是蛮管用的一招。当然还有</SPAN><SPAN lang=EN-US>FilterChainProxy</SPAN><SPAN style="FONT-FAMILY: 宋体">，它把一串的</SPAN><SPAN lang=EN-US>Filter</SPAN><SPAN style="FONT-FAMILY: 宋体">全部定义在一个</SPAN><SPAN lang=EN-US>bean</SPAN><SPAN style="FONT-FAMILY: 宋体">里，使配置简化了好多，呵呵。</SPAN></P>
<P></P>
<P><SPAN style="FONT-FAMILY: 宋体">我们来看看</SPAN><SPAN lang=EN-US>Filter</SPAN><SPAN style="FONT-FAMILY: 宋体">的一头一尾。头是</SPAN><SPAN lang=EN-US>httpSessionContextIntegrationFilter</SPAN><SPAN style="FONT-FAMILY: 宋体">，其实它的功能前面已经讨论过了，在执行前把</SPAN><SPAN lang=EN-US>HttpSession</SPAN><SPAN style="FONT-FAMILY: 宋体">里的</SPAN><SPAN lang=EN-US>Authentication</SPAN><SPAN style="FONT-FAMILY: 宋体">取出来放到</SPAN><SPAN lang=EN-US>SessionContextHolder</SPAN><SPAN style="FONT-FAMILY: 宋体">（</SPAN><SPAN lang=EN-US>Threadlocal</SPAN><SPAN style="FONT-FAMILY: 宋体">）里，在执行完毕后，把</SPAN><SPAN lang=EN-US>Authentication</SPAN><SPAN style="FONT-FAMILY: 宋体">塞回到</SPAN><SPAN lang=EN-US>HttpSession</SPAN><SPAN style="FONT-FAMILY: 宋体">。真正的实现代码有一堆，不过核心的代码无非就这么几行：</SPAN></P>
<P><SPAN lang=EN-US>Object contextFromSessionObject = httpSession.getAttribute(ACEGI_SECURITY_CONTEXT_KEY);</SPAN></P>
<P><SPAN lang=EN-US>SecurityContextHolder.setContext((SecurityContext) contextFromSessionObject);</SPAN></P>
<P><SPAN lang=EN-US>chain.doFilter(request, response);</SPAN></P>
<P><SPAN lang=EN-US>httpSession.setAttribute(ACEGI_SECURITY_CONTEXT_KEY,</SPAN><SPAN style="FONT-FAMILY: 宋体">，</SPAN><SPAN lang=EN-US>SecurityContextHolder.getContext());</SPAN></P>
<P></P>
<P><SPAN lang=EN-US>Filter</SPAN><SPAN style="FONT-FAMILY: 宋体">的尾是</SPAN><SPAN lang=EN-US>securityEnforcementFilter</SPAN><SPAN style="FONT-FAMILY: 宋体">，它的工作就是进真正的用户认证的流程控制了，具体的认证工作它会</SPAN><SPAN lang=EN-US>delegate</SPAN><SPAN style="FONT-FAMILY: 宋体">给</SPAN><SPAN lang=EN-US>FilterSecurityInterceptor</SPAN><SPAN style="FONT-FAMILY: 宋体">，但是不管怎么认证，结果无非是认证成功或失败，</SPAN><SPAN lang=EN-US>securityEnforcementFilter</SPAN><SPAN style="FONT-FAMILY: 宋体">只要管抓住异常再转到特定的页面就行了。下面就是这个类的信心代码：</SPAN></P>
<P><SPAN lang=EN-US><SPAN></SPAN>try {</SPAN></P>
<P><SPAN lang=EN-US><SPAN></SPAN>filterSecurityInterceptor.invoke(fi);</SPAN></P>
<P><SPAN lang=EN-US><SPAN></SPAN>}</SPAN></P>
<P><SPAN lang=EN-US><SPAN></SPAN>} catch (AuthenticationException authentication) {</SPAN></P>
<P><SPAN lang=EN-US><SPAN></SPAN><SPAN></SPAN>sendStartAuthentication(fi, authentication);</SPAN></P>
<P><SPAN lang=EN-US><SPAN></SPAN>} catch (AccessDeniedException accessDenied) {</SPAN></P>
<P><SPAN lang=EN-US><SPAN></SPAN>sendAccessDeniedError(fi, accessDenied);</SPAN></P>
<P><SPAN lang=EN-US><SPAN></SPAN>}</SPAN></P>
<P></P>
<P><SPAN style="FONT-FAMILY: 宋体">我们再来看看用户登录是怎么干的吧。</SPAN><SPAN lang=EN-US>Acegi</SPAN><SPAN style="FONT-FAMILY: 宋体">的用户登录很有意思，为了不让用户写任何这方面的代码，它也直接把这个功能放到</SPAN><SPAN lang=EN-US>Filter</SPAN><SPAN style="FONT-FAMILY: 宋体">里了，这个</SPAN><SPAN lang=EN-US>Filter</SPAN><SPAN style="FONT-FAMILY: 宋体">叫做</SPAN><SPAN lang=EN-US>authenticationProcessingFilter</SPAN><SPAN style="FONT-FAMILY: 宋体">。这个</SPAN><SPAN lang=EN-US>Filter</SPAN><SPAN style="FONT-FAMILY: 宋体">的要求是页面上的</SPAN><SPAN lang=EN-US>form</SPAN><SPAN style="FONT-FAMILY: 宋体">的</SPAN><SPAN lang=EN-US>Action</SPAN><SPAN style="FONT-FAMILY: 宋体">名字，登录名、密码的字段名都是定死的。一个简单的页面就这些啦：</SPAN></P>
<P><SPAN lang=EN-US>&lt;form action="&lt;c:url value=' j_acegi_security_check '/&gt;" method="POST"&gt;</SPAN></P>
<P><SPAN lang=EN-US>&lt;input type='text' &gt;</SPAN></P>
<P><SPAN lang=EN-US>&lt;input type='password' &gt;</SPAN></P>
<P><SPAN lang=EN-US>&lt;input type="submit"&gt;</SPAN></P>
<P><SPAN lang=EN-US>&lt;/form&gt;</SPAN></P>
<P><SPAN style="FONT-FAMILY: 宋体">记住</SPAN><SPAN lang=EN-US>action</SPAN><SPAN style="FONT-FAMILY: 宋体">必须叫</SPAN><SPAN lang=EN-US>j_acegi_security_check</SPAN><SPAN style="FONT-FAMILY: 宋体">，用户名必须叫</SPAN><SPAN lang=EN-US>j_username</SPAN><SPAN style="FONT-FAMILY: 宋体">，密码必须叫</SPAN><SPAN lang=EN-US>j_password</SPAN><SPAN style="FONT-FAMILY: 宋体">。呵呵，代码就不写了，无非就是判断只要</SPAN><SPAN lang=EN-US>Action</SPAN><SPAN style="FONT-FAMILY: 宋体">名字对，就把用户名、密码取出来认证一把，最后把认证成功的</SPAN><SPAN lang=EN-US>Authetication</SPAN><SPAN style="FONT-FAMILY: 宋体">对象填到</SPAN><SPAN lang=EN-US>SecurityContextHolder</SPAN><SPAN style="FONT-FAMILY: 宋体">里再导到相应页面，认证失败就导到出错页面。</SPAN></P>
<P></P>
<P><SPAN style="FONT-FAMILY: 宋体">呵呵，好了，认证的核心过程其实就这些了，虽然还有其它的好多的</SPAN><SPAN lang=EN-US>Filter</SPAN><SPAN style="FONT-FAMILY: 宋体">和关联，但是当我们把核心的内容分析清楚之后，其它的都不难了。（</SPAN><SPAN lang=EN-US>Authorization</SPAN><SPAN style="FONT-FAMILY: 宋体">是例外，有些部分我还没看明白）。</SPAN></P></SPAN>反正</div>]]></description>
	    <author><![CDATA[圈圈套圈圈]]></author>
	    <comments>http://xiecc.blog.163.com/blog/static/14032200671773359760</comments>
    <slash:comments>13</slash:comments>
    <guid isPermaLink="true">http://xiecc.blog.163.com/blog/static/14032200671773359760</guid>
    <pubDate>Thu, 17 Aug 2006 19:33:59 +0800</pubDate>
    <dcterms:modified>2006-08-17T19:33:59+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[被点到了]]></title>	
    <link>http://xiecc.blog.163.com/blog/static/14032200671482234105</link>
    <description><![CDATA[<div>记得去年比较流这个游戏，不知道今年还热不热，不过既然点到就玩一把吧。<br>1.什么使你最幸福? 一个心爱的老婆，一份热爱的工作<br>2.不开心会让什么方式使自己开心起来?&nbsp; 看看娱乐节目<br>3.最喜欢做什么?&nbsp; 一件事还真难答，要说写程序马上被人BS成书呆子，又不能说WS的事。只好说看电影和体育比赛，还有旅游吧<br>4.最向往什么?&nbsp; 可以写出Dave Thomas水准的书，做一个Dave Thomas那样的<span style="font-size: 10.5pt; font-weight: normal;"><span lang="EN-US">Pragmatic Programmer<br></span></span>5.此时最想对跟你提问的人说些什么? 承蒙老兄看得起，<img src="http://mimg.163.com/popo/smile04.gif"><br>下家给谁呢？ cg老大， 小鸟， ading姐，猪头这样在网易blog界威名赫赫的人物肯定不能少，冰河总是给我一种高深莫测的神秘感，一定要知道他的隐私，wy的技术偶比较佩服，剩下的留给tracystaring MM吧<br><br><br><br></div>]]></description>
	    <author><![CDATA[圈圈套圈圈]]></author>
	    <comments>http://xiecc.blog.163.com/blog/static/14032200671482234105</comments>
    <slash:comments>5</slash:comments>
    <guid isPermaLink="true">http://xiecc.blog.163.com/blog/static/14032200671482234105</guid>
    <pubDate>Mon, 14 Aug 2006 20:22:34 +0800</pubDate>
    <dcterms:modified>2006-08-14T20:22:34+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[技术牛人]]></title>	
    <link>http://xiecc.blog.163.com/blog/static/14032200671291655452</link>
    <description><![CDATA[<div><P>最近老被人叫做牛人, 心里好惭愧（seriously）。</P>
<P>其实公司里有好多牛人， 昨天听完wy的讲座，感觉自己很渺小。鸟对技术的敏锐性和知识面是偶无法比拟的。开发博客的那几个主力每个都是独挡一面的高手。还有象猪头那样精力过剩的程序高手，真是后生可畏啊。</P>
<P>不过也觉得很高兴，公司有这么牛人，何愁发展不起来？</P></div>]]></description>
	    <author><![CDATA[圈圈套圈圈]]></author>
	    <comments>http://xiecc.blog.163.com/blog/static/14032200671291655452</comments>
    <slash:comments>14</slash:comments>
    <guid isPermaLink="true">http://xiecc.blog.163.com/blog/static/14032200671291655452</guid>
    <pubDate>Sat, 12 Aug 2006 09:16:55 +0800</pubDate>
    <dcterms:modified>2006-08-12T09:16:55+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[我自己设计的中文分词算法]]></title>	
    <link>http://xiecc.blog.163.com/blog/static/14032200671110224190</link>
    <description><![CDATA[<div><P><STRONG><FONT style="BACKGROUND-COLOR: #330099" color=#0099ff size=4><FONT style="BACKGROUND-COLOR: #ffffff">我不是搞搜索专业的，当时毕设做了个简单的分词算法，就放到blog上。没想还有挺多人感兴趣的，记得那天点击量忽然达到2000（当时我的日点击量也就200），很多做搜索的人找我，说思路不错。也许我这辈子再也不搞搜索了，就把这篇文章放这留个纪念吧。</FONT><FONT style="BACKGROUND-COLOR: #ffffff"><FONT style="BACKGROUND-COLOR: #ffffff"><FONT style="BACKGROUND-COLOR: #ffffff"><FONT color=#330099></FONT></STRONG></FONT></FONT></FONT></FONT></P></FONT></FONT></FONT></FONT>
<P><STRONG><FONT color=#0099ff size=4></FONT></STRONG>&nbsp;</P>
<P><STRONG><FONT color=#ff6699 size=4>xiecc于2006年2月11日</FONT></STRONG></P>
<P><FONT size=4>最近折腾毕业论文，搞得人没心情写blog了。于是觉得不如把毕业论文里的东西贴出来当blog算了。这里主要介绍了我自己的中文分词算法，我觉得它比现在开源代码比较多的中文匹配法要好多了。这里的内容没有任何背景知识啥的，毕竟论文里的背景知道我也是从网上粘贴的，呵呵！因此这篇文章的内容可能适合做搜索引擎的人。如果要了解中文分词算法在搜索引擎中的重要性，或者最大匹配法的思想与过程，请去网上搜吧，资料还是蛮多的。</FONT><BR></P>
<P style="LINE-HEIGHT: 150%; 0pt: ">
</P><H3 style="TEXT-INDENT: 0pt; 0pt: "><FONT size=5><FONT face=黑体><SPAN lang=EN-US><SPAN>1.1.1</SPAN></SPAN><SPAN lang=EN-US> </SPAN></FONT></FONT><A><FONT face=黑体 color=#5a7594 size=5>最大匹配法分词的缺陷</FONT></A></H3>
<P style="LINE-HEIGHT: 150%; 0pt: "><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">尽管最大匹配法分词是常用的解决的方案，但是无疑它存在很多明显的缺陷，这些缺陷也限制了最大匹配法在大型搜索系统中的使用频率。最大匹配法的问题有以下几点：</SPAN></P>
<P style="LINE-HEIGHT: 150%; 0pt: "><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">一、长度限制</SPAN></P>
<P style="LINE-HEIGHT: 150%; 0pt: "><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">由于最大匹配法必须首先设定一个匹配词长的初始值，这个长度限制是最大匹配法在效率与词长之间的一种妥协。我们来看一下以下两种情况：</SPAN></P>
<P style="LINE-HEIGHT: 150%; 0pt: "><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">（</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%">1</SPAN><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">）词长过短，长词就会被切错。例如当词长被设成</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%">5</SPAN><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">时，也就意味着它只能分出长度为</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%">5</SPAN><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">以下词，例如当这个词为“中华人民共和国”长度为</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%">7</SPAN><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">的词时，我们只能取出其中的</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%">5</SPAN><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">个字去词库里匹配，例如“中华人民共”，显然词库里是不可能有这样的词存在的。因此我们无法下确的划分出“中华人民共和国”这样的词长大于</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%">5</SPAN><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">的词。</SPAN></P>
<P style="LINE-HEIGHT: 150%; 0pt: "><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">（</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%">2</SPAN><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">）词长过长，效率就比较低。也许有人会认为既然</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%">5</SPAN><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">个字无法满足我们的分词要求，何不将词长加大，例如加到</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%">10</SPAN><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">或者</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%">100</SPAN><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">，毕竟这个世界超过</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%">100</SPAN><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">个字长的词还是很少见的，我们的词长问题不就解决了？然而当词长过长时，我们却要付出另一方面的代价：效率。效率是分词算法、甚至是整个算法理论体系的关键，毕竟算法书里所有的高深的查询或排序算法都是从效率出发的，否则任何笨办法都可以解决分词效率低的问题。设想到我们把字长设成</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%">100</SPAN><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">个词时，我们必须将词从</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%">100</SPAN><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">开始一直往下匹配直到找到要查的字为止，而我们大多数词的字长却只有两三个字，这意味着前</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%">97</SPAN><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">次的匹配算法是徒劳的。</SPAN></P>
<P style="LINE-HEIGHT: 150%; 0pt: "><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">因此我们必须要在词长与效率之间进行妥协，既要求分词尽量准确，又要求我们的词长不能太长。尽管我们可能找到这样一个比较优化的字长值使两者都达到比较满足的状态，但是毕竟不管我们怎么设定，总会有些太长词分出来，或者带来效率问题。</SPAN></P>
<P style="LINE-HEIGHT: 150%; 0pt: ">
</P><P style="LINE-HEIGHT: 150%; 0pt: "><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">二、效率低</SPAN></P>
<P style="LINE-HEIGHT: 150%; 0pt: "><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">效率低是最大匹配法分词必然会来的问题。即使我们可以将字长设成相当短，例如</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%">5</SPAN><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">（注意，我们不能再缩短字长了，毕竟字长为</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%">5</SPAN><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">以上的词太多了，我们不能牺牲分词的准确），然而当我们的大数词长为</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%">2</SPAN><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">时，至少有</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%">3</SPAN><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">次的匹配算法是浪费掉的。回想一下算法书里提到的最简单的字符匹配与</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%">KMP</SPAN><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">算法之间天差地别的效率，我们知道通过某种方法，这些浪费的掉的匹配时间是可以补回来的。</SPAN></P>
<P style="LINE-HEIGHT: 150%; 0pt: ">
</P><P style="LINE-HEIGHT: 150%; 0pt: "><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">三、掩盖分词歧义</SPAN></P>
<P style="LINE-HEIGHT: 150%; 0pt: "><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">中文是如此复杂的语言，它的表达方式如此之多，语法文法如此精妙，机械的电脑是很难理解这么复杂的语言，因此它必然会带来歧意性，以下是两个简单的例子：</SPAN></P>
<P style="LINE-HEIGHT: 150%; 0pt: "><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%"><SPAN></SPAN>A.“</SPAN><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">有意见分歧</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%">”<SPAN> </SPAN></SPAN><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">（正向最大匹配和逆向最大匹配结果不同）</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%"><BR><SPAN></SPAN></SPAN><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">有意</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%">/<SPAN> </SPAN></SPAN><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">见</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%">/<SPAN> </SPAN></SPAN><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">分歧</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%">/</SPAN></P>
<P style="LINE-HEIGHT: 150%; 0pt: "><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%"><SPAN></SPAN></SPAN><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">有</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%">/<SPAN> </SPAN></SPAN><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">意见</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%">/<SPAN> </SPAN></SPAN><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">分歧</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%">/<BR>B.“</SPAN><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">结合成分子时</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%">” </SPAN><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">（正向最大匹配和逆向最大匹配结果相同）</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%"><BR><SPAN></SPAN></SPAN><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">结合</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%">/<SPAN> </SPAN></SPAN><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">成分</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%">/<SPAN> </SPAN></SPAN><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">子时</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%">/</SPAN><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">由于词的歧义性使我们在使用最大匹配法分词会产生错误的结果，而且使用正向分词与逆向分词往往会产生截然不同的结果。尽管使用回溯法或计算计算词的使用频率，可以使出现歧义的可能性减少，但是我们知道，这样的结果是不可避免的，因为中文的变化实在太多了。</SPAN></P>
<P style="LINE-HEIGHT: 150%; 0pt: ">
</P><P style="LINE-HEIGHT: 150%; 0pt: "><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">四、最大匹配的并不一定是想要的分词方式</SPAN></P>
<P style="LINE-HEIGHT: 150%; 0pt: "><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">最大匹配法基于的理念是找到最大的匹配词，但有的时候除了最大匹配词外，我们也可能只需要这个词的一部分。例如“感冒解毒胶囊”是一个完整的词，按照最大匹配法我们无法对它进行拆分了，这样我们输入“感冒”的时候就根本搜不到我们需要的词。这是我们需要的吗？做为生产这种药的厂商，它肯定希望用户输入“感冒”甚至“解毒”，我们都能查到对应的内容。</SPAN></P>
<P style="LINE-HEIGHT: 150%; 0pt: ">
</P><H2 style="TEXT-INDENT: 0pt; 18pt: "><FONT face=Arial><SPAN lang=EN-US><SPAN>1.2</SPAN></SPAN><SPAN lang=EN-US> </SPAN></FONT><A><SPAN style="FONT-FAMILY: 黑体"><FONT color=#5a7594 size=2>设计自己的中文分词算法</FONT></SPAN></A></H2>
<H3 style="TEXT-INDENT: 0pt; 0pt: "><FONT size=5><FONT face=黑体><SPAN lang=EN-US><SPAN>1.2.1</SPAN></SPAN><SPAN lang=EN-US> </SPAN></FONT></FONT><A><FONT face=黑体 color=#5a7594 size=5>设计目标</FONT></A></H3>
<P style="LINE-HEIGHT: 150%; 0pt: "><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">基于对分词算法的理解和对最大匹配法分词的分析，我们知道我们必须提出不同的解决方案，使分词算法的效率、分词的长度限制甚至歧义处理上得到提高。因此我们提出了如下的设计目标：</SPAN></P>
<P style="TEXT-INDENT: -21pt; LINE-HEIGHT: 150%"><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%"><SPAN>一、<SPAN> </SPAN></SPAN></SPAN><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">高效</SPAN></P>
<P style="LINE-HEIGHT: 150%; 0pt: "><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">中文分词算法必须要高效，毕竟效率对于搜索引擎的重要性是不言而喻的。而且我们面对的是海量的数据，而不是一篇几百字或几千字的文章，效率的差别的影响可能会使最后运行效率差几个小时甚至几天。因此我希望我们设计的算法一定要比最大匹配法高，毕竟我们已经常看到最大匹配法的很多次匹配都是浪费在无用功上了，肯定有办法把这些浪费的时间节省回来。</SPAN></P>
<P style="LINE-HEIGHT: 150%; 0pt: "><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">二、无长度限制</SPAN></P>
<P style="LINE-HEIGHT: 150%; 0pt: "><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">最大匹配法的长度限制真是很讨厌的事，我们很难找到词长与效率的之间的平衡。为什么我们需要长度的限制？为什么我们不能设计出任何词长的词（只要词库中存在）都可以分出来？</SPAN><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%"> </SPAN></P>
<P style="LINE-HEIGHT: 150%; 0pt: "><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">三、歧义包容</SPAN></P>
<P style="LINE-HEIGHT: 150%; 0pt: "><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">我们相信长度限制的问题总是可以解决的，因为虽然长度限制这个问题很难，但是它是有规律可循的，它是严谨的科学。但是当我们碰到中文歧义时，我知道不管我们怎么努力，它仍然是不可能彻底解决的。因为中文实在太博大精深了，即使有极强的人工智能和机器学习功能，这样的错误仍然是难以避免。既然无法避免？我们为什么不换一个角度去考虑？我们为什么不可以将出现歧义的各种可能性都包含进去，作为分词的参考。例如上述的“有意见分歧”的两种分词方法：</SPAN></P>
<P><SPAN lang=EN-US style="FONT-SIZE: 12pt"><SPAN></SPAN></SPAN><SPAN style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体">有意</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt">/<SPAN> </SPAN></SPAN><SPAN style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体">见</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt">/<SPAN> </SPAN></SPAN><SPAN style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体">分歧</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt">/</SPAN></P>
<P style="LINE-HEIGHT: 150%; 0pt: "><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%"><SPAN></SPAN></SPAN><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">有</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%">/<SPAN> </SPAN></SPAN><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">意见</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%">/<SPAN> </SPAN></SPAN><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">分歧</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%">/</SPAN></P>
<P style="LINE-HEIGHT: 150%; 0pt: "><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">为什么我们不能把这样两种结果都拿来分词呢？毕竟分词的目的是为了搜索，而不是为了教小孩读出。如果把两种分词的可能性都告诉搜索引擎，搜索引擎会很高兴的，因为这下不管是“有意”还是“意见”，它都可以搜到了。这就是我提出来另一个目标：歧义包容。</SPAN></P>
<P style="LINE-HEIGHT: 150%; 0pt: ">
</P><H3 style="TEXT-INDENT: 0pt; 0pt: "><FONT face=黑体><FONT size=5><SPAN lang=EN-US><SPAN>1.2.2</SPAN></SPAN><SPAN lang=EN-US> </SPAN></FONT></FONT><A><FONT face=黑体 color=#5a7594 size=5>算法的突破口</FONT></A><SPAN><FONT size=5><SPAN lang=EN-US style="FONT-FAMILY: ">—</SPAN><FONT face=黑体>词库</FONT></FONT></SPAN></H3>
<P style="LINE-HEIGHT: 150%; 0pt: "><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">虽然我们的目标已经确定下来了，但是要想出一个更好的算法却是非常难的事。毕竟算法需要的是灵感与突发奇想，这与系统的架构设计和面向对象的设计与编者编码刚好是相反的，象设计模式或重构这样的东西我们需要的实践、总结、再实践。而算法需要的却是当我们在山重水复疑无路的时候会换个角度思考。</SPAN></P>
<P style="LINE-HEIGHT: 150%; 0pt: "><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">但是分词算法的突破口在哪里呢？我们必须要有一个词库，我们必须将全文中的词与词库去匹配，这一切都是不可避免的。</SPAN></P>
<P style="LINE-HEIGHT: 150%; 0pt: "><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">真正要改善是就是我们的匹配过程，我们要减少匹配过程中的浪费，我们要解决匹配中的词长限制。但是我们有什么办法呢？每次的匹配我们必须要去词库中查找一次。怎么改善这样的做法？</SPAN></P>
<P style="LINE-HEIGHT: 150%; 0pt: "><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">我们总是把优化的思路定格在更好的匹配算法，更好地处理词条和全文。但是真正束缚我们的却是词库！是基于关系数据库的词库，我们需要的对词库的改造，我们要让我们的词库更适合用于匹配与分词！</SPAN></P>
<P style="LINE-HEIGHT: 150%; 0pt: "><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">这是几十年来关系数据库带给我们的思维：我们查找的词是数据库的某条记录，通过表格与关系代数，我们总能找到这个词。但是正是关系数据库的这种思维束缚着我们，关系数据库让我们的数据结构及关联表达得清楚又简单，并使某些查询的效率变得很高。但是这不适用于中文分词，有的时候退到几十年前流行的数据库模型也许更适合。这就是层次数据库。</SPAN></P>
<P style="LINE-HEIGHT: 150%; 0pt: "><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">我们要做的是将关系数据库的词按字打散，并存放到层次数据库中。以下就是一个示例：</SPAN></P>
<P style="LINE-HEIGHT: 150%; 0pt: "><IMG hspace=0 src="http://xiecc.itpub.net/resserver.php?blogId=1476&amp;resource=%B7%D6%B4%CA%B4%CA%BF%E2.gif&amp;mode=medium" align=baseline border=0></P>
<P style="LINE-HEIGHT: 150%; 0pt: ">
</P><P style="LINE-HEIGHT: 150%; 0pt: "><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">红色的字表示树上面的字串是可以单独组成一个词的，例如“感冒”它本身是词库里可以找到的词，所有红色的表示的是终止符。而黄色则表示树上面的字串是无法单独成词的，例如“感冒解”是不存在的词。</SPAN></P>
<P style="LINE-HEIGHT: 150%; 0pt: "><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">真的很奇妙，词库经过这样的改装后，所有的匹配的思维都变掉了。任何一个句子都会打散成单字去与树状结构的单字去匹配，词的长度变成了树的高度，每一次的匹配变成了树的遍历，而这种遍历的效率竟然都是线性的！</SPAN></P>
<P style="LINE-HEIGHT: 150%; 0pt: ">
</P><H3 style="TEXT-INDENT: 0pt; 0pt: "><FONT size=5><FONT face=黑体><SPAN lang=EN-US><SPAN>1.2.3</SPAN></SPAN><SPAN lang=EN-US> </SPAN></FONT></FONT><A><FONT face=黑体 color=#5a7594 size=5>中文分词算法设计</FONT></A></H3>
<P style="LINE-HEIGHT: 150%; 0pt: "><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">有了以上的中文词库后，我们分词算法设计就水到渠成的。首先我们来看一下分词的步骤：</SPAN></P>
<P style="LINE-HEIGHT: 150%; 0pt: "><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">（</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%">1</SPAN><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">）首先将要分的全文按标点符号打散成一个一个的句子。这算是预处理的一个步骤，目的是让我们处理的句子短，效率更高。毕竟中间有标点符号的词是不存在的。（注：真正实现时我们是基于</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%">lucene</SPAN><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">的</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%">SimpleAnalyzer</SPAN><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">来做的，因为</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%">SimpleAnalyzer</SPAN><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">本身就是为了将全文打散成句子，因此我们没必要耗费体力去实现这一步）。</SPAN></P>
<P style="LINE-HEIGHT: 150%; 0pt: "><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">（</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%">2</SPAN><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">）我们开始将要处理的句子在树状结构中遍历，如果找到匹配的就继续，如果遇到红色的终止符，我们就发现这个词是一个完整的词了，这样我们就可以把这个词作为一个一个分词了。</SPAN></P>
<P style="LINE-HEIGHT: 150%; 0pt: "><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">（</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%">3</SPAN><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">）从分词后的下一字开始继续做步骤</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%">2</SPAN><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">这样的遍历，如此循环往复就将词分完了。</SPAN></P>
<P style="LINE-HEIGHT: 150%; 0pt: "><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">可以看到，我们字符匹配效率几乎是线性的！我们所要做的只是取出每一个字去树上找到相应的匹配，每次的匹配代价都是</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%">O(1)</SPAN><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">（如果词库用</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%">Hash</SPAN><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">表的话），这样匹配下来的时间复杂度就是字符串本身的长度！对于一个长度为</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%">n</SPAN><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">的字符串来说，它的分词复杂度是</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%">O(n)</SPAN><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">。而最大匹配的平均复杂度是</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%">O(n<SUP>2</SUP>)</SPAN><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">。</SPAN></P>
<P style="LINE-HEIGHT: 150%; 0pt: "><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">当然我们这里没有考虑歧义包容与分支处理等情况，但即使加上这些我们复杂度仍然是有限的。</SPAN></P>
<P style="LINE-HEIGHT: 150%; 0pt: ">
</P><H3 style="TEXT-INDENT: 0pt; 0pt: "><FONT size=5><FONT face=黑体><SPAN lang=EN-US><SPAN>1.2.4</SPAN></SPAN><SPAN lang=EN-US> </SPAN></FONT></FONT><A><FONT face=黑体 color=#5a7594 size=5>中文分词算法的实现细节</FONT></A></H3>
<P style="LINE-HEIGHT: 150%; 0pt: "><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">一、建立词库</SPAN></P>
<P style="LINE-HEIGHT: 150%; 0pt: "><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">有了改装词库的基本思想后，建立词库的步骤变得很简单，但是仍然会有好多的细节需要注意。</SPAN></P>
<P style="LINE-HEIGHT: 150%; 0pt: "><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">首先是词库的保存格式。现在最常用的保存数据的方式当然是关系数据库，其次是文件系统中的二进制文件。显然关系数据库对于我们并不适用，而自定义的二进制文件则实现起来比较困难，而且读写的效率也会有问题。因为我们想到了最简单的方法是利用</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%">java</SPAN><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">的</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%">serialization</SPAN><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">的功能，把整个内存中的树状结构直接序列化成磁盘的文本文件是最方便的！而且读写的效率也会相当的高。</SPAN></P>
<P style="LINE-HEIGHT: 150%; 0pt: "><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">第二个问题是树的父子节点的导航。我们的树并不是一颗二叉树，父亲的子节点会有好多！尤其是第一层，我们会把词库中所有的首字都取出来作为根节点的子节点，这意味着如果首字有</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%">4000</SPAN><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">个的话，根节点就有</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%">4000</SPAN><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">个儿子。当然随着树层数的增多，节点的儿子数也会减少，毕竟以“感冒”开头的词在整个词库也只有四十多个，而以“感冒清”开头的词则只有两三个了。这意味着如果设计得不合理，我们树的匹配遍历过程并不完全是线性的。最坏的查找算法是</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%">O(N)</SPAN><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">（</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%">N</SPAN><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">代表儿子数）。当然如果我们建词库时将儿子有序排列，再按照二分查找的方法，则我们的复杂度会减到</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%">O(lgN)</SPAN><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">，这样的复杂度已经可以接受了。但是还有更简单又更快的存储方式，为什么不使用呢？那就是</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%">HashMap</SPAN><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">，毕竟在</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%">HashMap</SPAN><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">里查找东西时它的效率几乎是线性的，而且实现起来要比二分查询简单得多。当然用</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%">HashMap</SPAN><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">要付出存储空间变大的代价，但这样的代价来换取速度与简单性也是的。</SPAN></P>
<P style="LINE-HEIGHT: 150%; 0pt: "><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">第三个问题是找到有终结符的字后，我们必须要将它建成一个完整的词。这时我们必须能从字个往上回溯，直到找到根结点。因此我们在每个节点里都保存了父节点的指针。</SPAN></P>
<P style="LINE-HEIGHT: 150%; 0pt: ">
</P><P style="LINE-HEIGHT: 150%; 0pt: "><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">有了以上的设计思想，我们就动手建立了我们的词库，词库的来源是中医药数据库的词汇表，因为我们应用一直是围绕中医药的。我们找到了两个最重要的表，这两个表几乎包含了中医药的全部词库：</SPAN></P>
<P style="TEXT-INDENT: 12pt; LINE-HEIGHT: 150%; 0pt: "><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">一体化语言系统词库</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%"><SPAN> </SPAN>92112</SPAN><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">个词</SPAN></P>
<P style="TEXT-INDENT: 18pt; LINE-HEIGHT: 150%; 0pt: "><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">疾病大全、症状、证候</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%"> 20879</SPAN><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">个词</SPAN></P>
<P style="LINE-HEIGHT: 150%; 0pt: "><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">最后生成的词库是</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%">java serialization</SPAN><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">的一个文件，文件的大小是</SPAN>16M<SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%"> </SPAN><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">。当然这跟我们采用</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%">HashMap</SPAN><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">存放父子关联有关，也跟</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%">java</SPAN><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">的对象所占空间有关，虽然将词库按这种方式存放实际上也对词库进行了压缩（以“感”开头的字有数十个，关系数据库里就要保存数十个，但我们在词库只保存了一个“感”）。但文件仍然偏大，因此用</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%">oracle</SPAN><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">将这两个表导出后生成的文件大小是</SPAN>4M<SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">。不过这个大小仍然是可以接受的，毕竟效率才是关键。</SPAN></P>
<P style="LINE-HEIGHT: 150%; 0pt: ">
</P><P style="TEXT-INDENT: -21pt; LINE-HEIGHT: 150%"><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%"><SPAN>二、<SPAN> </SPAN></SPAN></SPAN><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">分词查询</SPAN></P>
<P style="LINE-HEIGHT: 150%; 0pt: "><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">虽然刚才对分词算法进行了描述，但实际上实现的时候我们还会碰到很多问题。</SPAN></P>
<P style="TEXT-INDENT: -18pt; LINE-HEIGHT: 150%"><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%"><SPAN>1、</SPAN></SPAN><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">分支处理。</SPAN></P>
<P style="LINE-HEIGHT: 150%; 0pt: "><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">这是分词算法时歧义包容所必然碰到的问题。为了歧义包容，我们采用了与最大分词法完全不同的理念，我们的理念是将词库中存在词全部收入囊中！而且会发生重叠。例如“感冒解毒胶囊”，由于词库里存在“感冒”、“解毒”和“感冒解毒胶囊”这三个词，因此在分词的时候，我们会分别分出这三个词，这样用户无论输入“感冒”、“解毒”或“感冒解毒胶囊”搜索引擎都会找到相应的结果。</SPAN></P>
<P style="LINE-HEIGHT: 150%; 0pt: "><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">因此当遇到分支时，我们会分解成两条路线！例如当我们匹配到“感冒”的“冒”时，我们会发现一个终止符，代表“感冒”是一个完整的字，将它收录到分词中。接下来我们会分成两支，一支是继续往下走，匹配树的下一层，因为“冒”不是树的叶子，往下走可能会碰到更大的匹配词，例如“感冒解毒胶囊”。而另一支则从根开始，直接用“解”去匹配树的第一层节点，最后发现了“解毒”也是其中的一个词。</SPAN></P>
<P style="LINE-HEIGHT: 150%; 0pt: "><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%">2</SPAN><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">、动态规划法</SPAN></P>
<P style="LINE-HEIGHT: 150%; 0pt: "><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">分支虽然使我们可以消除很多的歧义，但是显然它会带来副作用：导致分词的复杂度变大。如果一个句子很长时，分词的变化也许会呈指数级的增长，从一开始的两个分支变成四个、八个甚至更多。我们会发现很多句子虽然会有很多分支，但是这些分支又经常会汇聚到一个点，变成一个分支。例如：“感冒解毒胶囊可以治感冒”，我们在分词的时候可能会出现“感冒”，“解毒”，“感冒解毒”，“感冒解毒胶囊”等多个分支，但是当我们到达“囊”这个点的时候，所有的分支又会汇集到一起，因为大家接下来要处理的都是“可以治感冒”这个字符串。如果有办法让我们在汇聚以后只处理一个分支，那么算法的时间复杂度就不会象原来想象的那么坏。</SPAN></P>
<P style="LINE-HEIGHT: 150%; 0pt: "><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">而这刚好是动态规划法发挥威力的时候，动态规划要解决的问题是</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%">Overlapping sub-problem</SPAN><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">。它的处理方法就是将所有的子问题记录在公有的变量里（这里指的是类变量，它相对于某个</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%">method</SPAN><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">来说是公有变量，而不是真的全局变量）。当我遇到的子问题已经被处理过一次了，就直接跳过。这样节约的结果可以使算法复杂度得到质的改变，当然由于中文的变化多端，我们无法精确估计使用动态规划法后算法复杂度得到了多大的提高。</SPAN></P>
<P style="LINE-HEIGHT: 150%; 0pt: "><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">实际上的动态规划法的实现起来比说起来反而简单，我们只是简单地放了一个</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%">HashSet</SPAN><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">来存放已经分词过的位置：</SPAN></P>
<P style="LINE-HEIGHT: 150%; 0pt: ">
</P><P style="LINE-HEIGHT: 150%; 0pt: "><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">然后判断的函数也相当的简单：</SPAN></P>
<P style="LINE-HEIGHT: 150%; 0pt: ">
</P><P style="LINE-HEIGHT: 150%; 0pt: "><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">最后在分词的递归函数中加入这一句判断：</SPAN></P>
<P style="LINE-HEIGHT: 150%; 0pt: ">
</P><P style="LINE-HEIGHT: 150%; 0pt: "><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">当这个位置已经被处理过了就直接返回了。</SPAN></P>
<P style="LINE-HEIGHT: 150%; 0pt: ">
</P><P style="LINE-HEIGHT: 150%; 0pt: "><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%">3</SPAN><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">、词库预</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%">load</SPAN></P>
<P style="LINE-HEIGHT: 150%; 0pt: "><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">在使用基于词库的方法时，我们必须要面临的一个问题是：必要将词库读到内存中，而这通常会耗费很长的时间，幸运的是这样的工作我们只需要做一次，当我们将词库</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%">load</SPAN><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">进来以后，所有的工作都会在内存中进行，分词的速度会得到极速提升。我们选择的词库预</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%">load</SPAN><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">时机是我们第一次进行分词时，这相当于</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%">lazy load</SPAN><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">，只有用到的时候我们才去初始化。</SPAN></P>
<P style="LINE-HEIGHT: 150%; 0pt: ">
</P><P style="LINE-HEIGHT: 150%; 0pt: "><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">讲完算法，我们来看看分词部分的实现代码，实际上这部分的内容实现起来远比想中简单。在处理的过程中，我们对给每个句子（实际是</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%">lucene</SPAN><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">里用</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%">SimpleAnalyzer</SPAN><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">分词后的一个个</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%">Token</SPAN><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">）都新建一个</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%">ChineseSplitter</SPAN><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">，这是更加面向对象的做法，使我们处理起来更加方便简洁，因为我们会发现如果用一个</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%">Singleton</SPAN><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">的</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%">ChineseSplitter</SPAN><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">时，它的变量无法共享会导致整个</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%">Splitter</SPAN><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">里的递归方法跟上一堆的参数，容易出错，而且无法调试。代码如下：</SPAN></P>
<P style="LINE-HEIGHT: 150%; 0pt: ">
</P><P style="LINE-HEIGHT: 150%; 0pt: "><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">代码简单明了，只是做了词库预</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%">load</SPAN><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">的工作后就将实际的分词工作交给了</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%">ChineseSplitter</SPAN><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">。</SPAN></P>
<P style="LINE-HEIGHT: 150%; 0pt: "><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%">ChineseSplitter</SPAN><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">的核心功能实际上将句子中词典中能找到的词放到一个队列中，这中队列里提供了分词以后的所有词的信息：</SPAN></P>
<P style="LINE-HEIGHT: 150%; 0pt: ">
</P><P style="LINE-HEIGHT: 150%; 0pt: "><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">下面是分词的核心算法：</SPAN></P>
<P style="LINE-HEIGHT: 150%; 0pt: "><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体"><IMG hspace=0 src="http://xiecc.itpub.net/resserver.php?blogId=1476&amp;resource=Snap7.gif&amp;mode=medium" align=baseline border=0></SPAN></P>
<P style="LINE-HEIGHT: 150%; 0pt: ">
</P><P style="LINE-HEIGHT: 150%; 0pt: "><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">它是一个递归的过程，初始时我们调用的参数里</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%">pos</SPAN><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">为</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%">0</SPAN><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">，这样它就会一级一级递归下去并将所有可能的分词放入到</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%">tokenQueue</SPAN><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">里。</SPAN></P>
<P style="LINE-HEIGHT: 150%; 0pt: ">
</P><H3 style="TEXT-INDENT: 0pt; 0pt: "><FONT size=5><FONT face=黑体><SPAN lang=EN-US><SPAN>1.2.5</SPAN></SPAN><SPAN lang=EN-US> </SPAN></FONT></FONT><A><FONT face=黑体 color=#5a7594 size=5>中文分词的实验结果</FONT></A></H3>
<P style="LINE-HEIGHT: 150%; 0pt: "><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%">1</SPAN><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">、实验</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%">1</SPAN><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">——短文分词</SPAN></P>
<P style="LINE-HEIGHT: 150%; 0pt: "><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">在第一个实验中我们选了一篇</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%">2000</SPAN><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">字的文章（是关于中医药的专业论文）。然后用三种</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%">Analyzer</SPAN><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">对它进行处理，以下是实验结果：</SPAN></P>
<TABLE style="BORDER-RIGHT: medium none; BORDER-TOP: medium none; BORDER-LEFT: medium none; BORDER-BOTTOM: medium none; BORDER-COLLAPSE: collapse" cellSpacing=0 cellPadding=0 border=1>
<TBODY>
<TR>
<TD style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0pt; BORDER-LEFT: windowtext 1pt solid; WIDTH: 142pt; PADDING-TOP: 0pt; BORDER-BOTTOM: windowtext 1pt solid; BACKGROUND-COLOR: transparent" vAlign=top width=189>
<P style="LINE-HEIGHT: 150%; TEXT-ALIGN: center; 0pt: " align=center><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%">Analyzer</SPAN></P></TD>
<TD style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 5.4pt; BORDER-LEFT-COLOR: #e0dfe3; PADDING-BOTTOM: 0pt; WIDTH: 115.4pt; PADDING-TOP: 0pt; BORDER-BOTTOM: windowtext 1pt solid; BACKGROUND-COLOR: transparent" vAlign=top width=154>
<P style="LINE-HEIGHT: 150%; TEXT-ALIGN: center; 0pt: " align=center><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">分词算法</SPAN></P></TD>
<TD style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 5.4pt; BORDER-LEFT-COLOR: #e0dfe3; PADDING-BOTTOM: 0pt; WIDTH: 168.7pt; PADDING-TOP: 0pt; BORDER-BOTTOM: windowtext 1pt solid; BACKGROUND-COLOR: transparent" vAlign=top width=225>
<P style="LINE-HEIGHT: 150%; TEXT-ALIGN: center; 0pt: " align=center><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">耗时</SPAN></P></TD></TR>
<TR>
<TD style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0pt; BORDER-LEFT: windowtext 1pt solid; WIDTH: 142pt; BORDER-TOP-COLOR: #e0dfe3; PADDING-TOP: 0pt; BORDER-BOTTOM: windowtext 1pt solid; BACKGROUND-COLOR: transparent" vAlign=top width=189>
<P style="LINE-HEIGHT: 150%; 0pt: "><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%">SimpleAnalyzer</SPAN></P></TD>
<TD style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; PADDING-LEFT: 5.4pt; BORDER-LEFT-COLOR: #e0dfe3; PADDING-BOTTOM: 0pt; WIDTH: 115.4pt; BORDER-TOP-COLOR: #e0dfe3; PADDING-TOP: 0pt; BORDER-BOTTOM: windowtext 1pt solid; BACKGROUND-COLOR: transparent" vAlign=top width=154>
<P style="LINE-HEIGHT: 150%; 0pt: "><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">将文章按标点符号隔开成句子</SPAN></P></TD>
<TD style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; PADDING-LEFT: 5.4pt; BORDER-LEFT-COLOR: #e0dfe3; PADDING-BOTTOM: 0pt; WIDTH: 168.7pt; BORDER-TOP-COLOR: #e0dfe3; PADDING-TOP: 0pt; BORDER-BOTTOM: windowtext 1pt solid; BACKGROUND-COLOR: transparent" vAlign=top width=225>
<P style="LINE-HEIGHT: 150%; 0pt: "><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%">47ms</SPAN></P></TD></TR>
<TR>
<TD style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0pt; BORDER-LEFT: windowtext 1pt solid; WIDTH: 142pt; BORDER-TOP-COLOR: #e0dfe3; PADDING-TOP: 0pt; BORDER-BOTTOM: windowtext 1pt solid; BACKGROUND-COLOR: transparent" vAlign=top width=189>
<P style="LINE-HEIGHT: 150%; 0pt: "><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%">StandardAnalyzer</SPAN></P></TD>
<TD style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; PADDING-LEFT: 5.4pt; BORDER-LEFT-COLOR: #e0dfe3; PADDING-BOTTOM: 0pt; WIDTH: 115.4pt; BORDER-TOP-COLOR: #e0dfe3; PADDING-TOP: 0pt; BORDER-BOTTOM: windowtext 1pt solid; BACKGROUND-COLOR: transparent" vAlign=top width=154>
<P style="LINE-HEIGHT: 150%; 0pt: "><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">将文章的中文字分成一个一个的单字</SPAN></P></TD>
<TD style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; PADDING-LEFT: 5.4pt; BORDER-LEFT-COLOR: #e0dfe3; PADDING-BOTTOM: 0pt; WIDTH: 168.7pt; BORDER-TOP-COLOR: #e0dfe3; PADDING-TOP: 0pt; BORDER-BOTTOM: windowtext 1pt solid; BACKGROUND-COLOR: transparent" vAlign=top width=225>
<P style="LINE-HEIGHT: 150%; 0pt: "><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%">250ms</SPAN></P></TD></TR>
<TR>
<TD style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0pt; BORDER-LEFT: windowtext 1pt solid; WIDTH: 142pt; BORDER-TOP-COLOR: #e0dfe3; PADDING-TOP: 0pt; BORDER-BOTTOM: windowtext 1pt solid; BACKGROUND-COLOR: transparent" vAlign=top width=189>
<P style="LINE-HEIGHT: 150%; 0pt: "><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%">ChineseAnalyzer</SPAN></P></TD>
<TD style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; PADDING-LEFT: 5.4pt; BORDER-LEFT-COLOR: #e0dfe3; PADDING-BOTTOM: 0pt; WIDTH: 115.4pt; BORDER-TOP-COLOR: #e0dfe3; PADDING-TOP: 0pt; BORDER-BOTTOM: windowtext 1pt solid; BACKGROUND-COLOR: transparent" vAlign=top width=154>
<P style="LINE-HEIGHT: 150%; 0pt: "><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">我们的分词算法</SPAN></P></TD>
<TD style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; PADDING-LEFT: 5.4pt; BORDER-LEFT-COLOR: #e0dfe3; PADDING-BOTTOM: 0pt; WIDTH: 168.7pt; BORDER-TOP-COLOR: #e0dfe3; PADDING-TOP: 0pt; BORDER-BOTTOM: windowtext 1pt solid; BACKGROUND-COLOR: transparent" vAlign=top width=225>
<P style="LINE-HEIGHT: 150%; 0pt: "><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">词库没</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%">preload: 13359ms , </SPAN><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">词库</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%">preload: 63ms</SPAN></P></TD></TR></TBODY></TABLE>
<P style="LINE-HEIGHT: 150%; 0pt: "><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">我们没有找到最大匹配法分词可用的开源代码，因此只能用</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%">SimpleAnalyzer</SPAN><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">和</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%">StandardAnalyzer</SPAN><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">与之比较。这两种算法事实上是根本没有去查词库的，因此也不会按任何语义去分词，</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%">SimpleAnalyzer</SPAN><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">只是简单地将文章按标点符号隔开成句子，而</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%">StandardAnalyzer</SPAN><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">则只是简单地将文章的中文字分成一个一个的单字。结果确实让人惊讶，当词库</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%">preload</SPAN><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">以后，我们的分词速度竟然远超不需要查任何词库的</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%">StandardAnalyzer</SPAN><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">算法！</SPAN></P>
<P style="LINE-HEIGHT: 150%; 0pt: ">
</P><P style="LINE-HEIGHT: 150%; 0pt: "><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%">2</SPAN><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">、实验</SPAN><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%">2</SPAN><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">——建索引</SPAN></P>
<P style="LINE-HEIGHT: 150%; 0pt: "><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">这是将分词算法应用到我们的索引系统后的效果比较，我们的数据源是来自中医药数据库的几十张表，一共有九十万条记录：</SPAN></P>
<TABLE style="BORDER-RIGHT: medium none; BORDER-TOP: medium none; BORDER-LEFT: medium none; BORDER-BOTTOM: medium none; BORDER-COLLAPSE: collapse" cellSpacing=0 cellPadding=0 border=1>
<TBODY>
<TR>
<TD style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0pt; BORDER-LEFT: windowtext 1pt solid; WIDTH: 142pt; PADDING-TOP: 0pt; BORDER-BOTTOM: windowtext 1pt solid; BACKGROUND-COLOR: transparent" vAlign=top width=189>
<P style="LINE-HEIGHT: 150%; TEXT-ALIGN: center; 0pt: " align=center><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%">Analyzer</SPAN></P></TD>
<TD style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 5.4pt; BORDER-LEFT-COLOR: #e0dfe3; PADDING-BOTTOM: 0pt; WIDTH: 115.4pt; PADDING-TOP: 0pt; BORDER-BOTTOM: windowtext 1pt solid; BACKGROUND-COLOR: transparent" vAlign=top width=154>
<P style="LINE-HEIGHT: 150%; TEXT-ALIGN: center; 0pt: " align=center><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">分词算法</SPAN></P></TD>
<TD style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 5.4pt; BORDER-LEFT-COLOR: #e0dfe3; PADDING-BOTTOM: 0pt; WIDTH: 168.7pt; PADDING-TOP: 0pt; BORDER-BOTTOM: windowtext 1pt solid; BACKGROUND-COLOR: transparent" vAlign=top width=225>
<P style="LINE-HEIGHT: 150%; TEXT-ALIGN: center; 0pt: " align=center><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">耗时</SPAN></P></TD></TR>
<TR>
<TD style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0pt; BORDER-LEFT: windowtext 1pt solid; WIDTH: 142pt; BORDER-TOP-COLOR: #e0dfe3; PADDING-TOP: 0pt; BORDER-BOTTOM: windowtext 1pt solid; BACKGROUND-COLOR: transparent" vAlign=top width=189>
<P style="LINE-HEIGHT: 150%; 0pt: "><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%">StandardAnalyzer</SPAN></P></TD>
<TD style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; PADDING-LEFT: 5.4pt; BORDER-LEFT-COLOR: #e0dfe3; PADDING-BOTTOM: 0pt; WIDTH: 115.4pt; BORDER-TOP-COLOR: #e0dfe3; PADDING-TOP: 0pt; BORDER-BOTTOM: windowtext 1pt solid; BACKGROUND-COLOR: transparent" vAlign=top width=154>
<P style="LINE-HEIGHT: 150%; 0pt: "><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">将文章的中文字分成一个一个的单字</SPAN></P></TD>
<TD style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; PADDING-LEFT: 5.4pt; BORDER-LEFT-COLOR: #e0dfe3; PADDING-BOTTOM: 0pt; WIDTH: 168.7pt; BORDER-TOP-COLOR: #e0dfe3; PADDING-TOP: 0pt; BORDER-BOTTOM: windowtext 1pt solid; BACKGROUND-COLOR: transparent" vAlign=top width=225>
<P style="LINE-HEIGHT: 150%; 0pt: "><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%">35</SPAN><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">分钟</SPAN></P></TD></TR>
<TR>
<TD style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0pt; BORDER-LEFT: windowtext 1pt solid; WIDTH: 142pt; BORDER-TOP-COLOR: #e0dfe3; PADDING-TOP: 0pt; BORDER-BOTTOM: windowtext 1pt solid; BACKGROUND-COLOR: transparent" vAlign=top width=189>
<P style="LINE-HEIGHT: 150%; 0pt: "><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%">ChineseAnalyzer</SPAN></P></TD>
<TD style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; PADDING-LEFT: 5.4pt; BORDER-LEFT-COLOR: #e0dfe3; PADDING-BOTTOM: 0pt; WIDTH: 115.4pt; BORDER-TOP-COLOR: #e0dfe3; PADDING-TOP: 0pt; BORDER-BOTTOM: windowtext 1pt solid; BACKGROUND-COLOR: transparent" vAlign=top width=154>
<P style="LINE-HEIGHT: 150%; 0pt: "><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">我们的分词算法</SPAN></P></TD>
<TD style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; PADDING-LEFT: 5.4pt; BORDER-LEFT-COLOR: #e0dfe3; PADDING-BOTTOM: 0pt; WIDTH: 168.7pt; BORDER-TOP-COLOR: #e0dfe3; PADDING-TOP: 0pt; BORDER-BOTTOM: windowtext 1pt solid; BACKGROUND-COLOR: transparent" vAlign=top width=225>
<P style="LINE-HEIGHT: 150%; 0pt: "><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%">31</SPAN><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">分钟</SPAN></P></TD></TR></TBODY></TABLE>
<P style="LINE-HEIGHT: 150%; 0pt: "><SPAN style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体">由于建索引时数据库的查询操作会耗费很多的时间，因此两者的差别不是太明显，但结果至少说明了我们的分词效率确实是很高。</SPAN></P></div>]]></description>
	    <author><![CDATA[圈圈套圈圈]]></author>
	    <comments>http://xiecc.blog.163.com/blog/static/14032200671110224190</comments>
    <slash:comments>21</slash:comments>
    <guid isPermaLink="true">http://xiecc.blog.163.com/blog/static/14032200671110224190</guid>
    <pubDate>Fri, 11 Aug 2006 22:22:04 +0800</pubDate>
    <dcterms:modified>2006-08-11T22:22:04+08:00</dcterms:modified>
  </item>    
 </channel>
</rss>