<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0">

  <title><![CDATA[Log4D]]></title>
  
  <link href="http://log4d.com/" />
  <updated>2012-05-30T22:46:44+08:00</updated>
  <id>http://log4d.com/</id>
  <author>
    <name><![CDATA[alswl]]></name>
    
  </author>
  <generator uri="http://octopress.org/">Octopress</generator>

  
  <atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/dddspace" /><feedburner:info uri="dddspace" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry>
    <title type="html"><![CDATA[服务器 Push 技术]]></title>
    <link href="http://feedproxy.google.com/~r/dddspace/~3/p6-aa5OfdUU/" />
    <updated>2012-05-30T10:40:00+08:00</updated>
    <id>http://log4d.com/2012/05/comet</id>
	<content type="html">
		
		&lt;p&gt;服务器 Push 技术表示服务器可以主动推送消息给客户端浏览器。&lt;/p&gt;

&lt;h2&gt;实现方式&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Comet

&lt;ul&gt;
&lt;li&gt;Ajax 轮询&lt;/li&gt;
&lt;li&gt;iframe / htmlfile&lt;/li&gt;
&lt;li&gt;script tag （不中断的连续请求）&lt;/li&gt;
&lt;li&gt;Flash 通讯&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;WebSocket&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Comet 本意是彗星，彗星尾巴痕迹很像长连接工作方式，所以 Comet 指代长连接。
在 Ajax 轮询的分类上，存在一些分歧，这里我把轮询认为一种 Comet 方式。&lt;/p&gt;

&lt;p&gt;ps：「长连接」在一些场景下，是另外一种意义「HTTP: Keep alive」。不在本文讨论的范围中。&lt;/p&gt;

&lt;p&gt;参考链接：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.ibm.com/developerworks/cn/web/wa-lo-comet/"&gt;Comet：基于 HTTP 长连接的“服务器推”技术&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://socket.io/#browser-support"&gt;Socket.IO Supported transports&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;!--more--&gt;


&lt;h3&gt;浏览器支持情况&lt;/h3&gt;

&lt;p&gt;WebSocket 属于 HTML5 规范，需要「先进」浏览器支持，
Flash 通讯需要浏览器安装 Flash 插件，其他方式都可以适应常见浏览器。&lt;/p&gt;

&lt;p&gt;参考连接：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://zh.wikipedia.org/wiki/HTTP%E6%8C%81%E4%B9%85%E9%93%BE%E6%8E%A5"&gt;HTTP持久链接&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://en.wikipedia.org/wiki/Comet_(programming)"&gt;Comet (programming)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.cnblogs.com/tianzhiliang/archive/2011/06/13/2079564.html"&gt;一个误解: 单个服务器程序可承受最大连接数“理论”上是“65535”&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.zeitoun.net/articles/comet_and_php/start"&gt;How to implement COMET with PHP&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;各大网站连接情况&lt;/h2&gt;

&lt;p&gt;可以通过 url 请求来揣测一些东西，比如说，它们没有用 WebSocket，
否则 FireBug 是无法监测的，WebSocket 可以双向通讯。&lt;/p&gt;

&lt;h3&gt;新浪微博&lt;/h3&gt;

&lt;p&gt;未读信息链接： &lt;code&gt;http://rm.api.weibo.com/remind/unread_count.json?target=api&amp;amp;_pid=10001&amp;amp;count=2&amp;amp;source=3818214747&amp;amp;callback=STK_133834300664875&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;未读信息大约每20秒触发一次，像是 Ajax 轮询。&lt;/p&gt;

&lt;p&gt;IM 长连接：
&lt;code&gt;http://4.46.web1.im.weibo.com/im?jsonp=parent.org.cometd.script._callback5&amp;amp;message=%5B%7B%22channel%22%3A%22%2Fmeta%2Fconnect%22%2C%22connectionType%22%3A%22callback-polling%22%2C%22id%22%3A6%2C%22clientId%22%3A%22b02qp9qw9cgiuxxyn3%22%7D%5D&amp;amp;1338343019008&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;可以看出新浪在使用 JSONP 跨域做 IM 长连接，FireBug 中也始终有链接请求，
看上去像 Script Tag 请求方式。&lt;/p&gt;

&lt;h3&gt;知乎&lt;/h3&gt;

&lt;p&gt;请求链接：
&lt;code&gt;http://comet.zhihu.com/update?loc=http%3A%2F%2Fwww.zhihu.com%2F&amp;amp;channel=13781e6817833300f0a70f19&amp;amp;callback=zhp13781e6a6f22349b9865b47c8&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;依然能在 FireBug 中看到请求地址，说明客户端请求数据还是走 HTTP 方式，
并且会出现 update 动作链接一直出于请求状态，猜测知乎仍然使用 Script Tag 请求。&lt;/p&gt;

&lt;h2&gt;框架支持&lt;/h2&gt;

&lt;h3&gt;orbited2&lt;/h3&gt;

&lt;p&gt;&lt;a href="http://labs.gameclosure.com/orbited2/"&gt;http://labs.gameclosure.com/orbited2/&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;跨浏览器&lt;/li&gt;
&lt;li&gt;容易集成：IRC / XMPP / ActiveMQ / RabbitMQ&lt;/li&gt;
&lt;li&gt;Python&lt;/li&gt;
&lt;/ul&gt;


&lt;h3&gt;StreamHub&lt;/h3&gt;

&lt;p&gt;&lt;a href="http://www.stream-hub.com/"&gt;http://www.stream-hub.com/&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;免费版仅支持 10 个在线&lt;/li&gt;
&lt;li&gt;支持 Java / .net / iPhone&lt;/li&gt;
&lt;/ul&gt;


&lt;h3&gt;socket.io&lt;/h3&gt;

&lt;p&gt;&lt;a href="http://socket.io/"&gt;http://socket.io/&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;NodeJS&lt;/li&gt;
&lt;li&gt;推送方式：

&lt;ul&gt;
&lt;li&gt;WebSocket&lt;/li&gt;
&lt;li&gt;Adobe® Flash® Socket&lt;/li&gt;
&lt;li&gt;AJAX long polling&lt;/li&gt;
&lt;li&gt;AJAX multipart streaming&lt;/li&gt;
&lt;li&gt;Forever Iframe&lt;/li&gt;
&lt;li&gt;JSONP Polling&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;支持浏览器：

&lt;ul&gt;
&lt;li&gt;Internet Explorer 5.5+&lt;/li&gt;
&lt;li&gt;Safari 3+&lt;/li&gt;
&lt;li&gt;Google Chrome 4+&lt;/li&gt;
&lt;li&gt;Firefox 3+&lt;/li&gt;
&lt;li&gt;Opera 10.61+&lt;/li&gt;
&lt;li&gt;iPhone Safari&lt;/li&gt;
&lt;li&gt;iPad Safari&lt;/li&gt;
&lt;li&gt;Android WebKit&lt;/li&gt;
&lt;li&gt;WebOs WebKit&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;h3&gt;sockjs-client&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/sockjs/sockjs-client"&gt;https://github.com/sockjs/sockjs-client&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;支持 Node.js / Erlang / Lua / Python-Tornado&lt;/li&gt;
&lt;li&gt;跨浏览器&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;实战 Socket.io&lt;/h2&gt;

&lt;p&gt;考虑到上述候选框架的使用场景，这里选择 Socket.IO 作为 Comet 框架。&lt;/p&gt;

&lt;h3&gt;尴尬的 Pylons&lt;/h3&gt;

&lt;p&gt;Pylons 和 Comet 配合有问题，问题处在标准 WSGI 是非异步的。
（看邮件列表里面，似乎新的标准准备支持）。&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://stackoverflow.com/a/3090118"&gt;http://stackoverflow.com/a/3090118&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://mail.python.org/pipermail/web-sig/2008-July/003545.html"&gt;http://mail.python.org/pipermail/web-sig/2008-July/003545.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://pypi.python.org/pypi/Spawning/"&gt;Spawning&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;这样的话，我就直接选择使用 Node.JS 做 Comet 服务器，Nginx 负责转发。&lt;/p&gt;

&lt;h3&gt;简单Demo&lt;/h3&gt;

&lt;p&gt;node.js 代码&lt;/p&gt;

&lt;figure class='code'&gt;&lt;figcaption&gt;&lt;span&gt;app.js&lt;/span&gt;&lt;/figcaption&gt;&lt;div class="highlight"&gt;&lt;table&gt;&lt;tr&gt;&lt;td class="gutter"&gt;&lt;pre class="line-numbers"&gt;&lt;span class='line-number'&gt;1&lt;/span&gt;
&lt;span class='line-number'&gt;2&lt;/span&gt;
&lt;span class='line-number'&gt;3&lt;/span&gt;
&lt;span class='line-number'&gt;4&lt;/span&gt;
&lt;span class='line-number'&gt;5&lt;/span&gt;
&lt;span class='line-number'&gt;6&lt;/span&gt;
&lt;span class='line-number'&gt;7&lt;/span&gt;
&lt;span class='line-number'&gt;8&lt;/span&gt;
&lt;span class='line-number'&gt;9&lt;/span&gt;
&lt;span class='line-number'&gt;10&lt;/span&gt;
&lt;span class='line-number'&gt;11&lt;/span&gt;
&lt;span class='line-number'&gt;12&lt;/span&gt;
&lt;span class='line-number'&gt;13&lt;/span&gt;
&lt;span class='line-number'&gt;14&lt;/span&gt;
&lt;span class='line-number'&gt;15&lt;/span&gt;
&lt;span class='line-number'&gt;16&lt;/span&gt;
&lt;span class='line-number'&gt;17&lt;/span&gt;
&lt;span class='line-number'&gt;18&lt;/span&gt;
&lt;span class='line-number'&gt;19&lt;/span&gt;
&lt;span class='line-number'&gt;20&lt;/span&gt;
&lt;span class='line-number'&gt;21&lt;/span&gt;
&lt;span class='line-number'&gt;22&lt;/span&gt;
&lt;span class='line-number'&gt;23&lt;/span&gt;
&lt;span class='line-number'&gt;24&lt;/span&gt;
&lt;span class='line-number'&gt;25&lt;/span&gt;
&lt;span class='line-number'&gt;26&lt;/span&gt;
&lt;span class='line-number'&gt;27&lt;/span&gt;
&lt;span class='line-number'&gt;28&lt;/span&gt;
&lt;span class='line-number'&gt;29&lt;/span&gt;
&lt;span class='line-number'&gt;30&lt;/span&gt;
&lt;span class='line-number'&gt;31&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class='code'&gt;&lt;pre&gt;&lt;code class='js'&gt;&lt;span class='line'&gt;&lt;span class="cm"&gt;/* global __dirname, console */&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;
&lt;/span&gt;&lt;span class='line'&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;http&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;createServer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;handler&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;  &lt;span class="nx"&gt;io&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;socket.io&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;  &lt;span class="nx"&gt;fs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;fs&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;
&lt;/span&gt;&lt;span class='line'&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;8080&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;
&lt;/span&gt;&lt;span class='line'&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;handler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;  &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;readFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;__dirname&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;/index.html&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;      &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;          &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;              &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;writeHead&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;              &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;end&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Error loading index.html&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;          &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;
&lt;/span&gt;&lt;span class='line'&gt;          &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;writeHead&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;          &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;end&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;      &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;
&lt;/span&gt;&lt;span class='line'&gt;&lt;span class="nx"&gt;io&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sockets&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;connection&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;  &lt;span class="s1"&gt;&amp;#39;use strict&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;  &lt;span class="nx"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;news&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;hello&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;world, for everyone!&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;  &lt;span class="nx"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;my other event&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;  &lt;span class="nx"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;private message&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;from&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;I received a private message by &amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;from&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39; saying &amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;页面代码&lt;/p&gt;

&lt;figure class='code'&gt;&lt;figcaption&gt;&lt;span&gt;index.html &lt;/span&gt;&lt;/figcaption&gt;&lt;div class="highlight"&gt;&lt;table&gt;&lt;tr&gt;&lt;td class="gutter"&gt;&lt;pre class="line-numbers"&gt;&lt;span class='line-number'&gt;1&lt;/span&gt;
&lt;span class='line-number'&gt;2&lt;/span&gt;
&lt;span class='line-number'&gt;3&lt;/span&gt;
&lt;span class='line-number'&gt;4&lt;/span&gt;
&lt;span class='line-number'&gt;5&lt;/span&gt;
&lt;span class='line-number'&gt;6&lt;/span&gt;
&lt;span class='line-number'&gt;7&lt;/span&gt;
&lt;span class='line-number'&gt;8&lt;/span&gt;
&lt;span class='line-number'&gt;9&lt;/span&gt;
&lt;span class='line-number'&gt;10&lt;/span&gt;
&lt;span class='line-number'&gt;11&lt;/span&gt;
&lt;span class='line-number'&gt;12&lt;/span&gt;
&lt;span class='line-number'&gt;13&lt;/span&gt;
&lt;span class='line-number'&gt;14&lt;/span&gt;
&lt;span class='line-number'&gt;15&lt;/span&gt;
&lt;span class='line-number'&gt;16&lt;/span&gt;
&lt;span class='line-number'&gt;17&lt;/span&gt;
&lt;span class='line-number'&gt;18&lt;/span&gt;
&lt;span class='line-number'&gt;19&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class='code'&gt;&lt;pre&gt;&lt;code class='html'&gt;&lt;span class='line'&gt;&lt;span class="nt"&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;&lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;  &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;http-equiv=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;content-type&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;text/html; charset=utf-8&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;
&lt;/span&gt;&lt;span class='line'&gt;  &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;Socket.io Demo&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;  &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;/socket.io/socket.io.js&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;  &lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;      &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;socket&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;io&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;/&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;
&lt;/span&gt;&lt;span class='line'&gt;      &lt;span class="nx"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;news&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;          &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;          &lt;span class="nx"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;my other event&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;my&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;data&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;      &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;  &lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;&lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;&lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;
&lt;/span&gt;&lt;span class='line'&gt;&lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;连接成功之后，在浏览器控制台里面，可以使用 &lt;code&gt;socket.emit('my other event', {biu: 'biu'});&lt;/code&gt;
向服务器发送消息。&lt;/p&gt;

&lt;p&gt;服务器也可以通过 &lt;code&gt;socket.emit()&lt;/code&gt; 来向客户端推送消息。&lt;/p&gt;

&lt;p&gt;私有信息发送，使用 &lt;code&gt;socket.emit('private message', 'James', {some: 'message'});&lt;/code&gt; 。&lt;/p&gt;

&lt;h3&gt;跨平台&lt;/h3&gt;

&lt;p&gt;实测看来，在 IE8 下面， Socket.io 会降级使用 &lt;code&gt;htmlfile&lt;/code&gt; 来实现 Comet。&lt;/p&gt;

&lt;p&gt;而 Firefox 中会有 &lt;code&gt;websocket / htmlfile / xhr-polling / jsonp-polling&lt;/code&gt; 依次备选，
首选 websocket。&lt;/p&gt;

&lt;h3&gt;安全性&lt;/h3&gt;

&lt;p&gt;问题：提交数据的身份认证过程，以前在后台由 Web 框架自动完成，而现在流程是
Socket.IO -&gt; RabbitMQ -&gt; Web App，身份验证的复杂度增加了。&lt;/p&gt;

&lt;p&gt;思路：Socket.IO 使用 Nginx 代理转发，从而保留同一域名下面的 cookie 信息，
这样能够提交到 Socket.IO 服务器，每次 RabbitMQ Message 都记录 cookie 信息，
后台从 RabbitMQ 读取信息时候，再进行认证。&lt;/p&gt;

&lt;p&gt;实际操作：由于 Comet 中的数据流仅负责推送，客户端继续使用原始 POST
方式发送数据到服务器，所以暂时不会产生身份认证问题。&lt;/p&gt;

&lt;h2&gt;Node AMPQ 驱动&lt;/h2&gt;

&lt;p&gt;Socket.IO 提供了一个通用的 Comet 解决方案，下面就需要点润滑剂，将整个数据流跑通。
消息队列 RabbitMQ 正好适合用来做这个。&lt;/p&gt;

&lt;p&gt;Rabbit 官网提到了一个套件 &lt;a href="https://github.com/squaremo/rabbit.js"&gt;rabbit.js&lt;/a&gt; 。
遗憾的是这个库是混合了 RabbitMQ 和 Node.JS，提供了一个封装好的 Node.JS 库，
而我想要的仅仅是一个 AMPQ 协议驱动。&lt;a href="https://github.com/postwait/node-amqp/blob/master/amqp.js"&gt;node-amqp&lt;/a&gt; 则是我们需要的驱动。&lt;/p&gt;

&lt;h3&gt;Demo&lt;/h3&gt;

&lt;p&gt;服务器接收者脚本：&lt;/p&gt;

&lt;figure class='code'&gt;&lt;figcaption&gt;&lt;span&gt;app-amqp.js&lt;/span&gt;&lt;/figcaption&gt;&lt;div class="highlight"&gt;&lt;table&gt;&lt;tr&gt;&lt;td class="gutter"&gt;&lt;pre class="line-numbers"&gt;&lt;span class='line-number'&gt;1&lt;/span&gt;
&lt;span class='line-number'&gt;2&lt;/span&gt;
&lt;span class='line-number'&gt;3&lt;/span&gt;
&lt;span class='line-number'&gt;4&lt;/span&gt;
&lt;span class='line-number'&gt;5&lt;/span&gt;
&lt;span class='line-number'&gt;6&lt;/span&gt;
&lt;span class='line-number'&gt;7&lt;/span&gt;
&lt;span class='line-number'&gt;8&lt;/span&gt;
&lt;span class='line-number'&gt;9&lt;/span&gt;
&lt;span class='line-number'&gt;10&lt;/span&gt;
&lt;span class='line-number'&gt;11&lt;/span&gt;
&lt;span class='line-number'&gt;12&lt;/span&gt;
&lt;span class='line-number'&gt;13&lt;/span&gt;
&lt;span class='line-number'&gt;14&lt;/span&gt;
&lt;span class='line-number'&gt;15&lt;/span&gt;
&lt;span class='line-number'&gt;16&lt;/span&gt;
&lt;span class='line-number'&gt;17&lt;/span&gt;
&lt;span class='line-number'&gt;18&lt;/span&gt;
&lt;span class='line-number'&gt;19&lt;/span&gt;
&lt;span class='line-number'&gt;20&lt;/span&gt;
&lt;span class='line-number'&gt;21&lt;/span&gt;
&lt;span class='line-number'&gt;22&lt;/span&gt;
&lt;span class='line-number'&gt;23&lt;/span&gt;
&lt;span class='line-number'&gt;24&lt;/span&gt;
&lt;span class='line-number'&gt;25&lt;/span&gt;
&lt;span class='line-number'&gt;26&lt;/span&gt;
&lt;span class='line-number'&gt;27&lt;/span&gt;
&lt;span class='line-number'&gt;28&lt;/span&gt;
&lt;span class='line-number'&gt;29&lt;/span&gt;
&lt;span class='line-number'&gt;30&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class='code'&gt;&lt;pre&gt;&lt;code class='js'&gt;&lt;span class='line'&gt;&lt;span class="cm"&gt;/* global __dirname, console */&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;
&lt;/span&gt;&lt;span class='line'&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;conn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;amqp&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;createConnection&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;amqp://localhost&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;
&lt;/span&gt;&lt;span class='line'&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;socket works&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;&lt;span class="nx"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;ready&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;conn ready&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;  &lt;span class="nx"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;queue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;socket.io&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;passive&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;queue&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;      &lt;span class="nx"&gt;queue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;deliveryInfo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;          &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;#json:&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;          &lt;span class="nx"&gt;view&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;          &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;#headers:&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;          &lt;span class="nx"&gt;view&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;          &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;#deliveryInfo:&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;          &lt;span class="nx"&gt;view&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;deliveryInfo&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;      &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;
&lt;/span&gt;&lt;span class='line'&gt;&lt;span class="nx"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;error&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;error&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;
&lt;/span&gt;&lt;span class='line'&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;view&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;  &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;      &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;hasOwnProperty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;          &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;: &amp;#39;&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;      &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;用 Python 写的发送者脚本：&lt;/p&gt;

&lt;figure class='code'&gt;&lt;figcaption&gt;&lt;span&gt;producter.py&lt;/span&gt;&lt;/figcaption&gt;&lt;div class="highlight"&gt;&lt;table&gt;&lt;tr&gt;&lt;td class="gutter"&gt;&lt;pre class="line-numbers"&gt;&lt;span class='line-number'&gt;1&lt;/span&gt;
&lt;span class='line-number'&gt;2&lt;/span&gt;
&lt;span class='line-number'&gt;3&lt;/span&gt;
&lt;span class='line-number'&gt;4&lt;/span&gt;
&lt;span class='line-number'&gt;5&lt;/span&gt;
&lt;span class='line-number'&gt;6&lt;/span&gt;
&lt;span class='line-number'&gt;7&lt;/span&gt;
&lt;span class='line-number'&gt;8&lt;/span&gt;
&lt;span class='line-number'&gt;9&lt;/span&gt;
&lt;span class='line-number'&gt;10&lt;/span&gt;
&lt;span class='line-number'&gt;11&lt;/span&gt;
&lt;span class='line-number'&gt;12&lt;/span&gt;
&lt;span class='line-number'&gt;13&lt;/span&gt;
&lt;span class='line-number'&gt;14&lt;/span&gt;
&lt;span class='line-number'&gt;15&lt;/span&gt;
&lt;span class='line-number'&gt;16&lt;/span&gt;
&lt;span class='line-number'&gt;17&lt;/span&gt;
&lt;span class='line-number'&gt;18&lt;/span&gt;
&lt;span class='line-number'&gt;19&lt;/span&gt;
&lt;span class='line-number'&gt;20&lt;/span&gt;
&lt;span class='line-number'&gt;21&lt;/span&gt;
&lt;span class='line-number'&gt;22&lt;/span&gt;
&lt;span class='line-number'&gt;23&lt;/span&gt;
&lt;span class='line-number'&gt;24&lt;/span&gt;
&lt;span class='line-number'&gt;25&lt;/span&gt;
&lt;span class='line-number'&gt;26&lt;/span&gt;
&lt;span class='line-number'&gt;27&lt;/span&gt;
&lt;span class='line-number'&gt;28&lt;/span&gt;
&lt;span class='line-number'&gt;29&lt;/span&gt;
&lt;span class='line-number'&gt;30&lt;/span&gt;
&lt;span class='line-number'&gt;31&lt;/span&gt;
&lt;span class='line-number'&gt;32&lt;/span&gt;
&lt;span class='line-number'&gt;33&lt;/span&gt;
&lt;span class='line-number'&gt;34&lt;/span&gt;
&lt;span class='line-number'&gt;35&lt;/span&gt;
&lt;span class='line-number'&gt;36&lt;/span&gt;
&lt;span class='line-number'&gt;37&lt;/span&gt;
&lt;span class='line-number'&gt;38&lt;/span&gt;
&lt;span class='line-number'&gt;39&lt;/span&gt;
&lt;span class='line-number'&gt;40&lt;/span&gt;
&lt;span class='line-number'&gt;41&lt;/span&gt;
&lt;span class='line-number'&gt;42&lt;/span&gt;
&lt;span class='line-number'&gt;43&lt;/span&gt;
&lt;span class='line-number'&gt;44&lt;/span&gt;
&lt;span class='line-number'&gt;45&lt;/span&gt;
&lt;span class='line-number'&gt;46&lt;/span&gt;
&lt;span class='line-number'&gt;47&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class='code'&gt;&lt;pre&gt;&lt;code class='python'&gt;&lt;span class='line'&gt;&lt;span class="c"&gt;# coding=utf-8&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;&lt;span class="c"&gt;#! /usr/bin/env python2&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;
&lt;/span&gt;&lt;span class='line'&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;pika&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;json&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;logging&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;time&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;
&lt;/span&gt;&lt;span class='line'&gt;&lt;span class="n"&gt;logger&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getLogger&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;
&lt;/span&gt;&lt;span class='line'&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;    &lt;span class="n"&gt;conn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pika&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;BlockingConnection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;        &lt;span class="n"&gt;pika&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ConnectionParameters&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;localhost&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;    &lt;span class="n"&gt;chan&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;channel&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;    &lt;span class="n"&gt;chan&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;queue_declare&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;queue&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;socket.io&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;
&lt;/span&gt;&lt;span class='line'&gt;    &lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;        &lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;no&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;some&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Message&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;u&amp;#39;比如&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;u&amp;#39;中文信息&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;        &lt;span class="n"&gt;publish_text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;chan&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;socket.io&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;u&amp;#39;text &lt;/span&gt;&lt;span class="si"&gt;%d&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;        &lt;span class="n"&gt;publish_json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;chan&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;socket.io&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;        &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;add one message to RabbitMQ&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;        &lt;span class="c"&gt;#time.sleep(5) # sleep 5 sec&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;        &lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;-=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;
&lt;/span&gt;&lt;span class='line'&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;publish_text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;channel&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;queue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;    &lt;span class="n"&gt;channel&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;basic_publish&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;exchange&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;                          &lt;span class="n"&gt;routing_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;queue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;                          &lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;                          &lt;span class="n"&gt;properties&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;pika&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;BasicProperties&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;                              &lt;span class="n"&gt;content_type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;text/plain&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;                              &lt;span class="n"&gt;content_encoding&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;utf-8&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;                              &lt;span class="n"&gt;delivery_mode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;                         &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;
&lt;/span&gt;&lt;span class='line'&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;publish_json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;channel&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;queue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;    &lt;span class="n"&gt;channel&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;basic_publish&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;exchange&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;                          &lt;span class="n"&gt;routing_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;queue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;                          &lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;                          &lt;span class="n"&gt;properties&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;pika&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;BasicProperties&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;                              &lt;span class="n"&gt;content_type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;application/json&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;                              &lt;span class="n"&gt;content_encoding&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;utf-8&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;                              &lt;span class="n"&gt;delivery_mode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;                         &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;
&lt;/span&gt;&lt;span class='line'&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;__main__&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;    &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;使用 &lt;code&gt;node ./app-amqp.js&lt;/code&gt; 运行 Node.JS 服务器，然后运行 &lt;code&gt;producter.py&lt;/code&gt; 产生
RabbitMQ Message，我使用的数据格式是序列化的 JSON 字串，
还有 &lt;code&gt;JSON, Thrift, Protocol Buffers, MessagePack&lt;/code&gt; 这些格式可供选择。运行结果如下：&lt;/p&gt;

&lt;figure class='code'&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;div class="highlight"&gt;&lt;table&gt;&lt;tr&gt;&lt;td class="gutter"&gt;&lt;pre class="line-numbers"&gt;&lt;span class='line-number'&gt;1&lt;/span&gt;
&lt;span class='line-number'&gt;2&lt;/span&gt;
&lt;span class='line-number'&gt;3&lt;/span&gt;
&lt;span class='line-number'&gt;4&lt;/span&gt;
&lt;span class='line-number'&gt;5&lt;/span&gt;
&lt;span class='line-number'&gt;6&lt;/span&gt;
&lt;span class='line-number'&gt;7&lt;/span&gt;
&lt;span class='line-number'&gt;8&lt;/span&gt;
&lt;span class='line-number'&gt;9&lt;/span&gt;
&lt;span class='line-number'&gt;10&lt;/span&gt;
&lt;span class='line-number'&gt;11&lt;/span&gt;
&lt;span class='line-number'&gt;12&lt;/span&gt;
&lt;span class='line-number'&gt;13&lt;/span&gt;
&lt;span class='line-number'&gt;14&lt;/span&gt;
&lt;span class='line-number'&gt;15&lt;/span&gt;
&lt;span class='line-number'&gt;16&lt;/span&gt;
&lt;span class='line-number'&gt;17&lt;/span&gt;
&lt;span class='line-number'&gt;18&lt;/span&gt;
&lt;span class='line-number'&gt;19&lt;/span&gt;
&lt;span class='line-number'&gt;20&lt;/span&gt;
&lt;span class='line-number'&gt;21&lt;/span&gt;
&lt;span class='line-number'&gt;22&lt;/span&gt;
&lt;span class='line-number'&gt;23&lt;/span&gt;
&lt;span class='line-number'&gt;24&lt;/span&gt;
&lt;span class='line-number'&gt;25&lt;/span&gt;
&lt;span class='line-number'&gt;26&lt;/span&gt;
&lt;span class='line-number'&gt;27&lt;/span&gt;
&lt;span class='line-number'&gt;28&lt;/span&gt;
&lt;span class='line-number'&gt;29&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class='code'&gt;&lt;pre&gt;&lt;code class='text'&gt;&lt;span class='line'&gt;#json:
&lt;/span&gt;&lt;span class='line'&gt;data: &amp;quot;text 1&amp;quot;
&lt;/span&gt;&lt;span class='line'&gt;UnicodeEncodeError: &amp;#39;ascii&amp;#39; codec can&amp;#39;t encode characters in position 0-3: ordinal not icontentType: text/plain
&lt;/span&gt;&lt;span class='line'&gt;#headers:
&lt;/span&gt;&lt;span class='line'&gt;#deliveryInfo:
&lt;/span&gt;&lt;span class='line'&gt;contentType: text/plain
&lt;/span&gt;&lt;span class='line'&gt;contentEncoding: utf-8
&lt;/span&gt;&lt;span class='line'&gt;deliveryMode: 1
&lt;/span&gt;&lt;span class='line'&gt;queue: socket.io
&lt;/span&gt;&lt;span class='line'&gt;deliveryTag: 19
&lt;/span&gt;&lt;span class='line'&gt;redelivered: false
&lt;/span&gt;&lt;span class='line'&gt;exchange:
&lt;/span&gt;&lt;span class='line'&gt;routingKey: socket.io
&lt;/span&gt;&lt;span class='line'&gt;consumerTag: node-amqp-10880-0.06487216474488378
&lt;/span&gt;&lt;span class='line'&gt;#json:
&lt;/span&gt;&lt;span class='line'&gt;比如: 中文信息
&lt;/span&gt;&lt;span class='line'&gt;some: Message
&lt;/span&gt;&lt;span class='line'&gt;no: 1
&lt;/span&gt;&lt;span class='line'&gt;#headers:
&lt;/span&gt;&lt;span class='line'&gt;#deliveryInfo:
&lt;/span&gt;&lt;span class='line'&gt;contentType: application/json
&lt;/span&gt;&lt;span class='line'&gt;contentEncoding: utf-8
&lt;/span&gt;&lt;span class='line'&gt;deliveryMode: 1
&lt;/span&gt;&lt;span class='line'&gt;queue: socket.io
&lt;/span&gt;&lt;span class='line'&gt;deliveryTag: 20
&lt;/span&gt;&lt;span class='line'&gt;redelivered: false
&lt;/span&gt;&lt;span class='line'&gt;exchange:
&lt;/span&gt;&lt;span class='line'&gt;routingKey: socket.io
&lt;/span&gt;&lt;span class='line'&gt;consumerTag: node-amqp-10880-0.06487216474488378
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;里面有两个 Message，发送数据格式为 &lt;code&gt;text/plain&lt;/code&gt; 和 &lt;code&gt;application/json&lt;/code&gt; 。&lt;/p&gt;

