Jhat's Blog jhat.pw Jhat http://jhat.pw Mon, 04 Sep 2017 01:07:57 +0800 zh-CN hourly 1 三门问题Jhat <p>三门问题(Monty Hall problem)亦称为蒙提霍尔问题、蒙特霍问题或蒙提霍尔悖论,大致出自美国的电视游戏节目Let’s Make a Deal。问题名字来自该节目的主持人蒙提·霍尔(Monty Hall)。参赛者会看见三扇关闭了的门,其中一扇的后面有一辆汽车,选中后面有车的那扇门可赢得该汽车,另外两扇门后面则各藏有一只山羊。当参赛者选定了一扇门,但未去开启它的时候,节目主持人开启剩下两扇门的其中一扇,露出其中一只山羊。主持人其后会问参赛者要不要换另一扇仍然关上的门。作为参赛者究竟要不要换?</p> <p>讨论这个问题之前,先讨论一下为什么抽签是公平的。我们将问题修改为:</p> <div class="highlighter-rouge"><pre class="highlight"><code>有N扇门,有且仅有一扇门后面有一辆汽车,其它门后都是山羊。有N个人参赛,依次选中一扇门(不可与其他人选中同样的门)。由于是依次选择的,那么选择次序对选中结果是否有影响?即这N个参赛的人,选中汽车的概率是否一样? </code></pre> </div> <p>第一个人进行选择时,毫无疑问,选中的概率为<code class="highlighter-rouge">1/n</code>。</p> <p>第二个人进行选择时,汽车还在剩下的<code class="highlighter-rouge">N-1</code>扇门后面的概率为<code class="highlighter-rouge">1 - 1/n</code>,因此选中的概率为:</p> <script type="math/tex; mode=display">P = \left(1 - \frac{1}{n}\right) \times \frac{1}{n-1} = \frac{1}{n}</script> <p>第<code class="highlighter-rouge">i</code>个人进行选择时(<code class="highlighter-rouge">i&gt;2</code>),选中的概率为:</p> <script type="math/tex; mode=display">P(i) = \left(1 - ... \left(\left(1 - \left(1 - \frac{1}{n}\right) \times \frac{1}{n-1}\right) \times \frac{1}{n-2}\right) ... \times \frac{1}{n-i-1}\right) \times \frac{1}{n-i} = \frac{1}{n}</script> <p>如果把每一次抽签都看成一次独立事件的话,不难看出,随着抽签的进行,门的数量在减少,汽车还在剩余的门后的概率也在降低,但是每个人选中汽车的概率都是一样的,即为 <code class="highlighter-rouge">1/n</code>。</p> <p>由此可见,抽签无论先后,其实都是公平的,大家的概率都一样。</p> <p>回到三门问题,参赛者首次选中汽车的概率为<code class="highlighter-rouge">1/3</code>,如果坚持不换,那么选中汽车的概率始终为<code class="highlighter-rouge">1/3</code>。如果没有主持人这个上帝角色存在,不为参赛者排除一扇本后是山羊的们,那么无论参赛者是否交换,选中汽车的概率始终为<code class="highlighter-rouge">1/3</code>。(当然,一定是在没有看第一次选中的结果前决定要不要换)</p> <p>由于主持人这个上帝角色的存在,直接帮忙排除了一扇背后是山羊的门,如果重新选择,概率会是什么样?</p> <p>有的人会说,主持人排除一扇门之后,汽车肯定在剩下的两扇门后,在任一扇门的背后的概率均为<code class="highlighter-rouge">1/2</code>,因此换与不换没太大意义,反正概率都一样。</p> <p>我们知道,计算概率我们都是以一次独立事件为基础来进行的。主持人排除一扇门之后,如果新来一个参赛者从剩下的两扇门中选择,将此作为一次独立事件,确实其无论选择哪扇门,选中的概率均为<code class="highlighter-rouge">1/2</code>。</p> <p>但是这里只有一个参赛者,应该将其从第一次选择开始,到最后决定是否换,看做一个完整的独立事件。这么来看的话,参赛者第一选择之后,选中的概率为<code class="highlighter-rouge">1/3</code>,汽车在剩下的两扇门后的概率为<code class="highlighter-rouge">2/3</code>。由于主持人以上帝视角排除了一扇门,那么排除掉的那扇门背后有汽车的概率为<code class="highlighter-rouge">0</code>,所以最后剩下的那扇门后有汽车的概率为<code class="highlighter-rouge">2/3</code>,这样才满足参赛者第一次选择之后,汽车在剩下的两扇门后的概率为<code class="highlighter-rouge">2/3</code>。</p> <p>所以作为参赛者,应该换,换了之后选择的概率为<code class="highlighter-rouge">2/3</code>。</p> <p>也许还是有人不相信,那么我们按题目所设定的规则用代码来模拟实验,看看换与不换,选择汽车的概率分布是多少。</p> <p>在模拟过程中,我们将问题推广,门的数量为大于等于3扇,其它条件不变,分别模拟不同门的数量情况下,最终选中的概率情况,代码和最终结果如下。</p> <div class="language-python highlighter-rouge"><pre class="highlight"><code><span class="c">#!/usr/bin/env python</span> <span class="c"># -*- coding: UTF-8 -*- </span> <span class="c"># Author: Jhat</span> <span class="c"># Date: 2017-09-03</span> <span class="c"># Home: http://jhat.pw</span> <span class="c"># Vim: tabstop=4 shiftwidth=4 softtabstop=4</span> <span class="kn">from</span> <span class="nn">random</span> <span class="kn">import</span> <span class="n">randint</span> <span class="k">def</span> <span class="nf">probability</span><span class="p">(</span><span class="n">base</span><span class="p">,</span> <span class="n">limit</span><span class="p">):</span> <span class="n">c_not_change</span> <span class="o">=</span> <span class="mi">0</span> <span class="n">c_change</span> <span class="o">=</span> <span class="mi">0</span> <span class="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="nb">xrange</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="n">limit</span><span class="p">):</span> <span class="n">r_index</span> <span class="o">=</span> <span class="n">randint</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="n">base</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="n">i_not_change</span> <span class="o">=</span> <span class="n">randint</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="n">base</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="k">if</span> <span class="n">i_not_change</span> <span class="o">==</span> <span class="n">r_index</span><span class="p">:</span> <span class="n">c_not_change</span> <span class="o">+=</span> <span class="mi">1</span> <span class="k">continue</span> <span class="c"># 交换</span> <span class="k">if</span> <span class="n">r_index</span> <span class="o">&lt;</span> <span class="n">i_not_change</span><span class="p">:</span> <span class="n">s_index</span> <span class="o">=</span> <span class="p">[</span><span class="n">i</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">xrange</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="n">r_index</span><span class="p">)]</span> \ <span class="o">+</span> <span class="p">[</span><span class="n">i</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">xrange</span><span class="p">(</span><span class="n">r_index</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="n">i_not_change</span><span class="p">)]</span> \ <span class="o">+</span> <span class="p">[</span><span class="n">i</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">xrange</span><span class="p">(</span><span class="n">i_not_change</span><span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="n">base</span><span class="p">)]</span> <span class="k">else</span><span class="p">:</span> <span class="n">s_index</span> <span class="o">=</span> <span class="p">[</span><span class="n">i</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">xrange</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="n">i_not_change</span><span class="p">)]</span> \ <span class="o">+</span> <span class="p">[</span><span class="n">i</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">xrange</span><span class="p">(</span><span class="n">i_not_change</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="n">r_index</span><span class="p">)]</span> \ <span class="o">+</span> <span class="p">[</span><span class="n">i</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">xrange</span><span class="p">(</span><span class="n">r_index</span><span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="n">base</span><span class="p">)]</span> <span class="k">del</span> <span class="n">s_index</span><span class="p">[</span><span class="n">randint</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="nb">len</span><span class="p">(</span><span class="n">s_index</span><span class="p">)</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)]</span> <span class="n">s_index</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">r_index</span><span class="p">)</span> <span class="n">s_index</span><span class="o">.</span><span class="n">sort</span><span class="p">()</span> <span class="n">i_change</span> <span class="o">=</span> <span class="n">s_index</span><span class="p">[</span><span class="n">randint</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="nb">len</span><span class="p">(</span><span class="n">s_index</span><span class="p">)</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)]</span> <span class="k">if</span> <span class="n">i_change</span> <span class="o">==</span> <span class="n">r_index</span><span class="p">:</span> <span class="n">c_change</span> <span class="o">+=</span> <span class="mi">1</span> <span class="c"># 不换</span> <span class="c"># s_index = [i for i in xrange(0, i_not_change)] + [i for i in xrange(i_not_change + 1, base)]</span> <span class="c"># i_change = s_index[randint(0, len(s_index) - 1)]</span> <span class="c"># if i_change == r_index:</span> <span class="c"># c_change += 1</span> <span class="n">limit</span> <span class="o">=</span> <span class="nb">float</span><span class="p">(</span><span class="n">limit</span><span class="p">)</span> <span class="k">return</span> <span class="p">(</span><span class="n">c_not_change</span> <span class="o">/</span> <span class="n">limit</span><span class="p">,</span> <span class="n">c_change</span> <span class="o">/</span> <span class="n">limit</span><span class="p">)</span> <span class="k">for</span> <span class="n">base</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">3</span><span class="p">,</span> <span class="mi">11</span><span class="p">):</span> <span class="n">p_not_change</span> <span class="o">=</span> <span class="p">[]</span> <span class="n">p_change</span> <span class="o">=</span> <span class="p">[]</span> <span class="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">10</span><span class="p">):</span> <span class="n">p</span> <span class="o">=</span> <span class="n">probability</span><span class="p">(</span><span class="n">base</span><span class="p">,</span> <span class="mi">1000000</span><span class="p">)</span> <span class="n">p_not_change</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">p</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span> <span class="n">p_change</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">p</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span> <span class="k">print</span> <span class="n">base</span><span class="p">,</span> <span class="n">p_not_change</span> <span class="k">print</span> <span class="n">base</span><span class="p">,</span> <span class="n">p_change</span> </code></pre> </div> <p><br /> 模拟实验结果如下图所示:</p> <p><img src="http://jhat.pw/assets/images/blog/math/three-doors-problems/tdp_simulation_experiment.jpg" alt="N门模拟实验" /></p> <p>从程序模拟实验结果来看,三门问题,换之后选中汽车的概率为<code class="highlighter-rouge">2/3</code>。推广到<code class="highlighter-rouge">N</code>门问题之后,换之后选中的概率为:</p> <script type="math/tex; mode=display">P(n) = \frac{n-1}{n} \times \frac{1}{n-2}</script> Sun, 03 Sep 2017 00:00:00 +0800http://jhat.pw/blog/2017/09/03/three-doors-problems.htmlhttp://jhat.pw/blog/2017/09/03/three-doors-problems.html Java自签名证书问题Jhat <p>使用<a href="http://www.sonatype.com/nexus-repository-sonatype">Sonatype Nexus</a>自建了一个Maven仓库,出于安全考虑使用了 <code class="highlighter-rouge">HTTPS</code> 协议,不过 <code class="highlighter-rouge">SSL</code> 证书用的是自签名的证书,在使用<a href="http://maven.apache.org">Maven</a>时遇到了如下错误:</p> <pre><code class="language-plain">sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target </code></pre> <p>这是因为自签名的证书不在Java的可信证书范围内,因此需要手动将对应证书加入Java的可信证书列表中,具体步骤如下:</p> <h3 id="1-使用keytool导入证书">1. 使用keytool导入证书</h3> <div class="language-bash highlighter-rouge"><pre class="highlight"><code><span class="c"># cert_name.crt 为待导入的证书文件</span> <span class="c"># store_file 为导入的证书文件的存储文件名</span> <span class="c"># cert_name 为导入的证书存储别名</span> <span class="c"># 导入证书时需要输入密码,需要将该密码记住,后面将会用到</span> keytool -import -file cert_name.crt -keystore <span class="nv">$JAVA_HOME</span>/jre/lib/security/store_file -alias cert_name </code></pre> </div> <h3 id="2-在java程序的启动参数添加可信证书参数">2. 在Java程序的启动参数添加可信证书参数</h3> <div class="language-bash highlighter-rouge"><pre class="highlight"><code><span class="c"># 123456即为上一步输入的密码</span> -Djavax.net.ssl.trustStorePassword<span class="o">=</span>123456 -Djavax.net.ssl.trustStore<span class="o">=</span><span class="nv">$JAVA_HOME</span>/jre/lib/security/store_file </code></pre> </div> <p>完成上述两步之后自签名的证书也就可以被Java程序所信任,不在出错。</p> <p>对于<a href="http://maven.apache.org">Maven</a>,只需要在 <code class="highlighter-rouge">MAVEN_OPTS</code> 环境变量中添加上述参数即可:</p> <div class="language-bash highlighter-rouge"><pre class="highlight"><code><span class="c"># 配置在 ~/.bash_profile 或 ~/.bashrc 中即可</span> <span class="nb">export </span><span class="nv">MAVEN_OPTS</span><span class="o">=</span><span class="s2">"</span><span class="nv">$MAVEN_OPTS</span><span class="s2"> -Djavax.net.ssl.trustStorePassword=123456 -Djavax.net.ssl.trustStore=</span><span class="nv">$JAVA_HOME</span><span class="s2">/jre/lib/security/store_file"</span> </code></pre> </div> Wed, 25 May 2016 00:00:00 +0800http://jhat.pw/blog/2016/05/25/java-self-signed-certificates.htmlhttp://jhat.pw/blog/2016/05/25/java-self-signed-certificates.html Java技能树Jhat <h3 id="java核心技术总结">Java核心技术总结</h3> <p><img src="http://jhat.pw/assets/images/blog/language/java/java-skill-tree/java_core.gif" alt="Java核心技术总结" /></p> <h3 id="j2ee技术总结">J2EE技术总结</h3> <p><img src="http://jhat.pw/assets/images/blog/language/java/java-skill-tree/j2ee.gif" alt="J2EE技术总结" /></p> <h3 id="工作和学习总结">工作和学习总结</h3> <p><img src="http://jhat.pw/assets/images/blog/language/java/java-skill-tree/work_study.gif" alt="工作和学习总结" /></p> <h3 id="大数据相关技术总结">大数据相关技术总结</h3> <p><img src="http://jhat.pw/assets/images/blog/language/java/java-skill-tree/big_data.gif" alt="大数据相关技术总结" /></p> Fri, 18 Mar 2016 00:00:00 +0800http://jhat.pw/blog/2016/03/18/java-skill-tree.htmlhttp://jhat.pw/blog/2016/03/18/java-skill-tree.html 服务自动注册与发现Jhat <p>在企业级系统中,针对业务进行模块化拆分是不可避免的,而系统模块化拆分之后,必然存在A模块(服务使用方)依赖B模块(服务提供方)的场景,通常拆分之后的模块都是相对独立的,所以这样的场景下一般由服务提供方提供远程调用接口给服务使用方使用。而服务提供方为了保证在高并发的情况下仍然能为服务使用方提供稳定的服务,通常会对服务提供方部署多个实例,并对来自服务使用方的请求就行负载均衡,使这些请求尽量均匀的分布在所部署的各个服务提供方实例上。</p> <p>而要实现负载均衡,通常可以使用LVS、HAProxy、协议代理等技术解决。不过LVS的代价相对较大,而剩余的技术基本都是以加入代理的方式来实现负载均衡。如服务提供方与服务使用方之间的通信协议是基于HTTP的,那么简单有效的方法是在服务提供方、使用方之间加一层HTTP反向代理(nginx、apache),利用反向代理完实现负载均衡。但是使用代理的方式会增加一次额外的请求转发,无论代理的性能做得多好,这次额外的请求转发总还是需要消耗时间的。而且代理的引入也会导致服务提供、使用方之间的调用风险增加。比如之前在我司的业务系统中就遇到过一次nginx代理重复转发了一个请求,而服务提供方又没法判断重复请求,最后因为这个重复的请求导致系统出现问题。再者由于代理的存在,每次增加新的服务提供方部署实例时,可能都需要修改代理的配置,这样就不利于自动化新增服务提供方实例来对整个系统进行扩容了。</p> <p>更加靠谱的实现负载均衡的方法应该是,不用引入代理,直接在服务使用方做负载均衡。要在服务使用方做负载均衡,那么服务使用方就必须知道所有的服务提供方可用实例列表,只有满足了这个前置条件之后才有做负载均衡的基础。要使服务使用方知道所有的服务提供方可用实例列表最简单的方法就是所有的服务提供方可用实例列表直接配置在服务使用方中,但是这仅是简单的去除了中间代理,还是难以达到自动化新增服务提供方实例的目的。为了解决这个问题我们应该引入一个注册中心。</p> <p><img src="http://jhat.pw/assets/images/blog/architecture/service-registration-and-discovery/service-registration-and-discovery.svg" alt="服务自动注册与发现" /></p> <p>如上图所示,服务的提供方上线时将访问信息(如IP,端口)注册到注册中心,服务提供方下线时应该从注册中心取消注册;服务的使用方则在上线的时候从注册中心获取可用的服务信息(服务提供方可用实例列表);当可用的服务信息发生变化时,注册中心应该立刻通知到服务使用方。这样服务使用方就始终有一份最新的可用服务信息(服务提供方可用实例列表),基于该信息就可以根据实际业务需要选择合适的负载均衡策略来实现对服务提供方调用的负载均衡。</p> <p>就目前来说使用<a href="http://zookeeper.apache.org">ZooKeeper</a>在当做注册中心就是一个非常不错的选择。<a href="http://zookeeper.apache.org">ZooKeeper</a>有一种 <code class="highlighter-rouge">EPHEMERAL</code> 类型的目录节点,这样的目录节点在<a href="http://zookeeper.apache.org">ZooKeeper</a>会话断开后将会被自动删除,这样就非常适合服务提供方上线时创建一个这样的目录节点,并将访问信息存在这样的目录节点上(或者其子目录节点)。而服务使用方只需要从同样的目录节点上读取信息就可以知道所有可用服务信息(服务提供方可用实例列表),如果需要实时知道最新的可用服务信息,只需要监听对应目录节点的变化即可,因为当所监听的目录节点有变化时,<a href="http://zookeeper.apache.org">ZooKeeper</a>会主动通知。因此利用<a href="http://zookeeper.apache.org">ZooKeeper</a>就可以很好的完成服务的自动注册与发现,而且服务的提供方也可以很方便的就行扩容(直接上线、下线服务提供方实例即可,服务使用方可以立刻感知到新上线、下线的服务提供方实例)。</p> Fri, 11 Mar 2016 00:00:00 +0800http://jhat.pw/blog/2016/03/11/service-registration-and-discovery.htmlhttp://jhat.pw/blog/2016/03/11/service-registration-and-discovery.html Maven本地第三方库依赖Jhat <p>在使用Maven作为项目构建工具的过程中,有时还是会不可避免的遇到依赖的第三方库在Maven中央库中没有,只能使用本地依赖,虽然这样的情况极少发生,但当真的遇到时,应该如何优雅的解决呢?</p> <p>如果是简单粗暴的引入一个本地依赖的话,一般像下面这样配置就好了:</p> <div class="language-xml highlighter-rouge"><pre class="highlight"><code><span class="nt">&lt;project&gt;</span> ... <span class="nt">&lt;dependencies&gt;</span> ... <span class="nt">&lt;dependency&gt;</span> <span class="nt">&lt;groupId&gt;</span>org.jhat<span class="nt">&lt;/groupId&gt;</span> <span class="nt">&lt;artifactId&gt;</span>third-party<span class="nt">&lt;/artifactId&gt;</span> <span class="nt">&lt;version&gt;</span>1.0<span class="nt">&lt;/version&gt;</span> <span class="nt">&lt;scope&gt;</span>system<span class="nt">&lt;/scope&gt;</span> <span class="nt">&lt;systemPath&gt;</span>${project.basedir}/libs/third-party.jar<span class="nt">&lt;/systemPath&gt;</span> <span class="nt">&lt;/dependency&gt;</span> ... <span class="nt">&lt;/dependencies&gt;</span> ... <span class="nt">&lt;/project&gt;</span> </code></pre> </div> <p>这种方式使用起来最简单,但是并不建议这么做,因为Maven在打包的过程中会忽略system类型依赖,也就是说system类型的依赖信息不会写入MANIFEST.MF文件中,自然也不会将其拷贝到jar/war包的libs目录下,打成一个单独的jar包时也不会包含system类型依赖的任何内容。如果要解决上述问题,不同的Maven插件都需要单独配置对system类型依赖的处理,也就是说在不同的使用场景下,都需要用对应的Maven插件针对system类型依赖进行处理。</p> <p>为了更优雅的解决本地依赖,应该是将其存入本地Maven仓库,再将其当做普通的第三方依赖使用。 一种方法是执行如下命令,先手动将其存入本地Maven仓库,然后再使用。</p> <div class="language-bash highlighter-rouge"><pre class="highlight"><code>mvn org.apache.maven.plugins:maven-install-plugin:2.5.2:install-file -Dfile<span class="o">=</span>path-to-your-artifact-jar <span class="se">\</span> -DgroupId<span class="o">=</span>your.groupId <span class="se">\</span> -DartifactId<span class="o">=</span>your-artifactId <span class="se">\</span> -Dversion<span class="o">=</span>version <span class="se">\</span> -Dpackaging<span class="o">=</span>jar <span class="se">\</span> -DlocalRepositoryPath<span class="o">=</span>path-to-specific-local-repo </code></pre> </div> <p>这样有一点不好的是可能会忘记,或者存入错误的路径,尤其是团队协作的时候。更好的解决方法是将其配置在pom.xml里面,使用maven-install-plugin自动处理:</p> <div class="language-xml highlighter-rouge"><pre class="highlight"><code><span class="nt">&lt;project&gt;</span> ... <span class="nt">&lt;properties&gt;</span> ... <span class="nt">&lt;third-party.version&gt;</span>1.0<span class="nt">&lt;/third-party.version&gt;</span> ... <span class="nt">&lt;/properties&gt;</span> ... <span class="nt">&lt;dependencies&gt;</span> ... <span class="nt">&lt;dependency&gt;</span> <span class="nt">&lt;groupId&gt;</span>org.jhat<span class="nt">&lt;/groupId&gt;</span> <span class="nt">&lt;artifactId&gt;</span>third-party<span class="nt">&lt;/artifactId&gt;</span> <span class="nt">&lt;version&gt;</span>${third-party.version}<span class="nt">&lt;/version&gt;</span> <span class="nt">&lt;/dependency&gt;</span> ... <span class="nt">&lt;/dependencies&gt;</span> ... <span class="nt">&lt;build&gt;</span> ... <span class="nt">&lt;plugins&gt;</span> <span class="nt">&lt;plugin&gt;</span> <span class="nt">&lt;groupId&gt;</span>org.apache.maven.plugins<span class="nt">&lt;/groupId&gt;</span> <span class="nt">&lt;artifactId&gt;</span>maven-install-plugin<span class="nt">&lt;/artifactId&gt;</span> <span class="nt">&lt;executions&gt;</span> <span class="nt">&lt;execution&gt;</span> <span class="nt">&lt;id&gt;</span>install-third-party<span class="nt">&lt;/id&gt;</span> <span class="nt">&lt;phase&gt;</span>validate<span class="nt">&lt;/phase&gt;</span> <span class="nt">&lt;goals&gt;</span> <span class="nt">&lt;goal&gt;</span>install-file<span class="nt">&lt;/goal&gt;</span> <span class="nt">&lt;/goals&gt;</span> <span class="nt">&lt;configuration&gt;</span> <span class="c">&lt;!-- 此处的groupId, artifactId, version 需要和dependencies里面配置的完全一致 --&gt;</span> <span class="nt">&lt;groupId&gt;</span>org.jhat<span class="nt">&lt;/groupId&gt;</span> <span class="nt">&lt;artifactId&gt;</span>third-party<span class="nt">&lt;/artifactId&gt;</span> <span class="nt">&lt;version&gt;</span>${third-party.version}<span class="nt">&lt;/version&gt;</span> <span class="nt">&lt;packaging&gt;</span>jar<span class="nt">&lt;/packaging&gt;</span> <span class="nt">&lt;file&gt;</span>${project.basedir}/libs/third-party.jar<span class="nt">&lt;/file&gt;</span> <span class="nt">&lt;/configuration&gt;</span> <span class="nt">&lt;/execution&gt;</span> ... <span class="nt">&lt;/executions&gt;</span> <span class="nt">&lt;/plugin&gt;</span> ... <span class="nt">&lt;/plugins&gt;</span> ... <span class="nt">&lt;/build&gt;</span> ... <span class="nt">&lt;/project&gt;</span> </code></pre> </div> <p>需要注意的是maven-install-plugin应该在所有其它插件之前。</p> Sun, 28 Feb 2016 00:00:00 +0800http://jhat.pw/blog/2016/02/28/maven-system-path-dependency.htmlhttp://jhat.pw/blog/2016/02/28/maven-system-path-dependency.html Access-Control-Allow-OriginJhat <p>故事的起因是这样的,想找个获取股票交易实时数据的接口,找来找去最后找到了新浪财经,然而其接口却是这样的:</p> <ul> <li>Request URL:</li> </ul> <div class="highlighter-rouge"><pre class="highlight"><code>http://hq.sinajs.cn/rn=1454399448305&amp;list=sz300369 </code></pre> </div> <ul> <li>Request Headers:</li> </ul> <div class="highlighter-rouge"><pre class="highlight"><code>GET /rn=1454399448305&amp;list=sz300369 HTTP/1.1 Host: hq.sinajs.cn Connection: keep-alive Cache-Control: max-age=0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.111 Safari/537.36 Accept-Encoding: gzip, deflate, sdch Accept-Language: en-US,en;q=0.8,zh-CN;q=0.6,zh;q=0.4 </code></pre> </div> <ul> <li>Response Headers:</li> </ul> <div class="highlighter-rouge"><pre class="highlight"><code>HTTP/1.1 200 OK Cache-Control: no-cache Content-Length: 146 Connection: Keep-Alive Content-Type: application/x-javascript; charset=GBK Content-Encoding: gzip </code></pre> </div> <ul> <li>Response Body:</li> </ul> <div class="language-javascript highlighter-rouge"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">hq_str_sz300369</span><span class="o">=</span><span class="s2">"绿盟科技,32.500,31.950,35.150,35.150,32.120,35.150,0.000,5239999,179070472.050,3742815,35.150,300,35.140,500,35.080,200,35.010,500,35.000,0,0.000,0,0.000,0,0.000,0,0.000,0,0.000,2016-02-02,10:49:13,00"</span><span class="p">;</span> </code></pre> </div> <p>我是需要使用<code class="highlighter-rouge">Ajax</code>请求来获取实时交易数据,很自然的写出了如下代码:</p> <div class="language-javascript highlighter-rouge"><pre class="highlight"><code><span class="nx">$</span><span class="p">.</span><span class="nx">ajax</span><span class="p">({</span> <span class="na">url</span><span class="p">:</span> <span class="s1">'http://hq.sinajs.cn/rn=1454399448305&amp;list=sz300369'</span><span class="p">,</span> <span class="na">type</span><span class="p">:</span> <span class="s1">'GET'</span><span class="p">,</span> <span class="na">success</span><span class="p">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">data</span><span class="p">)</span> <span class="p">{</span> <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">data</span><span class="p">);</span> <span class="p">}</span> <span class="p">});</span> </code></pre> </div> <p>然后Chrome就报错了:</p> <div class="highlighter-rouge"><pre class="highlight"><code>XMLHttpRequest cannot load http://hq.sinajs.cn/rn=1454399448305&amp;list=sz300369. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost' is therefore not allowed access. </code></pre> </div> <p>而该Ajax请求、响应头信息如下:</p> <ul> <li>Request Headers:</li> </ul> <div class="highlighter-rouge"><pre class="highlight"><code>GET /rn=1454399448305&amp;list=sz300369 HTTP/1.1 Host: hq.sinajs.cn Connection: keep-alive Accept: */* Origin: http://localhost User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.111 Safari/537.36 Referer: http://localhost/stock/index.html Accept-Encoding: gzip, deflate, sdch Accept-Language: en-US,en;q=0.8,zh-CN;q=0.6,zh;q=0.4 </code></pre> </div> <ul> <li>Response Headers:</li> </ul> <div class="highlighter-rouge"><pre class="highlight"><code>HTTP/1.1 200 OK Cache-Control: no-cache Content-Length: 150 Connection: Keep-Alive Content-Type: application/x-javascript; charset=GBK Content-Encoding: gzip </code></pre> </div> <p>与直接请求相比(不通过Ajax)请求头多了个 <code class="highlighter-rouge">Origin: http://localhost</code> ,也正是因为这个 <code class="highlighter-rouge">Origin</code> 触发了浏览器的 <code class="highlighter-rouge">同源策略</code> ,从而导致Ajax请求无法正常访问。同源策略参考: <a href="https://developer.mozilla.org/zh-CN/docs/Web/Security/Same-origin_policy">https://developer.mozilla.org/zh-CN/docs/Web/Security/Same-origin_policy</a>。</p> <p>在A站点的页面下请求B站点的数据,如果遇到这样的问题,一种方式是在B站点的数据接口响应头添加:</p> <div class="highlighter-rouge"><pre class="highlight"><code>Access-Control-Allow-Origin: * </code></pre> </div> <p>更多解决方法参考:<a href="http://www.freebuf.com/articles/web/65468.html">http://www.freebuf.com/articles/web/65468.html</a>。</p> <p>但是让新浪财经给我加个 <code class="highlighter-rouge">Access-Control-Allow-Origin</code> 显然是不现实的,那就只能在客户端解决该问题了。仔细想过直接访问是可以请求到数据的,Ajax请求时请求头多了个 <code class="highlighter-rouge">Origin</code> 才请求不到数据,如果能把 <code class="highlighter-rouge">Origin</code> 从请求头去掉是不是就可以了呢?</p> <p>通过查看 <code class="highlighter-rouge">jQuery</code> 官方文档(<a href="http://api.jquery.com/jQuery.ajax">http://api.jquery.com/jQuery.ajax</a>)发现,原来 <code class="highlighter-rouge">dataType</code> 还可以设置为 <code class="highlighter-rouge">script</code> ,正好接口响应数据类型为 <code class="highlighter-rouge">application/x-javascript</code> ,那就这样试一试:</p> <div class="language-javascript highlighter-rouge"><pre class="highlight"><code><span class="nx">$</span><span class="p">.</span><span class="nx">ajax</span><span class="p">({</span> <span class="na">url</span><span class="p">:</span> <span class="s1">'http://hq.sinajs.cn/rn=1454399448305&amp;list=sz300369'</span><span class="p">,</span> <span class="na">type</span><span class="p">:</span> <span class="s1">'GET'</span><span class="p">,</span> <span class="na">dataType</span><span class="p">:</span> <span class="s1">'script'</span><span class="p">,</span> <span class="na">success</span><span class="p">:</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span> <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">hq_str_sz300369</span><span class="p">);</span> <span class="c1">// 因为请求、响应都是脚本类型数据,因此可以直接使用响应结果中的变量。</span> <span class="p">}</span> <span class="p">});</span> </code></pre> </div> <p>然而还是没法请求到数据,不过可喜的是不再报 <code class="highlighter-rouge">Access-Control-Allow-Origin</code> 的错了,而是一个语法错误。仔细看请求信息,发现jQuery给加了一个查询参数:</p> <div class="highlighter-rouge"><pre class="highlight"><code>?_=1454403309696 </code></pre> </div> <p>jQuery加的这个参数导致新浪财经服务器解析参数出错,所以没有得到预期的数据结果,那就继续看jQuery的文档,看看能否让其不加这个参数,仔细一看还真有:</p> <blockquote> <p>“script”: Evaluates the response as JavaScript and returns it as plain text. Disables caching by appending a query string parameter, _=[TIMESTAMP], to the URL unless the cache option is set to true. Note: This will turn POSTs into GETs for remote-domain requests.</p> </blockquote> <p>既然是这样,那就再加一个参数:</p> <div class="language-javascript highlighter-rouge"><pre class="highlight"><code><span class="nx">$</span><span class="p">.</span><span class="nx">ajax</span><span class="p">({</span> <span class="na">url</span><span class="p">:</span> <span class="s1">'http://hq.sinajs.cn/rn=1454399448305&amp;list=sz300369'</span><span class="p">,</span> <span class="na">type</span><span class="p">:</span> <span class="s1">'GET'</span><span class="p">,</span> <span class="na">dataType</span><span class="p">:</span> <span class="s1">'script'</span><span class="p">,</span> <span class="na">cache</span><span class="p">:</span> <span class="kc">true</span><span class="p">,</span> <span class="na">success</span><span class="p">:</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span> <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">hq_str_sz300369</span><span class="p">);</span> <span class="p">}</span> <span class="p">});</span> </code></pre> </div> <p>最后问题解决~</p> Tue, 02 Feb 2016 00:00:00 +0800http://jhat.pw/blog/2016/02/02/access-control-allow-origin-problem.htmlhttp://jhat.pw/blog/2016/02/02/access-control-allow-origin-problem.html 2015Jhat <h3 id="1-工作">1. 工作</h3> <p>两年的时间,说长不长,说短也不短。自毕业之后在绿盟一呆就是两年,这两年里一直都做的很开心,总是有新的事情可以做。但是始终觉得缺点什么,越到后面越是明显,甚至开始感到疲惫。大学那会一直都在搞Java开发,临毕业了却赶上了近几年最难找工作的一年,所拿到的Offer中各方面权衡之后最后选择了绿盟,但工作内容却是另一个方向。本想着既来之着安之,正好好好学学系统底层相关的,结果还是自己太懒,除了业务相关的也没有去更多的学习。</p> <p>时间一点点的过去,刚毕业那会的那份激情也在一点点消失殆尽,所以开始考虑还是去从事自己的老本行,换一个环境重新开始,所以选择离开。</p> <p>北京,曾经最不想去的城市。然而工作两年之后才重新认识北京,重新认识工作地点与工作内容。一开始还在犹豫是否要去北京,最后因为一个人而坚定自己的决心,感谢曾经遇到她。北京,一个充满梦与机会的地方,一切从这里重新开始。重拾老本行,以后也只专注于Java开发!坚持!坚持!坚持!</p> <h3 id="2-情感">2. 情感</h3> <p>一次看节目听人说:“不是不想,而是想法不够强烈!”,仔细想想确实如此,而且至今也不能确切的知道想要什么。曾经以为的,以及尝试过的,最后发现都是为了做而做,反而把大家都搞得很累,最后决定不再这样。然而当真正遇到合适的时候,却发现自己文盲得不行,也笨的不行,最终还是抓不住。</p> <p>依然相信缘分,一切随缘。明年让自己变得更好,想清楚到底要什么!</p> <h3 id="3-生活">3. 生活</h3> <p>某一天早上走在上班的路上,突然明白了什么似的,突然意识到自己才开始长大,曾经的那个自己是那么的无知。曾经以为的,也许并非那样,只是自己缺乏一颗足够热爱生活的心。生活并不缺少美,只是缺少发现美的眼光。</p> <h3 id="4-写在最后">4. 写在最后</h3> <p>换一个角度看待问题,改掉拖延症,不再逃避,2016会更好,做更好的自己。</p> Thu, 31 Dec 2015 00:00:00 +0800http://jhat.pw/blog/2015/12/31/2015.htmlhttp://jhat.pw/blog/2015/12/31/2015.html 使用Github, Jekyll打造自己的博客Jhat <h3 id="1-在github创建博客项目">1. 在<a href="https://github.com/">Github</a>创建博客项目</h3> <p><a href="https://pages.github.com/">https://pages.github.com/</a></p> <p><a href="https://help.github.com/categories/github-pages-basics/">https://help.github.com/categories/github-pages-basics/</a></p> <p>创建完成后,博客以源码的形式托管在Github,Github会自动生成一个站点,这样就有了一个不用自己维护且完全免费的博客。</p> <h4 id="11-自定义域名绑定">1.1 自定义域名绑定</h4> <p>在项目根目录下创建一个CNAME文件,将要绑定的域名写在里面即可。</p> <p><a href="https://help.github.com/articles/adding-a-cname-file-to-your-repository/">https://help.github.com/articles/adding-a-cname-file-to-your-repository/</a></p> <h3 id="2-使用jekyll">2. 使用<a href="http://jekyllrb.com/">Jekyll</a></h3> <p>Github Pages只支持静态页面,如果一个一个页面的编写,那就太麻烦了,这时Jekyll就派上用场了。Jekyll可以根据网页源码(如Markdown)生成静态文件,而且提供模板、变量、插件等功能。Github也支持Jekyll,因此只要按照Jekyll规范编写网页源码,提交代码后Github将自动生成对应的静态文件。</p> <p><a href="http://jekyll.bootcss.com/">http://jekyll.bootcss.com/</a></p> <p><a href="http://www.ruanyifeng.com/blog/2012/08/blogging_with_jekyll.html">http://www.ruanyifeng.com/blog/2012/08/blogging_with_jekyll.html</a></p> <h4 id="21-jekyll模板">2.1 Jekyll模板</h4> <p><a href="https://github.com/jekyll/jekyll/wiki/Themes">https://github.com/jekyll/jekyll/wiki/Themes</a></p> <p><a href="http://jekyllthemes.org/">http://jekyllthemes.org/</a></p> <h4 id="22-markdown转换">2.2 Markdown转换</h4> <p>可以使用Markdown来编写网页,Jekyll可以将Markdown文件转换成静态网页文件,默认使用的是kramdown,不过推荐使用redcarpet。在 <code class="highlighter-rouge">_config.yml</code> 中添加如下配置即可:</p> <div class="language-ruby highlighter-rouge"><pre class="highlight"><code><span class="ss">markdown: </span><span class="n">redcarpet</span> </code></pre> </div> <p>不同的Markdown转换器转换效果可能有所不同,因此最好是编写的同时预览一下生成效果。</p> <p>Markdown语法:<a href="http://segmentfault.com/markdown#articleHeader5">http://segmentfault.com/markdown#articleHeader5</a></p> <h4 id="23-源码语法高亮">2.3 源码语法高亮</h4> <p>如果有在博客中高亮显示源码的需要,推荐使用pygments插件,具体参考:</p> <p><a href="http://havee.me/internet/2013-08/support-pygments-in-jekyll.html">http://havee.me/internet/2013-08/support-pygments-in-jekyll.html</a></p> <p><a href="http://pygments.org/docs/cmdline/">http://pygments.org/docs/cmdline/</a></p> <p>同时还可以使用Solarized风格的样式,具体参考:</p> <p><a href="http://marcusmo.co.uk/blog/solarized-code-highlighting/">http://marcusmo.co.uk/blog/solarized-code-highlighting/</a></p> <h4 id="24-文件压缩">2.4 文件压缩</h4> <p>CSS, JavaScript压缩参考:</p> <p><a href="http://jekyllrb.com/docs/assets/">http://jekyllrb.com/docs/assets/</a></p> <p>不足的是JavaScript压缩只支持CoffeeScript。</p> <p>HTML压缩参考:</p> <p><a href="http://jch.penibelst.de/">http://jch.penibelst.de/</a></p> <h4 id="25-liquid模板引擎">2.5 Liquid模板引擎</h4> <p><a href="https://github.com/Shopify/liquid/wiki">https://github.com/Shopify/liquid/wiki</a></p> <p><a href="http://liquidmarkup.org/">http://liquidmarkup.org/</a></p> <p><a href="http://havee.me/internet/2013-11/jekyll-liquid-designers.html">http://havee.me/internet/2013-11/jekyll-liquid-designers.html</a></p> <h3 id="3-评论系统">3. 评论系统</h3> <p>名声最大的第三方评论系统当属<a href="https://disqus.com/">Disqus</a>了,不过其在国外,访问速度可能稍慢,而且还有被墙的风险,所以选择要慎重。国内的第三方评论系统参考:</p> <p><a href="http://lusongsong.com/reed/384.html">http://lusongsong.com/reed/384.html</a></p> <p>而我选择的是新浪微博评论箱,参考:</p> <p><a href="http://open.weibo.com/widget/comments.php">http://open.weibo.com/widget/comments.php</a></p> <h3 id="4-我的博客源码">4. 我的博客源码</h3> <p><a href="https://github.com/cpf624/cpf624.github.io">https://github.com/cpf624/cpf624.github.io</a></p> Thu, 03 Dec 2015 00:00:00 +0800http://jhat.pw/blog/2015/12/03/github-jekyll-blog.htmlhttp://jhat.pw/blog/2015/12/03/github-jekyll-blog.html ActiveMQ Client工作原理Jhat <h1 id="1-基本原理">1. 基本原理</h1> <p><img src="http://jhat.pw/assets/images/blog/tools/mq/activemq-client-principle/activemq_basic_principle.svg" alt="ActiveMQ Basic Principle" /></p> <p>ActiveMQ基本原理如上图所示,消息由Producer产生,Consumer消费。Producer和Consumer均属于ActiveMQ Client部分,不过一般运行在不同的机器上。Producer产生消息后通过网络发送给ActiveMQ Broker,Broker收到消息后进行存储,再投递给Consumer进行消费(Consumer也是通过网络与Broker连接)。</p> <p><img src="http://jhat.pw/assets/images/blog/tools/mq/activemq-client-principle/jms_architecture.svg" alt="JMS Architecture" /></p> <p>ActiveMQ完整实现了JMS API,JMS架构如上图所示。无论是生产者(Producer)还是消费者(Consumer),都需要用Connection Factory创建Connection,再在Connection上创建Session,最后由Session创建出Producer/Consumer实例。Producer要发送消息,首先需要通过对应的Session创建消息,再将创建出来的消息发送到指定的队列。同理,Consumer都是从Session接收消息进行消费。</p> <h1 id="2-网络结构">2. 网络结构</h1> <p><img src="http://jhat.pw/assets/images/blog/tools/mq/activemq-client-principle/activemq_client_network.svg" alt="ActiveMQ Client Network Model" /></p> <p>ActiveMQ所实现的Connection是由一个责任链模式的Transport完成的,参考: <a href="http://activemq.apache.org/configuring-transports.html">http://activemq.apache.org/configuring-transports.html</a>。概括来说分为网络类Transport和包装类Transport。</p> <h4 id="21-网络类transport">2.1 网络类Transport</h4> <p>网络类Transport针对不同网络环境进行实现,从而提供不同网络环境下Client与Broker进行连接的能力,也就是说网络类Transport将直接与Broker进行连接。网络类Transport主要包括TCPTransport、UDPTransport、MulticastTransport、SSLTransport、NIOTransport、HTTPTransport、HTTPSTransport、WebSocketsTransport等。</p> <h4 id="22-包装类transport">2.2 包装类Transport</h4> <p>包装类Transport则是在网络类Transport和其它包装类Transport的基础上包装出更多的功能。比如ResponseCorrelator在TCPTransport的基础上实现了消息请求与响应的映射,也就可以在其基础上轻松的实现请求、响应的异步处理。再如MutexTransport在ResponseCorrelator的基础上实现了互斥写保护,也就可以在其基础上轻松的保证并发环境下共享连接时消息发送的准确性。再如FanoutTransport可以持有多个其它Transport,通过其持有的Transport从而将消息同时发往不同的Broker。再如FailoverTransport可以持有多个其它可能可用的Transport,通过检查其所持有的Transport的可用性,选择出一个可用的Transport,并在Transport失效的情况下自动进行切换,对于集群环境的Broker就相当适用。</p> <h1 id="3-线程模型">3. 线程模型</h1> <p>从生产者(Producer)的角度来看ActiveMQ Client的线程模型相对简单,此处不做描述,从消费者(Consumer)角度来看ActiveMQ Client的线程模型如下图所示。 <img src="http://jhat.pw/assets/images/blog/tools/mq/activemq-client-principle/activemq_client_thread_model.svg" alt="ActiveMQ Client Thread Model" /></p> <h1 id="4-长连接维护">4. 长连接维护</h1> <p>ActiveMQ Consumer Client与ActiveMQ Broker之间的连接为长连接,长连接的维护主要靠三个Daemon线程来完成。</p> <ul> <li>Read Checker</li> </ul> <p>该线程定时检查是否有从Broker读取数据(Transport线程读取),如果超过一定时间未检查到就认为连接异常,并通知Connection连接异常。</p> <ul> <li>Write Checker</li> </ul> <p>该线程定时检查是否有向Broker写入数据,如果超过一定时间未检查到,则向Broker发送KeepAlive Commond,发送完成后Broker的响应将会被Transport线程读取到,从而维持了Client与Broker之间的长连接。</p> <ul> <li>Connect Checker</li> </ul> <p>该线程检查Client与Broker之间的连接状态,可检查连接是否已经建立、建立连接是否超时。</p> <h1 id="5-消息接收与消费">5. 消息接收与消费</h1> <p>TCPTransport会有一个Transport线程尝试从Broker读取数据,并将读取到的数据转换成相关Commond,然后交由TransportListener处理,而TransportListener一般就是对应的Connection。对于消息类Commond,在Connection中根据消息的ConsumerId进行调度,将消息调度到对应Session的Message Queue中。Session中会有Session Task线程负责将消息从Message Queue中取出,再一次根据ConsumerId进行调度,将消息调度到对应Message Consumer的Unconsumed Message Queue中。最终Application Consumer(ActiveMQ Client使用者)从Message Consumer的Unconsumed Message Queue中接收消息,而消息从Unconsumed Message Queue出队后,会先将消息放入Delivered Messages LinkedList中,才会将消息交给Application Consumer消费。如果消息被正常消费,被消费的消息将从Delivered Messages中移除;如果出现异常或因为其它原因,对消息进行回滚时,会将Delivered Messages中的消息全部取出,交由对应的Session Dispatcher重新进行调度,如果需要延迟将在Scheduler中完成。</p> <p>事务的提交、回滚都是以Session为单位的,因此用到事务时,一个Session最好只创建一个Consumer(Message Consumer和Application Consumer为一一对应的一个)。</p> <p>另外多个Session共享一个Connection时,如果某个Session所对应的Application Consumer已结束运行,但是又未关闭Session,积压在Message Consumer的Unconsumed Message Queue中的消息将无法继续被消费,只有关闭Session后,Broker才会重新推送那些未被消费的消息。</p> <h1 id="6-消息接收模式">6. 消息接收模式</h1> <p>消息都是从Broker传输到Client,默认情况下Broker会主动将消息PUSH至Client,当然也可以通过配置改为Client主动从Broker PULL消息,参考: <a href="http://activemq.apache.org/slow-consumer-handling.html">http://activemq.apache.org/slow-consumer-handling.html</a></p> <ul> <li>PUSH模式</li> </ul> <p>默认情况下,Broker会主动将消息PUSH至Client,这样做的目的是为了让消息能够即时到达Client,以最快的速度被消费。每个队列默认最多PUSH 1000条消息,当达到这个限制后,需要在已推送的消息中收到确认后才会继续推送消息。</p> <ul> <li>PULL模式</li> </ul> <p>如果遇到慢Consumer,每个消息的处理比较耗时的话,PUSH模式就可能将消息积压在Message Consumer的Unconsumed Message Queue中,一旦造成积压,继续添加更多的Consumer也无济于事,因为Broker已将消息推送出去,在得到确认前不会继续推送,因此可能造成部分消息长时间得不到处理。如果达到了PUSH的最大消息量限制,新到达的消息同样得不到即时处理,最终造成恶性循环。好在ActiveMQ支持Client主动PULL模式,在这种模式下,Broker不再主动推送消息,仅当收到Client的PULL Request后才向Client发送一条消息。这样消息一直在Broker中,通过简单的增加Consumer数量就可以加快消息的整体处理速度。</p> <h1 id="7-消息重传">7. 消息重传</h1> <p>消息重传都是在Client端重新调度完成,如果需要延迟,是在Scheduler中完成。但是如果消息重传一定次数后(未达到重传次数上限),关闭对应Session,Broker会重新推送消息,新的Consumer接收到消息后,消息的重传次数将重新从零开始计数。</p> Mon, 30 Nov 2015 00:00:00 +0800http://jhat.pw/blog/2015/11/30/activemq-client-principle.htmlhttp://jhat.pw/blog/2015/11/30/activemq-client-principle.html Install lxml on Mac OS XJhat <p>在Mac OS X EI Captian(10.11.1)上安装<code class="highlighter-rouge">lxml</code>时遇到如下错误:</p> <div class="highlighter-rouge"><pre class="highlight"><code>In file included from src/lxml/lxml.etree.c:239: /private/tmp/pip_build_root/lxml/src/lxml/includes/etree_defs.h:14:10: fatal error: 'libxml/xmlversion.h' file not found #include "libxml/xmlversion.h" ^ 1 error generated. error: command 'cc' failed with exit status 1 </code></pre> </div> <p>解决方法:</p> <div class="language-bash highlighter-rouge"><pre class="highlight"><code>brew install libxml2 brew install libxslt brew link libxml2 --force brew link libxslt --force </code></pre> </div> <p>如果再次出现同样的错误,运行上面4条命令之前需要先运行:</p> <div class="language-bash highlighter-rouge"><pre class="highlight"><code>brew unlink libxml2 brew unlink libxslt </code></pre> </div> <p>然后再安装<code class="highlighter-rouge">lxml</code>就可以了。</p> <div class="language-bash highlighter-rouge"><pre class="highlight"><code><span class="nv">STATIC_DEPS</span><span class="o">=</span><span class="nb">true </span>sudo pip install lxml </code></pre> </div> <p>10.9应该就有这样的问题了,应该可以用同样的方法解决。</p> <p>参考:<a href="http://stackoverflow.com/questions/19548011/cannot-install-lxml-on-mac-os-x-10-9">http://stackoverflow.com/questions/19548011/cannot-install-lxml-on-mac-os-x-10-9</a></p> Wed, 28 Oct 2015 00:00:00 +0800http://jhat.pw/blog/2015/10/28/install-lxml-on-mac-os-x.htmlhttp://jhat.pw/blog/2015/10/28/install-lxml-on-mac-os-x.html 消息队列使用关注点Jhat <p>Alice和Bob是两个完全独立的系统,现在Alice有一条消息需要发送给Bob,Bob接收到消息后需要进行一系列的处理,然后得到一个最终结果。从Alice发出消息,到Bob对消息进行有效处理,期间可能出现各种各样的状况,导致Alice所发出的消息没有被Bob有效处理。Alice静静的想了一下,从她发送消息开始,可能出现的状况有:</p> <blockquote> <ol> <li>网络不好,Bob始终接收不到消息;</li> <li>Bob不在;</li> <li>Bob收到消息了,但是抽风死掉了;</li> </ol> </blockquote> <p>不管是什么状况,Alice还是希望Bob可以有效的处理她发送的消息,所以她重发,重发,再重发,最后Alice累死在重发的路上。。。</p> <p>Duang一下,上帝出现了,救活了Alice,并给了她一个消息队列,然后Alice和Bob有可以一起愉快的玩耍了。</p> <p>故事讲完了,最近在项目中用到了消息队列,对在使用过程中考虑的因素总结如下:</p> <h3 id="1-并发性">1. 并发性</h3> <p>虽说消息队列主要是做消息的转发,不涉及逻辑处理,所以对单条消息的处理消耗并不大,但不管怎样始终还是有上线的。所以在选择消息队列时也需要关注接收消息的并发数,以及能够同时承载的生产者、消费者总数量。</p> <h3 id="2-可靠性">2. 可靠性</h3> <p>消息队列并不产生消息,而是接收生产者产生的消息,并转发给对应的消费者,在消息的接收、转发过程中就存在以下可靠性问题:</p> <ol> <li> <p><strong>消息接收的可靠性(这也和消息接收的并发性相关)</strong></p> <p>消息队列应该快速、可靠的接收来自生产者产生的消息,如果生产者往消息队列发送消息时延太大,或者还需要不断的重试,那消息队列存在的价值就不大了(因为它会成为整个系统中新的瓶颈)。</p> </li> <li> <p><strong>消息存储的可靠性</strong></p> <p>消息队列接收到消息后,对应消费者并不一定能够及时对消息进行消费,此时就需要消息队列对消息进行暂存。而且消息队列本身也存在宕机的可能性,无论是消费者的问题,还是消息队列本身的问题,只要是消息队列确认接收到的消息就不应该丢失,而且必须保证消息最终被消费者处理完成。</p> </li> <li> <p><strong>消息传递的可靠性</strong></p> <p>消息队列接收到来自生产者的消息后,在送达消费者前,可能还需要经过一系列的路由中转等;以及将消息转发给对应消费者,都应该有一定的机制来保证消息在传输过程中不丢,同时应该由消费者来最终确认消息处理完成。这里也就涉及消息队列支持的消息接收确认方式,一般包括自动确认方式、客户端确认方式、事物方式等。其中客户端确认方式和事物方式,消费者可以在合适的时机向消息队列确认已经接收到消息(可以在处理完成后才向消息队列确认),从而确保生产者发出的消息被有效处理。</p> </li> </ol> <p>PS:由于消费者自身的问题,可能存在消息处理完成,但向消息队列确认接收到消息失败的情况。这次消息队列会重发消息,因此消费者应该保证多次接收到相同的消息,最终处理结果应该一致的。</p> <h3 id="3-重发机制">3. 重发机制</h3> <p>对于消息队列的重发机制,需要考虑的问题主要有:</p> <blockquote> <ol> <li>消费者接收、处理消息失败后,消息队列什么时候重发消息?</li> <li>重发消息是否阻塞后续新到达的消息?</li> <li>重发消息是否支持延迟、以及延迟的方式(比如重发的延迟时间不断增加)?</li> <li>是否可以无限重发?</li> <li>当达到重发上限后,对应的消息会怎么处理?</li> </ol> </blockquote> <h3 id="4-定时延迟发送机制">4. 定时/延迟发送机制</h3> <p>在某些特定的场景下,可能希望消息队列接收到消息后,并不是立即转发给对应消费者,而是延迟一定的时间、或者在指定的时间再转发给对应消费者。如果能够按指定的规则重复发送消息那就更好了,这样就可以利用消息队列实现定时任务的功能了。</p> Mon, 28 Sep 2015 00:00:00 +0800http://jhat.pw/blog/2015/09/28/message-queue-use-focus.htmlhttp://jhat.pw/blog/2015/09/28/message-queue-use-focus.html 保持一个饥饿的心Jhat <p>猛然间发现自己好像才刚开始一点点长大,曾经是那么的年少无知。</p> <p>也许是因为智商太低,导致情商几乎为零,一直以来都是活在自己的世界里。对周围的一切总是后知后觉,甚至毫无知觉。但是一度还自我感觉良好,直到经历了一些人和事后才慢慢发现一切并不是自己所想象的那么美好。希望现在发现还为时不晚,还可以补救。</p> <p>有人来了,又走了。错过了,就不要后悔,能留下的请好好珍惜。</p> <p>从小到大总有那么一些人突然有一天就不再联系,直至消失不见。甚至有时候都忘记了曾经有过这么一个人。能留下的总是少之又少,而且大家都在忙着各自的事,总是聚少离多。虽不曾相见,至少还可以默默的想着对方,在需要的时候可以挺身而出。最后,请把对陌生人的那份礼貌,转化为耐心,留给最亲近的人。</p> <p>现状并不能令人满意,请保持一颗饥饿的心,改变这一切。</p> <p>不管是无知,还是懒惰,总之曾经以为可以轻松做到的都没有一个令人满意的结果。2015应该是充满想象的一年,更应该是脚踏实地的一年,总之应该交出一份满意的答卷。</p> <p>每周至少新学一道菜。</p> <p>每月至少一篇技术博文。</p> <p>落实各种基础项目,不能再拖了。</p> <p>最重要的是想明白自己到底想要什么。</p> Thu, 08 Jan 2015 00:00:00 +0800http://jhat.pw/blog/2015/01/08/keep-hungury.htmlhttp://jhat.pw/blog/2015/01/08/keep-hungury.html 开启新的征程Jhat <ol> <li> <p>这一年,该结束的都画上了句号,虽然不是那么完美。</p> <p>时间总是一分一秒的自顾自的走着,从来不会说停下来休息一下,不经意间,四年的光阴已悄然过去。最后半年的大学生活在毕业设计的主旋律下,穿插着实习和毕业旅行后结束。虽然很不情愿,但是再见总还是得说出口。和熟悉了四年的人、事、物意义作别,留下的只有回忆。</p> </li> <li> <p>这一年,一切才刚刚开始。</p> <p>开始认识新的人,开始接触新的事,开始满怀信心的做各种各样的计划,同时也开始为这些计划铺路。</p> <p>计划着锻炼身体,每天早起,但最后还是敌不过寒冬。</p> <p>计划着开始每天做计划,但却坚持了不到两个月,回过头来看那些计划,还是那么的不切实际。</p> <p>计划着为自己做一套完整的IT支撑系统,但是进度让人忧心忡忡。</p> <p>计划着每天自己做饭吃,虽然饭菜很可口,但总会心痛可怜的时间。</p> </li> <li> <p>这一年,计划很多,但是也很多,经历这些但是之后,也开始明白了很多。</p> <p>开始明白,从别人那里听来的不一定都是靠谱的,一切都需要自己去经历,只有经历过来才会真正的明白。</p> <p>开始明白,没有不加班的公司,只是多与少而已。</p> <p>开始明白,项目是做不完的,需求总是一个无底洞。</p> <p>开始明白,生活不仅仅是吃穿住行。</p> <p>开始明白,不想要的是什么;而自己想要的依然很模糊,一个人、一件事、还是一个数字。</p> <p>开始明白,想要获得更多的价值,必须不断提升自己的价值。</p> </li> <li> <p>明年,计划不变,行动加强!</p> </li> </ol> Wed, 01 Jan 2014 00:00:00 +0800http://jhat.pw/blog/2014/01/01/new-start.htmlhttp://jhat.pw/blog/2014/01/01/new-start.html 乐山骑行Jhat <p>很想去雅安、峨眉山、乐山骑一圈的,但是一查天气发现全部有雨,本都放弃了的,最后还是没经得住小伙伴的诱惑去了趟乐山。</p> <p>一大早就起来了,结果在市区里面还没骑多远就有点飘雨了,硬着头皮继续骑,还好没骑多远就停了,而且还出太阳了,瞬间就放心了,路上还看到不少的车队。</p> <p>过了新津不久遇到一个4人车队,排成一列,30KM/h的速度,中间两妹子一点也不含糊。果断跟在他们后面,确实省力不少。快到青龙镇的时候,准备给他们拍照的,相机都拿出来准备好了,突然听到后面有点不对劲,回头一看发现小伙伴摔倒了。赶紧停下来看看,还好不严重,只是有点擦伤。还得感谢他们也停下来关心小伙伴的情况,还好附近就有家乡村卫生站,简单的包扎后,休息了接近一个小时再次上路。</p> <p>快到彭山的时候饿了,停下来吃点东西,结果刚把车放开就倒下去了,拉起来看码表线断了,这是才发现不知道什么时候脚架位置不对了,车没法停稳了。而小伙伴的车前刹也有点卡,骑起来很费劲,这一路真实够悲催的。</p> <p>中午来到彭山后 ,一边找吃的一边找修车店,最后还是只是找到了吃的,味道还不错,两个人4菜1汤,真的是饿了。吃完后继续上路,虽然车况不怎么好。进入乐山界后,才看见有往成都放下骑行的车友,还相互打着招呼。</p> <p>好不容易快到目的地了,结果小伙伴发现他的后胎没气了,估计是在夹江那段给扎了,那段路一路都是碎陶瓷片。打满气继续往前骑,但是没多远又没气了,这次更严重,是完全没气了。而这时已经是19:00了,简单商量了一下,我先去酒店入住,他一个人推着过去。还有接近10KM的样子,要是推过去真不知道得什么时候了,还好好说歹说的搭上了公交车。</p> <p>晚上想想,虽然今天挺不顺的,但从小伙伴摔倒后,骑得都不是很快,所以自己体力消耗不是很大,而车况虽然不是最佳状态,但是继续骑也没什么问题。于是想第二天先去乐山大佛看看,然后找个修车点简单修一下,然后就去雅安转一圈,但是定酒店了两家酒店都满员了,其它也没找到合适的,就只好作罢了。</p> <p>第二天起来先去把回成都的车票买了,然后去乐山大佛,发现真的是人山人海,而自行车也没地方停,就在那绕了一圈,发现全都围起来了,在外面除了人什么也看不见。然后就去乐山的两个公园看看,先去的碧山湖森林公园,那里的水真是臭得不行,没想到居然还有人在那里钓鱼,而且还发现有个人居然钓了一条,虽然小得不行。然后来到海棠公园,路上过岷江时,也是堵得不行,在桥上发现整个桥上全是被堵下来的车。海棠公园就感觉相当不错了,非常幽静,青山所包围的换行线,有不少人在这里骑车或者散步。据说有11KM,磨蹭了一圈就去坐车回来了。</p> <p>这次出去虽然玩得不是很尽兴,倒是积累了不少经验, 真的是出门在外一点也不能侥幸,该准备的一个也不能少。</p> Wed, 02 Oct 2013 00:00:00 +0800http://jhat.pw/blog/2013/10/02/leshan-riding.htmlhttp://jhat.pw/blog/2013/10/02/leshan-riding.html 毕业了Jhat <p>转眼间四年已悄然走过,而我也不再是四年前那个单纯的少年(甚至有些白痴),四年的大学生活有过泪,有过笑;努力过,也颓废过。</p> <p>也不知道从什么时候才是,就对计算机有着浓厚的兴趣,甚至除了计算机什么都提不起兴趣,也是那时下定决心将来一定要上电子科大,然后高考结束后填志愿的那一刻,却拼命的想往北京走,将科大放在了第三志愿,最后发现还是自己想多了,不过这也算实现了多年来的梦想。记得刚进大学那会,并没有太多感慨,只是很简单的到了,开始接触新同学、新老师、新事务,一切从头开始。记得高中那会老师说现在好好学习,等进大学了想怎么耍就怎么耍。但是真实的情况是从大一开始周末就各种补课、实验,然后就是考试了,平时不努力,临时抱佛脚,显得整个学期都很匆忙。偶尔也会闲下来,每当无聊的时候就会想起黄老曾经说的“等你们到了大学,一定回怀念有英语周报做的日志“,确实,高中三点一线的生活虽然很苦,但挺充实。大学生活虽然丰富多彩了,却难免会有无聊的时刻。</p> <ol> <li> <p>班级</p> <p>至今依然清晰的记得第一次以及最后一次自我介绍,站在讲台上的那一刻自己真的很紧张。五湖四海的同学就这么聚在了一起,四年的时间也有过很多欢乐,烧烤、篮球赛(尤其是被坑那次)、联谊、毕业留影、授位等等,这一切至今依然历历在目,感谢曾经的你们。大一那会也很积极的竞选了班委,说实话那个学习委员真的当的很懒,和兆邦比起来真的无地自容。直到毕业那段时间,才深刻的意识到自己在班级以及寝室做得实在太少了,绝大部分时间基本都是在工作室,很是抱歉。</p> <p>临别时看着大家都很伤感,甚至很多兄弟都哭了,我也很伤感,但除了最后一次自我介绍外我从未哭过(当时也及时忍住了)。伤感是挺伤感的,但不想哭,因为哭解决不了问题,该分别的还是得分别,天下没有不散的宴席。我所能做的,只有在心中默默的记住大家的好,祝福大家有一个很好的前程,同时也感谢大家四年来对我的帮助和宽容。</p> </li> <li> <p>学生会</p> <p>第一个加入的社团当然是学生会了,这是上高中时就想好了的。还记得学生会招新宣讲时场面是多么的火爆,悲催的是面试没过,但是自己不甘心,还好宣讲的时候留了学姐的电话,上午打电话时还是被委婉的拒了 ,但下午却意外的接到电话让我过去,就这么很意外的进入学生会了,当时的心情那是个相当激动,也挺感谢这位学姐给我这样的机会。由于当时我们大一单独在沙河校区,所有活动的开展都得靠我们自己。所以紧接着就开始干部竞选了,这么好的机会当然不能放过,做着充分的准备,演讲稿修改了无数次,还让辅导员、部长给给意见,功夫不负有心人,顺利的当选了。而这次竞选感觉好像是大学里面准备得最充分的一件事了,其次就是大二找实习的准备,除此之外好像都没怎么好好准备过,直接就上了。这次演讲也是最激情的一次,直接惊动全场,但是从此慢慢的平淡下来,再也没像这样激情过。</p> <p>当选了,当然就得开始干活了,新生篮球赛、辩论赛、寝室风采大赛、新生晚会……都得由学生会组织。由于秘书处比较特殊,并不需要自己组织活动,更多的负责各部门的协调、活动记录和报到等,所以自己也就很自然的往主席团靠拢,参与着各种活动的策划,当然也会忙着自己的本职工作,忙的时候甚至可以忙到凌晨,很感谢曾经一起战斗过的队友。在学生会接近一年的时间里,结实了不少朋友(好像大学里面所认识的人大部分都是在这段时间认识的),当然也学到了很多。但是不到一年的时间,感觉自己不再有激情,或者说腻了,所以也就退了,还很感谢大杨神接手我的烂摊子,让我能够顺利的走上技术之路。</p> </li> <li> <p>工作室</p> <p>记得上高中时亚彬就和我说过,等上大学了一定要加工作室,但那时根本不知道工作室是什么。进大学后通过慢慢的观察和问学长才知道了工作室是干嘛的,当然也很有兴趣,还记得给微软俱乐部的负责人打了N个电话,但都没鸟我。同样因为只有我们一届在沙河,学院主体都在清水河,而且自己当时又在学生会,再加上一些其它原因,所以大一也就没有加工作室。大一快结束的时候知道了银杏黄,当时还以为很悠久了,结果我们那会是第二届,而且水得不行(当然,这都是后话了)。再包大神的带领下开始做项目,不知道为什么当时就对数据库赶兴趣,所以就从数据库开始学起了。大一那个暑假也是没有回家,一个人留在清水河,开始看各种各样的技术书籍,也是这个时候开始走上了Java这条不归路。</p> <p>第一个加入的工作室是梦飞,但是好景不长,一学期不到就被开了,因为当时自己太菜,在学长的带领下做项目时,虽然很菜,但还是有一颗追求完美和效率的心,所以加了新的实现后很果断的就把原来的删除了,导致整个项目跑不起来了,这件事给那位学长造成多大的麻烦不大而知,只能说抱歉了。加上自己面潜,和工作室的成员都不怎么熟,后面还说什么自己看了不该看的,总之自己被开了,当时真的是伤心死了。不过也没有什么,没有工作室那就自己好好干吧。</p> <p>没过多久志飞通过妍姐找到我(当时都很惊讶的发现原来是你),加入他刚创立的工作室,进去就出不来了,而在启梦(原名异维)也留下了很多回忆。工作室的第一个项目是给研究生院做的一个排课系统(当然不会是什么先进的排课算法,还是的人来排,只不过在网上办公而已),也是自己做的真正意义上的第一个项目,做得烂得不行,时不时的和数据库的连接就断了,必须重启,此后也是再也不敢用Hibernate了,简直不忍直视,唐老师却一直说做的挺好的,比他们以前用的系统好多了,当时就在想学校的这些系统得有多烂啊。后面工作室和研究生院也一直合作着,开发的类似学籍管理的系统就好多了,稳定性、安全性和性能都有一定的保证,当然架构还有待提升。</p> <p>最心痛的是自己即将毕业的时候工作室经历了很大的人事变动,一直很弱的前端一下子回到了原点 。也是在这个时候开始思考自己有什么做的不好的地方,工作室又该何去何从。之前一门心思的做项目,但却只有项目,没有文档,估计我毕业后维护起来会很困难,其它方面做得更是差至极点。还好还有时间去解决,开始拉着大家一起讨论,寻求新的出路,也是在这个时候才发现其实大家对工作室的感情都挺深的。经过大家一学期的努力,虽然工作室依然很弱,但至少让人看到了希望。</p> <p>感谢在工作室一起奋斗过,为工作室的明天一起努力过,在工作室最艰难的时候一起坚持的队友们,谢谢你们。而工作室的明天就靠你们了@『TF.Prince.』 @飞 @Ztupid Guy @安逸 ,还有更多大一大二的新生力量,加油!</p> </li> <li> <p>工作</p> <p>应该说上大学前就决定好了,本科毕业直接工作,坚决不读研,所以学习从来就没太过上心,懂事之后能逃的课都逃了,期末时预习一下就直接上了,还好从未挂科,还勉勉强强的拿过奖学金。从大二就开始找实习,当然也做着充分的准备,很幸运的拿到了淘宝的Offer,当收到Offer的那一刻正好在送包大神走(去阿里实习),当时真的好激动,本来还有些失落的,一下就满血复活了,而这也是自拿到科大录取通知书时的又一次激动。在我印象中总过就激动过这么两次,包括知道高考成绩那一刻都不曾激动过。放假后很兴奋的去杭州实习了,2个月很快,但淘宝却给我留下了很多,虽然感觉自己把淘宝坑了,因为实习时做的项目感觉很烂。待过四家公司,始终觉得淘宝最好了,那种工作氛围真的很好。很遗憾的是后面未能加入淘宝,当时师兄也很多帮助,但是时间实在太仓促了,都没怎么准备过,很遗憾的和淘宝擦肩而过。 说实话当初真的很想去北上广这样的地方工作,但是去海豚实习之后就再也不想去了,北京这样的地方真的不适合生活,除了工作什么也没有。而且在海豚工作感觉真的很压抑,所以最终还是毁约离开了。最终选择了绿盟,主要是因为这样就可以留在成都了,工作内容正好也可以强化自己的底层开发能力,而且工作也相对轻松。而我也希望工作是为了赚取第一桶金,工作这几年好好干,积累技术和人脉等,等有好的想法了就出去创业。加之成都这几年的IT行业发展的相当好,所以最终选择了留在成都,留在了绿盟。在绿盟工作也是轻松加愉快,同事之间相处的都挺好的。</p> </li> <li> <p>生活</p> <p>总的来说大学生活过的还是不错的,顺利的毕业了,也找到了自己满意的工作,虽然没有太多的活动,绝大部分时间都在做技术,但是做着自己喜欢的事也挺好的。而要说有没有遗憾的话,当然也有不少,比如摄影、Dota、篮球、吉他…曾经想过的,结果一个都没学会,川藏线也没去成。最大的遗憾还是没有谈过恋爱,不知为什么,虽然被无情的拒绝了很多次,却始终无法忘记那个女生,也有过其她尝试,却始终是力不从心。</p> </li> </ol> <p>毕业了,好好为下一个目标奋斗,加油!!!</p> Sat, 10 Aug 2013 00:00:00 +0800http://jhat.pw/blog/2013/08/10/graduation.htmlhttp://jhat.pw/blog/2013/08/10/graduation.html 杂记Jhat <p>经历着各种各样的人和事,有过得意,失意也在所难免;有无从选择的恐慌,也有选择前的迷茫。</p> <p>虽是人来人往,却得继续坚持,哪怕再苦再累。</p> <p><br />       十多年前,有着唯一而确切的梦想,很庆幸自己坚持下来了,并最终得以实现。</p> <p>四年前,怀揣着激动的心情踏入大学校园,那一刻,是上一个梦想的终点,也是下一个梦想的起点。</p> <p>然而四年过去了,下一个梦想是什么?自己想要什么?一无所知。</p> <p><br />       唯一不变的是知道自己热爱技术,热爱互联网行业。</p> <p>工作是用自己的兴趣爱好去帮助老板实现梦想。</p> <p>唯有创业才是实现自我梦想的最好途径。然而何时开始?如何开始?</p> <p><br />       看过唐山大地震后,那种儿时的无辜,青春的无畏、年迈的孤独、灾难面前的无助无不纠结着内心。</p> <p>亲情、友情、爱情什么才是值得信任,并付诸所有去维护?</p> <p>然而有时又不得不感叹,这一切在现实面前是那么苍白无力。</p> <p>但是一切喧嚣过后,静下心来,唯有亲情始终不离不弃,其次是友情、爱情。</p> Thu, 02 May 2013 00:00:00 +0800http://jhat.pw/blog/2013/05/02/miscellanea.htmlhttp://jhat.pw/blog/2013/05/02/miscellanea.html 选择Jhat <p>路,是自己走出来的,但却越走越窄。</p> <p>如果说高考是一座独木桥,当决定和成千上万的人一起去挤这座独木桥的那一刻,我们就 做出了人生中极为重要的一次选择。然而有的人却没能坚持到最后,或者中途返回了,又或者不幸摔了下去。</p> <p>当有幸闯过独木桥之后,理想中的对面并非那么完美,还没等我们休息好,一个个的十字路口就接踵而至,还未准备好的我们,开始徘徊,开始迷茫,甚至开始退缩。</p> <p>勇敢的我们绝不甘如此,选择才是唯一的出路。那么如何选择?靠信念,信念是什么?还是靠理想?理想又在哪里?</p> <p>慢慢的,我们发现,原本如此宽广的路,在我们脚下却越走越窄。甚至在不经意间发现,某个十字路口走错了,这时又该如何?</p> <p>选择,并不是每个人都有这样的机会,所以有选择的人总是幸福的,然而有选择的人又是痛苦的,因为每一次选择都必须做出艰难的决定,每一次选择都是对信仰和理想的一次考验。</p> <p>只有坚定信仰和理想,我们才能从容的做出每一次选择,走到最后。</p> Sun, 21 Oct 2012 00:00:00 +0800http://jhat.pw/blog/2012/10/21/choice.htmlhttp://jhat.pw/blog/2012/10/21/choice.html PHP验证码Jhat <p>在用PHP写自己的博客时,当做到登录这块时,需要使用一个图片验证码,在网上搜了一大圈,都没找到一个满意的结果,最终参照网友的代码,自己做了一些更改,并抽取成一个通用的函数。</p> <p>首先是生成一张字符窜图片:</p> <div class="language-php highlighter-rouge"><pre class="highlight"><code><span class="cp">&lt;?php</span> <span class="sd">/** * 将字符窜生成图片(包含随机线条等混淆信息) * @access public * @param string $_str 字符窜 * @param int $_width 图片宽度 * @param int $_height 图片高度 * @param bool $_flag 图片是否需要边框 */</span> <span class="k">function</span> <span class="nf">create_str_image</span><span class="p">(</span><span class="nv">$_str</span><span class="p">,</span> <span class="nv">$_width</span><span class="p">,</span> <span class="nv">$_height</span><span class="p">,</span> <span class="nv">$_flag</span> <span class="o">=</span> <span class="kc">true</span><span class="p">)</span> <span class="p">{</span> <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nb">is_int</span><span class="p">(</span><span class="nv">$_width</span><span class="p">)</span> <span class="o">||</span> <span class="nv">$_width</span> <span class="o">&lt;=</span> <span class="mi">0</span> <span class="o">||</span> <span class="o">!</span><span class="nb">is_int</span><span class="p">(</span><span class="nv">$_height</span><span class="p">)</span> <span class="o">||</span> <span class="nv">$_height</span> <span class="o">&lt;=</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="kc">null</span><span class="p">;</span> <span class="p">}</span> <span class="nv">$_str_len</span> <span class="o">=</span> <span class="nb">strlen</span><span class="p">(</span><span class="nv">$_str</span><span class="p">);</span> <span class="k">if</span> <span class="p">(</span><span class="nv">$_str_len</span> <span class="o">&lt;=</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="kc">null</span><span class="p">;</span> <span class="p">}</span> <span class="c1">// 创建一张图像 </span> <span class="nv">$_img</span> <span class="o">=</span> <span class="nb">imagecreatetruecolor</span><span class="p">(</span><span class="nv">$_width</span><span class="p">,</span> <span class="nv">$_height</span><span class="p">);</span> <span class="c1">// 白色 </span> <span class="nv">$_white</span> <span class="o">=</span> <span class="nb">imagecolorallocate</span><span class="p">(</span><span class="nv">$_img</span><span class="p">,</span> <span class="mi">255</span><span class="p">,</span> <span class="mi">255</span><span class="p">,</span> <span class="mi">255</span><span class="p">);</span> <span class="c1">// 填充 </span> <span class="nb">imagefill</span><span class="p">(</span><span class="nv">$_img</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="nv">$_white</span><span class="p">);</span> <span class="c1">// 边框 </span> <span class="k">if</span> <span class="p">((</span><span class="nx">bool</span><span class="p">)</span><span class="nv">$_flag</span><span class="p">)</span> <span class="p">{</span> <span class="nv">$_rnd_color</span> <span class="o">=</span> <span class="nb">imagecolorallocate</span><span class="p">(</span><span class="nv">$_img</span><span class="p">,</span> <span class="nb">mt_rand</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">255</span><span class="p">),</span> <span class="nb">mt_rand</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">255</span><span class="p">),</span> <span class="nb">mt_rand</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">255</span><span class="p">));</span> <span class="nb">imagerectangle</span><span class="p">(</span><span class="nv">$_img</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="nv">$_width</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="nv">$_height</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="nv">$_rnd_color</span><span class="p">);</span> <span class="p">}</span> <span class="nv">$_rnd_count</span> <span class="o">=</span> <span class="nv">$_width</span> <span class="o">&gt;</span> <span class="nv">$_height</span> <span class="o">?</span> <span class="nv">$_width</span> <span class="o">-</span> <span class="nv">$_height</span> <span class="o">:</span> <span class="nv">$_height</span> <span class="o">-</span> <span class="nv">$_width</span><span class="p">;</span> <span class="c1">// 随机画线 </span> <span class="k">for</span> <span class="p">(</span><span class="nv">$i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="nv">$i</span> <span class="o">&lt;</span> <span class="nv">$_rnd_count</span><span class="p">;</span> <span class="nv">$i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> <span class="nv">$_rnd_color</span> <span class="o">=</span> <span class="nb">imagecolorallocate</span><span class="p">(</span><span class="nv">$_img</span><span class="p">,</span> <span class="nb">mt_rand</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">255</span><span class="p">),</span> <span class="nb">mt_rand</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">255</span><span class="p">),</span> <span class="nb">mt_rand</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">255</span><span class="p">));</span> <span class="nb">imageline</span><span class="p">(</span><span class="nv">$_img</span><span class="p">,</span> <span class="nb">mt_rand</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="nv">$_width</span><span class="p">),</span> <span class="nb">mt_rand</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="nv">$_height</span><span class="p">),</span> <span class="nb">mt_rand</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="nv">$_width</span><span class="p">),</span> <span class="nb">mt_rand</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="nv">$_height</span><span class="p">),</span> <span class="nv">$_rnd_color</span><span class="p">);</span> <span class="p">}</span> <span class="c1">// 随机雪花 </span> <span class="k">for</span> <span class="p">(</span><span class="nv">$i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="nv">$i</span> <span class="o">&lt;</span> <span class="nv">$_rnd_count</span><span class="p">;</span> <span class="nv">$i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> <span class="nv">$_rnd_color</span> <span class="o">=</span> <span class="nb">imagecolorallocate</span><span class="p">(</span><span class="nv">$_img</span><span class="p">,</span> <span class="nb">mt_rand</span><span class="p">(</span><span class="mi">200</span><span class="p">,</span> <span class="mi">255</span><span class="p">),</span> <span class="nb">mt_rand</span><span class="p">(</span><span class="mi">200</span><span class="p">,</span> <span class="mi">255</span><span class="p">),</span> <span class="nb">mt_rand</span><span class="p">(</span><span class="mi">200</span><span class="p">,</span> <span class="mi">255</span><span class="p">));</span> <span class="nb">imagestring</span><span class="p">(</span><span class="nv">$_img</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="nb">mt_rand</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="nv">$_width</span><span class="p">),</span> <span class="nb">mt_rand</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="nv">$_height</span><span class="p">),</span> <span class="s1">'*'</span><span class="p">,</span> <span class="nv">$_rnd_color</span><span class="p">);</span> <span class="p">}</span> <span class="c1">// 输出验证码 </span> <span class="nv">$_str_width</span> <span class="o">=</span> <span class="mf">0.9</span> <span class="o">*</span> <span class="nv">$_width</span> <span class="o">/</span> <span class="nv">$_str_len</span><span class="p">;</span> <span class="nv">$_str_height</span> <span class="o">=</span> <span class="mf">0.9</span> <span class="o">*</span> <span class="nv">$_height</span><span class="p">;</span> <span class="nv">$_str_pos</span> <span class="o">=</span> <span class="mf">0.1</span> <span class="o">*</span> <span class="nv">$_width</span><span class="p">;</span> <span class="c1">// 使用时需要修改一下字体路径 </span> <span class="c1">// 默认情况下,生成的图片字体很小,所以才选择使用了别的字体 </span> <span class="nv">$_font</span> <span class="o">=</span> <span class="nv">$_SERVER</span><span class="p">[</span><span class="s2">"DOCUMENT_ROOT"</span><span class="p">]</span> <span class="o">.</span> <span class="s2">"/fonts/FreeMonoOblique.ttf"</span><span class="p">;</span> <span class="k">for</span> <span class="p">(</span><span class="nv">$i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="nv">$i</span> <span class="o">&lt;</span> <span class="nv">$_str_len</span><span class="p">;</span> <span class="nv">$i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> <span class="nv">$_rnd_color</span> <span class="o">=</span> <span class="nb">imagecolorallocate</span><span class="p">(</span><span class="nv">$_img</span><span class="p">,</span> <span class="nb">mt_rand</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">100</span><span class="p">),</span> <span class="nb">mt_rand</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">150</span><span class="p">),</span> <span class="nb">mt_rand</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">200</span><span class="p">));</span> <span class="nb">imagettftext</span><span class="p">(</span><span class="nv">$_img</span><span class="p">,</span> <span class="nv">$_str_height</span><span class="p">,</span> <span class="nb">mt_rand</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">45</span><span class="p">),</span> <span class="nv">$_str_pos</span><span class="p">,</span> <span class="nv">$_str_height</span><span class="p">,</span> <span class="nv">$_rnd_color</span><span class="p">,</span> <span class="nv">$_font</span><span class="p">,</span> <span class="nv">$_str</span><span class="p">[</span><span class="nv">$i</span><span class="p">]);</span> <span class="nv">$_str_pos</span> <span class="o">+=</span> <span class="nv">$_str_width</span><span class="p">;</span> <span class="p">}</span> <span class="k">return</span> <span class="nv">$_img</span><span class="p">;</span> <span class="p">}</span> <span class="cp">?&gt;</span> </code></pre> </div> <p>默认情况下是不支持图片生成的,还需要安装php5-gd,并将/etc/php5/apache2/php.ini文件中的gd.jpeg_ignore_warning = 0注释取消。</p> <p>现在图片是生成出来了,但是要显示到页面,还得有如下代码:</p> <div class="language-php highlighter-rouge"><pre class="highlight"><code><span class="cp">&lt;?php</span> <span class="sd">/** * @param int $len 随机字符窜长度,默认值:4 * @param int $width 图片宽度,默认值:140 * @param int $height 图片高度,默认值:40 * @param bool $flag 是否需要边框,默认值:true * @param string $type 图片类型,默认值:image/png * @param string $key SESSION存放键,默认值:random_validation_code */</span> <span class="k">include_once</span><span class="p">(</span><span class="nx">__DIR__</span> <span class="o">.</span> <span class="s2">"/include/array.php"</span><span class="p">);</span> <span class="k">include_once</span><span class="p">(</span><span class="nx">__DIR__</span> <span class="o">.</span> <span class="s2">"/include/random.php"</span><span class="p">);</span> <span class="k">include_once</span><span class="p">(</span><span class="nx">__DIR__</span> <span class="o">.</span> <span class="s2">"/include/images.php"</span><span class="p">);</span> <span class="nv">$len</span> <span class="o">=</span> <span class="nx">array_get_int</span><span class="p">(</span><span class="nv">$_REQUEST</span><span class="p">,</span> <span class="s2">"len"</span><span class="p">,</span> <span class="mi">4</span><span class="p">);</span> <span class="nv">$width</span> <span class="o">=</span> <span class="nx">array_get_int</span><span class="p">(</span><span class="nv">$_REQUEST</span><span class="p">,</span> <span class="s2">"width"</span><span class="p">,</span> <span class="mi">140</span><span class="p">);</span> <span class="nv">$height</span> <span class="o">=</span> <span class="nx">array_get_int</span><span class="p">(</span><span class="nv">$_REQUEST</span><span class="p">,</span> <span class="s2">"height"</span><span class="p">,</span> <span class="mi">37</span><span class="p">);</span> <span class="nv">$flag</span> <span class="o">=</span> <span class="nx">array_get_bool</span><span class="p">(</span><span class="nv">$_REQUEST</span><span class="p">,</span> <span class="s2">"flag"</span><span class="p">,</span> <span class="kc">true</span><span class="p">);</span> <span class="nv">$type</span> <span class="o">=</span> <span class="nx">array_get_string</span><span class="p">(</span><span class="nv">$_REQUEST</span><span class="p">,</span> <span class="s2">"type"</span><span class="p">,</span> <span class="s2">"png"</span><span class="p">);</span> <span class="nv">$key</span> <span class="o">=</span> <span class="nx">array_get_string</span><span class="p">(</span><span class="nv">$_REQUEST</span><span class="p">,</span> <span class="s2">"key"</span><span class="p">,</span> <span class="s2">"vcode"</span><span class="p">);</span> <span class="nv">$str</span> <span class="o">=</span> <span class="nx">random_str</span><span class="p">(</span><span class="nv">$len</span><span class="p">);</span> <span class="nv">$img</span><span class="o">=</span> <span class="nx">create_str_image</span><span class="p">(</span><span class="nv">$str</span><span class="p">,</span> <span class="nv">$width</span><span class="p">,</span> <span class="nv">$height</span><span class="p">,</span> <span class="nv">$flag</span><span class="p">);</span> <span class="k">if</span> <span class="p">(</span><span class="nv">$img</span> <span class="o">!=</span> <span class="kc">null</span><span class="p">)</span> <span class="p">{</span> <span class="nb">session_start</span><span class="p">();</span> <span class="c1">//输出图像 </span> <span class="k">switch</span><span class="p">(</span><span class="nb">strtolower</span><span class="p">(</span><span class="nv">$type</span><span class="p">))</span> <span class="p">{</span> <span class="k">case</span> <span class="s2">"jpeg"</span><span class="o">:</span> <span class="nb">header</span><span class="p">(</span><span class="s2">"Content-Type: image/jpeg"</span><span class="p">);</span> <span class="nb">imagejpeg</span><span class="p">(</span><span class="nv">$img</span><span class="p">);</span> <span class="k">break</span><span class="p">;</span> <span class="k">case</span> <span class="s2">"gif"</span><span class="o">:</span> <span class="nb">header</span><span class="p">(</span><span class="s2">"Content-Type: image/gif"</span><span class="p">);</span> <span class="nb">imagegif</span><span class="p">(</span><span class="nv">$img</span><span class="p">);</span> <span class="k">break</span><span class="p">;</span> <span class="k">default</span><span class="o">:</span> <span class="nb">header</span><span class="p">(</span><span class="s2">"Content-Type: image/png"</span><span class="p">);</span> <span class="nb">imagepng</span><span class="p">(</span><span class="nv">$img</span><span class="p">);</span> <span class="k">break</span><span class="p">;</span> <span class="p">}</span> <span class="c1">// 销毁 </span> <span class="nb">imagedestroy</span><span class="p">(</span><span class="nv">$img</span><span class="p">);</span> <span class="c1">// 保存在session </span> <span class="nv">$_SESSION</span><span class="p">[</span><span class="nv">$key</span><span class="p">]</span> <span class="o">=</span> <span class="nv">$str</span><span class="p">;</span> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span> <span class="nb">header</span><span class="p">(</span><span class="s2">"Content-Type: text/plain"</span><span class="p">);</span> <span class="k">echo</span> <span class="s2">"fail to create image"</span><span class="p">;</span> <span class="p">}</span> <span class="c1">// print_r(array($len, $width, $height, $flag, $type, $key)); </span><span class="cp">?&gt;</span> </code></pre> </div> <p>为了更通用一些,所以所有参数都可以通过Request Param加入。</p> Thu, 06 Sep 2012 00:00:00 +0800http://jhat.pw/blog/2012/09/06/php-verification-code.htmlhttp://jhat.pw/blog/2012/09/06/php-verification-code.html 北京之行Jhat <p>一直都很想去北京看看,看看各大软件公司都是怎样的,所以这次暑假选择去北京实习,同时也是一个很好的旅游机会,一共在北京呆了6周,总体感受,这是一个不适合生活的城市,对于火爆的房地产市场也就不吐槽了。对于餐饮,味道只能说将就,始终还是没有川菜好,关键是在外面吃饭毫无服务可言,真的就是先交钱,后吃饭,剩余的什么也没有了。</p> <p>初到北京时,坐公交去公司,感觉乘务员在报站时那地道的北京味儿确实中听。然而转了一辆车之后,估计这辆车上的人应该很少像我这样刚到北京的外来者。但是从他们的面部表情来看,要么是一副没有睡醒的状态,要么就是愁眉苦脸的状态,也许这还是清晨,始终还是太早了吧。</p> <p>来北京的一大目的就是来旅游的,虽然周末只有一天,还是尽量将想去的地方都跑了一趟。</p> <ol> <li> <p>第一周</p> <p>虽然是周日,但是还是很早的起来了,因为还有些工作室的事情要做,所以先去公司把该做的事做了,吃完午饭后,和一起过来的2个实习生一起出去逛,先是来到清华,在门口就发现人很多,进去之后发现人更多,而且以旅行团居多。在校园里,也没有太多的感触,只是觉得这里的建筑更有点历史,有点欧洲风格而已,但是对这一切都不怎么了解。当从西门出来时,发现门口居然排着长龙,大热天的,居然顶着烈日排队也有这么多人想进去。来到北大东门,发现情况也差不多,最后还是同行的一位师兄,不知道怎么和保安说的,让我们从一偏门进去了,未名湖确实漂亮,但是人也太多了点,我在想,平时也是这样吗,北大的情侣岂不是很悲捶。</p> <p>从北大出来之后,已经很累了,但是还是坚持去了躺圆明园,虽然知道有那么一段耻辱的历史,很惭愧,那段历史的详情早就忘得差不多了,所以在这里出来看看残存的建筑之外并没有太多的感触。</p> </li> <li> <p>第二周</p> <p>说好这周去爬长城,由于相对距离较远,也就没时间去其它地方了,所以睡到快中午了才起来,吃完饭后坐了2个小时左右的公交才到长城脚下。果然是著名景点,自然也是人满为患,爬长城的路上也基本等于大家相互簇拥着往前走。无论是高度,还是难度,和想象中的长城完全不是那么回事,匆匆爬上去,呆了会儿,然后就下来回去了。</p> </li> <li> <p>第三周</p> <p>本打算早上就去天安门的,结果睡过头了,吃完午饭后又磨蹭了一会,2点才出发。来到天安门广场,发现要过安检才能过去,顿时就谋生了一个想法,如果想干点坏事,应该怎么办,想要集中足够多的人又该怎么办。最后得出结论,空降,是最好的办法,但是遇上航空管制也就没办法了。</p> <p>等来到故宫门前,已经是下午5点了,很失望的发现工作人员已经在清场了,故宫要关门了。此行的主要目的就是来看看故宫的,这么就意味着此行的意义不大了。最终在城墙外绕着护城河来到北海公园,也快到关门的时间了,所以赶紧买票匆匆进去逛逛,从白塔俯视紫禁城,确实够壮观的,决定下周一定要进去看看。</p> </li> <li> <p>第四周</p> <p>继续上周没有完成的目的地,所以直接往故宫赶,但是进去之后发现除了建筑之外,也没有什么,还是只有看全景给人一种壮观的感受更好。</p> <p>从故宫出来后,本想再去国家博物馆看看的,但是发现需要提前预定,所以就没戏了,遂决定再去天坛看看吧。路上就在想,隐约记得北京还有个圆形建筑,其回音效果极好,但就是想不起名字了。来到天坛发现也快到关门时间了,所以也就只是买了张门票进去看看,进去之后发现原来路上想的那个圆形建筑就在这里,原来就是回音壁。可以没买景点门票,也进不去。从里面的人流量来看,估计再好的回音效果,也是不可能听得到的了。</p> </li> <li> <p>第五周</p> <p>好像也没有什么地方可去了,周末又只有一天,没法跑得太远,所以就老老实实的呆着了。</p> </li> <li> <p>第六周</p> <p>以出差的名义回来了。</p> <p>在北京看了这么多景点,发现这些景点基本以建筑为主,而且都还有一段过往历史,所以来这里旅游应该来说更主要的目的还是回味历史吧,而且可以触景生情。但是对于建筑,要说古代风格,基本也都没有了,差不多都是后期维护改造出来的。对于历史,也没太多常识,所以也就成了匆匆而来,匆匆而去。</p> </li> </ol> Mon, 20 Aug 2012 00:00:00 +0800http://jhat.pw/blog/2012/08/20/beijing-trip.htmlhttp://jhat.pw/blog/2012/08/20/beijing-trip.html 画圈圈Jhat <p>在亲朋好友的欢声笑语中,P出生了,这时Z来了,带来一张白纸,干干净净的白纸,摇摇头,放下白纸就走了。</p> <p>P一天天的长大,也渐渐的知道,一定要努力,努力在自己出生时得到的那张白纸上画圈圈,只有圈圈获得越多,将来才生活的越好。所以P一直很努力,努力的得到可以得到的每一个圈圈,再慎重的画上去。慢慢的P发现,每当自己多得到一个圈圈,就会得到不少人的祝福、羡慕、甚至是嫉妒,渐渐的P也开始享受这种成就感。</p> <p>有一天,父母告诉P,你也长大了,去找Z,让他给你一个很重要的圈圈。于是P找到Z,没费什么劲,Z就在P的白纸上画好了一个圈圈,临走前告诉P,好好保管,不然你就不是你了。</p> <p>生活在继续,P也继续努力画着圈圈。慢慢的P发现,有些圈圈画的毫无意义,完全是可有可无的,但是少了这么一个可有可无的圈圈,很多流程就走不通了,甚至有些时候,还是连环圈,想画这个就必须先画那个。。。绕来绕去,结果又绕回来了。这样的事情多了,P也就渐渐的厌倦了这种画圈圈的生活,但是从小,所有的人都告诉P,要多画圈圈,不管有没有用,都先画上去,说不定将来哪天就用到了呢?所以P只好继续,因为在所有人眼里,P一直是个懂事的好孩子。</p> <p>终于有一天,P被告知:去吧,拿着你的圈圈去换你想要的生活。P很高兴,因为再也不用整天只为了画圈圈了。但是,很快,P失望了,因为他发现这些圈圈用处不大,并不能换来他真正想要的生活。</p> <p>生活还在继续,本以为画圈圈的生活可以结束了,但是P发现,身边的人还在继续画圈圈,只是画圈圈的目的有所不同,方式各有差异而已。于是P又继续画起圈圈,因为他知道,有时候,要是少了一个圈圈,那就是寸步难行。</p> <p>有一天,P很不小心的弄丢了一个圈圈,正好是那个很重要的圈圈,P发现少了这个圈圈什么也做不了,P想这是Z给他的,于是又去找Z,于是发生了下面一段金典的对白:</p> <blockquote> <p>Z:你是谁?</p> <p>P:我是P啊,当初你还送过我一个圈圈呢。</p> <p>Z:来干什么?</p> <p>P:那个圈圈给弄丢了,想找你再要一个。</p> <p>Z:怎么证明你是P?</p> <p>P:。。。</p> </blockquote> <p>这下可把P难住了,因为这么多年来,虽然平时很少用到,但是关键时刻都需要那个圈圈来证明自己,没了那个圈圈怎么才能证明自己呢?尽管P尝试了各种办法向Z求情,还找出各式各样写着自己名字的圈圈来证明自己,但是Z始终还是不给那个圈圈给P,最后Z告诉P,回去把,回去找那个有你们全家人名字的圈圈来。P又碰了几次壁,终于把那个圈圈拿到Z面前,Z简单的看了看,很快就给了P一个新圈圈。</p> <p>生活还在继续,慢慢的P老了,终于有一天P死了,在亲朋好友们的悲痛声中,Z来了,拿出那张纸,那张P画了一生圈圈的纸,看了看,摇摇头,走了。</p> Sun, 19 Aug 2012 00:00:00 +0800http://jhat.pw/blog/2012/08/19/draw-a-circle.htmlhttp://jhat.pw/blog/2012/08/19/draw-a-circle.html