&lt;p&gt;参考链接：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://pika.github.com/"&gt;Pika Document&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;Socket.IO + RabbitMQ&lt;/h2&gt;

&lt;p&gt;最后提供 Socket.IO + RabbitMQ 的完整 Demo，客户端会实时接受到来自消息发送者的消息。&lt;/p&gt;

&lt;figure class='code'&gt;&lt;figcaption&gt;&lt;span&gt;app-amqp.socket.js&lt;/span&gt;&lt;/figcaption&gt;&lt;div class="highlight"&gt;&lt;table&gt;&lt;tr&gt;&lt;td class="gutter"&gt;&lt;pre class="line-numbers"&gt;&lt;span class='line-number'&gt;1&lt;/span&gt;
&lt;span class='line-number'&gt;2&lt;/span&gt;
&lt;span class='line-number'&gt;3&lt;/span&gt;
&lt;span class='line-number'&gt;4&lt;/span&gt;
&lt;span class='line-number'&gt;5&lt;/span&gt;
&lt;span class='line-number'&gt;6&lt;/span&gt;
&lt;span class='line-number'&gt;7&lt;/span&gt;
&lt;span class='line-number'&gt;8&lt;/span&gt;
&lt;span class='line-number'&gt;9&lt;/span&gt;
&lt;span class='line-number'&gt;10&lt;/span&gt;
&lt;span class='line-number'&gt;11&lt;/span&gt;
&lt;span class='line-number'&gt;12&lt;/span&gt;
&lt;span class='line-number'&gt;13&lt;/span&gt;
&lt;span class='line-number'&gt;14&lt;/span&gt;
&lt;span class='line-number'&gt;15&lt;/span&gt;
&lt;span class='line-number'&gt;16&lt;/span&gt;
&lt;span class='line-number'&gt;17&lt;/span&gt;
&lt;span class='line-number'&gt;18&lt;/span&gt;
&lt;span class='line-number'&gt;19&lt;/span&gt;
&lt;span class='line-number'&gt;20&lt;/span&gt;
&lt;span class='line-number'&gt;21&lt;/span&gt;
&lt;span class='line-number'&gt;22&lt;/span&gt;
&lt;span class='line-number'&gt;23&lt;/span&gt;
&lt;span class='line-number'&gt;24&lt;/span&gt;
&lt;span class='line-number'&gt;25&lt;/span&gt;
&lt;span class='line-number'&gt;26&lt;/span&gt;
&lt;span class='line-number'&gt;27&lt;/span&gt;
&lt;span class='line-number'&gt;28&lt;/span&gt;
&lt;span class='line-number'&gt;29&lt;/span&gt;
&lt;span class='line-number'&gt;30&lt;/span&gt;
&lt;span class='line-number'&gt;31&lt;/span&gt;
&lt;span class='line-number'&gt;32&lt;/span&gt;
&lt;span class='line-number'&gt;33&lt;/span&gt;
&lt;span class='line-number'&gt;34&lt;/span&gt;
&lt;span class='line-number'&gt;35&lt;/span&gt;
&lt;span class='line-number'&gt;36&lt;/span&gt;
&lt;span class='line-number'&gt;37&lt;/span&gt;
&lt;span class='line-number'&gt;38&lt;/span&gt;
&lt;span class='line-number'&gt;39&lt;/span&gt;
&lt;span class='line-number'&gt;40&lt;/span&gt;
&lt;span class='line-number'&gt;41&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class='code'&gt;&lt;pre&gt;&lt;code class='js'&gt;&lt;span class='line'&gt;&lt;span class="cm"&gt;/* global __dirname, console */&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;
&lt;/span&gt;&lt;span class='line'&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;http&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;createServer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;handler&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;  &lt;span class="nx"&gt;io&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;socket.io&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;  &lt;span class="nx"&gt;fs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;fs&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;
&lt;/span&gt;&lt;span class='line'&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;8080&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;
&lt;/span&gt;&lt;span class='line'&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;handler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;  &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;readFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;__dirname&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;/index.html&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;      &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;          &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;              &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;writeHead&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;              &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;end&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Error loading index.html&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;          &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;
&lt;/span&gt;&lt;span class='line'&gt;          &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;writeHead&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;          &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;end&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;      &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;
&lt;/span&gt;&lt;span class='line'&gt;&lt;span class="nx"&gt;io&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sockets&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;connection&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;io ready&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;
&lt;/span&gt;&lt;span class='line'&gt;  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;conn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;amqp&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;createConnection&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;amqp://localhost&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;  &lt;span class="nx"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;ready&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;conn ready&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;      &lt;span class="nx"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;queue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;socket.io&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;passive&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;queue&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;          &lt;span class="nx"&gt;queue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;deliveryInfo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;              &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;              &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;deliveryInfo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;contentType&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;              &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;deliveryInfo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;contentType&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;application/json&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;                  &lt;span class="nx"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;news&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;              &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;              &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;deliveryInfo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;contentType&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;text/plain&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;                  &lt;span class="nx"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;news&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;              &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;          &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;      &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;在运行 &lt;code&gt;producter.py&lt;/code&gt; 后，Python 脚本持续产生 Message 到 RabbitMQ，
&lt;code&gt;app-amqp-socket.js&lt;/code&gt; 订阅读取 Message 并推送到浏览器端。
浏览器可以在 Console 里面看到日志：&lt;/p&gt;

&lt;figure class='code'&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;div class="highlight"&gt;&lt;table&gt;&lt;tr&gt;&lt;td class="gutter"&gt;&lt;pre class="line-numbers"&gt;&lt;span class='line-number'&gt;1&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class='code'&gt;&lt;pre&gt;&lt;code class='text'&gt;&lt;span class='line'&gt;Object { 比如=&amp;quot;中文信息&amp;quot;, some=&amp;quot;Message&amp;quot;, no=1}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;至此，我们可以完成 WebApp -&gt; RabbitMQ -&gt; Socket.IO -&gt; Browser 的实时推送。&lt;/p&gt;

		
  

&lt;div style="margin-top:15px;background:none repeat scroll 0pt 0pt rgb(238,238,238)"&gt;
  &lt;p&gt;
  &lt;strong&gt;版权所有 &amp;copy; 2010 转载本站文章请注明：&lt;/strong&gt; 转载自
  &lt;a href="http://log4d.com/" target="_blank"&gt;Log4D&lt;/a&gt;&lt;br&gt;
  &lt;strong&gt;原文链接:&lt;/strong&gt; &lt;a href="http://log4d.com/2012/05/comet/" target="_blank"&gt;http://log4d.com/2012/05/comet/&lt;/a&gt;&lt;br&gt;
  您可以随意地转载本站的文章，但是必须在醒目位置注明来源及本站链接，不可以将本站文章商业化使用，或者修改、转换或者以本作品为基础进行创作。&lt;br&gt;
  3a1ff193cee606bd1e2ea554a16353ee
  &lt;/p&gt;
&lt;/div&gt;

		
	&lt;img src="http://feeds.feedburner.com/~r/dddspace/~4/p6-aa5OfdUU" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://log4d.com/2012/05/comet/</feedburner:origLink></entry>
  
  <entry>
    <title type="html"><![CDATA[《开源和自由》幻灯片]]></title>
    <link href="http://feedproxy.google.com/~r/dddspace/~3/Ea1mJOLVLOc/" />
    <updated>2012-05-27T19:35:00+08:00</updated>
    <id>http://log4d.com/2012/05/opensource-and-freedom</id>
	<content type="html">
		
		&lt;p&gt;周末回学校一趟，和几个老同学、老师聚会，然后给学弟学妹们做了一个分享。&lt;/p&gt;

&lt;p&gt;我的主题是《开源与自由》。
为了让同学们不瞌睡，几乎是当一个故事讲的，没太多技术内容。&lt;/p&gt;

&lt;object id="__sse13092676" width="425" height="355"&gt;
    &lt;param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=random-120527065445-phpapp01&amp;stripped_title=20120528&amp;userName=alswl" /&gt;
    &lt;param name="allowFullScreen" value="true"/&gt;
    &lt;param name="allowScriptAccess" value="always"/&gt;&lt;param name="wmode" value="transparent"/&gt;
    &lt;embed name="__sse13092676" src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=random-120527065445-phpapp01&amp;stripped_title=20120528&amp;userName=alswl" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" wmode="transparent" width="425"
height="355"&gt;&lt;/embed&gt;
&lt;/object&gt;


		
  

&lt;div style="margin-top:15px;background:none repeat scroll 0pt 0pt rgb(238,238,238)"&gt;
  &lt;p&gt;
  &lt;strong&gt;版权所有 &amp;copy; 2010 转载本站文章请注明：&lt;/strong&gt; 转载自
  &lt;a href="http://log4d.com/" target="_blank"&gt;Log4D&lt;/a&gt;&lt;br&gt;
  &lt;strong&gt;原文链接:&lt;/strong&gt; &lt;a href="http://log4d.com/2012/05/opensource-and-freedom/" target="_blank"&gt;http://log4d.com/2012/05/opensource-and-freedom/&lt;/a&gt;&lt;br&gt;
  您可以随意地转载本站的文章，但是必须在醒目位置注明来源及本站链接，不可以将本站文章商业化使用，或者修改、转换或者以本作品为基础进行创作。&lt;br&gt;
  3a1ff193cee606bd1e2ea554a16353ee
  &lt;/p&gt;
&lt;/div&gt;

		
	&lt;img src="http://feeds.feedburner.com/~r/dddspace/~4/Ea1mJOLVLOc" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://log4d.com/2012/05/opensource-and-freedom/</feedburner:origLink></entry>
  
  <entry>
    <title type="html"><![CDATA[让 Octopress 支持 RSS2.0]]></title>
    <link href="http://feedproxy.google.com/~r/dddspace/~3/qCrNtv8lDxw/" />
    <updated>2012-05-22T16:18:00+08:00</updated>
    <id>http://log4d.com/2012/05/support-rss</id>
	<content type="html">
		
		&lt;p&gt;土鳖人人网的 &lt;strong&gt;日志导入&lt;/strong&gt; 功能仅支持 RSS2.0，而 Octopress 输出的订阅格式是 Atom1.0。
于是为了让人人网的同学能看见我那些技术宅，又或非技术宅的文章，
我只能昧着良心，给 Octopress 加上过时的 RSS2.0 输出。&lt;/p&gt;

&lt;p&gt;在 &lt;code&gt;source/&lt;/code&gt; 下创建新文件 &lt;code&gt;rss.xml&lt;/code&gt; ，内容如下：&lt;/p&gt;

&lt;div&gt;&lt;script src='https://gist.github.com/2767610.js?file='&gt;&lt;/script&gt;
&lt;noscript&gt;&lt;pre&gt;&lt;code&gt;---
layout: nil
---
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;
&amp;lt;rss xmlns:dc=&amp;quot;http://purl.org/dc/elements/1.1/&amp;quot; version=&amp;quot;2.0&amp;quot;&amp;gt;
    &amp;lt;channel&amp;gt;
        &amp;lt;description&amp;gt;&amp;lt;![CDATA[{{ site.title }}]]&amp;gt;&amp;lt;/description&amp;gt;
        &amp;lt;title&amp;gt;&amp;lt;![CDATA[{{ site.title }}]]&amp;gt;&amp;lt;/title&amp;gt;
        &amp;lt;link&amp;gt;{{ site.url }}/&amp;lt;/link&amp;gt;
        &amp;lt;pubDate&amp;gt;{{ site.time | date_to_xmlschema }}&amp;lt;/pubDate&amp;gt;

        {% for post in site.posts limit: 20 %}
        &amp;lt;item&amp;gt;
            &amp;lt;description&amp;gt;
                &amp;lt;![CDATA[
                {{ post.content | expand_urls: site.url | cdata_escape }}
                {% include post/copyright.html %}
                ]]&amp;gt;
            &amp;lt;/description&amp;gt;
            &amp;lt;title&amp;gt;&amp;lt;![CDATA[{{ post.title | cdata_escape }}]]&amp;gt;&amp;lt;/title&amp;gt;
            &amp;lt;link&amp;gt;{{ site.url }}{{ post.url }}&amp;lt;/link&amp;gt;
            &amp;lt;pubDate&amp;gt;{{ post.date | date_to_xmlschema }}&amp;lt;/pubDate&amp;gt;
            &amp;lt;guid isPermaLink=&amp;quot;false&amp;quot;&amp;gt;{{ site.url }}{{ post.id }}&amp;lt;/guid&amp;gt;

            &amp;lt;source url=&amp;quot;{{ site.url }}/rss.xml&amp;quot;&amp;gt;&amp;lt;![CDATA[{{ site.title }}]]&amp;gt;&amp;lt;/source&amp;gt;
        &amp;lt;/item&amp;gt;
        {% endfor %}
    &amp;lt;/channel&amp;gt;
&amp;lt;/rss&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/noscript&gt;&lt;/div&gt;


&lt;p&gt;然后，访问 &lt;code&gt;http://site.url/rss.xml&lt;/code&gt; 即可。
我的 RSS2.0 地址是 &lt;a href="http://log4d.com/rss.xml"&gt;http://log4d.com/rss.xml&lt;/a&gt;。&lt;/p&gt;

&lt;p&gt;最后，再让我吐槽一下人人网的工程师们：「导入日志后格式处理的一塌糊涂，几乎不能看」，真土鳖。&lt;/p&gt;

		
  

&lt;div style="margin-top:15px;background:none repeat scroll 0pt 0pt rgb(238,238,238)"&gt;
  &lt;p&gt;
  &lt;strong&gt;版权所有 &amp;copy; 2010 转载本站文章请注明：&lt;/strong&gt; 转载自
  &lt;a href="http://log4d.com/" target="_blank"&gt;Log4D&lt;/a&gt;&lt;br&gt;
  &lt;strong&gt;原文链接:&lt;/strong&gt; &lt;a href="http://log4d.com/2012/05/support-rss/" target="_blank"&gt;http://log4d.com/2012/05/support-rss/&lt;/a&gt;&lt;br&gt;
  您可以随意地转载本站的文章，但是必须在醒目位置注明来源及本站链接，不可以将本站文章商业化使用，或者修改、转换或者以本作品为基础进行创作。&lt;br&gt;
  3a1ff193cee606bd1e2ea554a16353ee
  &lt;/p&gt;
&lt;/div&gt;

		
	&lt;img src="http://feeds.feedburner.com/~r/dddspace/~4/qCrNtv8lDxw" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://log4d.com/2012/05/support-rss/</feedburner:origLink></entry>
  
  <entry>
    <title type="html"><![CDATA[给 Octopress 加上标签功能]]></title>
    <link href="http://feedproxy.google.com/~r/dddspace/~3/i03Me0Kjivk/" />
    <updated>2012-05-21T15:17:00+08:00</updated>
    <id>http://log4d.com/2012/05/tag-cloud</id>
	<content type="html">
		
		&lt;p&gt;上周，我将 Log4D 由 Wordpress 转换为 Octopress，略加打理，颇为顺手。
自动分类 / 评论转移 / 代码高亮 / 图床 的问题一一解决之后，
就只剩下 tag 的问题没有搞定了。&lt;/p&gt;

&lt;p&gt;我当时使用了YORKXIN的&lt;a href="https://gist.github.com/1394128"&gt;修改版本&lt;/a&gt;来处理 Wordpress
的数据迁移，这个脚本很好用，数据没有遗失，甚至是让我担心的 category /
tag 都给予了保留。具体使用方法可以参见&lt;a href="http://blog.dayanjia.com/2012/04/migration-to-octopress-from-wordpress/"&gt;从Wordpress迁移到Octopress&lt;/a&gt;。&lt;/p&gt;

&lt;p&gt;只是虽然 tag 的数据保留了，但是 &lt;strong&gt;Octopress 仅支持 category 的分类，而完全忽略
tag&lt;/strong&gt;。这是我不能容忍的：category 和 tag 分别代表 有序 / 无序 的知识点归纳方法。
&lt;strong&gt;一篇文章只能属于一个 category，但可以同时属于多个 tag&lt;/strong&gt;。
Octopress 的设计方法显然和我长期养成的知识归纳体系冲突，我开始吭次吭次寻找插件。&lt;/p&gt;

&lt;!--more--&gt;


&lt;p&gt;ps：Octopress 官方也推荐了一个所谓「&lt;a href="https://github.com/tokkonopapa/octopress-tagcloud"&gt;octopress-tagcloud&lt;/a&gt;」的插件，
&lt;strong&gt;但这仅仅是让 category 用 列表 / 标签云的形式展示出来，并没有给文章加入 tag
概念&lt;/strong&gt;。更多官方插件可以查看
&lt;a href="https://github.com/imathis/octopress/wiki/3rd-party-plugins"&gt;3rd party plugins&lt;/a&gt;。&lt;/p&gt;

&lt;p&gt;就在我准备放弃，自己动手用蹩脚的 ruby 水平写插件时候，突然在 github 找到这种插件：
&lt;a href="https://github.com/robbyedwards/octopress-tag-pages"&gt;robbyedwards / octopress-tag-pages&lt;/a&gt;和
&lt;a href="https://github.com/robbyedwards/octopress-tag-cloud"&gt;robbyedwards / octopress-tag-cloud&lt;/a&gt;。前者负责采集文章的 tag 信息，后者提供标签云展示功能。赞美 Github。&lt;/p&gt;

&lt;p&gt;这两个插件使用很简单，将插件文件放入对应的目录（&lt;strong&gt;注意备份，存在覆盖的情况&lt;/strong&gt;）。
然后再给插件「octopress-tag-cloud」添加一个专属页面存放标签云即可。
这个标签云生成的标记是 &lt;code&gt;li...li&lt;/code&gt; ，需要在 &lt;code&gt;sass/custom/_styles.scss&lt;/code&gt; 添加对应的样式：&lt;/p&gt;

&lt;figure class='code'&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;div class="highlight"&gt;&lt;table&gt;&lt;tr&gt;&lt;td class="gutter"&gt;&lt;pre class="line-numbers"&gt;&lt;span class='line-number'&gt;1&lt;/span&gt;
&lt;span class='line-number'&gt;2&lt;/span&gt;
&lt;span class='line-number'&gt;3&lt;/span&gt;
&lt;span class='line-number'&gt;4&lt;/span&gt;
&lt;span class='line-number'&gt;5&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class='code'&gt;&lt;pre&gt;&lt;code class='css'&gt;&lt;span class='line'&gt;&lt;span class="nf"&gt;#content&lt;/span&gt; &lt;span class="nt"&gt;article&lt;/span&gt; &lt;span class="nc"&gt;.cloud&lt;/span&gt; &lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;  &lt;span class="k"&gt;display&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;inline&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;  &lt;span class="k"&gt;list-style&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;none&lt;/span&gt; &lt;span class="k"&gt;outside&lt;/span&gt; &lt;span class="k"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;  &lt;span class="k"&gt;padding&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;4px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;第二个插件 octopress-tag-cloud 会和 Octopress 官方推荐的所谓「Octopress Tag Cloud」
 文件 / tag 标记 冲突，我建议修改官方的那个插件。&lt;/p&gt;

&lt;p&gt;我修改过的 octopress-tagcloud 在这里，被重命名为
&lt;a href="https://github.com/alswl/octopress-category-list"&gt;alswl / octopress-category-list&lt;/a&gt;。&lt;/p&gt;

&lt;p&gt;这个版本同时参考了 &lt;a href="http://pfmiles.github.com/blog/liquid-error-about-regexp-match-when-using-octopress-tagcloud/"&gt;pf_miles&lt;/a&gt; 的 utf-8 修改，以修复问题 &lt;code&gt;Liquid error: incompatible encoding regexp match (ASCII-8BIT regexp with UTF-8 string)&lt;/code&gt; 。&lt;/p&gt;

&lt;p&gt;最后 Show 一下我的&lt;a href="http://log4d.com/tag/"&gt;一坨标签云&lt;/a&gt;，
等有时间我再将标签和类别精简一下，以适应 Octopress。&lt;/p&gt;

		
  

&lt;div style="margin-top:15px;background:none repeat scroll 0pt 0pt rgb(238,238,238)"&gt;
  &lt;p&gt;
  &lt;strong&gt;版权所有 &amp;copy; 2010 转载本站文章请注明：&lt;/strong&gt; 转载自
  &lt;a href="http://log4d.com/" target="_blank"&gt;Log4D&lt;/a&gt;&lt;br&gt;
  &lt;strong&gt;原文链接:&lt;/strong&gt; &lt;a href="http://log4d.com/2012/05/tag-cloud/" target="_blank"&gt;http://log4d.com/2012/05/tag-cloud/&lt;/a&gt;&lt;br&gt;
  您可以随意地转载本站的文章，但是必须在醒目位置注明来源及本站链接，不可以将本站文章商业化使用，或者修改、转换或者以本作品为基础进行创作。&lt;br&gt;
  3a1ff193cee606bd1e2ea554a16353ee
  &lt;/p&gt;
&lt;/div&gt;

		
	&lt;img src="http://feeds.feedburner.com/~r/dddspace/~4/i03Me0Kjivk" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://log4d.com/2012/05/tag-cloud/</feedburner:origLink></entry>
  
  <entry>
    <title type="html"><![CDATA[《写给大家看的设计书》读后感]]></title>
    <link href="http://feedproxy.google.com/~r/dddspace/~3/cOT0qwHydbM/" />
    <updated>2012-05-19T18:10:00+08:00</updated>
    <id>http://log4d.com/2012/05/the-non-designers-design-book</id>
	<content type="html">
		
		&lt;p&gt;我读过两本关于视觉设计的书，一本是&lt;a href="http://book.douban.com/subject/6783748/"&gt;《写给程序员的Web设计书》&lt;/a&gt;，
这是第二本&lt;a href="http://book.douban.com/subject/3323633/"&gt;《写给大家看的设计书》&lt;/a&gt;。&lt;/p&gt;

&lt;p&gt;&lt;img src="http://img3.douban.com/lpic/s6485795.jpg" alt="写给大家看的设计书" /&gt;&lt;/p&gt;

&lt;p&gt;我对前者的评价是「作者花了大约25%的篇幅来讲述设计理念和方法，这也是我真正想看的部分。
本来想从书中获取更多布局、色彩、字体的内容，发现还是太少了。图灵系的书翻译不错。」&lt;/p&gt;

&lt;p&gt;相对应的，《写给大家看的设计书》是我真心想看的设计入门书。作者的文字功底好，经验丰富，
范例适合，取材广泛，总之，是不可多得的一本好书。&lt;/p&gt;

&lt;!--more--&gt;


&lt;p&gt;书中提到了设计四大原则：亲密性 / 对齐 / 重复 / 对比。依靠这四个原则，
就可以设计出效果不错的出版物（包括书籍、文档、幻灯片、网页等等）&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;对比（Contrast）：对比的基本思想是，要避免页面上的元素过于相似，如果元素
（字体、颜色、大小、线宽、形状、空间等）不相同，那就干脆让它们截然不同。
要让页面引人注目，对比通常是最重要的一个因素，正是它能使读者首先看到这个页面。&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;重复（Repetition）：让设计中的视觉要素在整个作品中重复出现。
可以重复颜色、形状、材质、空间关系、线宽、字体、大小和图片，等等。
这样依赖，既能增加条理性，还可以加强统一性。&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;对齐（Alignment）：任何东西都不能在页面上随意安放。
每个元素都应当与页面的另一个元素有某种视觉联系。这样能建立一种清晰、
精巧而且清爽的外观。&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;亲密性（Proximity）：彼此相关的项应当靠近，归组在一起。
如果多个项相互之间存在很近的亲密性，它们就会成为一个视觉单元，
而不是多个孤立的元素。这有助于组织信息，减少混乱，为读者提供清晰的结构。&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;除了设计的四大原则，书中还花费 1/3 的篇幅介绍西文字体，
看完可以对字体有一些初步认识。唯一遗憾的是，中文字体属于 CJK 体系，
书中没有介绍。&lt;/p&gt;

&lt;p&gt;西文字体主要分&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Oldstyle&lt;/li&gt;
&lt;li&gt;Modern&lt;/li&gt;
&lt;li&gt;Slab serif&lt;/li&gt;
&lt;li&gt;Sans serif&lt;/li&gt;
&lt;li&gt;Script&lt;/li&gt;
&lt;li&gt;Decorative&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;我认为做产品的、做前端的，或者对艺术和美感兴趣的（比如我），都应该读一读这本书。&lt;/p&gt;

		
  

&lt;div style="margin-top:15px;background:none repeat scroll 0pt 0pt rgb(238,238,238)"&gt;
  &lt;p&gt;
  &lt;strong&gt;版权所有 &amp;copy; 2010 转载本站文章请注明：&lt;/strong&gt; 转载自
  &lt;a href="http://log4d.com/" target="_blank"&gt;Log4D&lt;/a&gt;&lt;br&gt;
  &lt;strong&gt;原文链接:&lt;/strong&gt; &lt;a href="http://log4d.com/2012/05/the-non-designers-design-book/" target="_blank"&gt;http://log4d.com/2012/05/the-non-designers-design-book/&lt;/a&gt;&lt;br&gt;
  您可以随意地转载本站的文章，但是必须在醒目位置注明来源及本站链接，不可以将本站文章商业化使用，或者修改、转换或者以本作品为基础进行创作。&lt;br&gt;
  3a1ff193cee606bd1e2ea554a16353ee
  &lt;/p&gt;
&lt;/div&gt;

		
	&lt;img src="http://feeds.feedburner.com/~r/dddspace/~4/cOT0qwHydbM" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://log4d.com/2012/05/the-non-designers-design-book/</feedburner:origLink></entry>
  
  <entry>
    <title type="html"><![CDATA[关于 NetworkManager / PolicyKit / ConsoleKit 的那些屌事]]></title>
    <link href="http://feedproxy.google.com/~r/dddspace/~3/nPYJP49oJXE/" />
    <updated>2012-05-17T09:07:00+08:00</updated>
    <id>http://log4d.com/2012/05/networkmanager-policykit-consolekit</id>
	<content type="html">
		
		&lt;p&gt;在使用 Awesome 的过程中，我又遇到了一个老问题「NetworkManager 在非 Gnome
环境启动后，会无法 添加 / 删除 / 编辑 无线连接」。明眼人一看就知道，
这是权限的问题。&lt;/p&gt;

&lt;h2&gt;问题描述&lt;/h2&gt;

&lt;p&gt;我的环境是 &lt;strong&gt;ArchLinux / xmonad 0.10 / awesome v3.4.11 / GDM 3.4.1 / NetworkManager 0.9.4.0&lt;/strong&gt;，
下面我用 awesome 做示例，其他非 Gnome WM 也应该是类似配置。&lt;/p&gt;

&lt;p&gt;我的 WM 启动流程是：
通过 GDM 启动 xmonad / awesome，启动 xsession 是 &lt;code&gt;/usr/share/xsessions/awesome.desktop&lt;/code&gt;，
内容如下&lt;/p&gt;

&lt;!--more--&gt;




&lt;figure class='code'&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;div class="highlight"&gt;&lt;table&gt;&lt;tr&gt;&lt;td class="gutter"&gt;&lt;pre class="line-numbers"&gt;&lt;span class='line-number'&gt;1&lt;/span&gt;
&lt;span class='line-number'&gt;2&lt;/span&gt;
&lt;span class='line-number'&gt;3&lt;/span&gt;
&lt;span class='line-number'&gt;4&lt;/span&gt;
&lt;span class='line-number'&gt;5&lt;/span&gt;
&lt;span class='line-number'&gt;6&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class='code'&gt;&lt;pre&gt;&lt;code class='ini'&gt;&lt;span class='line'&gt;&lt;span class="k"&gt;[Desktop Entry]&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;&lt;span class="na"&gt;Name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;Awesome&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;&lt;span class="na"&gt;Comment&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;This session logs you into Awesome&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;&lt;span class="na"&gt;Type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;Application&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;&lt;span class="na"&gt;Exec&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;ck-launch-session dbus-launch $HOME/.start-session.sh awesome&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;&lt;span class="na"&gt;TryExec&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;/usr/bin/awesome&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;&lt;code&gt;$HOME/.start-session.sh&lt;/code&gt; 中的作用是启动 &lt;strong&gt;nm-applet&lt;/strong&gt; 和 &lt;strong&gt;exec awesome&lt;/strong&gt;。&lt;/p&gt;

&lt;p&gt;启动之后的情况是 NetworkManager 无线 编辑/删除 按钮变灰无法点击，或者可以点击，
但是会发生 &lt;strong&gt;insufficient privileges&lt;/strong&gt; 错误。&lt;/p&gt;

&lt;p&gt;&lt;img src="http://upload.log4d.com/2012/05/insufficient-privileges.png" alt="insufficient privileges" /&gt;&lt;/p&gt;

&lt;h2&gt;问题原因&lt;/h2&gt;

&lt;p&gt;这个问题是由 PolicyKit 和 ConsoleKit 启动不当引起的。&lt;/p&gt;

&lt;p&gt;PolicyKit 是：&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;PolicyKit allows fine-tuned capabilities in desktop enviroment. Traditionally only privilaged user (root) was allowed to configure network. However while in server enviroment it is reasonable assumption it would be too limiting to not allowed to connect to hotspot on laptop. Still however you may not want to give full privilages to this person (like installing programs) or you want to limit options for some people (for example on your children laptops only &amp;#8216;trusted&amp;#8217; networks with parential filters can be used). As far as I remember it works like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Program send message to daemon via dbus about action&lt;/li&gt;
&lt;li&gt;Daemon uses PolicyKit libraries/configuration (in fact PolicyKit daemon) to determine if user is allowed to perform action. It may happen that the certain confition must be fullfilled (like entering password or hardware access).&lt;/li&gt;
&lt;li&gt;Deamon performs action according to it (returns auth error or perform action)&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;ConsoleKit 是：&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;In short consolekit is service which tracks user sessions (i.e. where user is logged in). It allows switching users without logging out [many user can be logged in on the same hardware at the same time with one user active]. It is also used to check if session is &amp;#8220;local&amp;#8221; i.e. if user have direct access to hardware (which may be considered more secure then remote access).&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;参考：&lt;a href="http://unix.stackexchange.com/questions/5220/what-are-consolekit-and-policykit-how-do-they-work"&gt;What are ConsoleKit and PolicyKit? How do they work?&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;所以简而言之，ConsoleKit 是用来管理用户会话的，PolicyKit 是用来处理用户申请特殊权限的，
他们两个经常工作在一起。&lt;/p&gt;

&lt;p&gt;有个 PolicyKit 认证 API 教程可以一看：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.kissuki.com/blog/2009/03/10/policykit/"&gt;使用 PolicyKit 进行身份认证（上）&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.kissuki.com/blog/2009/03/12/policykit/"&gt;使用 PolicyKit 进行身份认证（中）&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.kissuki.com/blog/2009/03/13/policykit/"&gt;使用 PolicyKit 进行身份认证（下）&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;我的这个问题就是由于 PolicyKit 无法正确授权引起的。&lt;/p&gt;

&lt;h2&gt;问题解决&lt;/h2&gt;

&lt;p&gt;我开始吭次吭次的 Google，一会就找到了 Arch Wiki 中 &lt;a href="https://wiki.archlinux.org/index.php/NetworkManager#Set_up_PolicyKit_permissions"&gt;NetworkManager&lt;/a&gt; 的解决办法：&lt;/p&gt;

&lt;figure class='code'&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;div class="highlight"&gt;&lt;table&gt;&lt;tr&gt;&lt;td class="gutter"&gt;&lt;pre class="line-numbers"&gt;&lt;span class='line-number'&gt;1&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class='code'&gt;&lt;pre&gt;&lt;code class='bash'&gt;&lt;span class='line'&gt;&lt;span class="nb"&gt;exec &lt;/span&gt;ck-launch-session dbus-launch wm
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;写的很清楚，使用 &lt;strong&gt;ck-launch-session&lt;/strong&gt; 和 &lt;strong&gt;dbus-launch&lt;/strong&gt; 来加载 WM。但是我已经使用
&lt;code&gt;ck-launch-session&lt;/code&gt; 来启动 WM 了。&lt;/p&gt;

&lt;p&gt;随后我把怀疑的目光放到 &lt;code&gt;/usr/lib/polkit-gnome/polkit-gnome-authentication-agent-1&lt;/code&gt;
这个程序给系统提供 PolicyKit 权限认证，请求时候会让用户输入密码，如下图：&lt;/p&gt;

&lt;p&gt;&lt;img src="http://upload.log4d.com/2012/05/policykit-agent.png" alt="PolicyKit Agent" /&gt;&lt;/p&gt;

&lt;p&gt;可惜还是不行。&lt;/p&gt;

&lt;p&gt;我甚至还参考&lt;a href="http://blog.san-ss.com.ar/2011/03/using-gnome-keyring-in-xmonad.html"&gt;Using gnome keyring in xmonad&lt;/a&gt;
试图手工建立一个 Gnome Keyring。事实证明，Gnome Keyring 和这个问题无关。&lt;/p&gt;

&lt;p&gt;最后，我用 &lt;code&gt;ck-list-sessions&lt;/code&gt; 命令查看运行的用户 Session，发现同时运行着两个，
一个处于 &lt;code&gt;Active&lt;/code&gt;，一个不处于 &lt;code&gt;Active&lt;/code&gt;，这下真相大白了：GDM 启动时候会自己启动
&lt;code&gt;ck-launch-session&lt;/code&gt;，不用自己手动启动，否则会造成两个会话而无法正确授权。&lt;/p&gt;

&lt;figure class='code'&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;div class="highlight"&gt;&lt;table&gt;&lt;tr&gt;&lt;td class="gutter"&gt;&lt;pre class="line-numbers"&gt;&lt;span class='line-number'&gt;1&lt;/span&gt;
&lt;span class='line-number'&gt;2&lt;/span&gt;
&lt;span class='line-number'&gt;3&lt;/span&gt;
&lt;span class='line-number'&gt;4&lt;/span&gt;
&lt;span class='line-number'&gt;5&lt;/span&gt;
&lt;span class='line-number'&gt;6&lt;/span&gt;
&lt;span class='line-number'&gt;7&lt;/span&gt;
&lt;span class='line-number'&gt;8&lt;/span&gt;
&lt;span class='line-number'&gt;9&lt;/span&gt;
&lt;span class='line-number'&gt;10&lt;/span&gt;
&lt;span class='line-number'&gt;11&lt;/span&gt;
&lt;span class='line-number'&gt;12&lt;/span&gt;
&lt;span class='line-number'&gt;13&lt;/span&gt;
&lt;span class='line-number'&gt;14&lt;/span&gt;
&lt;span class='line-number'&gt;15&lt;/span&gt;
&lt;span class='line-number'&gt;16&lt;/span&gt;
&lt;span class='line-number'&gt;17&lt;/span&gt;
&lt;span class='line-number'&gt;18&lt;/span&gt;
&lt;span class='line-number'&gt;19&lt;/span&gt;
&lt;span class='line-number'&gt;20&lt;/span&gt;
&lt;span class='line-number'&gt;21&lt;/span&gt;
&lt;span class='line-number'&gt;22&lt;/span&gt;
&lt;span class='line-number'&gt;23&lt;/span&gt;
&lt;span class='line-number'&gt;24&lt;/span&gt;
&lt;span class='line-number'&gt;25&lt;/span&gt;
&lt;span class='line-number'&gt;26&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class='code'&gt;&lt;pre&gt;&lt;code class='bash'&gt;&lt;span class='line'&gt;Session2:
&lt;/span&gt;&lt;span class='line'&gt;  unix-user &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;1000&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;  &lt;span class="nv"&gt;realname&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Jason Ti&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;  &lt;span class="nv"&gt;seat&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Seat1&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;  session-type &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;  &lt;span class="nv"&gt;active&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; TRUE
&lt;/span&gt;&lt;span class='line'&gt;  x11-display &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;:0&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;  x11-display-device &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;/dev/tty7&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;  display-device &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;  remote-host-name &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;  is-local &lt;span class="o"&gt;=&lt;/span&gt; TRUE
&lt;/span&gt;&lt;span class='line'&gt;  on-since &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;2012-05-17T00:54:31.706019Z&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;  login-session-id &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;2&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;Session3:
&lt;/span&gt;&lt;span class='line'&gt;  unix-user &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;1000&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;  &lt;span class="nv"&gt;realname&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Jason Ti&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;  &lt;span class="nv"&gt;seat&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Seat1&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;  session-type &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;  &lt;span class="nv"&gt;active&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; False
&lt;/span&gt;&lt;span class='line'&gt;  x11-display &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;:0&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;  x11-display-device &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;/dev/tty7&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;  display-device &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;  remote-host-name &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;  is-local &lt;span class="o"&gt;=&lt;/span&gt; TRUE
&lt;/span&gt;&lt;span class='line'&gt;  on-since &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;2012-05-17T00:54:33.3465302Z&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;  login-session-id &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;2&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;修正 &lt;code&gt;/usr/share/xsessions/awesome.desktop&lt;/code&gt; 如下：&lt;/p&gt;

&lt;figure class='code'&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;div class="highlight"&gt;&lt;table&gt;&lt;tr&gt;&lt;td class="gutter"&gt;&lt;pre class="line-numbers"&gt;&lt;span class='line-number'&gt;1&lt;/span&gt;
&lt;span class='line-number'&gt;2&lt;/span&gt;
&lt;span class='line-number'&gt;3&lt;/span&gt;
&lt;span class='line-number'&gt;4&lt;/span&gt;
&lt;span class='line-number'&gt;5&lt;/span&gt;
&lt;span class='line-number'&gt;6&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class='code'&gt;&lt;pre&gt;&lt;code class='ini'&gt;&lt;span class='line'&gt;&lt;span class="k"&gt;[Desktop Entry]&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;&lt;span class="na"&gt;Name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;Awesome&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;&lt;span class="na"&gt;Comment&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;This session logs you into Awesome&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;&lt;span class="na"&gt;Type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;Application&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;&lt;span class="na"&gt;Exec&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;$HOME/.start-session.sh awesome&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;&lt;span class="na"&gt;TryExec&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;/usr/bin/awesome&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;事实上，在启动完 GDM 还没进入 WM 之前，&lt;code&gt;Ctrl+Alt+F1&lt;/code&gt; 切换到命令行下面，查看进程会发现&lt;/p&gt;

&lt;figure class='code'&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;div class="highlight"&gt;&lt;table&gt;&lt;tr&gt;&lt;td class="gutter"&gt;&lt;pre class="line-numbers"&gt;&lt;span class='line-number'&gt;1&lt;/span&gt;
&lt;span class='line-number'&gt;2&lt;/span&gt;
&lt;span class='line-number'&gt;3&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class='code'&gt;&lt;pre&gt;&lt;code class='ini'&gt;&lt;span class='line'&gt;&lt;span class="err"&gt;root&lt;/span&gt;       &lt;span class="err"&gt;637&lt;/span&gt;     &lt;span class="err"&gt;1&lt;/span&gt;  &lt;span class="err"&gt;0&lt;/span&gt; &lt;span class="err"&gt;08:44&lt;/span&gt; &lt;span class="err"&gt;?&lt;/span&gt;        &lt;span class="err"&gt;00:00:00&lt;/span&gt; &lt;span class="err"&gt;/usr/lib/polkit-1/polkitd&lt;/span&gt; &lt;span class="err"&gt;--no-debug&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;&lt;span class="err"&gt;root&lt;/span&gt;      &lt;span class="err"&gt;1072&lt;/span&gt;     &lt;span class="err"&gt;1&lt;/span&gt;  &lt;span class="err"&gt;0&lt;/span&gt; &lt;span class="err"&gt;08:44&lt;/span&gt; &lt;span class="err"&gt;?&lt;/span&gt;        &lt;span class="err"&gt;00:00:00&lt;/span&gt; &lt;span class="err"&gt;/usr/sbin/console-kit-daemon&lt;/span&gt; &lt;span class="err"&gt;--no-daemon&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;&lt;span class="err"&gt;rtkit&lt;/span&gt;     &lt;span class="err"&gt;1260&lt;/span&gt;     &lt;span class="err"&gt;1&lt;/span&gt;  &lt;span class="err"&gt;0&lt;/span&gt; &lt;span class="err"&gt;08:45&lt;/span&gt; &lt;span class="err"&gt;?&lt;/span&gt;        &lt;span class="err"&gt;00:00:00&lt;/span&gt; &lt;span class="err"&gt;/usr/lib/rtkit-daemon&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;果不其然，PolicyKit 和 ConsoleKit 已经在运行了。&lt;/p&gt;

&lt;p&gt;实测 Awesome / Xmonad 已经可以正常授权 NetworkManager 来编辑无线了。&lt;/p&gt;

		
  

&lt;div style="margin-top:15px;background:none repeat scroll 0pt 0pt rgb(238,238,238)"&gt;
  &lt;p&gt;
  &lt;strong&gt;版权所有 &amp;copy; 2010 转载本站文章请注明：&lt;/strong&gt; 转载自
  &lt;a href="http://log4d.com/" target="_blank"&gt;Log4D&lt;/a&gt;&lt;br&gt;
  &lt;strong&gt;原文链接:&lt;/strong&gt; &lt;a href="http://log4d.com/2012/05/networkmanager-policykit-consolekit/" target="_blank"&gt;http://log4d.com/2012/05/networkmanager-policykit-consolekit/&lt;/a&gt;&lt;br&gt;
  您可以随意地转载本站的文章，但是必须在醒目位置注明来源及本站链接，不可以将本站文章商业化使用，或者修改、转换或者以本作品为基础进行创作。&lt;br&gt;
  3a1ff193cee606bd1e2ea554a16353ee
  &lt;/p&gt;
&lt;/div&gt;

		
	&lt;img src="http://feeds.feedburner.com/~r/dddspace/~4/nPYJP49oJXE" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://log4d.com/2012/05/networkmanager-policykit-consolekit/</feedburner:origLink></entry>
  
  <entry>
    <title type="html"><![CDATA[使用独立图床子域名]]></title>
    <link href="http://feedproxy.google.com/~r/dddspace/~3/m7NPYm_EHA4/" />
    <updated>2012-05-09T16:21:00+08:00</updated>
    <id>http://log4d.com/2012/05/image-host</id>
	<content type="html">
		
		&lt;p&gt;最近在将 Wordpres 切换到 OctoPress，顺便将图片统一放到&lt;a href="http://upload.log4d.com"&gt;Upload4D&lt;/a&gt;管理。&lt;/p&gt;

&lt;p&gt;我挑选图床管理程序有下面几个需求，需求由强到弱排列：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;开源&lt;/li&gt;
&lt;li&gt;简单&lt;/li&gt;
&lt;li&gt;不需数据库支持&lt;/li&gt;
&lt;li&gt;支持分目录&lt;/li&gt;
&lt;li&gt;允许上传图片&lt;/li&gt;
&lt;li&gt;支持后台直接操作文件&lt;/li&gt;
&lt;li&gt;支持用户管理，不允许其他人上传&lt;/li&gt;
&lt;li&gt;页面美观&lt;/li&gt;
&lt;li&gt;不要生成缩略图等文件&lt;/li&gt;
&lt;li&gt;软件持续更新&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;于是我踏上了「考古之旅」，先后试用了 MiniGal Nano / MG2 /
CF Image Host Script / minishowcase 等等图床软件，评测记录如下。&lt;/p&gt;

&lt;!--more--&gt;


&lt;h2&gt;参赛选手&lt;/h2&gt;

&lt;h3&gt;&lt;a href="http://www.minigal.dk/minigal-nano.html"&gt;MiniGal Nano&lt;/a&gt;&lt;/h3&gt;

&lt;p&gt;&lt;img src="http://upload.log4d.com/2012/05/mg-nano.png" title="MiniGal Nano" alt="MG Nano" /&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;没有上传功能&lt;/li&gt;
&lt;li&gt;没有后台管理功能&lt;/li&gt;
&lt;li&gt;2010年最后更新&lt;/li&gt;
&lt;/ul&gt;


&lt;h3&gt;&lt;a href="http://www.minigal.dk/mg2.html"&gt;MG2&lt;/a&gt;&lt;/h3&gt;

&lt;p&gt;&lt;img src="http://upload.log4d.com/2012/05/mg2-front.png" alt="MG2 前台" /&gt;
&lt;img src="http://upload.log4d.com/2012/05/mg2-admin.png" alt="MG2 管理界面" /&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;假目录，其实所有照片在同一目录下面&lt;/li&gt;
&lt;li&gt;界面丑&lt;/li&gt;
&lt;li&gt;09年更新&lt;/li&gt;
&lt;/ul&gt;


&lt;h3&gt;&lt;a href="http://meiu.cn/"&gt;美优网 Meiu Studio|php相册系统&lt;/a&gt;&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;国产&lt;/li&gt;
&lt;li&gt;需要 MySQL&lt;/li&gt;
&lt;/ul&gt;


&lt;h3&gt;&lt;a href="http://www.codefuture.co.uk/projects/imagehost/"&gt;CF Image Hosting Script v1.4.2&lt;/a&gt;&lt;/h3&gt;

&lt;p&gt;&lt;img src="http://upload.log4d.com/2012/05/cf-image-host.png" alt="CF Image Hosting" /&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;据说煎蛋在使用&lt;/li&gt;
&lt;li&gt;无法用户控制&lt;/li&gt;
&lt;li&gt;无目录&lt;/li&gt;
&lt;/ul&gt;


&lt;h3&gt;&lt;a href="http://minishowcase.net/"&gt;Minishowcase&lt;/a&gt;&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;没看见上传功能&lt;/li&gt;
&lt;li&gt;没看见目录功能&lt;/li&gt;
&lt;li&gt;丑&lt;/li&gt;
&lt;li&gt;2009年更新&lt;/li&gt;
&lt;/ul&gt;


&lt;h3&gt;&lt;a href="http://qdig.sourceforge.net/"&gt;Qdig&lt;/a&gt;&lt;/h3&gt;

&lt;p&gt;&lt;img src="http://upload.log4d.com/2012/05/qdig.png" alt="Qdig" /&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;无法上传&lt;/li&gt;
&lt;li&gt;丑&lt;/li&gt;
&lt;li&gt;2006年更新&lt;/li&gt;
&lt;/ul&gt;


&lt;h3&gt;&lt;a href="http://sourceforge.net/projects/ifoto/"&gt;iFoto, CSS-based GD2 photo gallery&lt;/a&gt;&lt;/h3&gt;

&lt;p&gt;&lt;img src="http://upload.log4d.com/2012/05/ifoto.png" alt="iFoto" /&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;无法上传&lt;/li&gt;
&lt;li&gt;丑&lt;/li&gt;
&lt;li&gt;2006年更新&lt;/li&gt;
&lt;/ul&gt;


&lt;h3&gt;&lt;a href="http://encode-explorer.siineiolekala.net/"&gt;Encode Explorer&lt;/a&gt;&lt;/h3&gt;

&lt;p&gt;&lt;img src="http://upload.log4d.com/2012/05/encode-explorer.png" alt="Encode Explorer" /&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;这其实是一个文件管理器&lt;/li&gt;
&lt;li&gt;支持预览&lt;/li&gt;
&lt;li&gt;不支持多文件上传&lt;/li&gt;
&lt;li&gt;其他要求全部达到&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;最终选择&lt;/h2&gt;

&lt;p&gt;最后，我选择了 Encode Explorer，坑爹吧，获胜者居然是一个文件管理软件，
而不是一个图床软件。&lt;/p&gt;

&lt;p&gt;Encode Explorer 是单文件程序，代码一共3k多行，我看了一下，还能支持多语言，
我就加上了中文支持，并且修正了新建目录/新建文件的权限 bug，改为目录755,
文件644，并且这两个模式可以在配置文件修改。&lt;/p&gt;

&lt;p&gt;修改之后的 Encode Explorer 可以在
&lt;a href="https://github.com/alswl/encode-explorer"&gt;alswl / encode-explorer&lt;/a&gt; 找到。&lt;/p&gt;

&lt;p&gt;既然已经不单纯是图床了，那我也把以前的一些附件放到这个子域名下，域名也要由
img.log4d.com 改为 upload.log4d.com 。&lt;/p&gt;

&lt;p&gt;我用 sed 命令将原来的图片和附件命令批量修改，命令如下
&lt;code&gt;sed -i 's/log4d.com\/wp-content\/uploads/upload.log4d.com/g' ./_posts/*&lt;/code&gt;。&lt;/p&gt;

&lt;p&gt;ps:今天是我博客独立3周年纪念日，本来想在今天之前把 Wordpress 迁移到
OctoPress，可惜最近太忙，就耽误了。&lt;/p&gt;

		
  

&lt;div style="margin-top:15px;background:none repeat scroll 0pt 0pt rgb(238,238,238)"&gt;
  &lt;p&gt;
  &lt;strong&gt;版权所有 &amp;copy; 2010 转载本站文章请注明：&lt;/strong&gt; 转载自
  &lt;a href="http://log4d.com/" target="_blank"&gt;Log4D&lt;/a&gt;&lt;br&gt;
  &lt;strong&gt;原文链接:&lt;/strong&gt; &lt;a href="http://log4d.com/2012/05/image-host/" target="_blank"&gt;http://log4d.com/2012/05/image-host/&lt;/a&gt;&lt;br&gt;
  您可以随意地转载本站的文章，但是必须在醒目位置注明来源及本站链接，不可以将本站文章商业化使用，或者修改、转换或者以本作品为基础进行创作。&lt;br&gt;
  3a1ff193cee606bd1e2ea554a16353ee
  &lt;/p&gt;
&lt;/div&gt;

		
	&lt;img src="http://feeds.feedburner.com/~r/dddspace/~4/m7NPYm_EHA4" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://log4d.com/2012/05/image-host/</feedburner:origLink></entry>
  
  <entry>
    <title type="html"><![CDATA[《HTML5 实战 WebApp 阅读应用 – Shiu》幻灯片]]></title>
    <link href="http://feedproxy.google.com/~r/dddspace/~3/_BfBWtiN-D8/" />
    <updated>2012-05-05T00:00:00+08:00</updated>
    <id>http://log4d.com/2012/05/shiu-slide-show</id>
	<content type="html">
		
		&lt;p&gt;&lt;p&gt;今天去南京 HTML5 沙龙分享了一个幻灯片，讲 Shiu 的开发，同时也分享在这里。&lt;/p&gt;
&lt;p&gt;&lt;object height="355" id="__sse12809450" width="425"&gt; &lt;param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=slide-120505055956-phpapp02&amp;amp;stripped_title=html5-webapp-shiu&amp;amp;userName=alswl" /&gt; &lt;param name="allowFullScreen" value="true" /&gt; &lt;param name="allowScriptAccess" value="always" /&gt; &lt;param name="wmode" value="transparent" /&gt; &lt;embed allowfullscreen="true" allowscriptaccess="always" height="355" name="__sse12809450" src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=slide-120505055956-phpapp02&amp;amp;stripped_title=html5-webapp-shiu&amp;amp;userName=alswl" type="application/x-shockwave-flash" width="425" wmode="transparent"&gt; &lt;/embed&gt; &lt;/object&gt;&lt;/p&gt;
&lt;p&gt;Shiu 的源码托管在 Github，地址是 &lt;a href="https://github.com/alswl/shiu"&gt;https://github.com/alswl/shiu&lt;/a&gt; 感兴趣可以去看看。&lt;/p&gt;
&lt;p&gt;噢，Shiu (/ʃʐy/)，中文音标 (shi r&amp;uuml;))，是一款基于 WebApp 的阅读应用。&lt;/p&gt;
&lt;/p&gt;

		
  

&lt;div style="margin-top:15px;background:none repeat scroll 0pt 0pt rgb(238,238,238)"&gt;
  &lt;p&gt;
  &lt;strong&gt;版权所有 &amp;copy; 2010 转载本站文章请注明：&lt;/strong&gt; 转载自
  &lt;a href="http://log4d.com/" target="_blank"&gt;Log4D&lt;/a&gt;&lt;br&gt;
  &lt;strong&gt;原文链接:&lt;/strong&gt; &lt;a href="http://log4d.com/2012/05/shiu-slide-show/" target="_blank"&gt;http://log4d.com/2012/05/shiu-slide-show/&lt;/a&gt;&lt;br&gt;
  您可以随意地转载本站的文章，但是必须在醒目位置注明来源及本站链接，不可以将本站文章商业化使用，或者修改、转换或者以本作品为基础进行创作。&lt;br&gt;
  3a1ff193cee606bd1e2ea554a16353ee
  &lt;/p&gt;
&lt;/div&gt;

		
	&lt;img src="http://feeds.feedburner.com/~r/dddspace/~4/_BfBWtiN-D8" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://log4d.com/2012/05/shiu-slide-show/</feedburner:origLink></entry>
  
  <entry>
    <title type="html"><![CDATA[Vim 下模拟 Emacs 键绑定]]></title>
    <link href="http://feedproxy.google.com/~r/dddspace/~3/lU0Eu9uXI14/" />
    <updated>2012-04-20T00:00:00+08:00</updated>
    <id>http://log4d.com/2012/04/vim-emacs-key-binding</id>
	<content type="html">
		
		&lt;p&gt;Vimer 需要 Emacs 键绑定？看上去很蛋疼的需求吧。其实不然，大部分的 Shell / Readline 默认绑定的是 Emacs 键位绑定（处于输入状态下，Emacs 的键位很好用）。Vim 的模式切换很牛逼，但是 Insert 模式下面，只有寥寥几个快捷键，我修改了配置文件，绑定需要的 Emcas 按键到 Vim 中来。&lt;/p&gt;

&lt;p&gt;Github 中搜索关键字 Vim Emcas key bind，出来一些结果，不是很完美，我又慢慢调教了几个星期，放出我的 .vimrc。&lt;/p&gt;

&lt;figure class='code'&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;div class="highlight"&gt;&lt;table&gt;&lt;tr&gt;&lt;td class="gutter"&gt;&lt;pre class="line-numbers"&gt;&lt;span class='line-number'&gt;1&lt;/span&gt;
&lt;span class='line-number'&gt;2&lt;/span&gt;
&lt;span class='line-number'&gt;3&lt;/span&gt;
&lt;span class='line-number'&gt;4&lt;/span&gt;
&lt;span class='line-number'&gt;5&lt;/span&gt;
&lt;span class='line-number'&gt;6&lt;/span&gt;
&lt;span class='line-number'&gt;7&lt;/span&gt;
&lt;span class='line-number'&gt;8&lt;/span&gt;
&lt;span class='line-number'&gt;9&lt;/span&gt;
&lt;span class='line-number'&gt;10&lt;/span&gt;
&lt;span class='line-number'&gt;11&lt;/span&gt;
&lt;span class='line-number'&gt;12&lt;/span&gt;
&lt;span class='line-number'&gt;13&lt;/span&gt;
&lt;span class='line-number'&gt;14&lt;/span&gt;
&lt;span class='line-number'&gt;15&lt;/span&gt;
&lt;span class='line-number'&gt;16&lt;/span&gt;
&lt;span class='line-number'&gt;17&lt;/span&gt;
&lt;span class='line-number'&gt;18&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class='code'&gt;&lt;pre&gt;&lt;code class='bash'&gt;&lt;span class='line'&gt;&lt;span class="s2"&gt;&amp;quot; 模拟 Emacs 键绑定&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; Move
&lt;/span&gt;&lt;span class='line'&gt;inoremap &amp;lt;C-a&amp;gt; &amp;lt;Home&amp;gt;
&lt;/span&gt;&lt;span class='line'&gt;inoremap &amp;lt;C-e&amp;gt; &amp;lt;End&amp;gt;
&lt;/span&gt;&lt;span class='line'&gt;&lt;span class="s2"&gt;&amp;quot;inoremap &amp;lt;C-p&amp;gt; &amp;lt;Up&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;inoremap &amp;lt;C-n&amp;gt; &amp;lt;Down&amp;gt;
&lt;/span&gt;&lt;span class='line'&gt;inoremap &amp;lt;C-b&amp;gt; &amp;lt;Left&amp;gt;
&lt;/span&gt;&lt;span class='line'&gt;inoremap &amp;lt;C-f&amp;gt; &amp;lt;Right&amp;gt;
&lt;/span&gt;&lt;span class='line'&gt;inoremap &amp;lt;M-b&amp;gt; &amp;lt;C-o&amp;gt;b
&lt;/span&gt;&lt;span class='line'&gt;inoremap &amp;lt;M-f&amp;gt; &amp;lt;C-o&amp;gt;w
&lt;/span&gt;&lt;span class='line'&gt;&lt;span class="s2"&gt;&amp;quot; Rubout word / line and enter insert mode&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; use &amp;lt;Esc&amp;gt;&amp;lt;Right&amp;gt; instead of &amp;lt;C-o&amp;gt;
&lt;/span&gt;&lt;span class='line'&gt;inoremap &amp;lt;C-w&amp;gt; &amp;lt;Esc&amp;gt;dbcl
&lt;/span&gt;&lt;span class='line'&gt;&lt;span class="err"&gt;&amp;quot;&lt;/span&gt; delete
&lt;/span&gt;&lt;span class='line'&gt;inoremap &amp;lt;C-u&amp;gt; &amp;lt;Esc&amp;gt;d0cl
&lt;/span&gt;&lt;span class='line'&gt;inoremap &amp;lt;C-k&amp;gt; &amp;lt;Esc&amp;gt;&amp;lt;Right&amp;gt;C
&lt;/span&gt;&lt;span class='line'&gt;inoremap &amp;lt;C-d&amp;gt; &amp;lt;Esc&amp;gt;&amp;lt;Right&amp;gt;s
&lt;/span&gt;&lt;span class='line'&gt;inoremap &amp;lt;M-d&amp;gt; &amp;lt;C-o&amp;gt;de
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;需要的朋友请取用，我的 Vim 配置文件和插件在 &lt;a href="https://github.com/alswl/dotfiles"&gt;https://github.com/alswl/dotfiles&lt;/a&gt; 。&lt;/p&gt;

		
  

&lt;div style="margin-top:15px;background:none repeat scroll 0pt 0pt rgb(238,238,238)"&gt;
  &lt;p&gt;
  &lt;strong&gt;版权所有 &amp;copy; 2010 转载本站文章请注明：&lt;/strong&gt; 转载自
  &lt;a href="http://log4d.com/" target="_blank"&gt;Log4D&lt;/a&gt;&lt;br&gt;
  &lt;strong&gt;原文链接:&lt;/strong&gt; &lt;a href="http://log4d.com/2012/04/vim-emacs-key-binding/" target="_blank"&gt;http://log4d.com/2012/04/vim-emacs-key-binding/&lt;/a&gt;&lt;br&gt;
  您可以随意地转载本站的文章，但是必须在醒目位置注明来源及本站链接，不可以将本站文章商业化使用，或者修改、转换或者以本作品为基础进行创作。&lt;br&gt;
  3a1ff193cee606bd1e2ea554a16353ee
  &lt;/p&gt;
&lt;/div&gt;

		
	&lt;img src="http://feeds.feedburner.com/~r/dddspace/~4/lU0Eu9uXI14" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://log4d.com/2012/04/vim-emacs-key-binding/</feedburner:origLink></entry>
  
  <entry>
    <title type="html"><![CDATA[使用 Vundle 管理 Vim 插件]]></title>
    <link href="http://feedproxy.google.com/~r/dddspace/~3/miTtDPSluD0/" />
    <updated>2012-04-14T00:00:00+08:00</updated>
    <id>http://log4d.com/2012/04/vundle</id>
	<content type="html">
		
		&lt;p&gt;早在这个月初，我就在 Vim 的邮件列表看到了一封关于 Vim 插件管理的
&lt;a href="https://groups.google.com/d/topic/vim-cn/mPES0sNT87Q/discussion"&gt;邮件&lt;/a&gt;。
才惊呼原来有这么强大的插件可以用来管理我那一坨插件，
今天细细阅读并查了一些资料，变开始配置自己的 Vim。&lt;/p&gt;

&lt;h2&gt;几种管理插件&lt;/h2&gt;

&lt;p&gt;Vim 的插件管理工具有蛮多，比如：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/gmarik/vundle"&gt;Vundle&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.vim.org/scripts/script.php?script_id=2905"&gt;vim-addon-manager&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.vim.org/scripts/script.php?script_id=2332"&gt;vpathogen.vim&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.vim.org/scripts/script.php?script_id=3458"&gt;vvundle&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/c9s/Vimana"&gt;vvimana&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.douban.com/note/173144456/"&gt;一位同学自己写的&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Vim-addon-manager 和 vimana 的对比，参见
&lt;a href="http://yixf.name/2011/10/26/vim%E7%9A%84%E6%8F%92%E4%BB%B6%E7%AE%A1%E7%90%86%E5%B7%A5%E5%85%B7/"&gt;Vim的插件管理工具&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;我最会选择了 Vundle，通过子目录管理插件，支持 Git 更新。
我其实不太喜欢子目录，觉得目录太多看着烦，但是考虑到在没有一个良好的 PKG
包描述文件的前提下，分子目录是一种简单有效的方法。&lt;/p&gt;

&lt;!--more--&gt;


&lt;p&gt;Vundle 通过 git 来对插件进行更新，有三种源可以添加：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;github 中 vim-scripts 的项目（这个账号是为 Pathogen 建的，用来建立对 Vim.org 上脚本的镜像）&lt;/li&gt;
&lt;li&gt;github 某个 Vim 插件项目&lt;/li&gt;
&lt;li&gt;某个 git 源&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;以上也是我推荐的选择插件顺序，我认为没有必要去取最新的开发版插件。&lt;/p&gt;

&lt;h2&gt;Vundle 安装&lt;/h2&gt;

&lt;p&gt;无二话，官方文档的 &lt;a href="https://github.com/gmarik/vundle"&gt;Quick Start&lt;/a&gt;
写的很详细 ，一句话：&lt;/p&gt;

&lt;figure class='code'&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;div class="highlight"&gt;&lt;table&gt;&lt;tr&gt;&lt;td class="gutter"&gt;&lt;pre class="line-numbers"&gt;&lt;span class='line-number'&gt;1&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class='code'&gt;&lt;pre&gt;&lt;code class='bash'&gt;&lt;span class='line'&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;git clone https://github.com/gmarik/vundle.git ~/.vim/bundle/vundle
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;然后开始配置 .vimrc，我的 &lt;a href="https://github.com/alswl/dotfiles/blob/master/.vimrc"&gt;.vimrc&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;重点是配置各种 &lt;code&gt;Bundle&lt;/code&gt; 我的配置如下&lt;/p&gt;

&lt;figure class='code'&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;div class="highlight"&gt;&lt;table&gt;&lt;tr&gt;&lt;td class="gutter"&gt;&lt;pre class="line-numbers"&gt;&lt;span class='line-number'&gt;1&lt;/span&gt;
&lt;span class='line-number'&gt;2&lt;/span&gt;
&lt;span class='line-number'&gt;3&lt;/span&gt;
&lt;span class='line-number'&gt;4&lt;/span&gt;
&lt;span class='line-number'&gt;5&lt;/span&gt;
&lt;span class='line-number'&gt;6&lt;/span&gt;
&lt;span class='line-number'&gt;7&lt;/span&gt;
&lt;span class='line-number'&gt;8&lt;/span&gt;
&lt;span class='line-number'&gt;9&lt;/span&gt;
&lt;span class='line-number'&gt;10&lt;/span&gt;
&lt;span class='line-number'&gt;11&lt;/span&gt;
&lt;span class='line-number'&gt;12&lt;/span&gt;
&lt;span class='line-number'&gt;13&lt;/span&gt;
&lt;span class='line-number'&gt;14&lt;/span&gt;
&lt;span class='line-number'&gt;15&lt;/span&gt;
&lt;span class='line-number'&gt;16&lt;/span&gt;
&lt;span class='line-number'&gt;17&lt;/span&gt;
&lt;span class='line-number'&gt;18&lt;/span&gt;
&lt;span class='line-number'&gt;19&lt;/span&gt;
&lt;span class='line-number'&gt;20&lt;/span&gt;
&lt;span class='line-number'&gt;21&lt;/span&gt;
&lt;span class='line-number'&gt;22&lt;/span&gt;
&lt;span class='line-number'&gt;23&lt;/span&gt;
&lt;span class='line-number'&gt;24&lt;/span&gt;
&lt;span class='line-number'&gt;25&lt;/span&gt;
&lt;span class='line-number'&gt;26&lt;/span&gt;
&lt;span class='line-number'&gt;27&lt;/span&gt;
&lt;span class='line-number'&gt;28&lt;/span&gt;
&lt;span class='line-number'&gt;29&lt;/span&gt;
&lt;span class='line-number'&gt;30&lt;/span&gt;
&lt;span class='line-number'&gt;31&lt;/span&gt;
&lt;span class='line-number'&gt;32&lt;/span&gt;
&lt;span class='line-number'&gt;33&lt;/span&gt;
&lt;span class='line-number'&gt;34&lt;/span&gt;
&lt;span class='line-number'&gt;35&lt;/span&gt;
&lt;span class='line-number'&gt;36&lt;/span&gt;
&lt;span class='line-number'&gt;37&lt;/span&gt;
&lt;span class='line-number'&gt;38&lt;/span&gt;
&lt;span class='line-number'&gt;39&lt;/span&gt;
&lt;span class='line-number'&gt;40&lt;/span&gt;
&lt;span class='line-number'&gt;41&lt;/span&gt;
&lt;span class='line-number'&gt;42&lt;/span&gt;
&lt;span class='line-number'&gt;43&lt;/span&gt;
&lt;span class='line-number'&gt;44&lt;/span&gt;
&lt;span class='line-number'&gt;45&lt;/span&gt;
&lt;span class='line-number'&gt;46&lt;/span&gt;
&lt;span class='line-number'&gt;47&lt;/span&gt;
&lt;span class='line-number'&gt;48&lt;/span&gt;
&lt;span class='line-number'&gt;49&lt;/span&gt;
&lt;span class='line-number'&gt;50&lt;/span&gt;
&lt;span class='line-number'&gt;51&lt;/span&gt;
&lt;span class='line-number'&gt;52&lt;/span&gt;
&lt;span class='line-number'&gt;53&lt;/span&gt;
&lt;span class='line-number'&gt;54&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class='code'&gt;&lt;pre&gt;&lt;code class='vim'&gt;&lt;span class='line'&gt;&lt;span class="c"&gt;&amp;quot; My Bundles here:&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;
&lt;/span&gt;&lt;span class='line'&gt;&lt;span class="c"&gt;&amp;quot; vim-scripts repos&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;
&lt;/span&gt;&lt;span class='line'&gt;&lt;span class="c"&gt;&amp;quot; Syntax&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;Bundle &lt;span class="s1"&gt;&amp;#39;asciidoc.vim&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;Bundle &lt;span class="s1"&gt;&amp;#39;confluencewiki.vim&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;Bundle &lt;span class="s1"&gt;&amp;#39;html5.vim&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;Bundle &lt;span class="s1"&gt;&amp;#39;JavaScript-syntax&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;&lt;span class="c"&gt;&amp;quot;Bundle &amp;#39;mako.vim&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;Bundle &lt;span class="s1"&gt;&amp;#39;moin.vim&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;Bundle &lt;span class="s1"&gt;&amp;#39;python.vim--Vasiliev&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;Bundle &lt;span class="s1"&gt;&amp;#39;xml.vim&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;
&lt;/span&gt;&lt;span class='line'&gt;&lt;span class="c"&gt;&amp;quot; Color&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;
&lt;/span&gt;&lt;span class='line'&gt;Bundle &lt;span class="s1"&gt;&amp;#39;desert256.vim&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;Bundle &lt;span class="s1"&gt;&amp;#39;Impact&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;Bundle &lt;span class="s1"&gt;&amp;#39;matrix.vim&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;Bundle &lt;span class="s1"&gt;&amp;#39;vibrantink&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;Bundle &lt;span class="s1"&gt;&amp;#39;vividchalk.vim&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;
&lt;/span&gt;&lt;span class='line'&gt;&lt;span class="c"&gt;&amp;quot; Ftplugin&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;Bundle &lt;span class="s1"&gt;&amp;#39;python_fold&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;
&lt;/span&gt;&lt;span class='line'&gt;&lt;span class="c"&gt;&amp;quot; Indent&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;&lt;span class="c"&gt;&amp;quot;Bundle &amp;#39;indent/html.vim&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;Bundle &lt;span class="s1"&gt;&amp;#39;IndentAnything&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;Bundle &lt;span class="s1"&gt;&amp;#39;Javascript-Indentation&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;Bundle &lt;span class="s1"&gt;&amp;#39;mako.vim--Torborg&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;Bundle &lt;span class="s1"&gt;&amp;#39;gg/python.vim&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;
&lt;/span&gt;&lt;span class='line'&gt;&lt;span class="c"&gt;&amp;quot; Plugin&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;Bundle &lt;span class="s1"&gt;&amp;#39;The-NERD-tree&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;Bundle &lt;span class="s1"&gt;&amp;#39;AutoClose--Alves&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;Bundle &lt;span class="s1"&gt;&amp;#39;auto_mkdir&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;Bundle &lt;span class="s1"&gt;&amp;#39;cecutil&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;Bundle &lt;span class="s1"&gt;&amp;#39;fcitx.vim&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;Bundle &lt;span class="s1"&gt;&amp;#39;FencView.vim&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;&lt;span class="c"&gt;&amp;quot;Bundle &amp;#39;FuzzyFinder&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;Bundle &lt;span class="s1"&gt;&amp;#39;jsbeautify&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;Bundle &lt;span class="s1"&gt;&amp;#39;L9&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;Bundle &lt;span class="s1"&gt;&amp;#39;Mark&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;Bundle &lt;span class="s1"&gt;&amp;#39;matrix.vim&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;Bundle &lt;span class="s1"&gt;&amp;#39;mru.vim&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;Bundle &lt;span class="s1"&gt;&amp;#39;The-NERD-Commenter&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;&lt;span class="c"&gt;&amp;quot;Bundle &amp;#39;project.vim&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;Bundle &lt;span class="s1"&gt;&amp;#39;restart.vim&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;Bundle &lt;span class="s1"&gt;&amp;#39;taglist.vim&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;&lt;span class="c"&gt;&amp;quot;Bundle &amp;#39;templates.vim&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;&lt;span class="c"&gt;&amp;quot;Bundle &amp;#39;vimim.vim&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;Bundle &lt;span class="s1"&gt;&amp;#39;ZenCoding.vim&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;Bundle &lt;span class="s1"&gt;&amp;#39;css_color.vim&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;span class='line'&gt;Bundle &lt;span class="s1"&gt;&amp;#39;hallettj/jslint.vim&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;需要注意的是，Vim 插件名称可能存在重名的情况，这时候就需要在插件后面加上作者的姓氏，
比如 &lt;code&gt;Bundle 'Javascript-Indentation'&lt;/code&gt; ，而遇到插件名有空格和斜杠的话，
需要将空格和斜杠替换为 &lt;code&gt;-&lt;/code&gt; 。&lt;/p&gt;

&lt;p&gt;执行 &lt;code&gt;BundleInstall&lt;/code&gt; 即可完成安装，如果出现错误提示，多半是名称有问题，
去 github 和 vim.org 搜索一下吧。&lt;/p&gt;

&lt;p&gt;更多参考：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://blog.houqp.me/use-vundle-to-manage-your-plugins/"&gt;Vim插件管理利器——Vundle&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.cnblogs.com/qiangji/archive/2011/07/31/Vundle.html"&gt;使用Vundle 来管理 Vim 插件&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;ps：这篇文章使用 Markdown 写的，以前都是用 Asciidoc 写，貌似是由于 github 带动，
Mardown 自 2010 年之后使用人群猛涨，证据在此，上图是 Markdown，下图是 Asciidoc&lt;/p&gt;

&lt;p&gt;&lt;img src="http://upload.log4d.com/2012/04/markdown-asciidoc.png" alt="Markdown vs Asciidoc" /&gt;&lt;/p&gt;

		
  

&lt;div style="margin-top:15px;background:none repeat scroll 0pt 0pt rgb(238,238,238)"&gt;
  &lt;p&gt;
  &lt;strong&gt;版权所有 &amp;copy; 2010 转载本站文章请注明：&lt;/strong&gt; 转载自
  &lt;a href="http://log4d.com/" target="_blank"&gt;Log4D&lt;/a&gt;&lt;br&gt;
  &lt;strong&gt;原文链接:&lt;/strong&gt; &lt;a href="http://log4d.com/2012/04/vundle/" target="_blank"&gt;http://log4d.com/2012/04/vundle/&lt;/a&gt;&lt;br&gt;
  您可以随意地转载本站的文章，但是必须在醒目位置注明来源及本站链接，不可以将本站文章商业化使用，或者修改、转换或者以本作品为基础进行创作。&lt;br&gt;
  3a1ff193cee606bd1e2ea554a16353ee
  &lt;/p&gt;
&lt;/div&gt;

		
	&lt;img src="http://feeds.feedburner.com/~r/dddspace/~4/miTtDPSluD0" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://log4d.com/2012/04/vundle/</feedburner:origLink></entry>
  
  <entry>
    <title type="html"><![CDATA[Fcitx 配置]]></title>
    <link href="http://feedproxy.google.com/~r/dddspace/~3/HQYCH4ahSTQ/" />
    <updated>2012-04-01T00:00:00+08:00</updated>
    <id>http://log4d.com/2012/04/fcitx-config</id>
	<content type="html">
		
		&lt;p&gt;&lt;h2&gt;&lt;a name="_fcitx"&gt;&lt;/a&gt;Fcitx&lt;/h2&gt;
&lt;p&gt;&lt;img alt="Fcitx" src="http://upload.log4d.com/2012/04/fcitx.png" style="border-width: 0;" /&gt;&lt;/p&gt;
&lt;p&gt;Fcitx 简介：&lt;/p&gt;
&lt;pre&gt;小企鹅中文输入法（Free Chinese Input Toy for X，fcitx）
是一个以 GPL 方式发布的输入法框架， 编写它的目是为桌面环境提供一个灵活的输入方案。&lt;/pre&gt;&lt;/p&gt;

&lt;p&gt;本程序目前可以支持XIM和GTK2，GTK3，QT4的IM Module，可为支持&lt;br /&gt;
XIM 的 X 应用程序提供输入服务。 fcitx 的源码包内提供了区位和全/简/双拼，&lt;br /&gt;
并支持基于码表的输入法（自带五笔、二笔和仓颉等输入码表）。&lt;/p&gt;

&lt;p&gt;您可以从 http://fcitx.googlecode.com 下载最新的发布版本。
&lt;p&gt;当年刚开始使用 Linux 时候，使用的是 iBus，随后发现 Fcitx 这个输入法， 试用了一下就发现自己所需要的 双拼 / 模糊音 / 自定义输入 功能都有提供， 遂转移阵地到 Fcitx。&lt;!--more--&gt;&lt;/p&gt;
&lt;h2&gt;&lt;a name="_fcitx_安装"&gt;&lt;/a&gt;Fcitx 安装&lt;/h2&gt;
&lt;p&gt;大部分发行版软件源都有 Fcitx，Arch 下安装使用命令 &lt;tt&gt;pacman -S fcitx&lt;/tt&gt; 即可安装最新版本。Ubuntu 的安装可以参考 &lt;a href="http://wiki.ubuntu.org.cn/Fcitx"&gt;http://wiki.ubuntu.org.cn/Fcitx&lt;/a&gt; 。&lt;/p&gt;
&lt;h2&gt;&lt;a name="_fcitx_配置"&gt;&lt;/a&gt;Fcitx 配置&lt;/h2&gt;
&lt;p&gt;详细的配置文档参见 &lt;a href="http://fcitx.github.com/handbook/fcitx.html"&gt;http://fcitx.github.com/handbook/fcitx.html&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;&lt;a name="_fcitx_特殊符号"&gt;&lt;/a&gt;Fcitx 特殊符号&lt;/h2&gt;
&lt;p&gt;当我们需要输入特殊符号（数字符号、箭头等等）时候，往往需要去网上搜索对应的 unicode 码，然后拷贝过来。Fcitx 提供一个很方便的功能叫做「特殊符号输入」， 可以定义自己的特殊符号。&lt;/p&gt;
&lt;p&gt;在 &lt;tt&gt;/usr/share/fcitx/pinyin/pySym.mb&lt;/tt&gt; / &lt;tt&gt;~/.config/fcitx/pinyin/pySym.mb&lt;/tt&gt; （ps：我当前版本是4.2.1，所以是这个路径，老版本可能不是这个路径） 中定义需要使用的特殊符号，格式为 &lt;tt&gt;&amp;lt;编码&amp;gt; &amp;lt;符号&amp;gt;&lt;/tt&gt; ，比如：&lt;/p&gt;
&lt;pre&gt;yinyue ♩
yinyue ♪
yinyue ♫
...&lt;/pre&gt;
&lt;p&gt;那么，在 Fcitx 中输入 &lt;tt&gt;yinyue&lt;/tt&gt; 就会出现如下候选框&lt;/p&gt;
&lt;p&gt;&lt;img alt="Fcitx 特殊符号" src="http://upload.log4d.com/2012/04/fcitx-1.png" style="border-width: 0;" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;tt&gt;pySym.mb&lt;/tt&gt; 文件中，「编码」和「符号」均不允许出现空格，所以比较适合短小的符号， 而颜文字或者长句不适合在这里出现。颜文字以及其他较长的文字如何快速输入， 就要看 Fcitx 的「快速输入」功能了。&lt;/p&gt;
&lt;p&gt;我在这里提供的配置文件包括了常用符号、数字、星座、箭头等等，喜欢可以直接拿去。 ps：我定义的「编码」是全拼，所以可能会混淆正常输入，建议全拼用户将「编码」略做 修改，添加前缀比如 &lt;tt&gt;z&lt;/tt&gt; （文档中说 &lt;tt&gt;v&lt;/tt&gt; 不能被使用为前缀）。&lt;/p&gt;
&lt;p&gt;配置完成之后，使用 &lt;tt&gt;fcitx -r&lt;/tt&gt; 重启 Fcitx（使用 Ctrl+5 可以刷新配置文件， 但并不能刷新全部配置文件，建议重启 Fcitx）。 待会配置「快速输入」之后，也需要重启 Fcitx 来让配置文件生效。&lt;/p&gt;
&lt;p&gt;我的配置文件 &lt;a href="https://github.com/alswl/fcitx-config/blob/master/pinyin/pySym.mb"&gt;fcitx-config / pinyin / pySym.mb&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;&lt;a name="_fcitx_快速输入"&gt;&lt;/a&gt;Fcitx 快速输入&lt;/h2&gt;
&lt;p&gt;Fcitx 的「快速输入」和「特殊符号」很类似，后者管理字符，前者管理自定义语句。&lt;/p&gt;
&lt;p&gt;快速输入通过 &lt;tt&gt;；&lt;/tt&gt; 按键启用，随后输入相应的「字符组合」，Fcitx 会自动补全。&lt;/p&gt;
&lt;p&gt;编码对照文件存放在 &lt;tt&gt;~/.config/fcitx/data/QuickPhrase.mb&lt;/tt&gt; 或 &lt;tt&gt;share&lt;/tt&gt; 目录下对应的文件中，格式为 &lt;tt&gt;&amp;lt;字符组合&amp;gt; &amp;lt;短语&amp;gt;&lt;/tt&gt; ，范例如下&lt;/p&gt;
&lt;pre&gt;# 颜文字欢呼 （颜文字太需要了，卖个萌什么的太管用了）
yhuanhu (/&amp;ge;▽&amp;le;/)
yhuanhu ヾ(o◕&amp;forall;◕)ﾉ&lt;/pre&gt;
&lt;p&gt;在输入法中，键入 &lt;tt&gt;；&lt;/tt&gt; 之后再输入 &lt;tt&gt;yhuanhu&lt;/tt&gt; 就会出现下面候选框：&lt;/p&gt;
&lt;p&gt;&lt;img alt="Fcitx 快速输入" src="http://upload.log4d.com/2012/04/fcitx-2.png" style="border-width: 0;" /&gt;&lt;/p&gt;
&lt;p&gt;从图中可以看出，Fcitx 还自动进行了「字符组合」补全。&lt;/p&gt;
&lt;p&gt;我的 &lt;a href="https://github.com/alswl/fcitx-config/blob/master/data/QuickPhrase.mb"&gt;fcitx-config / data / QuickPhrase.mb&lt;/a&gt; 配置文件按类别收集了一些颜文字，可以直接拿过来使用。&lt;/p&gt;
&lt;p&gt;参考链接：&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;a href="http://zhan.renren.com/fullcirclectt?tagId=163058&amp;amp;checked=true"&gt;FCCTT推送特别篇&amp;mdash;&amp;mdash;FCITX输入法快速输入表情&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://site.douban.com/widget/notes/4567539/note/197244464/"&gt;颜文字收集整理╰(&lt;strong&gt;&amp;deg;▽&amp;deg;&lt;/strong&gt;)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;a name="_fcitx_中文键位映射"&gt;&lt;/a&gt;Fcitx 中文键位映射&lt;/h2&gt;
&lt;p&gt;很多朋友和我一样，喜欢使用「和」来替换&amp;ldquo;/&amp;rdquo;，至于为什么，知乎有一个回答就解释的很好 &lt;a href="http://www.zhihu.com/question/19589668"&gt;为什么大家引用时常用直角引号（「」）而不是弯引号（&amp;ldquo;&amp;rdquo;）？&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Fcitx 完全可以通过配置中英文键位映射来修改中文状态下面的输入。全局配置文件在 &lt;tt&gt;/usr/share/fcitx/data/punc.mb.zh_CN&lt;/tt&gt; 中， 个人配置文件在 &lt;tt&gt;~/.config/fcitx/data/punc.mb/zh_CN&lt;/tt&gt; 这个对应位置。&lt;/p&gt;
&lt;p&gt;我的配置 &lt;a href="https://github.com/alswl/fcitx-config/blob/master/data/punc.mb.zh_CN"&gt;fcitx-config / data / punc.mb.zh_CN&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;&lt;a name="_最后"&gt;&lt;/a&gt;最后&lt;/h2&gt;
&lt;p&gt;关于 Fcitx，有 bug 可以到官网反馈，处理起来效率很高， 感谢作者们给大家带来这么优秀的开源软件。&lt;/p&gt;
&lt;p&gt;Update:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;2012-03-02 感谢 @Weng Xuetian 指正 &lt;tt&gt;Ctrl + F5&lt;/tt&gt; 是错误的，需要使用 &lt;tt&gt;Ctrl + 5&lt;/tt&gt; 重载配置。&lt;/li&gt;
&lt;/ul&gt;
&lt;/p&gt;

		
  

&lt;div style="margin-top:15px;background:none repeat scroll 0pt 0pt rgb(238,238,238)"&gt;
  &lt;p&gt;
  &lt;strong&gt;版权所有 &amp;copy; 2010 转载本站文章请注明：&lt;/strong&gt; 转载自
  &lt;a href="http://log4d.com/" target="_blank"&gt;Log4D&lt;/a&gt;&lt;br&gt;
  &lt;strong&gt;原文链接:&lt;/strong&gt; &lt;a href="http://log4d.com/2012/04/fcitx-config/" target="_blank"&gt;http://log4d.com/2012/04/fcitx-config/&lt;/a&gt;&lt;br&gt;
  您可以随意地转载本站的文章，但是必须在醒目位置注明来源及本站链接，不可以将本站文章商业化使用，或者修改、转换或者以本作品为基础进行创作。&lt;br&gt;
  3a1ff193cee606bd1e2ea554a16353ee
  &lt;/p&gt;
&lt;/div&gt;

		
	&lt;img src="http://feeds.feedburner.com/~r/dddspace/~4/HQYCH4ahSTQ" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://log4d.com/2012/04/fcitx-config/</feedburner:origLink></entry>
  
  <entry>
    <title type="html"><![CDATA[GAE 编程指南读书笔记]]></title>
    <link href="http://feedproxy.google.com/~r/dddspace/~3/IsQOF5gG3t0/" />
    <updated>2012-03-24T00:00:00+08:00</updated>
    <id>http://log4d.com/2012/03/gae</id>
	<content type="html">
		
		&lt;p&gt;&lt;p&gt;GAE 和我蛮有缘分，我初学 Python 的其中一个原因就是当时 GAE 刚推出， 当时想法是免费的应用要用起来，要不然就浪费了。随后也假模假样的看文档， 就是没有什么产出。&lt;/p&gt;
&lt;p&gt;去年写了一个小应用 &lt;a href="https://github.com/alswl/dbevent2gc"&gt;dbevent2gc&lt;/a&gt; ， 期间发现 GAE 和普通程序开发的诸多不同，又遭遇 GAE 配额大幅缩水， 写出来的应用运转的不太稳定。在南京图书馆的架上看见这本《GAE 编程指南读书笔记》， 立即借回家仔细阅读。&lt;!--more--&gt;&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;GAE 的简介&lt;br /&gt;
		&lt;ul&gt;
			&lt;li&gt;运行时环境 Python / Java&lt;/li&gt;
			&lt;li&gt;数据存储 Datastore（实体 / 查询 / 索引 / 事务）&lt;/li&gt;
			&lt;li&gt;服务（Memcache / GAccount / 任务队列 / 计划任务）&lt;/li&gt;
			&lt;li&gt;工具（SDK / appcfg / dev_appserver / 控制台）&lt;/li&gt;
		&lt;/ul&gt;
	&lt;/li&gt;
	&lt;li&gt;入门（安装 / GAccount / webapp / app.yaml / /_ah/admin / 注册部署 / login:required）&lt;/li&gt;
	&lt;li&gt;处理流程：请求 - 前端 - 引用服务器 / 静态文件服务器 - 服务&lt;br /&gt;
		&lt;ul&gt;
			&lt;li&gt;配额限制：请求限制 / CPU 限制 / 服务限制 / 部署限制 （最新配额：http://code.google.com/intl/zh-CN/appengine/docs/quotas.html）&lt;/li&gt;
		&lt;/ul&gt;
	&lt;/li&gt;
	&lt;li&gt;数据存储&lt;br /&gt;
		&lt;ul&gt;
			&lt;li&gt;GAE 的数据存储方式和传统的 RDBMS 差异比较大，更类似于对象数据库。&lt;/li&gt;
			&lt;li&gt;类别 kind / 键 / 键名 key name&lt;/li&gt;
			&lt;li&gt;可以通过键来获取和操作对象&lt;br /&gt;
				&lt;ul&gt;
					&lt;li&gt;&lt;tt&gt;e = db.get(db.Key(&amp;#39;Entity&amp;#39;, &amp;#39;alphabeta&amp;#39;))&lt;/tt&gt; / &lt;tt&gt;e = Entity.get(k)&lt;/tt&gt;&lt;/li&gt;
					&lt;li&gt;&lt;tt&gt;e = db.get(k)&lt;/tt&gt;&lt;/li&gt;
					&lt;li&gt;&lt;tt&gt;e.delete()&lt;/tt&gt; / &lt;tt&gt;db.delete(e1, e2)&lt;/tt&gt; / &lt;tt&gt;db.delete(k)&lt;/tt&gt;&lt;/li&gt;
				&lt;/ul&gt;
			&lt;/li&gt;
			&lt;li&gt;Expando 基类可以任意扩展属性，Model 基类则不可。&lt;/li&gt;
			&lt;li&gt;GAE 中基本类型与 Python / Java 中基本类型的差异&lt;/li&gt;
			&lt;li&gt;多值属性&lt;/li&gt;
		&lt;/ul&gt;
	&lt;/li&gt;
	&lt;li&gt;数据查询&lt;br /&gt;
		&lt;ul&gt;
			&lt;li&gt;查询和类别 &lt;tt&gt;db.query()&lt;/tt&gt; &lt;tt&gt;query.filter()&lt;/tt&gt; &lt;tt&gt;query.order()&lt;/tt&gt;&lt;/li&gt;
			&lt;li&gt;查询和键：查询结果要么返回实体，要么返回键（ &lt;tt&gt;key_only=True&lt;/tt&gt; ）&lt;/li&gt;
			&lt;li&gt;可以用 GQL 写查询语句，不能写 CUD&lt;/li&gt;
			&lt;li&gt;获取结果： &lt;tt&gt;fetch()&lt;/tt&gt;&lt;/li&gt;
		&lt;/ul&gt;
	&lt;/li&gt;
	&lt;li&gt;索引&lt;br /&gt;
		&lt;ul&gt;
			&lt;li&gt;每条查询都需要维护一条索引，在 &lt;tt&gt;index.yaml&lt;/tt&gt; 中可以配置&lt;/li&gt;
			&lt;li&gt;排序之后的索引查询很快，查询效率和返回结果集有关&lt;/li&gt;
			&lt;li&gt;实体的每个属性会自动维护两条索引：升序和降序&lt;/li&gt;
			&lt;li&gt;查询时候选取对应的索引进行查询，条件语句可能和排序语句相冲突&lt;/li&gt;
			&lt;li&gt;不等于 / IN 操作符将引发一系列变换出的查询&lt;/li&gt;
			&lt;li&gt;多值字段的索引：每个值会成为索引中一行 / 实体会因此分散 / 取第一次成功扫描到的行&lt;/li&gt;
			&lt;li&gt;多值会引入爆炸索引问题&lt;/li&gt;
		&lt;/ul&gt;
	&lt;/li&gt;
	&lt;li&gt;事务&lt;br /&gt;
		&lt;ul&gt;
			&lt;li&gt;通过实体组来控制事务，实体组会在同一块存储区&lt;/li&gt;
			&lt;li&gt;GAE 使用乐观锁&lt;/li&gt;
			&lt;li&gt;使用 &lt;tt&gt;AModel(parent=p)&lt;/tt&gt; 构造祖先，然后通过 &lt;tt&gt;run_in_transation()&lt;/tt&gt; 回调事务处理函数&lt;/li&gt;
			&lt;li&gt;BigTable 中使用日志+时间戳来跟踪实体的修改，保证数据并发和一致性&lt;/li&gt;
			&lt;li&gt;事务更新和索引更新：可能返回的索引结果和实体不一致&lt;/li&gt;
		&lt;/ul&gt;
	&lt;/li&gt;
	&lt;li&gt;Python 数据建模&lt;br /&gt;
		&lt;ul&gt;
			&lt;li&gt;声明 / 类型 / 验证（ &lt;tt&gt;validate()&lt;/tt&gt; ）&lt;/li&gt;
			&lt;li&gt;不编入索引的属性 &lt;tt&gt;indexed=False&lt;/tt&gt;&lt;/li&gt;
			&lt;li&gt;时间类型的自动值&lt;/li&gt;
			&lt;li&gt;模型变化带来的维护问题：修改属性类型 / 添加一个必要属性是不向后兼容的。&lt;/li&gt;
			&lt;li&gt;关系建模&lt;br /&gt;
				&lt;ul&gt;
					&lt;li&gt;db.ReferenceProperty&lt;/li&gt;
					&lt;li&gt;collection_name&lt;/li&gt;
				&lt;/ul&gt;
			&lt;/li&gt;
			&lt;li&gt;多对多关系的处理&lt;br /&gt;
				&lt;ul&gt;
					&lt;li&gt;键列表方法：使用多值属性&lt;/li&gt;
					&lt;li&gt;链接模型方法：相当于中间表概念&lt;/li&gt;
				&lt;/ul&gt;
			&lt;/li&gt;
			&lt;li&gt;模型的继承：通过 &lt;tt&gt;db.PolyModel&lt;/tt&gt; 实现多态查询&lt;/li&gt;
		&lt;/ul&gt;
	&lt;/li&gt;
	&lt;li&gt;Memcache&lt;br /&gt;
		&lt;ul&gt;
			&lt;li&gt;CRUD&lt;/li&gt;
		&lt;/ul&gt;
	&lt;/li&gt;
	&lt;li&gt;获取 URL 资源&lt;br /&gt;
		&lt;ul&gt;
			&lt;li&gt;&lt;tt&gt;urlfetch()&lt;/tt&gt;&lt;/li&gt;
		&lt;/ul&gt;
	&lt;/li&gt;
	&lt;li&gt;RPC 异步请求调用，闭包调用&lt;/li&gt;
	&lt;li&gt;邮件和 XMPP&lt;br /&gt;
		&lt;ul&gt;
			&lt;li&gt;额，亲用到时候看 Google 官方文档吧～&lt;/li&gt;
		&lt;/ul&gt;
	&lt;/li&gt;
	&lt;li&gt;大批量数据操作和远程访问&lt;br /&gt;
		&lt;ul&gt;
			&lt;li&gt;&lt;tt&gt;/remote_api&lt;/tt&gt;&lt;/li&gt;
			&lt;li&gt;Bulk Loader 大量数据操作&lt;/li&gt;
			&lt;li&gt;远程 shell &lt;tt&gt;remote_api_shell.py app-id&lt;/tt&gt;&lt;/li&gt;
		&lt;/ul&gt;
	&lt;/li&gt;
	&lt;li&gt;任务队列和计划任务&lt;br /&gt;
		&lt;ul&gt;
			&lt;li&gt;队列： &lt;tt&gt;queue.yaml&lt;/tt&gt; / 令牌桶&lt;/li&gt;
			&lt;li&gt;计划任务： &lt;tt&gt;cron.yaml&lt;/tt&gt;&lt;/li&gt;
			&lt;li&gt;都是通过设定主动触发某个 url&lt;/li&gt;
		&lt;/ul&gt;
	&lt;/li&gt;
	&lt;li&gt;Django&lt;br /&gt;
		&lt;ul&gt;
			&lt;li&gt;看 Django 文档吧，亲～&lt;/li&gt;
		&lt;/ul&gt;
	&lt;/li&gt;
	&lt;li&gt;部署&lt;br /&gt;
		&lt;ul&gt;
			&lt;li&gt;上传 &lt;tt&gt;appcfg.py update ./clock&lt;/tt&gt;&lt;/li&gt;
			&lt;li&gt;通过 url 使用特定版本： &lt;tt&gt;version-id.latest.app-id.appspot.com&lt;/tt&gt;&lt;/li&gt;
			&lt;li&gt;版本只维护代码，数据库还是同一份&lt;/li&gt;
			&lt;li&gt;下载日志 &lt;tt&gt;appcfg.py request_logs clock logs.txt&lt;/tt&gt;&lt;/li&gt;
		&lt;/ul&gt;
	&lt;/li&gt;
&lt;/ul&gt;
&lt;/p&gt;

		
  

&lt;div style="margin-top:15px;background:none repeat scroll 0pt 0pt rgb(238,238,238)"&gt;
  &lt;p&gt;
  &lt;strong&gt;版权所有 &amp;copy; 2010 转载本站文章请注明：&lt;/strong&gt; 转载自
  &lt;a href="http://log4d.com/" target="_blank"&gt;Log4D&lt;/a&gt;&lt;br&gt;
  &lt;strong&gt;原文链接:&lt;/strong&gt; &lt;a href="http://log4d.com/2012/03/gae/" target="_blank"&gt;http://log4d.com/2012/03/gae/&lt;/a&gt;&lt;br&gt;
  您可以随意地转载本站的文章，但是必须在醒目位置注明来源及本站链接，不可以将本站文章商业化使用，或者修改、转换或者以本作品为基础进行创作。&lt;br&gt;
  3a1ff193cee606bd1e2ea554a16353ee
  &lt;/p&gt;
&lt;/div&gt;

		
	&lt;img src="http://feeds.feedburner.com/~r/dddspace/~4/IsQOF5gG3t0" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://log4d.com/2012/03/gae/</feedburner:origLink></entry>
  
  <entry>
    <title type="html"><![CDATA[在Python中调试代码]]></title>
    <link href="http://feedproxy.google.com/~r/dddspace/~3/Oc_DmrUKDJM/" />
    <updated>2012-03-20T00:00:00+08:00</updated>
    <id>http://log4d.com/2012/03/python-debug</id>
	<content type="html">
		
		&lt;p&gt;撰写程序时候，需要在调试上面花费不少时间，好的调试工具可以让这个过程如虎添翼， 靠打 log 调试会是一种很痛苦的过程，我总结一下 Pylons 开发的调试技巧。&lt;/p&gt;
&lt;p&gt;吐槽：团队开发时候，每个成员需要学习、总结和分享各自的开发技巧， 这样才能自我提升并提高开发效率。这属于团队文化建设，开发是一种艺术创造过程， 绝对不是简单的复制和粘帖。&lt;/p&gt;
&lt;h2&gt;&lt;a name="_在_python_中调试"&gt;&lt;/a&gt;在 Python 中调试&lt;/h2&gt;
&lt;h3&gt;&lt;a name="_pdb"&gt;&lt;/a&gt;pdb&lt;/h3&gt;
&lt;p&gt;在代码中加入下列语句即可启用交互式调试。&lt;/p&gt;
&lt;pre class="brush: python;fontsize: 100; first-line: 1; "&gt;import pdb;pdb.set_trace()&lt;/pre&gt;
&lt;p&gt;在 pdb 中，可以使用 &lt;tt&gt;h / l / b / n / s / c / j / a / p / ! / q&lt;/tt&gt; 这些命令所代表的含义可以通过 &lt;tt&gt;h(elp)&lt;/tt&gt; 打印出来。&lt;/p&gt;
&lt;p&gt;参考链接：&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;a href="http://magustest.com/blog/python/use-pdb-debug-python/comment-page-1"&gt;用PDB库调试Python程序&lt;!--more--&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&lt;a name="_ipdb"&gt;&lt;/a&gt;ipdb&lt;/h3&gt;
&lt;p&gt;比 pdb 更好用的是 ipdb，需要预先安装 IPython，通过 IPython 可以提供更强的交互功能。&lt;/p&gt;
&lt;p&gt;安装 ipdb: &lt;tt&gt;easy_install ipdb&lt;/tt&gt; ， 使用方法依然是 &lt;tt&gt;import ipdb;ipdb.set_trace()&lt;/tt&gt; 。&lt;/p&gt;
&lt;p&gt;ps: 根据我的测试，ipdb 0.61 不能和 ipython 0.91 正常工作， 会报 &lt;tt&gt;ImportError: No module named core.debugger&lt;/tt&gt; 错误，请尝试使用 ipython 0.10 或者更新版本。这个错误在 ipdb 官网有 issue 描述 （&lt;a href="https://github.com/gotcha/ipdb/issues/9"&gt;link&lt;/a&gt;）。&lt;/p&gt;
&lt;h3&gt;&lt;a name="_使用_embed_python_shell"&gt;&lt;/a&gt;使用 embed python shell&lt;/h3&gt;
&lt;p&gt;除了特定代码的调试，有时候我们还需要在开发一个功能之前进行尝试性代码撰写， 这点在 web 开发时候尤其有用。托 Python 动态语言特性的福，我们可以很方便的使用 Interactivate Shell 进行开发。&lt;/p&gt;
&lt;p&gt;在项目的根目录建立一个 Python 脚本，比如 &lt;tt&gt;shell.py&lt;/tt&gt; ，其中代码如下：&lt;/p&gt;
&lt;pre class="brush: python;fontsize: 100; first-line: 1; "&gt;#!/usr/bin/env python
#coding=utf-8&lt;/pre&gt;&lt;/p&gt;

&lt;p&gt;# desc: 这个shell提供Python上下文环境，方便调试&lt;br /&gt;
# author: alswl&lt;br /&gt;
# date: 2012-03-20&lt;/p&gt;

&lt;p&gt;def main():&lt;br /&gt;
        # Do something for init here.&lt;br /&gt;
    try:&lt;br /&gt;
        from IPython.frontend.terminal.embed import InteractiveShellEmbed&lt;br /&gt;
        ipshell = InteractiveShellEmbed()&lt;br /&gt;
        ipshell()&lt;br /&gt;
    except ImportError:&lt;br /&gt;
        import code&lt;br /&gt;
        pyshell = code.InteractiveConsole(locals=locals())&lt;br /&gt;
        pyshell.interact()&lt;/p&gt;

&lt;p&gt;if __name__ == &amp;#39;__main__&amp;#39;:&lt;br /&gt;
    main()
&lt;p&gt;这段代码先尝试使用 IPython 作为交互 shell，如果没有安装就使用原生 Python 作为 交互 Shell。(强烈建议使用 IPython)。&lt;/p&gt;
&lt;p&gt;请在 &lt;tt&gt;main()&lt;/tt&gt; 方法开始时候做一些初始化动作，比如载入 webapp 的实例并初始化各路config， 这样就能实现即时代码测试功能，提高开发效率，不用一遍遍地跑流程。&lt;/p&gt;
&lt;p&gt;参考链接&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;a href="http://qixinglu.com/archives/embed_python_shell_in_code"&gt;http://qixinglu.com/archives/embed_python_shell_in_code&lt;/a&gt; （注意， 这篇文章是2011年的，其中引入 IPython 的 &lt;tt&gt;InteractiveShellEmbed&lt;/tt&gt; 的方法已经过期，请参考上面的代码）&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&lt;a name="_gae_中的_pdb"&gt;&lt;/a&gt;GAE 中的 pdb&lt;/h3&gt;
&lt;p&gt;有一些特定系统，比如 GAE 和 nosetests，他们会重定向 &lt;tt&gt;std:in&lt;/tt&gt; 和 &lt;tt&gt;std:out&lt;/tt&gt; ， 造成 pdb 无法正确输入和输出，在使用的使用，需要用以下代码做个 hack。&lt;/p&gt;
&lt;pre class="brush: python;fontsize: 100; first-line: 1; "&gt;import sys
import pdb
for attr in (&amp;#39;stdin&amp;#39;, &amp;#39;stdout&amp;#39;, &amp;#39;stderr&amp;#39;):
    setattr(sys, attr, getattr(sys, &amp;#39;__%s__&amp;#39; % attr))
pdb.set_trace()&lt;/pre&gt;
&lt;h2&gt;&lt;a name="_pylons_调试"&gt;&lt;/a&gt;Pylons 调试&lt;/h2&gt;
&lt;p&gt;Paster 的 Shell 交互式调试更显犀利（官方所称杀手级功能）， 可以直接使用 &lt;tt&gt;paster shell dev.ini&lt;/tt&gt; 命令启用交互界面，默认会先尝试载入 IPython，不存在就载入原生 Shell。&lt;/p&gt;
&lt;p&gt;我当前使用的 Paster 版本为 1.7.5,无法正确识 IPython 0.11及以上版本， 请使用0.9.1或者0.10。&lt;/p&gt;
&lt;p&gt;参考链接：&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;a href="http://wiki.pylonshq.com/pages/viewpage.action?pageId=9011323"&gt;How can I use &amp;quot;paster shell&amp;quot; to develop doctest tests?&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://stackoverflow.com/questions/7389388/pylons-paster-shell-does-not-run-in-ipython"&gt;stackoverflow 上关于 IPython 版本的问题&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

		
  

&lt;div style="margin-top:15px;background:none repeat scroll 0pt 0pt rgb(238,238,238)"&gt;
  &lt;p&gt;
  &lt;strong&gt;版权所有 &amp;copy; 2010 转载本站文章请注明：&lt;/strong&gt; 转载自
  &lt;a href="http://log4d.com/" target="_blank"&gt;Log4D&lt;/a&gt;&lt;br&gt;
  &lt;strong&gt;原文链接:&lt;/strong&gt; &lt;a href="http://log4d.com/2012/03/python-debug/" target="_blank"&gt;http://log4d.com/2012/03/python-debug/&lt;/a&gt;&lt;br&gt;
  您可以随意地转载本站的文章，但是必须在醒目位置注明来源及本站链接，不可以将本站文章商业化使用，或者修改、转换或者以本作品为基础进行创作。&lt;br&gt;
  3a1ff193cee606bd1e2ea554a16353ee
  &lt;/p&gt;
&lt;/div&gt;

		
	&lt;img src="http://feeds.feedburner.com/~r/dddspace/~4/Oc_DmrUKDJM" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://log4d.com/2012/03/python-debug/</feedburner:origLink></entry>
  
  <entry>
    <title type="html"><![CDATA[Chrome 独立代理设置]]></title>
    <link href="http://feedproxy.google.com/~r/dddspace/~3/nMz_UR-v9hk/" />
    <updated>2012-03-15T00:00:00+08:00</updated>
    <id>http://log4d.com/2012/03/chrome-proxy</id>
	<content type="html">
		
		&lt;p&gt;&lt;p&gt;Chrome 在2011年4月份时候，加入了两个新的实验性扩展分支，分别是 Web Navigation Extension API 以及 Proxy Extension API， 通过他们，可以让 Chrome 使用自己独立的代理。&lt;/p&gt;
&lt;p&gt;借助这个新功能，我们可以通过 SwitchySharp 使用某个 list 完成部分网址代理。&lt;/p&gt;
&lt;p&gt;我的环境： Arch Linux / Chromiun(17.0.963.78) / Proxy SwitchySharp 1.9.38。&lt;!--more--&gt;&lt;/p&gt;
&lt;h2&gt;&lt;a name="_安装_proxy_switchysharp"&gt;&lt;/a&gt;安装 Proxy SwitchySharp&lt;/h2&gt;
&lt;p&gt;由于 &lt;a href="http://code.google.com/p/switchyplus/"&gt;SwitchyPlus&lt;/a&gt; 停止维护， 因此这里我使用 &lt;a href="http://code.google.com/p/switchysharp/"&gt;Proxy SwitchySharp&lt;/a&gt;。&lt;/p&gt;
&lt;p&gt;Proxy SwitchySharp 介绍如下：&lt;/p&gt;
&lt;pre class="brush: plain;fontsize: 100; first-line: 1; "&gt;轻松快捷地管理和切换多个代理设置。基于 &amp;quot;Proxy Switchy!&amp;quot; 和 &amp;quot;SwitchyPlus&amp;quot; 开发。
使用 SwitchySharp 和 GFW List 的图文教程（一次成功，无需重启）  http://is.gd/swap2&lt;/pre&gt;&lt;/p&gt;

&lt;p&gt;**注意！我无法在这个页面回复你的提问。如果有任何故障反馈、求助、建议，请移步项目主页，谢谢！=&amp;gt; http://code.google.com/p/switchysharp/issues/entry&lt;/p&gt;

&lt;p&gt;特色：&lt;/p&gt;

&lt;p&gt;: 使用 Chrome 代理 API，只修改浏览器代理设置，不修改系统代理设置。&lt;br /&gt;
: 支持自动切换模式，可根据 URL 使用不同的代理情景模式。&lt;br /&gt;
: 可导入、导出设置。&lt;br /&gt;
: 支持在线列表，且能兼容 GFW List  。&lt;br /&gt;
: 使用事件监视代理更改，更高效准确。&lt;br /&gt;
: 支持改进的快速切换模式，随意在代理之间切换。&lt;/p&gt;

&lt;p&gt;为什么我要做这个扩展？ =&amp;gt;&lt;br /&gt;
   由于 @gh05tw01f 停止支持和更新 SwitchyPlus 项目，我决定自己对其代码进行修改。&lt;br /&gt;
在自己用的同时，本着开源的精神，我也将项目使用 GPL 授权，并上传至商店方便各位使用。&lt;/p&gt;

&lt;p&gt;为什么你应该从 SwitchyPlus 转移到 SwitchySharp ？=&amp;gt;&lt;br /&gt;
    最重要的原因是， SwitchyPlus 项目已经不再更新，作者也不提供支持。而本项目还在开发过程中，提供支持和更新。&lt;br /&gt;
    其次，此扩展支持设置的导入导出，这是 SwitchyPlus 中没有的功能。&lt;br /&gt;
    最后，此扩展修复了 SwitchyPlus 中的很多 bug ，且增加了很多激动人心（？）的新功能，如一键切换中使用自动切换模式等。
&lt;p&gt;相关链接：&lt;a href="https://chrome.google.com/webstore/detail/dpplabbmogkhghncfbfdeeokoefdjegm?hl=zh_CN"&gt;安装地址&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;&lt;a name="_配置_proxy_switchysharp"&gt;&lt;/a&gt;配置 Proxy SwitchySharp&lt;/h2&gt;
&lt;ul&gt;
	&lt;li&gt;在Chrome地址栏输入 about:flags 找到&amp;ldquo;实验性扩展程序 API&amp;rdquo;启用并重启浏览器。 （新版本可以不勾选）&lt;/li&gt;
	&lt;li&gt;勾选在隐身模式下启用。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;配置主界面如下：&lt;/p&gt;
&lt;p&gt;&lt;a href="http://upload.log4d.com/2012/03/switchysharp_1.png"&gt; &lt;img alt="SwitchySharp config" height="428" src="http://upload.log4d.com/2012/03/switchysharp_1.png" style="border-width: 0;" width="600" /&gt; &lt;/a&gt;&lt;/p&gt;
&lt;p&gt;其中的 HTTP 代理和端口，根据自己的需要填写。&lt;/p&gt;
&lt;p&gt;相关链接： &lt;a href="http://youcan.hourb.com/archives/19"&gt;让Chrome浏览器用上独立的代理 | 非诚勿扰&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;&lt;a name="_socks_用户的福音"&gt;&lt;/a&gt;Socks 用户的福音&lt;/h2&gt;
&lt;p&gt;Chrome 是不支持 socks 类型的代理服务器的（&lt;a href="http://code.google.com/p/chromium/issues/detail?id=29914"&gt;bug 地址&lt;/a&gt;），所以类似 &lt;tt&gt;ssh -D&lt;/tt&gt; 建立的 socks 连接都会无法使用，我们需要通过 Privoxy 来将 socks 转换到 http。&lt;/p&gt;
&lt;p&gt;Arch Linux 下安装 Privoxy，其他发行版也是类似。&lt;/p&gt;
&lt;pre&gt;pacman -S privoxy&lt;/pre&gt;
&lt;p&gt;配置 Privoxy，修改 &lt;tt&gt;/etc/privoxy/config&lt;/tt&gt; 添加一行：&lt;/p&gt;
&lt;pre&gt;forward-socks5 / 127.0.0.1:7070 .&lt;/pre&gt;
&lt;p&gt;注意上面的空格和末尾的点。&lt;/p&gt;
&lt;p&gt;配置好 Privoxy 后，重启服务，Privoxy 默认在 8118 端口提供服务，可以使用 &lt;tt&gt;127.0.0.1:8118&lt;/tt&gt; 来访问代理服务器。&lt;/p&gt;
&lt;p&gt;参考链接： * &lt;a href="http://xijie.wordpress.com/2009/12/08/ssh-socks5-%E8%BD%AC-http-3/"&gt;ssh socks5 转 http &amp;laquo; 细节的力量&lt;/a&gt; * &lt;a href="http://www.privoxy.org/"&gt;Privoxy - Home Page&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;&lt;a name="_使用某个_list"&gt;&lt;/a&gt;使用某个 list&lt;/h2&gt;
&lt;p&gt;这事不能说太细，看图说话。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://upload.log4d.com/2012/03/switchysharp_2.png"&gt; &lt;img alt="SwitchySharp config" height="410" src="http://upload.log4d.com/2012/03/switchysharp_2.png" style="border-width: 0;" width="600" /&gt; &lt;/a&gt;&lt;/p&gt;
&lt;p&gt;注意将某 list 加入切换规则，否则会无法获取 appspot 中的内容。&lt;/p&gt;
&lt;p&gt;参考链接：https://autoproxy.org/zh-CN/node/61 （自备梯子）&lt;/p&gt;
&lt;/p&gt;

		
  

&lt;div style="margin-top:15px;background:none repeat scroll 0pt 0pt rgb(238,238,238)"&gt;
  &lt;p&gt;
  &lt;strong&gt;版权所有 &amp;copy; 2010 转载本站文章请注明：&lt;/strong&gt; 转载自
  &lt;a href="http://log4d.com/" target="_blank"&gt;Log4D&lt;/a&gt;&lt;br&gt;
  &lt;strong&gt;原文链接:&lt;/strong&gt; &lt;a href="http://log4d.com/2012/03/chrome-proxy/" target="_blank"&gt;http://log4d.com/2012/03/chrome-proxy/&lt;/a&gt;&lt;br&gt;
  您可以随意地转载本站的文章，但是必须在醒目位置注明来源及本站链接，不可以将本站文章商业化使用，或者修改、转换或者以本作品为基础进行创作。&lt;br&gt;
  3a1ff193cee606bd1e2ea554a16353ee
  &lt;/p&gt;
&lt;/div&gt;

		
	&lt;img src="http://feeds.feedburner.com/~r/dddspace/~4/nMz_UR-v9hk" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://log4d.com/2012/03/chrome-proxy/</feedburner:origLink></entry>
  
  <entry>
    <title type="html"><![CDATA[影响力读书笔记]]></title>
    <link href="http://feedproxy.google.com/~r/dddspace/~3/1hYHStx17kI/" />
    <updated>2012-03-05T00:00:00+08:00</updated>
    <id>http://log4d.com/2012/03/influence</id>
	<content type="html">
		
		&lt;p&gt;&lt;ul&gt;
	&lt;li&gt;本书研究 - 社会心理学 - 顺从心理学。&lt;/li&gt;
	&lt;li&gt;日常生活中有大量心理捷径。&lt;/li&gt;
	&lt;li&gt;在某个环境下机械地回应某一信息的倾向叫做自动化反应或&amp;ldquo;按一下就播放&amp;rdquo;式反应； 对所有相关信息进行彻底分析后做出反应的倾向，则叫做可控式反应。&lt;/li&gt;
&lt;/ul&gt;
&lt;p style="text-align: center;"&gt;&lt;img alt="Influence" height="146" src="http://img3.douban.com/mpic/s1003546.jpg" width="101" /&gt;&lt;a href="http://book.douban.com/subject/1005576/"&gt;豆瓣链接&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;&lt;a name="_互惠"&gt;&lt;/a&gt;1. 互惠&lt;/h2&gt;
&lt;ul&gt;
	&lt;li&gt;互惠是人类社会群体的一个独有特征。&lt;/li&gt;
	&lt;li&gt;利用小礼物，使目标答应原来会拒绝的请求。&lt;/li&gt;
	&lt;li&gt;互惠原理适用于强加的恩惠。&lt;/li&gt;
	&lt;li&gt;互惠原理可触发不对等交换。&lt;/li&gt;
	&lt;li&gt;违背互惠原理，接受而不试图回报他人善举的人，是不受群体欢迎的。（进化适应器）&lt;/li&gt;
	&lt;li&gt;互惠式让步：面对接受的善意，我们感到有义务要偿还。&lt;/li&gt;
	&lt;li&gt;拒绝-后撤策略：先提出较大的要求，遭到拒绝之后再提出真正的较小要求。&lt;br /&gt;
		&lt;ul&gt;
			&lt;li&gt;责任感&lt;/li&gt;
			&lt;li&gt;满意感&lt;/li&gt;
		&lt;/ul&gt;
	&lt;/li&gt;
	&lt;li&gt;如何防范：&lt;br /&gt;
		&lt;ul&gt;
			&lt;li&gt;拒绝最初的善意 / 分清楚请求者是否有善意或别有所图&lt;/li&gt;
			&lt;li&gt;明辩敌友：善意自然应当得到善意回报，可对销售策略却没有这个必要。&lt;!--more--&gt;&lt;/li&gt;
		&lt;/ul&gt;
	&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;a name="_承诺和一致"&gt;&lt;/a&gt;2. 承诺和一致&lt;/h2&gt;
&lt;ul&gt;
	&lt;li&gt;人人都有一种言行一致，同时也显得言行一致的愿望。&lt;/li&gt;
	&lt;li&gt;人类普遍人为言行一致是基本的人格特征。信仰、言语和行为前后不一的人， 会被堪称是脑筋混乱、表里不一，甚至精神有毛病。另一方面， 言行高度一致大多跟个性坚强、智力出众挂钩，它是逻辑性、稳定性和诚实感的核心。&lt;/li&gt;
	&lt;li&gt;每当一个人当中选择了一种立场，便产生了维持它的动机，这样才能显得言行一致。&lt;/li&gt;
	&lt;li&gt;言行一致的优势：&lt;br /&gt;
		&lt;ul&gt;
			&lt;li&gt;为复杂的现代生活提供一种捷径，被验证过的模式会提供好处&lt;/li&gt;
			&lt;li&gt;避免费力的思考。&lt;/li&gt;
		&lt;/ul&gt;
	&lt;/li&gt;
	&lt;li&gt;激活一致性的关键：承诺&lt;/li&gt;
	&lt;li&gt;承诺之后甚至会加大顺从度，去做之前小请求毫不相关的事情。&lt;/li&gt;
	&lt;li&gt;承诺需要当事人积极、公开、、经过一番努力后自由选择的。&lt;br /&gt;
		&lt;ul&gt;
			&lt;li&gt;只有当我们认为外界不存在强大的压力时，我们才会为自己的行为发自内心地负起责任。&lt;/li&gt;
			&lt;li&gt;观察当事人，通过他的行为确定一个人自身信仰、价值观和态度&lt;/li&gt;
			&lt;li&gt;书面承诺的效果很显著&lt;/li&gt;
			&lt;li&gt;公开承诺假话和具有持久的效力，人们会忠于自己的公开决定。&lt;/li&gt;
			&lt;li&gt;额外的努力对承诺者的影响力更大。&lt;/li&gt;
		&lt;/ul&gt;
	&lt;/li&gt;
	&lt;li&gt;承诺之后，尽管环境发生了变化，承诺仍然会持续的发挥效用（自己长出腿）。&lt;br /&gt;
		&lt;ul&gt;
			&lt;li&gt;这是为了保持内心信仰系统一致。&lt;/li&gt;
			&lt;li&gt;抛低球：用甜头引诱，然后再找接口撤销。&lt;/li&gt;
		&lt;/ul&gt;
	&lt;/li&gt;
	&lt;li&gt;公共利益往往是一个很好的承诺点。&lt;/li&gt;
	&lt;li&gt;防范引诱性承诺&lt;br /&gt;
		&lt;ul&gt;
			&lt;li&gt;肠胃信号&lt;/li&gt;
			&lt;li&gt;心灵深处的力量，寻找和信任自己做出反应那一瞬间的乍现灵光。&lt;/li&gt;
		&lt;/ul&gt;
	&lt;/li&gt;
	&lt;li&gt;容易被攻击的弱点&lt;br /&gt;
		&lt;ul&gt;
			&lt;li&gt;年龄&lt;/li&gt;
			&lt;li&gt;个人主义&lt;/li&gt;
		&lt;/ul&gt;
	&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;a name="_社会认同"&gt;&lt;/a&gt;3. 社会认同&lt;/h2&gt;
&lt;ul&gt;
	&lt;li&gt;社会认同原理：在判断何为正确时，我们会根据别人的意见行事。&lt;/li&gt;
	&lt;li&gt;推导&lt;br /&gt;
		&lt;ul&gt;
			&lt;li&gt;我们对社会认同的反应方式完全是无意识的、条件反射式的，这样一来， 偏颇甚至伪造的证据也能愚弄我们。&lt;/li&gt;
			&lt;li&gt;认为一种想法正确的人越多，持有这种想法的人就会觉得它正确。&lt;/li&gt;
		&lt;/ul&gt;
	&lt;/li&gt;
	&lt;li&gt;人越多反而越不安全&lt;br /&gt;
		&lt;ul&gt;
			&lt;li&gt;现场有大量旁观者在场时，旁观者伸出援手的可能性最低。&lt;/li&gt;
			&lt;li&gt;避免这种情况：指定对象要求救援。&lt;/li&gt;
		&lt;/ul&gt;
	&lt;/li&gt;
	&lt;li&gt;模仿自杀（维特效应）：报道自杀的消息，促使一部分跟自杀者类似的人走向了绝路。&lt;/li&gt;
	&lt;li&gt;不确定性的帮助：在人不确定时候，会根据他人的行为指导自己的行为。&lt;/li&gt;
	&lt;li&gt;防范：&lt;br /&gt;
		&lt;ul&gt;
			&lt;li&gt;那些从众行为往往是赤裸裸伪造的，甚至是可笑的。&lt;/li&gt;
			&lt;li&gt;在自己不明白真相时候，取了解真相，避免对集体智慧的极大信任。&lt;/li&gt;
		&lt;/ul&gt;
	&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;a name="_喜好"&gt;&lt;/a&gt;4. 喜好&lt;/h2&gt;
&lt;ul&gt;
	&lt;li&gt;社会纽带的影响比对产品本身的好恶强两倍&lt;/li&gt;
	&lt;li&gt;喜好的缘由：&lt;br /&gt;
		&lt;ul&gt;
			&lt;li&gt;外表：一个人的正面特征能主刀他人看待此人的眼光。 长相好的人更容易在需要帮助的时候获得帮助，在改变听众意见时候也更具有说服力。&lt;/li&gt;
			&lt;li&gt;相似性：人们喜欢与自己相似的人，无论是在观点、个性、背景还是生活方式。&lt;/li&gt;
			&lt;li&gt;恭维：人们喜欢听人恭维奉承。&lt;/li&gt;
			&lt;li&gt;接触和合作：人们对熟悉的人有好感。&lt;br /&gt;
				&lt;ul&gt;
					&lt;li&gt;接触带来的熟悉往往能导致更大的好感，但是接触本身蕴含了让人反感的体验， 也许会适得其反。&lt;/li&gt;
					&lt;li&gt;在接触时候，努力创造一种&amp;ldquo;我们和他们在为了同一目标而奋斗&amp;rdquo;的氛围， 会提升合作顺利程度。&lt;/li&gt;
				&lt;/ul&gt;
			&lt;/li&gt;
		&lt;/ul&gt;
	&lt;/li&gt;
	&lt;li&gt;关联性：&lt;br /&gt;
		&lt;ul&gt;
			&lt;li&gt;糟糕的消息会让报信人也染上不详。&lt;/li&gt;
			&lt;li&gt;流行文化的导向&lt;/li&gt;
			&lt;li&gt;新闻、天气和体育的惊人力量：能将成功联系到自己，将自己的公共形象变得光辉。&lt;/li&gt;
		&lt;/ul&gt;
	&lt;/li&gt;
	&lt;li&gt;防范：&lt;br /&gt;
		&lt;ul&gt;
			&lt;li&gt;警惕自己的好感度是否超过正常指标&lt;/li&gt;
		&lt;/ul&gt;
	&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;a name="_权威"&gt;&lt;/a&gt;5. 权威&lt;/h2&gt;
&lt;ul&gt;
	&lt;li&gt;人往往会听从于专家和上级，难以公然违抗他们。 权威的上级的命令，往往会被无条件的执行，甚至违抗常识、道德和法律。&lt;/li&gt;
	&lt;li&gt;权威的象征往往就能降伏我们：&lt;br /&gt;
		&lt;ul&gt;
			&lt;li&gt;头衔&lt;/li&gt;
			&lt;li&gt;衣着&lt;/li&gt;
			&lt;li&gt;身份标识&lt;/li&gt;
		&lt;/ul&gt;
	&lt;/li&gt;
	&lt;li&gt;防范：&lt;br /&gt;
		&lt;ul&gt;
			&lt;li&gt;分清楚真正的权威，判断是否是专家&lt;/li&gt;
		&lt;/ul&gt;
	&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;a name="_稀缺"&gt;&lt;/a&gt;6. 稀缺&lt;/h2&gt;
&lt;ul&gt;
	&lt;li&gt;物以稀为贵&lt;/li&gt;
	&lt;li&gt;对失去某种东西的恐惧，似乎要比对获得同一物品的渴望，更能激发人们的行动力。&lt;/li&gt;
	&lt;li&gt;稀缺的特征：数量有限/时间有限。&lt;/li&gt;
	&lt;li&gt;逆反心理&lt;br /&gt;
		&lt;ul&gt;
			&lt;li&gt;保住既得利益的愿望，是心理逆反理论的核心。&lt;/li&gt;
			&lt;li&gt;我们基本可以根据获得一种东西的难易程度，迅速准确地判断它的价值。&lt;/li&gt;
			&lt;li&gt;每当东西获取起来比以前难，我们拥有 它的自由受了限制，我们就越发地想要得到它。&lt;/li&gt;
			&lt;li&gt;信息审查对受众的影响：人们对封锁的信息更接受、更包容。&lt;/li&gt;
		&lt;/ul&gt;
	&lt;/li&gt;
	&lt;li&gt;创造稀缺的条件：&lt;br /&gt;
		&lt;ul&gt;
			&lt;li&gt;新的稀缺：失去比获得带来的震动更大。&lt;/li&gt;
			&lt;li&gt;竞争稀缺资源：人们在竞争稀缺资源时候，往往会变得狂热愚昧。&lt;/li&gt;
		&lt;/ul&gt;
	&lt;/li&gt;
	&lt;li&gt;防范：&lt;br /&gt;
		&lt;ul&gt;
			&lt;li&gt;警惕在顺从环境下面高涨的情绪&lt;/li&gt;
			&lt;li&gt;理解物品的价值来源于本身，而不是稀缺程度。&lt;/li&gt;
			&lt;li&gt;避免竞争环境下面的情绪狂热。&lt;/li&gt;
		&lt;/ul&gt;
	&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;a name="_新时代环境的影响力"&gt;&lt;/a&gt;7. 新时代环境的影响力&lt;/h2&gt;
&lt;ul&gt;
	&lt;li&gt;我们容易根据孤立的代表性特征做决定，因为现代生活节奏太快，信息太纷杂。&lt;/li&gt;
	&lt;li&gt;当代的信息爆炸了。&lt;/li&gt;
	&lt;li&gt;我们需要使用捷径来做出快速的相应。&lt;/li&gt;
	&lt;li&gt;我们要采取一切合理的方法：抵制、威胁、对峙、谴责、抗议， 来报复刺激我们的捷径反应为目的的虚假信号。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;a name="_alswl_的总结"&gt;&lt;/a&gt;8. alswl 的总结&lt;/h2&gt;
&lt;p&gt;关于如何防范，其实只要掌握两点：&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;避免懒惰，勤加思考（反捷径）&lt;/li&gt;
	&lt;li&gt;天上不会掉馅饼（反虚假捷径刺激信号）&lt;/li&gt;
&lt;/ul&gt;
&lt;/p&gt;

		
  

&lt;div style="margin-top:15px;background:none repeat scroll 0pt 0pt rgb(238,238,238)"&gt;
  &lt;p&gt;
  &lt;strong&gt;版权所有 &amp;copy; 2010 转载本站文章请注明：&lt;/strong&gt; 转载自
  &lt;a href="http://log4d.com/" target="_blank"&gt;Log4D&lt;/a&gt;&lt;br&gt;
  &lt;strong&gt;原文链接:&lt;/strong&gt; &lt;a href="http://log4d.com/2012/03/influence/" target="_blank"&gt;http://log4d.com/2012/03/influence/&lt;/a&gt;&lt;br&gt;
  您可以随意地转载本站的文章，但是必须在醒目位置注明来源及本站链接，不可以将本站文章商业化使用，或者修改、转换或者以本作品为基础进行创作。&lt;br&gt;
  3a1ff193cee606bd1e2ea554a16353ee
  &lt;/p&gt;
&lt;/div&gt;

		
	&lt;img src="http://feeds.feedburner.com/~r/dddspace/~4/1hYHStx17kI" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://log4d.com/2012/03/influence/</feedburner:origLink></entry>
  
  <entry>
    <title type="html"><![CDATA[给MoinMoin写插件]]></title>
    <link href="http://feedproxy.google.com/~r/dddspace/~3/gK6ZmIvUVes/" />
    <updated>2012-02-10T00:00:00+08:00</updated>
    <id>http://log4d.com/2012/02/the-write-the-plugins-for-moinmoin</id>
	<content type="html">
		
		&lt;p&gt;&lt;h2&gt;1. 使用 MoinMoin&lt;/h2&gt;
&lt;p&gt;前些日子，我写了一篇&lt;a href="../2011/12/moinmoin-kms"&gt;使用MoinMoin作为个人KMS&lt;/a&gt; 大赞MoinMoin的各种好处。MoinMoin的其中一个好处是基于GPL的开源， 我们可以方便的给MoinMoin撰写自己的插件（当然也可以去官方的wiki上获取大量现成插件）。&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;a href="http://moinmo.in/MoinDev"&gt;MoinMoin开发者wiki地址&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://docs.moinmo.in/"&gt;MoinMoin开发API文档（这个官方wiki居然很少提及）&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://moinmo.in/MoinDev/Translation"&gt;MoinMoin的多国语翻译组wiki地址&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;我在使用MoinMoin过程中，有一个急迫需要的功能：&lt;/p&gt;
&lt;blockquote&gt;
	&lt;p&gt;保存一篇网页时候，要将里面的图片保存到本地，而不是使用外链接方式保存， 因为由于各种不可预测的原因，原始图片数据很有可能丢失或者无法连接。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;这个功能对于将Wiki产品转化为KMS应用非常需要，可惜MoinMoin官方并没有提供， 我也没在MoinMoin的开发者插件库中找到类似功能，就自己写了一个插件image2attach。&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;a href="http://moinmo.in/MoinMoinExtensions"&gt;MoinMoin插件库&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://moinmo.in/ActionMarket/Image2Attach"&gt;image2attach在MoinMoin官方Wiki的地址&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;现在我分享一下如何写MoinMoin插件，技术大牛可以直接移步官方开发文档， 我这里只是写一些简单的内容，帮助像我一样的同学。&lt;/p&gt;
&lt;p&gt;以下内容需要Python编程基础～&lt;!--more--&gt;&lt;/p&gt;
&lt;h2&gt;&lt;a name="_moinmoin_系统结构"&gt;&lt;/a&gt;2. MoinMoin 系统结构&lt;/h2&gt;
&lt;p&gt;MoinMoin的UML图：&lt;/p&gt;
&lt;p&gt;&lt;img alt="MoinMoin" height="432" src="http://upload.log4d.com/2012/02/MoinMoinArchitecture.png" style="border-width: 0;" width="600" /&gt;&lt;/p&gt;
&lt;h2&gt;&lt;a name="_moinmoin_常用对象"&gt;&lt;/a&gt;3. MoinMoin 常用对象&lt;/h2&gt;
&lt;h3&gt;&lt;a name="_request"&gt;&lt;/a&gt;3.1. request&lt;/h3&gt;
&lt;p&gt;这个request和普通jsp/asp中request很类似（实际上这个request就是继承 &lt;a href="http://werkzeug.pocoo.org/"&gt;werkzeug&lt;/a&gt;的Request）。&lt;/p&gt;
&lt;p&gt;除了正常的web request功能，Moin的request还带了Wiki自身的信息。&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;request.getText # 多国语函数，经常使用 &lt;tt&gt;_ = request.getText&lt;/tt&gt; 来简化代码&lt;/li&gt;
	&lt;li&gt;request.dicts # 获取定义在页面中的Dict，参见http://moinmo.in/HelpOnDictionaries&lt;/li&gt;
	&lt;li&gt;request.groups # 获取权限管理中的组别&lt;/li&gt;
	&lt;li&gt;request.user.may # 检查用户权限&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&lt;a name="_page"&gt;&lt;/a&gt;3.2. Page&lt;/h3&gt;
&lt;p&gt;Page是最常见的类，它代表某个Wiki页面，通过它可以获取某个页面所有信息。 age本身是只读的，如果需要编辑需要使用PageEditor。&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;Page.exists() # 是否存在&lt;/li&gt;
	&lt;li&gt;Page.getRevList() # 版本列表&lt;/li&gt;
	&lt;li&gt;Page.current_rev() # 当前版本&lt;/li&gt;
	&lt;li&gt;Page.getPagePath() # 存储路径&lt;/li&gt;
	&lt;li&gt;Page.get_raw_body() # 获取存储的数据&lt;/li&gt;
	&lt;li&gt;Page.send_page() # 发送格式化好页面&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&lt;a name="_pageeditor"&gt;&lt;/a&gt;3.3. PageEditor&lt;/h3&gt;
&lt;p&gt;上面说到Page是只读的，那当我们需要编辑页面时候，就要用到PageEditor类了。&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;PageEditor.saveText() # 保存内容&lt;/li&gt;
	&lt;li&gt;PageEditor.deletePage() # 删除页面&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&lt;a name="_attachfile"&gt;&lt;/a&gt;3.4. AttachFile&lt;/h3&gt;
&lt;p&gt;顾名思义，AttachFile用来管理页面附件。&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;AttachFile.exists() # 检查附件是否存在&lt;/li&gt;
	&lt;li&gt;AttachFile.getAttachDir() # 获取附件存放的本地目录&lt;/li&gt;
	&lt;li&gt;AttachFile.getAttachUrl() # 获取附件url&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&lt;a name="_wikiutil"&gt;&lt;/a&gt;3.5. wikiutil&lt;/h3&gt;
&lt;p&gt;wikiutil 是MoinMoin提供的一个帮助类，包含一些常用的小功能。&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;wikiutil.escape() # html转义&lt;/li&gt;
	&lt;li&gt;wikiutil.createTicket() # 生成一串唯一key，用来页面验证&lt;/li&gt;
	&lt;li&gt;wikiutil.checkTicket() # 检查ticket&lt;/li&gt;
	&lt;li&gt;wikiutil.invoke_extension_function() # 注入脚本类插件&lt;/li&gt;
	&lt;li&gt;wikiutil.version2timestamp() # 将MoinMoin时间转换成UNIX时间戳&lt;/li&gt;
	&lt;li&gt;wikiutil.timestamp2version() # 参考楼上&lt;/li&gt;
	&lt;li&gt;wikiutil.renderText() # 将wiki text转换成html来展现&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&lt;a name="_user"&gt;&lt;/a&gt;3.6. user&lt;/h3&gt;
&lt;p&gt;用户类，CRUD操作，不解释。&lt;/p&gt;
&lt;h3&gt;&lt;a name="_formatter"&gt;&lt;/a&gt;3.7. formatter&lt;/h3&gt;
&lt;p&gt;formatter将输出展现类，将wiki text转换为各种预定义的格式。 需要和parser配合使用（两者关系看上去像抽象工厂模式）。&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;formatter.text() # 格式化为普通文本&lt;/li&gt;
	&lt;li&gt;formatter.img() # 格式化为图片&lt;/li&gt;
	&lt;li&gt;formatter.number_list() # 格式化为有序列表&lt;/li&gt;
	&lt;li&gt;formatter.bullet_list() # 格式化为无序列表&lt;/li&gt;
	&lt;li&gt;formatter.listitem() # 格式化为列表项&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&lt;a name="_parser"&gt;&lt;/a&gt;3.8. parser&lt;/h3&gt;
&lt;p&gt;formatter完成的工作是展现解析后的wiki内容，而负责解析的就是parser了。&lt;/p&gt;
&lt;p&gt;流程是这样的：&lt;/p&gt;
&lt;pre&gt;wiki -&amp;gt; parser -&amp;gt; formatter&lt;/pre&gt;
&lt;p&gt;每一个parser都对应一个或者多个formatter。系统内置的 parser/formatter 有：&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;docbook&lt;/li&gt;
	&lt;li&gt;html&lt;/li&gt;
	&lt;li&gt;plain&lt;/li&gt;
	&lt;li&gt;python&lt;/li&gt;
	&lt;li&gt;rst&lt;/li&gt;
	&lt;li&gt;cvs&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;a name="_moinmoin_运行流程"&gt;&lt;/a&gt;4. MoinMoin 运行流程&lt;/h2&gt;
&lt;ol type="1"&gt;
	&lt;li&gt;cgi.py&lt;/li&gt;
	&lt;li&gt;通过url获取pagename和action，然后调用对应的Page方法和Action对象&lt;br /&gt;
		&lt;ol type="a"&gt;
			&lt;li&gt;Page().send_page()创建普通页面&lt;/li&gt;
			&lt;li&gt;MoinMoin.action.getHandler()用来获取对应action&lt;/li&gt;
		&lt;/ol&gt;
	&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;&lt;a name="_moinmoin_开发配置"&gt;&lt;/a&gt;5. MoinMoin 开发配置&lt;/h2&gt;
&lt;h3&gt;&lt;a name="_禁用pyc缓存"&gt;&lt;/a&gt;5.1. 禁用pyc缓存&lt;/h3&gt;
&lt;p&gt;MoinMoin 为了提高系统效率，会为 python 文件生成pyc缓存，如果放任它们的话。 每次修改python源码效果都得不到立即体现。所以我们要在开发阶段禁用系统缓存。&lt;/p&gt;
&lt;p&gt;在文件 &lt;tt&gt;/usr/lib/python2.7/site-packages/MoinMoin/config/multiconfig.py&lt;/tt&gt; 的第815行左右，修改 &lt;tt&gt;options_no_group_name&lt;/tt&gt; 中的 &lt;tt&gt;cache&lt;/tt&gt; 时间。&lt;/p&gt;
&lt;p&gt;当改为0时候，就不使用 &lt;tt&gt;pyc&lt;/tt&gt; 缓存，这样就不用重启服务器来清楚缓存了。&lt;/p&gt;
&lt;pre&gt;options_no_group_name = {
        # ...
        #&amp;#39;cache&amp;#39;: (600, 30), # cache action is very cheap/efficient
        &amp;#39;cache&amp;#39;: (0, 0), # cache action is very cheap/efficient #XXX alswl
        # ...
}&lt;/pre&gt;
&lt;h2&gt;&lt;a name="_image2attach_范例"&gt;&lt;/a&gt;6. image2attach 范例&lt;/h2&gt;
&lt;p&gt;image2attach这个插件功能很简单，就是读取wiki文本内容，找出所有图片， 然会将这些图片从互联网上下载到本地，并将文中的图片链接改为MoinMoin的附件链接。&lt;/p&gt;
&lt;h3&gt;&lt;a name="_创建插件文件"&gt;&lt;/a&gt;6.1. 创建插件文件&lt;/h3&gt;
&lt;p&gt;在 &lt;tt&gt;data/plugin/action/&lt;/tt&gt; 目录下创建文件Image2Attach.py。 （请使用大写文件，Moin会自动识别大写开头的Python文件为插件）&lt;/p&gt;
&lt;h3&gt;&lt;a name="_基本框架"&gt;&lt;/a&gt;6.2. 基本框架&lt;/h3&gt;
&lt;ol type="1"&gt;
	&lt;li&gt;&lt;tt&gt;execute()&lt;/tt&gt; ：hook函数，用来给上层调用，签名必须是 &lt;tt&gt;def execute(pagename, request)&lt;/tt&gt;&lt;/li&gt;
	&lt;li&gt;&lt;tt&gt;Class Image2Attach&lt;/tt&gt; ：主要类，处理逻辑。&lt;br /&gt;
		&lt;ol type="a"&gt;
			&lt;li&gt;&lt;tt&gt;process() / process_line()&lt;/tt&gt; ：处理每行wiki text，会抓取&amp;lt;a&amp;gt;和&amp;lt;img&amp;gt;&lt;/li&gt;
			&lt;li&gt;&lt;tt&gt;process_transclude() / process_link()&lt;/tt&gt; ：分别处理&amp;lt;a&amp;gt; / &amp;lt;img&amp;gt;&lt;/li&gt;
			&lt;li&gt;&lt;tt&gt;fetch_image()&lt;/tt&gt; ：下载图片&lt;/li&gt;
			&lt;li&gt;&lt;tt&gt;add_attachment()&lt;/tt&gt; ：将图片作为附件加入到wiki&lt;/li&gt;
			&lt;li&gt;&lt;tt&gt;write_file()&lt;/tt&gt; ：写入wiki text&lt;/li&gt;
		&lt;/ol&gt;
	&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;总的来说，开发Moin插件还是比较方便的，官方提供了详尽（但不够顺畅）的教程和 &lt;a href="http://docs.moinmo.in/moin/1.9/"&gt;API文档&lt;/a&gt;。 我大部分时间在看Moin的API文档， Moin作为一款久经考研的Wiki系统，开放的代码也有很多地方可以学习。&lt;/p&gt;
&lt;/p&gt;

		
  

&lt;div style="margin-top:15px;background:none repeat scroll 0pt 0pt rgb(238,238,238)"&gt;
  &lt;p&gt;
  &lt;strong&gt;版权所有 &amp;copy; 2010 转载本站文章请注明：&lt;/strong&gt; 转载自
  &lt;a href="http://log4d.com/" target="_blank"&gt;Log4D&lt;/a&gt;&lt;br&gt;
  &lt;strong&gt;原文链接:&lt;/strong&gt; &lt;a href="http://log4d.com/2012/02/the-write-the-plugins-for-moinmoin/" target="_blank"&gt;http://log4d.com/2012/02/the-write-the-plugins-for-moinmoin/&lt;/a&gt;&lt;br&gt;
  您可以随意地转载本站的文章，但是必须在醒目位置注明来源及本站链接，不可以将本站文章商业化使用，或者修改、转换或者以本作品为基础进行创作。&lt;br&gt;
  3a1ff193cee606bd1e2ea554a16353ee
  &lt;/p&gt;
&lt;/div&gt;

		
	&lt;img src="http://feeds.feedburner.com/~r/dddspace/~4/gK6ZmIvUVes" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://log4d.com/2012/02/the-write-the-plugins-for-moinmoin/</feedburner:origLink></entry>
  
  <entry>
    <title type="html"><![CDATA[再读《重构》]]></title>
    <link href="http://feedproxy.google.com/~r/dddspace/~3/03wLok3vF2Y/" />
    <updated>2012-02-05T00:00:00+08:00</updated>
    <id>http://log4d.com/2012/02/refactory</id>
	<content type="html">
		
		&lt;p&gt;&lt;p&gt;Martin Fowler 的《&lt;a href="http://book.douban.com/subject/1229923/"&gt;重构-改善既有代码的设计&lt;/a&gt;》这本书，是我大学老师推荐给我的。 当时我在撰写代码过程中，发现当代码量到某个数量级时候（1000+行）， 就会逐渐失去对代码的控制能力。昆哥推荐了两本书《&lt;a href="http://book.douban.com/subject/1792387/"&gt;UML和模式应用&lt;/a&gt;》和《重构》这本书。&lt;/p&gt;
&lt;p&gt;&lt;img align="" alt="refactory" height="139" src="http://img1.douban.com/mpic/s1669771.jpg" width="106" /&gt;&lt;/p&gt;
&lt;p&gt;这本书是2年前购买的，可惜以我当时的代码感知和撰写能力，看起来颇为吃力。 半途就看得云里雾里而中断了。最近我又重新拾起这本书， 将书中所写的境况与我这两年多来遇到的问题相互印证，才感受到这本经典的力量。&lt;!--more--&gt;&lt;/p&gt;
&lt;p&gt;Martin 其人：&lt;/p&gt;
&lt;pre&gt;ThoughtWorks的首席科学家，当今世界软件开发领域最具影响力的五位大师之一。
他在UML推广普及、领域建模、企业应用开发和敏捷方法等方面建树卓著，被称为软件开发的教父。&lt;/pre&gt;
&lt;p&gt;大学时候有段时间我对 Martin 的敏捷非常痴迷。现在对技术的选择没以前那么冲动了， 但是毫不妨碍我对 Martin 的敬仰之情。&lt;/p&gt;
&lt;h2&gt;&lt;a name="_重构原则"&gt;&lt;/a&gt;1. 重构原则&lt;/h2&gt;
&lt;h3&gt;&lt;a name="_重构的定义"&gt;&lt;/a&gt;1.1. 重构的定义&lt;/h3&gt;
&lt;pre&gt;对软件内部结构的一种调整，目的是在不改变&amp;rdquo;软件之可察行为&amp;ldquo;前提下，提高其可理解性，降低其修改成本。&lt;/pre&gt;&lt;/p&gt;

&lt;p&gt;重构就是在代码写好之后改进它的设计。
&lt;ul&gt;
	&lt;li&gt;重构和添加新功能并不冲突，但是当开发者身份在两者之间切换时候，不能混淆在一起。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&lt;a name="_重构的意义"&gt;&lt;/a&gt;1.2. 重构的意义&lt;/h3&gt;
&lt;ul&gt;
	&lt;li&gt;优秀设计的根本是：消除重复部分！（DRY = Don&amp;rsquo;t repeat yourself）&lt;/li&gt;
	&lt;li&gt;重构让代码更清晰，更容易理解&lt;/li&gt;
	&lt;li&gt;清晰的代码可以更方便的找到bug，重构可以写出更强健的代码&lt;/li&gt;
	&lt;li&gt;良好的设计可以在长远时间上提高开发速度&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&lt;a name="_重构的时间"&gt;&lt;/a&gt;1.3. 重构的时间&lt;/h3&gt;
&lt;ul&gt;
	&lt;li&gt;随时进行重构（在我看来，重构更是一种开发的习惯）&lt;/li&gt;
	&lt;li&gt;事不过三，代码重复不要超过三次（否则就要&amp;rdquo;抽&amp;ldquo;出来）&lt;/li&gt;
	&lt;li&gt;添加功能时候并一一重构（个人理解是，添加新功能之前，分析并重构，从而更方便添加新功能）&lt;/li&gt;
	&lt;li&gt;修补错误时&lt;/li&gt;
	&lt;li&gt;code review时&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&lt;a name="_重构和开发进度"&gt;&lt;/a&gt;1.4. 重构和开发进度&lt;/h3&gt;
&lt;p&gt;重构的意义之一也是提高开发进度。杀手锏是&amp;rdquo;不要告诉经理&amp;ldquo;。&lt;/p&gt;
&lt;h3&gt;&lt;a name="_重构的难题"&gt;&lt;/a&gt;1.5. 重构的难题&lt;/h3&gt;
&lt;ul&gt;
	&lt;li&gt;数据层（数据模型）的变更压力&lt;/li&gt;
	&lt;li&gt;修改接口&lt;/li&gt;
	&lt;li&gt;那些难以通过重构改变的设计改动&lt;/li&gt;
	&lt;li&gt;代码不能运行&lt;/li&gt;
	&lt;li&gt;项目期限压力 dead line&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&lt;a name="_重构与设计"&gt;&lt;/a&gt;1.6. 重构与设计&lt;/h3&gt;
&lt;ul&gt;
	&lt;li&gt;编程不是机械的开发，（软件开发是艺术行为！）&lt;/li&gt;
	&lt;li&gt;设计和重构的平衡（预先设计的难度和重构灵活性的平衡）&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&lt;a name="_重构与性能"&gt;&lt;/a&gt;1.7. 重构与性能&lt;/h3&gt;
&lt;ul&gt;
	&lt;li&gt;重构确实会在短期内降低代码执行效率，但优化阶段是可以调整的，而且调整会更容易。&lt;/li&gt;
	&lt;li&gt;提前优化是万恶之源&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&lt;a name="_那些bad_smell"&gt;&lt;/a&gt;1.8. 那些Bad Smell&lt;/h3&gt;
&lt;ul&gt;
	&lt;li&gt;重复的代码（这才是真正万恶之源，鄙视一切Ctrl+C/P）&lt;/li&gt;
	&lt;li&gt;过长函数，会导致责任不明确/难以切割/难以理解等一系列问题&lt;/li&gt;
	&lt;li&gt;过大类，职责不明确，垃圾滋生地&lt;/li&gt;
	&lt;li&gt;过长参数列（面向对象不是说说而已）&lt;/li&gt;
	&lt;li&gt;发散式变化，一个类会响应多种需求而被修改&lt;/li&gt;
	&lt;li&gt;散弹式修改（其实就是没有封装变化处，由于一个需求，多处需要被修改）&lt;/li&gt;
	&lt;li&gt;依赖情节（一个类对其他类过多的依赖）&lt;/li&gt;
	&lt;li&gt;数据泥团（如果数据有意义，就将结构数据变成对象）&lt;/li&gt;
	&lt;li&gt;type code，使用Class替代&lt;/li&gt;
	&lt;li&gt;switch，少用，考虑多态&lt;/li&gt;
	&lt;li&gt;过多平行的类，使用类继承并联起来&lt;/li&gt;
	&lt;li&gt;冗余类，去除它&lt;/li&gt;
	&lt;li&gt;夸夸其谈的未来性（Matin的文字，侯俊杰的翻译真是&amp;hellip;出彩&amp;hellip;）&lt;/li&gt;
	&lt;li&gt;临时值域，封装它&lt;/li&gt;
	&lt;li&gt;过度耦合的消息链，使用真正需要的函数和对象，而不要依赖于消息链&lt;/li&gt;
	&lt;li&gt;过度的deleate&lt;/li&gt;
	&lt;li&gt;过度使用其他类private值域&lt;/li&gt;
	&lt;li&gt;重复作用的类&lt;/li&gt;
	&lt;li&gt;不完美的类库，（类库老了，使用者也没办法阿）&lt;/li&gt;
	&lt;li&gt;纯数据类（类需要行为）&lt;/li&gt;
	&lt;li&gt;不纯粹的继承（拒绝父类的接口的类）&lt;/li&gt;
	&lt;li&gt;过多注释，注释多了，就说明代码不清楚了&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&lt;a name="_从测试开始"&gt;&lt;/a&gt;1.9. 从测试开始&lt;/h3&gt;
&lt;p&gt;无测试，无重构，只依赖手工测试，重构时候人会崩溃的。&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;重构的保真就是自动化测试（如果真的要无聊的手工测试，我也不反对）&lt;/li&gt;
	&lt;li&gt;单元测试&lt;/li&gt;
	&lt;li&gt;功能测试&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&lt;a name="_kent_back说"&gt;&lt;/a&gt;1.10. Kent Back说&lt;/h3&gt;
&lt;pre&gt;如果我纯粹为今天工作，明天我将完全无法工作。&lt;/pre&gt;&lt;/p&gt;

&lt;p&gt;间接层的价值：&lt;/p&gt;

&lt;p&gt;* 允许逻辑共享&lt;br /&gt;
* 分开解释&amp;rdquo;意图&amp;ldquo;和&amp;rdquo;实现&amp;ldquo;&lt;br /&gt;
* 将变化加以隔离&lt;br /&gt;
* 将条件逻辑加以编码&lt;/p&gt;

&lt;p&gt;计算机科学是这样一门学科：它相信所有问题都可以通过一个间接层来解决。 &amp;#8211;Dennis DeBruler
&lt;p&gt;我相信，撰写代码时候不仅仅考虑当下功能，要考虑到有可能出现的情况， 在可能的平衡下面，为将来的扩展做好准备。（也许不仅仅是自己的明天， 还要考虑团队成员的今天工作内容）&lt;/p&gt;
&lt;h2&gt;&lt;a name="_重构名录"&gt;&lt;/a&gt;2. 重构名录&lt;/h2&gt;
&lt;h3&gt;&lt;a name="_重新组织函数"&gt;&lt;/a&gt;2.1. 重新组织函数&lt;/h3&gt;
&lt;dl&gt;
	&lt;dt&gt;Extract Method（提炼函数）&lt;/dt&gt;
	&lt;dd&gt;将一段独立的，不依赖上下文的代码组织并独立出来。&lt;/dd&gt;
	&lt;dt&gt;Inline Method（将函数内联化）&lt;/dt&gt;
	&lt;dd&gt;当函数内部代码简短而容易理解时候，去除这个非必要的间接层。&lt;/dd&gt;
	&lt;dt&gt;Inline Temp（将临时变量内联化）&lt;/dt&gt;
	&lt;dd&gt;去除只被赋值一次的临时变量。（当有意义时候，应该保留）&lt;/dd&gt;
	&lt;dt&gt;Replace Temp with Query（以查询取代临时变量）&lt;/dt&gt;
	&lt;dd&gt;将临时变量提取到一个独立函数，并将原来变量引用替换为函数调用。 （我还是担心性能的问题，另外将临时变量限定在一个段落p中，可以避免额外的引用）&lt;/dd&gt;
	&lt;dt&gt;Introduce Explainning Variable（引入解释性变量）&lt;/dt&gt;
	&lt;dd&gt;将复杂表达式的结果放入临时变量，并用变量名来解释表达式用途。 （自注释代码的表现）&lt;/dd&gt;
	&lt;dt&gt;Split Temporary Variable（剖析临时变量）&lt;/dt&gt;
	&lt;dd&gt;除了循环变量和临时集合变量，临时变量赋值不能超过一次。&lt;/dd&gt;
	&lt;dt&gt;Remove Assignments to Parameters（移除对参数的赋值动作）&lt;/dt&gt;
	&lt;dd&gt;不对函数参数进行赋值动作，如果要赋值，创建一个新的临时变量。&lt;/dd&gt;
	&lt;dt&gt;Replace Method with Method Object（以函数对象取代函数）&lt;/dt&gt;
	&lt;dd&gt;把函数变成对象，再把临时变量变成对象值域。该方法在分解函数时候常用。 （Martin 对小型函数特别迷恋，我认为这个方法更应该用在有逻辑意义的方法上面）&lt;/dd&gt;
	&lt;dt&gt;Substitute Algorithm（替换算法）&lt;/dt&gt;
	&lt;dd&gt;用更清晰的算法。 （码农都知道）&lt;/dd&gt;
&lt;/dl&gt;
&lt;h3&gt;&lt;a name="_在对象之间搬移特性"&gt;&lt;/a&gt;2.2. 在对象之间搬移特性&lt;/h3&gt;
&lt;p&gt;（面向对象编程原则之一就是职责归属，搬移其实也就意味着职责重新规划）&lt;/p&gt;
&lt;dl&gt;
	&lt;dt&gt;Move Method（搬移函数）&lt;/dt&gt;
	&lt;dd&gt;将函数移动到被最多次调用的类里面去。 （往往在逻辑意义上，这个函数就应该归属于这个类）&lt;/dd&gt;
	&lt;dt&gt;Move Field（搬移值域）&lt;/dt&gt;
	&lt;dd&gt;将值域移动到被最多次调用的类里面去。&lt;/dd&gt;
	&lt;dt&gt;Extract Class（提炼类）&lt;/dt&gt;
	&lt;dd&gt;将开发过程中逐渐变得臃肿的类拆分成数个类，形成清楚的抽象，明确的职责。&lt;/dd&gt;
	&lt;dt&gt;Inline Class（将类内联化）&lt;/dt&gt;
	&lt;dd&gt;将不再担任足够职责的类搬到另外一个类中，并移除这个原始类。&lt;/dd&gt;
	&lt;dt&gt;Hide Delegate（隐藏委托关系）&lt;/dt&gt;
	&lt;dd&gt;将直接调用变成间接，在中间添加一层，从而从容面对变更，隔离变化。 （&amp;ldquo;哪里变化，封装哪里&amp;rdquo;这是设计模式的一个经典原则）&lt;/dd&gt;
	&lt;dt&gt;Remove Middle Man（移除中间人）&lt;/dt&gt;
	&lt;dd&gt;和Hide Delegate相反，移除做了过多简单委托的类。 （应该Hide Delegate需要加入成本，多维护一层，这需要控制一种平衡）&lt;/dd&gt;
	&lt;dt&gt;Introduce Foreign Method（引入外加函数）&lt;/dt&gt;
	&lt;dd&gt;当类无法进行修改时候，使用静态函数接受这种类型的类实例，&lt;/dd&gt;
	&lt;dt&gt;Introduce Local Extenstion（引入本地扩展）&lt;/dt&gt;
	&lt;dd&gt;使用子类继承/wrapper类来实现额外的函数。&lt;/dd&gt;
&lt;/dl&gt;
&lt;h3&gt;&lt;a name="_重新组织数据"&gt;&lt;/a&gt;2.3. 重新组织数据&lt;/h3&gt;
&lt;dl&gt;
	&lt;dt&gt;Self Encapsulate Field（自封装值域）&lt;/dt&gt;
	&lt;dd&gt;使用getter/setter。 （个人觉得这样很繁琐，.net中的属性方式处理的不错）&lt;/dd&gt;
	&lt;dt&gt;Replace Date Value with Object （以对象取代数据值）&lt;/dt&gt;
	&lt;dd&gt;当数据项有额外的数据和行为时候，将它变成一个类&lt;/dd&gt;
	&lt;dt&gt;Change Value to Reference（将实值对象改为引用对象）&lt;/dt&gt;
	&lt;dd&gt;有一些类型，比如日期、星期，不需要保存太多副本。&lt;/dd&gt;
	&lt;dt&gt;Change Reference to Value（将引用对象改为实值对象）&lt;/dt&gt;
	&lt;dd&gt;和楼上相反的情况，引用会带来复杂的内存分配，在分布式系统中，实值对象特别有用。&lt;/dd&gt;
	&lt;dt&gt;Replace Array with Object（以对象取代数组）&lt;/dt&gt;
	&lt;dd&gt;不应该将不同的元素存放到数组中，应该使用值域。&lt;/dd&gt;
	&lt;dt&gt;Duplicate Observed Data（复制被监视数据）&lt;/dt&gt;
	&lt;dd&gt;通过观察者模式，将业务数据和GUI数据进行同步控制&lt;/dd&gt;
	&lt;dt&gt;Change Unidirectional Association to Bidirectional（将单向关联改为双向）&lt;/dt&gt;
	&lt;dd&gt;使用双向连接，从而能让两个类能互相使用对方特性。&lt;/dd&gt;
	&lt;dt&gt;Change Bidirectional Assicuation to Unidirectional（将双向关联改为单向）&lt;/dt&gt;
	&lt;dd&gt;当一个类不再需要另外一个类特性时候作修改。&lt;/dd&gt;
	&lt;dt&gt;Replace Magic Number with Symbolic Constant（以符号常量/字面常量取代魔法数）&lt;/dt&gt;
	&lt;dd&gt;使用有意义的名称，比如pi,gravity。&lt;/dd&gt;
	&lt;dt&gt;Encapsulate Field（封装值域）&lt;/dt&gt;
	&lt;dd&gt;使用getter/setter。&lt;/dd&gt;
	&lt;dt&gt;Encapsulate Collection（封装集群）&lt;/dt&gt;
	&lt;dd&gt;避免直接修改容器对象，而是封装出类方法来修改。将变化控制在既有方法内。&lt;/dd&gt;
	&lt;dt&gt;Replace Record with Data Class（以数据类取代记录）&lt;/dt&gt;
	&lt;dd&gt;将传统编程中的结构体转换为数据类。&lt;/dd&gt;
	&lt;dt&gt;Replace Type Code with Class（以类别取代型别码）&lt;/dt&gt;
	&lt;dd&gt;使用类型集合类来替换型别码。&lt;/dd&gt;
	&lt;dt&gt;Replace Type Code with Subclass（以子类取代型别码）&lt;/dt&gt;
	&lt;dd&gt;使用多态来替换型别码，发挥面向对象编程的优势。 （小心处理ORM映射）&lt;/dd&gt;
	&lt;dt&gt;Replace Type Code with State/Strategy（以State/Strategy取代型别码）&lt;/dt&gt;
	&lt;dd&gt;使用State/Strategy模式来因对type code会发生变化的情况。 将状态类作为父类，再进行继承。&lt;/dd&gt;
	&lt;dt&gt;Replace Subclass with Fields（以值域取代子类）&lt;/dt&gt;
	&lt;dd&gt;当子类的差异仅仅体现在返回常量数据的函数上时候，进行这样的替换。&lt;/dd&gt;
&lt;/dl&gt;
&lt;h3&gt;&lt;a name="_简化条件表达式"&gt;&lt;/a&gt;2.4. 简化条件表达式&lt;/h3&gt;
&lt;p&gt;简化的核心思想，是将过程式的if/else替换为面向对象的多态。&lt;/p&gt;
&lt;dl&gt;
	&lt;dt&gt;Decompose Conditional（分解条件式）&lt;/dt&gt;
	&lt;dd&gt;将复杂的条件式提炼为独立函数。&lt;/dd&gt;
	&lt;dt&gt;Consolidate Conditional Expression（合并条件式）&lt;/dt&gt;
	&lt;dd&gt;将多个条件式判断提炼成一个独立函数。这和上面的分解条件式都需要一个前提： 这几个条件式是要有逻辑关联的。&lt;/dd&gt;
	&lt;dt&gt;Consolidate Duplicate Conditional Fragments（合并重复的条件判断）&lt;/dt&gt;
	&lt;dd&gt;将所有分支里面都拥有的代码提炼到分支判断之后运行。&lt;/dd&gt;
	&lt;dt&gt;Remove Control Flag（移除控制标志）&lt;/dt&gt;
	&lt;dd&gt;使用 break/return 取代控制标记。单一出口，多出口。控制标记让程序接口看上去混乱。&lt;/dd&gt;
	&lt;dt&gt;Replace Nested Conditional with Guard Clauses（以卫语句取代嵌套条件式）&lt;/dt&gt;
	&lt;dd&gt;保留正常情况下面下的顺序执行，提前对非正常情况进行单独检查并返回。 （我更倾向于使用Exception）&lt;/dd&gt;
	&lt;dt&gt;Replace Conditional with Polymorphism（以多态取代条件式）&lt;/dt&gt;
	&lt;dd&gt;将条件式的每个分支放入一个subclass内覆写函数中，然后将原始函数生命为抽象函数。 （这个方法之前的5种重构手段是代码小手段，引入多态才能充分发挥OOP优势）&lt;/dd&gt;
	&lt;dt&gt;Introduce Null Object（引入Null对象）&lt;/dt&gt;
	&lt;dd&gt;将无效值替换为null object，从而可以让程序正常运行。 （这好象是一种hack方法，我倾向使用Exception，作者的用以可能是通过Null来减少判断代码）&lt;/dd&gt;
	&lt;dt&gt;Introduce Assertion（引入断言）&lt;/dt&gt;
	&lt;dd&gt;通过断言来发现程序错误，实际使用中，可以配合 debug mode 使用。&lt;/dd&gt;
&lt;/dl&gt;
&lt;h3&gt;&lt;a name="_简化函数调用"&gt;&lt;/a&gt;2.5. 简化函数调用&lt;/h3&gt;
&lt;dl&gt;
	&lt;dt&gt;Rename Method（重命名函数）&lt;/dt&gt;
	&lt;dd&gt;A good name is better than a line of comment.&lt;/dd&gt;
	&lt;dt&gt;Add Parameter（添加参数）&lt;/dt&gt;
	&lt;dd&gt;你没看错，就是添加参数。 （啊？Matin老师，不带这么水的阿）&lt;/dd&gt;
	&lt;dt&gt;Remove Parameter（移除参数）&lt;/dt&gt;
	&lt;dd&gt;不要就丢掉。&lt;/dd&gt;
	&lt;dt&gt;Separate Query from Modifier（将查询参数和修改参数分离）&lt;/dt&gt;
	&lt;dd&gt;将一个即查询状态又修改状态的函数分离开来，职责分离清楚。 （我以前很喜欢写多面手函数～）&lt;/dd&gt;
	&lt;dt&gt;Parameterize Method（令函数携带参数）&lt;/dt&gt;
	&lt;dd&gt;同一逻辑功能函数，通过重载接受不同参数。而不要建立多个同样的函数。&lt;/dd&gt;
	&lt;dt&gt;Replace Parameter with Explicit Methods（以明确函数取代参数）&lt;/dt&gt;
	&lt;dd&gt;将单一函数分解为多个函数从而去掉参数，前提是这几个函数的逻辑功能区别较大。&lt;/dd&gt;
	&lt;dt&gt;Preserve Whole Object（保持对象完整）&lt;/dt&gt;
	&lt;dd&gt;传递完整的对象，取代几个参数的传递。&lt;/dd&gt;
	&lt;dt&gt;Replace Parameter with Methods（以函数取代参数）&lt;/dt&gt;
	&lt;dd&gt;如果目标函数需要的是几个参数操作的结果，就直接传递这个结果，而不是数个参数。&lt;/dd&gt;
	&lt;dt&gt;Introduce Parameter Object(引入参数对象)&lt;/dt&gt;
	&lt;dd&gt;当几个参数经常同时出现，就封装他们。 （他们之间往往就有逻辑关系）&lt;/dd&gt;
	&lt;dt&gt;Remove Setting Method（移除设值函数）&lt;/dt&gt;
	&lt;dd&gt;如果类的某个值域初始化后不再改变，就去掉它的setting方法。 （我理解为原则：&amp;ldquo;减少疑惑，保持唯一&amp;rdquo;）&lt;/dd&gt;
	&lt;dt&gt;Hide Method（隐藏某个函数）&lt;/dt&gt;
	&lt;dd&gt;使用 private 标记未被其他类调用的方法。&lt;/dd&gt;
	&lt;dt&gt;Replace Constructor with Factory Method（以工厂函数取代构造函数）&lt;/dt&gt;
	&lt;dd&gt;引入工厂模式。&lt;/dd&gt;
	&lt;dt&gt;Encapsulate Downcast（封装向下转型动作）&lt;/dt&gt;
	&lt;dd&gt;当知道什么类型时候，将其封装在产生函数里面，减少引用者的困扰。&lt;/dd&gt;
	&lt;dt&gt;Replace Error Code with Exception（以异常取代错误码）&lt;/dt&gt;
	&lt;dd&gt;如其名。 （关于异常使用的时机，抛出的方式，捕捉的粒度，我困惑了很久。 最后的总结的经验是：在什么层级处理并且仅处理该层级的异常。等有时间详细成文送出）&lt;/dd&gt;
	&lt;dt&gt;Replace Exception with Test（以测试取代异常）&lt;/dt&gt;
	&lt;dd&gt;异常不是条件判断。&lt;/dd&gt;
&lt;/dl&gt;
&lt;h3&gt;&lt;a name="_处理概括关系"&gt;&lt;/a&gt;2.6. 处理概括关系&lt;/h3&gt;
&lt;p&gt;关于 OOP 继承的那些事儿。&lt;/p&gt;
&lt;dl&gt;
	&lt;dt&gt;Pull Up Field（值域上移）&lt;/dt&gt;
	&lt;dd&gt;子类重复的值域放到父类去。 （其实还是基于责任归属的问题）&lt;/dd&gt;
	&lt;dt&gt;Pull Up Method（函数上移）&lt;/dt&gt;
	&lt;dd&gt;子类中重复函数移到父类。&lt;/dd&gt;
	&lt;dt&gt;Pull Up Construction Body（构造函数本体上移）&lt;/dt&gt;
	&lt;dd&gt;共用的构造函数片段上移。&lt;/dd&gt;
	&lt;dt&gt;Push Down Method（函数下移）&lt;/dt&gt;
	&lt;dd&gt;将父类中近被某个子类调用的函数下移。&lt;/dd&gt;
	&lt;dt&gt;Push Down Field（值域下移）&lt;/dt&gt;
	&lt;dd&gt;同上。&lt;/dd&gt;
	&lt;dt&gt;Extract Subclass（提炼子类）&lt;/dt&gt;
	&lt;dd&gt;当某个类只有部分特性被用到，就需要提取出子类。&lt;/dd&gt;
	&lt;dt&gt;Extract Superclass（提炼超类）&lt;/dt&gt;
	&lt;dd&gt;和上面相反。&lt;/dd&gt;
	&lt;dt&gt;Extract Interface（提炼接口）&lt;/dt&gt;
	&lt;dd&gt;将相同的子集提取接口。&lt;/dd&gt;
	&lt;dt&gt;Collapse hierarchy（折叠继承体系）&lt;/dt&gt;
	&lt;dd&gt;父类和子类并无太大区别时候，合体吧亲。&lt;/dd&gt;
	&lt;dt&gt;From Template Mehod（塑造模板函数）&lt;/dt&gt;
	&lt;dd&gt;将子类的同功能不同实现函数上移到父类，并在子类提供同名不同实现被调用的子函数。&lt;/dd&gt;
	&lt;dt&gt;Replace Inheritance with Delegation（以委托取代继承）&lt;/dt&gt;
	&lt;dd&gt;将父类变成一个值域，在调用这个值域的方法。is-a &amp;rarr; has-a （继承太多就会出问题）&lt;/dd&gt;
	&lt;dt&gt;Replace Delegation with Inheritance（以继承取代委托）&lt;/dt&gt;
	&lt;dd&gt;和上面相反的应用，当子类和父类出现明显的继承关系时候使用。&lt;/dd&gt;
&lt;/dl&gt;
&lt;h3&gt;&lt;a name="_大型重构"&gt;&lt;/a&gt;2.7. 大型重构&lt;/h3&gt;
&lt;p&gt;这一章讲的内容有点高屋建瓴，这里就不概括了，建议读原文。&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;Tease Apart Inheritance（梳理并分解继承体系）&lt;/li&gt;
	&lt;li&gt;Convert Procedural Design to Objects（将过程化设计转化为对象设计）&lt;/li&gt;
	&lt;li&gt;Separate Domain from Presentation（将领域和表述/显示分离）&lt;/li&gt;
	&lt;li&gt;Extract hierarchy（提炼继承体系）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;少年，coding时候重构你的代码吧！&lt;/p&gt;
&lt;/p&gt;

		
  

&lt;div style="margin-top:15px;background:none repeat scroll 0pt 0pt rgb(238,238,238)"&gt;
  &lt;p&gt;
  &lt;strong&gt;版权所有 &amp;copy; 2010 转载本站文章请注明：&lt;/strong&gt; 转载自
  &lt;a href="http://log4d.com/" target="_blank"&gt;Log4D&lt;/a&gt;&lt;br&gt;
  &lt;strong&gt;原文链接:&lt;/strong&gt; &lt;a href="http://log4d.com/2012/02/refactory/" target="_blank"&gt;http://log4d.com/2012/02/refactory/&lt;/a&gt;&lt;br&gt;
  您可以随意地转载本站的文章，但是必须在醒目位置注明来源及本站链接，不可以将本站文章商业化使用，或者修改、转换或者以本作品为基础进行创作。&lt;br&gt;
  3a1ff193cee606bd1e2ea554a16353ee
  &lt;/p&gt;
&lt;/div&gt;

		
	&lt;img src="http://feeds.feedburner.com/~r/dddspace/~4/03wLok3vF2Y" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://log4d.com/2012/02/refactory/</feedburner:origLink></entry>
  
  <entry>
    <title type="html"><![CDATA[暗时间读书笔记]]></title>
    <link href="http://feedproxy.google.com/~r/dddspace/~3/uJ_i1X6gHnM/" />
    <updated>2012-01-15T00:00:00+08:00</updated>
    <id>http://log4d.com/2012/01/an-shi-jian</id>
	<content type="html">
		
		&lt;p&gt;&lt;p&gt;&lt;a href="http://mindhacks.cn/"&gt;pongba&lt;/a&gt;的大作《&lt;a href="http://book.douban.com/subject/6709809"&gt;暗时间&lt;/a&gt;》，讲述效率、习惯、思维，还有一些数学史话和算法，推荐一看。&lt;/p&gt;
&lt;p&gt;&lt;img alt="" height="432" src="http://img3.douban.com/lpic/s6586365.jpg" width="309" /&gt;&lt;/p&gt;
&lt;p&gt;ps：我的读书笔记比较水，也许成为摘抄更合适。我习惯这种大纲式的笔记，方便我回想。这里有&lt;a href="http://book.douban.com/review/5012104/"&gt;一篇很赞的评论&lt;/a&gt;，介绍了三头牛，其中有笑来老师和刘未鹏。&lt;!--more--&gt;&lt;/p&gt;
&lt;h2&gt;&lt;a name="_效率_记忆和学习"&gt;&lt;/a&gt;1. 效率、记忆和学习&lt;/h2&gt;
&lt;ul&gt;
	&lt;li&gt;暗时间&lt;br /&gt;
		&lt;ul&gt;
			&lt;li&gt;那些瓶颈较细的能够抓住每一粒时间之沙，虽然啥子总量一样，但相对却拥有更长的生命。&lt;/li&gt;
		&lt;/ul&gt;
	&lt;/li&gt;
	&lt;li&gt;投入时间和效率&lt;br /&gt;
		&lt;ul&gt;
			&lt;li&gt;投入时间这个说法本身就是荒唐的，实际投入的是时间和效率的乘积。&lt;/li&gt;
			&lt;li&gt;避免工作内容切换带来的上下文时间损耗&lt;/li&gt;
			&lt;li&gt;通过锻炼缩短进入状态的能力&lt;/li&gt;
			&lt;li&gt;能够迅速进入专注状态，以及能够长期保持专注状态，是高效学习的两个最重要习惯。&lt;/li&gt;
		&lt;/ul&gt;
	&lt;/li&gt;
	&lt;li&gt;设计你自己的进度条&lt;br /&gt;
		&lt;ul&gt;
			&lt;li&gt;设计你自己的进度条&lt;/li&gt;
			&lt;li&gt;不要过早退出循环&lt;br /&gt;
				&lt;ul&gt;
					&lt;li&gt;绝大多数情况下你并不孤单，你遇到的问题早就有人遇到过，你踩过的坑里尽是前人的脚印。&lt;/li&gt;
				&lt;/ul&gt;
			&lt;/li&gt;
			&lt;li&gt;兴趣遍地都是，专注和持之以恒才是真正稀缺的&lt;br /&gt;
				&lt;ul&gt;
					&lt;li&gt;性格里面有没有维持兴趣的火种一直燃烧下去的燃料&lt;/li&gt;
				&lt;/ul&gt;
			&lt;/li&gt;
			&lt;li&gt;靠专业技能的陈宫是最具有可复制性的&lt;/li&gt;
			&lt;li&gt;反思是让人得以改进自己的最重要思维品质&lt;/li&gt;
			&lt;li&gt;一生的知识积累，自学的起码占90%&lt;/li&gt;
		&lt;/ul&gt;
	&lt;/li&gt;
	&lt;li&gt;如何有效的记忆与学习&lt;br /&gt;
		&lt;ul&gt;
			&lt;li&gt;最终目的是要在恰当的时候能够想起来去使用&lt;/li&gt;
			&lt;li&gt;记忆线索的提取&lt;br /&gt;
				&lt;ul&gt;
					&lt;li&gt;知识信息：精细的概念、逻辑、一般的解题原则、通用的解题手法、背景知识、类似的问题&lt;/li&gt;
					&lt;li&gt;环境因素：环境、味道、声音&lt;/li&gt;
					&lt;li&gt;语言背景&lt;/li&gt;
				&lt;/ul&gt;
			&lt;/li&gt;
			&lt;li&gt;如何记忆&lt;br /&gt;
				&lt;ul&gt;
					&lt;li&gt;主动回顾&lt;/li&gt;
					&lt;li&gt;创造回忆的机会&lt;/li&gt;
					&lt;li&gt;虚拟别人的经历&lt;/li&gt;
					&lt;li&gt;抽象和推广&lt;/li&gt;
					&lt;li&gt;比较自己的经历&lt;/li&gt;
				&lt;/ul&gt;
			&lt;/li&gt;
		&lt;/ul&gt;
	&lt;/li&gt;
	&lt;li&gt;学习密度和专注力&lt;br /&gt;
		&lt;ul&gt;
			&lt;li&gt;并非靠自制力去强迫不受干扰，真正的效率源自于内心对一个事物的强烈的热忱。&lt;/li&gt;
			&lt;li&gt;专注力的意义&lt;br /&gt;
				&lt;ul&gt;
					&lt;li&gt;专注力可以让表层意识全功率运作&lt;/li&gt;
					&lt;li&gt;专注力可以让潜意识进入一种专注状态，在非工作时间持续发挥作用。&lt;/li&gt;
				&lt;/ul&gt;
			&lt;/li&gt;
			&lt;li&gt;获取专注力&lt;br /&gt;
				&lt;ul&gt;
					&lt;li&gt;人在接触一样新事物时候都是极其专注的（小时候的故事）。&lt;/li&gt;
					&lt;li&gt;克服焦虑，焦虑会严重影响专注力&lt;/li&gt;
					&lt;li&gt;享受困难，保持乐观心态&lt;/li&gt;
					&lt;li&gt;GTD，要事第一，让不重要的事情来找自己&lt;/li&gt;
				&lt;/ul&gt;
			&lt;/li&gt;
		&lt;/ul&gt;
	&lt;/li&gt;
	&lt;li&gt;刘未鹏的学习习惯&lt;br /&gt;
		&lt;ul&gt;
			&lt;li&gt;学习和思考&lt;br /&gt;
				&lt;ul&gt;
					&lt;li&gt;Google &amp;amp; Wiki&lt;/li&gt;
					&lt;li&gt;看书挑剔，只看经典&lt;/li&gt;
					&lt;li&gt;做读书笔记&lt;/li&gt;
					&lt;li&gt;将思考变成习惯，避免焦虑&lt;/li&gt;
					&lt;li&gt;多看心理学与思维的书，因为它们是跨学科的&lt;/li&gt;
					&lt;li&gt;学习知识的技巧：它的本质是什么？它的第一原则是什么？它的知识结构是怎样的？&lt;/li&gt;
					&lt;li&gt;学习和思考时候常问自己问题&lt;br /&gt;
						&lt;ul&gt;
							&lt;li&gt;你的问题到底是什么&lt;/li&gt;
							&lt;li&gt;有什么收获&lt;/li&gt;
							&lt;li&gt;设想自己正在将东西讲给别人听&lt;/li&gt;
							&lt;li&gt;设想讲给一个不懂的人听&lt;/li&gt;
							&lt;li&gt;市场反省和注意自己的思维过程&lt;/li&gt;
							&lt;li&gt;养成反驳自己的想法的习惯&lt;/li&gt;
							&lt;li&gt;问自己，真的理解了么&lt;/li&gt;
						&lt;/ul&gt;
					&lt;/li&gt;
				&lt;/ul&gt;
			&lt;/li&gt;
			&lt;li&gt;时间和效率&lt;br /&gt;
				&lt;ul&gt;
					&lt;li&gt;趁着对一件事情有热情的时候，一股脑儿把万事开头那个最难的阶段熬过去&lt;/li&gt;
					&lt;li&gt;重要的事情优先&lt;/li&gt;
					&lt;li&gt;重要的事情要营造比较大的时间快来完成&lt;/li&gt;
					&lt;li&gt;同时也要善于利用小块时间&lt;/li&gt;
					&lt;li&gt;重视知识的本质&lt;/li&gt;
					&lt;li&gt;重视提前积累的强大力量（要把眼光多看，就能提前准备）&lt;/li&gt;
					&lt;li&gt;抬起头来（停下来，问问自己做的事情是否有意义）&lt;/li&gt;
					&lt;li&gt;退订RSS（这个嘛，过滤就好了）&lt;/li&gt;
					&lt;li&gt;总结最近得到的新知识&lt;/li&gt;
					&lt;li&gt;保持看书（书本的知识质量优于互联网上的知识）&lt;/li&gt;
					&lt;li&gt;制定简要的阅读计划&lt;/li&gt;
				&lt;/ul&gt;
			&lt;/li&gt;
			&lt;li&gt;时间和效率2&lt;br /&gt;
				&lt;ul&gt;
					&lt;li&gt;根据主体来查阅资料，而不是根据资料来查阅主题&lt;/li&gt;
					&lt;li&gt;好资料是根据思考过程来推导，坏资料是上来就写定理公式&lt;/li&gt;
					&lt;li&gt;学习一样东西，首先要在大脑中积累充分的疑惑感&lt;/li&gt;
					&lt;li&gt;有选择的阅读&lt;/li&gt;
					&lt;li&gt;书籍分为两类，一种是知识的，一种是思维的&lt;/li&gt;
					&lt;li&gt;看不懂的时候，有可能是几种原因：&lt;br /&gt;
						&lt;ul&gt;
							&lt;li&gt;看的不够使劲&lt;/li&gt;
							&lt;li&gt;牵扯到了不懂的概念&lt;/li&gt;
							&lt;li&gt;作者讲述的顺序不对&lt;/li&gt;
						&lt;/ul&gt;
					&lt;/li&gt;
					&lt;li&gt;在阅读之前就获取书本质量的评估&lt;/li&gt;
					&lt;li&gt;如何搜索好书：同作者，Amazon/Douban推荐，提到其他著作的数，别人之作的索引&lt;/li&gt;
				&lt;/ul&gt;
			&lt;/li&gt;
			&lt;li&gt;知识结构&lt;br /&gt;
				&lt;ul&gt;
					&lt;li&gt;抓住不变量（本质的知识）&lt;/li&gt;
				&lt;/ul&gt;
			&lt;/li&gt;
			&lt;li&gt;习惯的养成&lt;br /&gt;
				&lt;ul&gt;
					&lt;li&gt;人容易珍视自己长期积累的信念&lt;/li&gt;
					&lt;li&gt;理智是情感的奴隶&lt;/li&gt;
					&lt;li&gt;不自我欺骗，承认养成习惯的难度，并注意观察自己的行为，经常自我认知&lt;/li&gt;
				&lt;/ul&gt;
			&lt;/li&gt;
		&lt;/ul&gt;
	&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;a name="_逃出你的肖申克"&gt;&lt;/a&gt;2. 逃出你的肖申克&lt;/h2&gt;
&lt;ul&gt;
	&lt;li&gt;亲身经历才能明白&lt;br /&gt;
		&lt;ul&gt;
			&lt;li&gt;切身体验：心理学上表明，人无法从强度上正确感受到他人痛苦&lt;/li&gt;
			&lt;li&gt;别人口中的故事：会受到讲述人自己观念的影响而影响&lt;/li&gt;
			&lt;li&gt;为什么：往往他人只讲述how，而不是why&lt;/li&gt;
			&lt;li&gt;世界是复杂的：影响的因素太多，未必是别人认为的&lt;/li&gt;
			&lt;li&gt;未来是不确定的：&amp;ldquo;你只要&amp;hellip;&amp;hellip;就能&amp;hellip;&amp;hellip;&amp;rdquo;的错觉。只有做好准备，而无万全之策&lt;/li&gt;
			&lt;li&gt;别人的道理，自己的事情：知识经验跨越情景转移失败&lt;/li&gt;
			&lt;li&gt;认识失调和自我辩护：自我辩护倾向&lt;/li&gt;
			&lt;li&gt;失败即成功：自己的失败，也能给予一些信息和帮助&lt;/li&gt;
			&lt;li&gt;情绪对照：pass&lt;/li&gt;
			&lt;li&gt;天性：进化心理学，理性vs情绪&lt;/li&gt;
			&lt;li&gt;习惯&lt;/li&gt;
		&lt;/ul&gt;
	&lt;/li&gt;
	&lt;li&gt;亲身经历未必明白&lt;br /&gt;
		&lt;ul&gt;
			&lt;li&gt;很傻很天真的条件反射：遇到失败容易放弃，其实没有好的结果并不代表过程就错了。 判定成功失败从更长远的上来做统计&lt;/li&gt;
			&lt;li&gt;认知偏差：将失败归于外界，将成功归于自身&lt;/li&gt;
			&lt;li&gt;情绪系统：我们平时的决策强烈依赖情绪系统输出。情绪是决策系统之一，而不应该是全部&lt;/li&gt;
		&lt;/ul&gt;
	&lt;/li&gt;
	&lt;li&gt;不需经历也能明白-理性的力量&lt;br /&gt;
		&lt;ul&gt;
			&lt;li&gt;不应该让事实替代我们进行思考和推理，而需要进行社会学习（从别人错误中学习）&lt;/li&gt;
			&lt;li&gt;人类最强大的能力之一是归纳和推理（和波利亚解题的归纳/联想相对应）&lt;/li&gt;
		&lt;/ul&gt;
	&lt;/li&gt;
	&lt;li&gt;错觉和偏见&lt;br /&gt;
		&lt;ul&gt;
			&lt;li&gt;平凡的解释vs疯狂的解释&lt;/li&gt;
			&lt;li&gt;理所当然的错误：人往往无法看到或设想另一种可能性&lt;/li&gt;
			&lt;li&gt;打破这种的偏见唯一途径就是开阔视野，积累知识，以及和具有不同知识背景的人讨论&lt;/li&gt;
		&lt;/ul&gt;
	&lt;/li&gt;
	&lt;li&gt;新皮层和原始皮层&lt;br /&gt;
		&lt;ul&gt;
			&lt;li&gt;理智vs情绪&lt;/li&gt;
		&lt;/ul&gt;
	&lt;/li&gt;
	&lt;li&gt;理智和情感&lt;br /&gt;
		&lt;ul&gt;
			&lt;li&gt;我们的理性大脑非常善于对自己的行为作出立即的，看上去合理的解释。&lt;/li&gt;
			&lt;li&gt;思想钢印&lt;/li&gt;
			&lt;li&gt;大脑符合用进废退的原理，越经常使用的区域会越来越强大。&lt;/li&gt;
			&lt;li&gt;习惯之所以难以改变，就是因为习惯是自我巩固的。&lt;/li&gt;
			&lt;li&gt;能够改变既有的习惯，依靠的不是自制力，而是知识。&lt;/li&gt;
		&lt;/ul&gt;
	&lt;/li&gt;
	&lt;li&gt;书写是为了更好的思考&lt;/li&gt;
	&lt;li&gt;为什么你从现在开始就应该写博客&lt;/li&gt;
	&lt;li&gt;我能与我不能&lt;br /&gt;
		&lt;ul&gt;
			&lt;li&gt;我想&amp;rarr;我不能&amp;rarr;我不想&lt;/li&gt;
			&lt;li&gt;自利归因&lt;/li&gt;
		&lt;/ul&gt;
	&lt;/li&gt;
	&lt;li&gt;遇到问题为什么应该自己动手&lt;br /&gt;
		&lt;ul&gt;
			&lt;li&gt;捷径未必正确，只是小聪明&lt;/li&gt;
			&lt;li&gt;问题之外的知识会更多&lt;/li&gt;
		&lt;/ul&gt;
	&lt;/li&gt;
	&lt;li&gt;什么才是你的不可替代性和核心竞争力&lt;br /&gt;
		&lt;ul&gt;
			&lt;li&gt;专业领域技能&lt;/li&gt;
			&lt;li&gt;跨领域的技能&lt;/li&gt;
			&lt;li&gt;学习能力&lt;/li&gt;
			&lt;li&gt;性格要素&lt;/li&gt;
		&lt;/ul&gt;
	&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;a name="_跟波利亚学解题"&gt;&lt;/a&gt;3. 跟波利亚学解题&lt;/h2&gt;
&lt;ul&gt;
	&lt;li&gt;跟波利亚学解题&lt;br /&gt;
		&lt;ul&gt;
			&lt;li&gt;联想&lt;br /&gt;
				&lt;ul&gt;
					&lt;li&gt;联想是为了补上从条件到结论、从已知到未知之间缺失的链环&lt;/li&gt;
					&lt;li&gt;联想可以将问题向上归约一层，或者将条件往下推导一层&lt;/li&gt;
					&lt;li&gt;Working Backward (倒过来解)：将需要求解的问题本身当作条件，再进行推导。&lt;/li&gt;
				&lt;/ul&gt;
			&lt;/li&gt;
			&lt;li&gt;一些思维方法&lt;br /&gt;
				&lt;ul&gt;
					&lt;li&gt;时刻不忘未知量：始终知道自己需要什么&lt;/li&gt;
					&lt;li&gt;用特例启发思考&lt;/li&gt;
					&lt;li&gt;反过来推导：结论往往蕴含丰富的条件&lt;/li&gt;
					&lt;li&gt;试错：穷举&lt;/li&gt;
					&lt;li&gt;调整题目的条件：通过调整条件，找到条件和结论之间是如何联系的&lt;/li&gt;
					&lt;li&gt;求解一个类似的题目：寻求通用的方法&lt;/li&gt;
					&lt;li&gt;列出所有可能和问题相关的定理或性质&lt;/li&gt;
					&lt;li&gt;考察反面，考察其他所有情况&lt;/li&gt;
					&lt;li&gt;将问题泛化，并求解这个泛化的问题&lt;/li&gt;
					&lt;li&gt;意识孵化法（即前面提到的，将问题存在潜意识里面）&lt;/li&gt;
					&lt;li&gt;烫手山芋法（2B方法）&lt;/li&gt;
					&lt;li&gt;让联想更容易发生&lt;br /&gt;
						&lt;ul&gt;
							&lt;li&gt;已有知识是双刃剑：提供了解决问题的捷径，同时也是思维的桎梏&lt;/li&gt;
							&lt;li&gt;使用抽象将问题泛化，只抓住本质&lt;/li&gt;
						&lt;/ul&gt;
					&lt;/li&gt;
					&lt;li&gt;好题目，坏题目&lt;/li&gt;
					&lt;li&gt;思考的习惯：记录&lt;br /&gt;
						&lt;ul&gt;
							&lt;li&gt;人的记忆资源是有限的&lt;/li&gt;
							&lt;li&gt;将精力集中在某个过程，而不是全部过程上&lt;/li&gt;
							&lt;li&gt;记录更能刺激神经兴奋&lt;/li&gt;
							&lt;li&gt;记录可以方便的回顾，防止进入思维定势&lt;/li&gt;
							&lt;li&gt;方便解题之后整理&lt;/li&gt;
						&lt;/ul&gt;
					&lt;/li&gt;
					&lt;li&gt;练习练习&lt;br /&gt;
						&lt;ul&gt;
							&lt;li&gt;将外显记忆转化为内隐记忆&lt;/li&gt;
							&lt;li&gt;养成正确思维习惯&lt;/li&gt;
							&lt;li&gt;增加领域知识&lt;/li&gt;
							&lt;li&gt;帮助养成策略性联想&lt;/li&gt;
						&lt;/ul&gt;
					&lt;/li&gt;
					&lt;li&gt;启发法并不能精准的命中目标，而只能划定一个大致的范围&lt;/li&gt;
					&lt;li&gt;总结的意义：在解题过程中寻找一般性的、跨问题的思维思维法则&lt;/li&gt;
				&lt;/ul&gt;
			&lt;/li&gt;
			&lt;li&gt;锤子和钉子&lt;br /&gt;
				&lt;ul&gt;
					&lt;li&gt;记住问题是什么&lt;/li&gt;
					&lt;li&gt;专注于想要解决的问题&lt;/li&gt;
				&lt;/ul&gt;
			&lt;/li&gt;
			&lt;li&gt;鱼是最后一个看到水的（这章像是赚稿费的，果然是文章集，呵呵）&lt;br /&gt;
				&lt;ul&gt;
					&lt;li&gt;Think out of the box&lt;/li&gt;
				&lt;/ul&gt;
			&lt;/li&gt;
			&lt;li&gt;知其所以然&lt;br /&gt;
				&lt;ul&gt;
					&lt;li&gt;我们要下蛋的鸡&lt;/li&gt;
					&lt;li&gt;两种思维形式&lt;br /&gt;
						&lt;ul&gt;
							&lt;li&gt;联想&lt;/li&gt;
							&lt;li&gt;演绎&amp;amp;归纳&lt;/li&gt;
						&lt;/ul&gt;
					&lt;/li&gt;
					&lt;li&gt;所以然是什么？什么是问题的价值？&lt;br /&gt;
						&lt;ul&gt;
							&lt;li&gt;内隐化：将知识变成本能&lt;/li&gt;
							&lt;li&gt;跨情境运用&lt;/li&gt;
							&lt;li&gt;对问题解的更多记忆提取线索：通过线索记住这个问题以及解法&lt;/li&gt;
							&lt;li&gt;更多的知识：(beyond the question)&lt;/li&gt;
							&lt;li&gt;重要分析推理，而不是联想：推理更靠谱&lt;/li&gt;
							&lt;li&gt;寻找问题原始出处：那里也许讲的更详细&lt;/li&gt;
							&lt;li&gt;整理自己的思路&lt;/li&gt;
						&lt;/ul&gt;
					&lt;/li&gt;
				&lt;/ul&gt;
			&lt;/li&gt;
			&lt;li&gt;为什么要知其所以然&lt;br /&gt;
				&lt;ul&gt;
					&lt;li&gt;更难忘记&lt;/li&gt;
					&lt;li&gt;知识结构是树状的，越往上走，需要记忆的节点越少&lt;/li&gt;
				&lt;/ul&gt;
			&lt;/li&gt;
			&lt;li&gt;康托尔、歌德尔、图灵（pass）&lt;/li&gt;
			&lt;li&gt;快速排序：让未知世界无机可乘，让答案的任何一个分支都是等概率&lt;/li&gt;
			&lt;li&gt;贝叶斯算法：（黑客与画家也提到这个算法）&lt;/li&gt;
		&lt;/ul&gt;
	&lt;/li&gt;
&lt;/ul&gt;
&lt;/p&gt;

		
  

&lt;div style="margin-top:15px;background:none repeat scroll 0pt 0pt rgb(238,238,238)"&gt;
  &lt;p&gt;
  &lt;strong&gt;版权所有 &amp;copy; 2010 转载本站文章请注明：&lt;/strong&gt; 转载自
  &lt;a href="http://log4d.com/" target="_blank"&gt;Log4D&lt;/a&gt;&lt;br&gt;
  &lt;strong&gt;原文链接:&lt;/strong&gt; &lt;a href="http://log4d.com/2012/01/an-shi-jian/" target="_blank"&gt;http://log4d.com/2012/01/an-shi-jian/&lt;/a&gt;&lt;br&gt;
  您可以随意地转载本站的文章，但是必须在醒目位置注明来源及本站链接，不可以将本站文章商业化使用，或者修改、转换或者以本作品为基础进行创作。&lt;br&gt;
  3a1ff193cee606bd1e2ea554a16353ee
  &lt;/p&gt;
&lt;/div&gt;

		
	&lt;img src="http://feeds.feedburner.com/~r/dddspace/~4/uJ_i1X6gHnM" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://log4d.com/2012/01/an-shi-jian/</feedburner:origLink></entry>
  
  <entry>
    <title type="html"><![CDATA[baidu ting下载音乐脚本]]></title>
    <link href="http://feedproxy.google.com/~r/dddspace/~3/_rCj8IjPs84/" />
    <updated>2012-01-03T00:00:00+08:00</updated>
    <id>http://log4d.com/2012/01/tingdownload</id>
	<content type="html">
		
		&lt;p&gt;&lt;p&gt;度娘终于干了一件好事，&lt;a href="http://ting.baidu.com"&gt;Baidu Ting&lt;/a&gt;上线了， 正版音乐免费下载，类似于&lt;a href="http://www.google.cn/music"&gt;谷歌音乐&lt;/a&gt;。 关于音乐版权和免费的问题， 有很多问题需要取讨论， 比如说这种商业模式是否对传统唱片业产生冲击又或是有积极影响？ 作为普通消费者，暂时不用考虑这些问题，先享受这些服务好了。&lt;/p&gt;
&lt;p&gt;Baidu Ting的音乐质量是128KBps，音质算好，里面的idv3信息也勉强可以，有:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;歌名&lt;/li&gt;
	&lt;li&gt;歌手&lt;/li&gt;
	&lt;li&gt;部分专辑名（偶尔也出现&amp;ldquo;201-8月新歌快递&amp;rdquo;这种比较山寨的字）&lt;/li&gt;
	&lt;li&gt;部分唱片封面图片&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;虽然比不上谷歌音乐连歌曲风格都准备好了，但是比杂乱无章的那些音乐mp3要好太多了。&lt;/p&gt;
&lt;h2&gt;&lt;a name="_自动下载脚本tingdownload"&gt;&lt;/a&gt;自动下载脚本tingdownload&lt;/h2&gt;
&lt;p&gt;早上下了几首音乐，就顺手写了一个脚本，用来批量从Badu Ting下载音乐。&lt;/p&gt;
&lt;p&gt;代码在&lt;a href="https://github.com/alswl/tingdownload"&gt;github-tingdownload&lt;!--more--&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;&lt;a name="_需要"&gt;&lt;/a&gt;需要&lt;/h2&gt;
&lt;ul&gt;
	&lt;li&gt;Python 2 (仅在Python2.7下测试)&lt;/li&gt;
	&lt;li&gt;BeautifulSoup(已包含在目录下)&lt;/li&gt;
	&lt;li&gt;simplejson（已包含在目录下)&lt;/li&gt;
	&lt;li&gt;一点点Python基础&lt;/li&gt;
	&lt;li&gt;Linux/Windows（我在Linux没问题，Windows应该也可以）&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;a name="_使用方法"&gt;&lt;/a&gt;使用方法&lt;/h2&gt;
&lt;p&gt;在Shell(命令行)里输入下面随便一个命令，就会在当前目录下面出现 &lt;tt&gt;musics&lt;/tt&gt; 文件夹， 里面就有下载好的音乐。&lt;/p&gt;
&lt;pre&gt;# 使用说明
usage: tingdownload.py [-h] [--input INPUT] [Keyword [Keyword ...]]&lt;/pre&gt;&lt;/p&gt;

&lt;p&gt;A script to download music from ting.baidu.com.&lt;/p&gt;

&lt;p&gt;positional arguments:&lt;br /&gt;
  Keyword&lt;/p&gt;

&lt;p&gt;optional arguments:&lt;br /&gt;
  -h, &amp;#8211;help            show this help message and exit&lt;br /&gt;
  &amp;#8211;input INPUT, -i INPUT&lt;br /&gt;
                        a list file to input musics&lt;pre class="brush: bash;fontsize: 100; first-line: 1; "&gt;# 示例
python tingdownload.py 老男孩 #单个文件下载
./tingdownload.py 老男孩 #单个文件下载（给python文件加上可执行权限）
python tingdownload.py 老男孩 Raise\n Me\n Up # 多文件名，如果有空格，请记得加上空格反转&amp;#39;\n&amp;#39;&lt;/pre&gt;
&lt;p&gt;批量下载的话，可以准备一个列表文件，每个歌曲名用回车隔开，如下：&lt;/p&gt;
&lt;pre&gt;还过得去
不敢太幸福
小情歌
爱情靠不住
我爱我
你可以不用给我答案     金莎
没有这首歌         后弦
        回不去了吗         萧亚轩
        有些事现在不做 一辈子都不会做了  五月天
        第一夫人    张杰&lt;/pre&gt;
&lt;p&gt;将这个list文件作为输入传入执行脚本：&lt;/p&gt;
&lt;pre&gt;python2.7 tingdownload.py --input ~/music.txt&lt;/pre&gt;
&lt;p&gt;运行结果如下，列出四种情况：&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;下载成功，如果文件已经存在，会跳过&lt;/li&gt;
	&lt;li&gt;下载失败，由于网络原因&lt;/li&gt;
	&lt;li&gt;下载失败，由于关键词不准确而出现太多结果&lt;/li&gt;
	&lt;li&gt;下载失败，没有关键词匹配的结果&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="brush: bash;fontsize: 100; first-line: 1; "&gt;█▓▒░alswl@x201█▓▒░ ~/dev/project/python/tingdownload/ ./tingdownload.py 黄昏\ 周传雄 考试什么 --input ~/a.txt
&amp;gt; Start download 黄昏 周传雄...
# Info: File &amp;quot;/home/alswl/dev/project/python/tingdownload/musics/周传雄-黄昏.mp3&amp;quot; exists.
&amp;gt; Start download 考试什么...
# Info: File &amp;quot;/home/alswl/dev/project/python/tingdownload/musics/徐良-考试什么的去死吧.mp3&amp;quot; exists.
&amp;gt; Start download 还过得去...&lt;/pre&gt;&lt;/p&gt;

&lt;p&gt;&amp;gt; Start download 不敢太幸福&amp;#8230;&lt;br /&gt;
&amp;gt; Start download 小情歌&amp;#8230;&lt;br /&gt;
# Failed: Too more result found for keyword 小情歌.&lt;br /&gt;
&amp;gt; Start download 爱情靠不住&amp;#8230;&lt;/p&gt;

&lt;p&gt;== Download success (4) ==&lt;br /&gt;
黄昏 周传雄&lt;br /&gt;
考试什么&lt;br /&gt;
还过得去&lt;br /&gt;
不敢太幸福&lt;/p&gt;

&lt;p&gt;== Download failed for too many result (1) ==&lt;br /&gt;
小情歌
&lt;p&gt;Enjoy it.&lt;/p&gt;
&lt;/p&gt;

		
  

&lt;div style="margin-top:15px;background:none repeat scroll 0pt 0pt rgb(238,238,238)"&gt;
  &lt;p&gt;
  &lt;strong&gt;版权所有 &amp;copy; 2010 转载本站文章请注明：&lt;/strong&gt; 转载自
  &lt;a href="http://log4d.com/" target="_blank"&gt;Log4D&lt;/a&gt;&lt;br&gt;
  &lt;strong&gt;原文链接:&lt;/strong&gt; &lt;a href="http://log4d.com/2012/01/tingdownload/" target="_blank"&gt;http://log4d.com/2012/01/tingdownload/&lt;/a&gt;&lt;br&gt;
  您可以随意地转载本站的文章，但是必须在醒目位置注明来源及本站链接，不可以将本站文章商业化使用，或者修改、转换或者以本作品为基础进行创作。&lt;br&gt;
  3a1ff193cee606bd1e2ea554a16353ee
  &lt;/p&gt;
&lt;/div&gt;

		
	&lt;img src="http://feeds.feedburner.com/~r/dddspace/~4/_rCj8IjPs84" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://log4d.com/2012/01/tingdownload/</feedburner:origLink></entry>
  
  <entry>
    <title type="html"><![CDATA[My 2011]]></title>
    <link href="http://feedproxy.google.com/~r/dddspace/~3/0qcJy5wrMmc/" />
    <updated>2011-12-31T00:00:00+08:00</updated>
    <id>http://log4d.com/2011/12/my-2011</id>
	<content type="html">
		
		&lt;p&gt;&lt;p&gt;这个时间点，办公室里都是同事，想必晚上回家之后，那个零点肯定寂寞空虚冷， 手里夹根烟了。所以趁现在心情还不落寞，把年终小结写了。&lt;/p&gt;
&lt;p&gt;每当目光从走过的脚步上扫过，总感觉之前的成绩不够漂亮，可以做的更好。 回顾过去是为了收获更卓越的明天。&lt;/p&gt;
&lt;p&gt;2011，从不喜爱的ERP行业抽身，奔赴互联网，作出自己的选择。&lt;/p&gt;
&lt;p&gt;我成为了一名Python程序员，并完全转换到Linux环境。&lt;/p&gt;
&lt;p&gt;花了两个多月时间独自一个人装修，算是在这个城市扎根下来了。&lt;/p&gt;
&lt;p&gt;依然是一个光棍，执着于自己的执念。&lt;/p&gt;
&lt;p&gt;要么身体在路上，要么精神在路上，我来细数一下2011年精神的转折点。&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;走出软件作坊 # 反思DW的工作&lt;/li&gt;
	&lt;li&gt;人月神话 # 寻找DW的问题，并尝试解决方案&lt;/li&gt;
	&lt;li&gt;黑客与画家&lt;/li&gt;
	&lt;li&gt;暗时间&lt;/li&gt;
	&lt;li&gt;构建高性能Web站点&lt;/li&gt;
	&lt;li&gt;重构&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;新年的愿望有两个：&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;离梦想更近一步&lt;/li&gt;
	&lt;li&gt;找一个靠谱的姑娘，我感觉她需要我，我也需要她了&lt;/li&gt;
&lt;/ul&gt;
&lt;/p&gt;

		
  

&lt;div style="margin-top:15px;background:none repeat scroll 0pt 0pt rgb(238,238,238)"&gt;
  &lt;p&gt;
  &lt;strong&gt;版权所有 &amp;copy; 2010 转载本站文章请注明：&lt;/strong&gt; 转载自
  &lt;a href="http://log4d.com/" target="_blank"&gt;Log4D&lt;/a&gt;&lt;br&gt;
  &lt;strong&gt;原文链接:&lt;/strong&gt; &lt;a href="http://log4d.com/2011/12/my-2011/" target="_blank"&gt;http://log4d.com/2011/12/my-2011/&lt;/a&gt;&lt;br&gt;
  您可以随意地转载本站的文章，但是必须在醒目位置注明来源及本站链接，不可以将本站文章商业化使用，或者修改、转换或者以本作品为基础进行创作。&lt;br&gt;
  3a1ff193cee606bd1e2ea554a16353ee
  &lt;/p&gt;
&lt;/div&gt;

		
	&lt;img src="http://feeds.feedburner.com/~r/dddspace/~4/0qcJy5wrMmc" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://log4d.com/2011/12/my-2011/</feedburner:origLink></entry>
  
</feed>

