<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>工作 on bystander&#39;s blog</title>
    <link>http://blog.leaver.me/tags/%E5%B7%A5%E4%BD%9C/</link>
    <description>Recent content in 工作 on bystander&#39;s blog</description>
    <generator>Hugo</generator>
    <language>zh-CN</language>
    <lastBuildDate>Sat, 07 Mar 2020 14:37:40 +0800</lastBuildDate>
    <atom:link href="http://blog.leaver.me/tags/%E5%B7%A5%E4%BD%9C/rss.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>几个浏览器的使用体验</title>
      <link>http://blog.leaver.me/2020/03/07/%E5%87%A0%E4%B8%AA%E6%B5%8F%E8%A7%88%E5%99%A8%E7%9A%84%E4%BD%BF%E7%94%A8%E4%BD%93%E9%AA%8C/</link>
      <pubDate>Sat, 07 Mar 2020 14:37:40 +0800</pubDate>
      <guid>http://blog.leaver.me/2020/03/07/%E5%87%A0%E4%B8%AA%E6%B5%8F%E8%A7%88%E5%99%A8%E7%9A%84%E4%BD%BF%E7%94%A8%E4%BD%93%E9%AA%8C/</guid>
      <description>&lt;p&gt;前段时间，由于对 Chrome 即将成为 IE 和一些隐私方面的担忧。也顺便想尝试一下其他的浏览器，于是稍微换了一些。当然，现在又回到了 Chrome。简单记录一下。&lt;/p&gt;
&lt;p&gt;Brave 浏览器，基于 Chromium 网页浏览器由 Mozilla 项目的联合创始人、JavaScript 的创造者布蘭登·艾克宣布。宣称阻止网站跟踪器和移除侵入式网络广告。确实可以拦截部分广告，另外有一个特色的挖矿钱包功能，就是你可以选择接受通知，看广告，然后获取虚拟货币。界面也很漂亮。但是这个东西。速度嘛，感觉也没有宣称的那么快。毕竟。道理上说不通啊。你都8倍了。Google 的开发者是水瓶不行么。。另外，这个玩意对于国内网站不够友好。国内的电商网站，比如淘宝，京东，等，基本上默认情况下，打开全屏幕空白。。因为认为是广告。&lt;/p&gt;
&lt;p&gt;Firefox 浏览器，火狐浏览器，基本上算是最后一个有点名气的非 Chromium 内核的浏览器了。其实我觉得还不错，我比较喜欢内置的画中画功能。另外，速度上，我感觉也不差。但是Firefox 的 收藏夹功能真的是。。乱。最大的问题就是因为内核的原因。核心工作用的几个网站都用不了。因为开发网站的同学不兼容。不得不放弃。手机上也可以。&lt;/p&gt;
&lt;p&gt;Edge 浏览器，微软基于 Chromium 的浏览器，界面风格我还挺喜欢，首页的广告默认存在，可以通过安装其他tab插件来解决屏蔽，支持 Chrome 扩展，但是注意，功能很不完善，很多同步功能都是废的。设置里面很多时间，你选了其他选项，根本看不到变化，刷新一下，发现好像生效了。有个特色的Collection功能。如果专门查个什么资料，还是有点用，但是可以通过新建一个收藏夹的文件夹来基本替代。手机版内置去广告插件，还不错。Mac 和 iOS 的一些联动基本没有，比如你想吧手机上的发给电脑，只能通过 Airdrop 了。不能直接发送。和 Chrome 不同。还需要完善，可以跟进。多等几个版本看看。&lt;/p&gt;
&lt;p&gt;Safari 浏览器，其实挺简洁的，就是没啥进步，和公司不少网站也是不兼容的。插件也基本用不了，这点非常蛋疼，还要安装 App，阅读列表功能非常喜欢。可以同步。&lt;/p&gt;
&lt;p&gt;除了 Safari，其他几个浏览器的手机上也是有阅读列表这个功能的，但是很奇怪，大家都不支持同步，只在手机上保存。估计觉得可以通过收藏夹替代。另外，不少浏览器对于手机和PC/Mac的收藏夹是默认分开的，叫做移动设备书签。这个真的是。有点难用。 除了 Edge 的手机 App 还是很好用的，其他的几个浏览器手机上的体验都很奇怪，比如最基本的 Tab 页新增。最好的还是 Safari。&lt;/p&gt;
&lt;p&gt;综上所属，目前依然 Chrome。新时代的 IE。&lt;/p&gt;</description>
    </item>
    <item>
      <title>2019 年终总结</title>
      <link>http://blog.leaver.me/2020/01/08/2019-%E5%B9%B4%E7%BB%88%E6%80%BB%E7%BB%93/</link>
      <pubDate>Wed, 08 Jan 2020 08:40:22 +0800</pubDate>
      <guid>http://blog.leaver.me/2020/01/08/2019-%E5%B9%B4%E7%BB%88%E6%80%BB%E7%BB%93/</guid>
      <description>&lt;p&gt;2019 年很快过去了,以前有大把时间的时候没有感觉，而现在，时光如流水，怎么也抓不住。2019年，心情复杂。&lt;/p&gt;
&lt;h2 id=&#34;失去的一年&#34;&gt;失去的一年&lt;/h2&gt;
&lt;p&gt;这一年，爷爷生病离世，改变了很多事情。人生很短，一定要珍惜当下，珍惜眼前人。很多东西都可以通过各种方式重新获得。但是，生病，亲人，这些总是无能为力。今年体检，查出来中老年常见的血脂高。当然目前只高一点点，2019年，工作太忙。锻炼的很少。2020年，一定要坚持锻炼。&lt;/p&gt;
&lt;p&gt;给父母也申请了体检，查下来没有什么大问题，心里放下很多，然后该买的保险，也给父母和自己都买了一些。虽然保额不算太高，但是也是有个保障。&lt;/p&gt;
&lt;p&gt;对 XX 失去期待，基本上放弃了想要改变的想法，眼看着一些人被浪费，效率被无限拉低，还是多从自己做起，一屋不扫，何以扫天下。&lt;/p&gt;
&lt;h2 id=&#34;得到的一年&#34;&gt;得到的一年&lt;/h2&gt;
&lt;p&gt;2019年也是得到的一年，看了10多本书，心理学和经济学，还有一些小说，学习了一些新的技术， Golang，分布式事务，也成为 Seata 的 Committer，另外也对外做了一次500人场的Service Mesh 技术分享,之后又分享了几次。&lt;/p&gt;
&lt;p&gt;这一年，在杭州买了房，定了居。买了Air Pods 2，买了 Surge Mac，拿到了公司5年陈的戒指，顺便买了一个手链，买了很多家居用品，自己处理家里的大大小小的事情，自己在家做饭，吃火锅。&lt;/p&gt;
&lt;p&gt;这一年，也去湖北参加了同学的婚礼，在武大促膝长谈，跟朋友们在家里吃了饭，也去青海团建，吃了让人念念不忘的炕锅羊肉。&lt;/p&gt;
&lt;p&gt;年末的时候，买了开言英语的年费会员，目前坚持了一个多月了。刚开始很简单，有了一点信心。2020年继续努力。&lt;/p&gt;
&lt;p&gt;职业上有了晋升，当然也只是title变更，不过是资本家的把戏，不过5年，也算给自己一个交代。&lt;/p&gt;
&lt;h2 id=&#34;寻求改变的一年&#34;&gt;寻求改变的一年&lt;/h2&gt;
&lt;p&gt;这一年，尝试体验了一些新的产品，比如彻底放弃了余额宝，转为银行的产品。比如开始熟练微信支付。&lt;/p&gt;
&lt;p&gt;这一年，工作上，试图寻求突破，但很多事情并非能以人的意志为转移，并没有很好的达到自己的期望，作为公司层面可以理解，谁又能成为不可或缺的人。但是从个人角度来看。一旦没有上升空间，做的事情也没有比较大的价值，处在修修补补，到处支持，到处迁移的情况下，俗称搬砖，精力被无限的消耗，这样下去，核心竞争力没了，加班加不过新人，迟早成为马老板眼里的老白兔，这时候，就应该考虑是不是需要有新的机会和挑战，主动做出改变。2020年，多想一些，做点改变。&lt;/p&gt;
&lt;p&gt;生活上，经历了一些改变，也迎接一些改变，变化总是存在的。如果一切可预知，那么人生岂不是也毫无意义。2020年，多锻炼身体，一周两次不能少，也出去走走。&lt;/p&gt;
&lt;h2 id=&#34;2020-年&#34;&gt;2020 年&lt;/h2&gt;
&lt;p&gt;2020年，多做一些高价值的事情，能够坚持读一些英文的paper，探索一些新的非工作上的领域，最重要的，坚持读书不能少。&lt;/p&gt;</description>
    </item>
    <item>
      <title>《非暴力沟通》笔记</title>
      <link>http://blog.leaver.me/2019/10/27/%E9%9D%9E%E6%9A%B4%E5%8A%9B%E6%B2%9F%E9%80%9A%E7%AC%94%E8%AE%B0/</link>
      <pubDate>Sun, 27 Oct 2019 06:29:11 +0800</pubDate>
      <guid>http://blog.leaver.me/2019/10/27/%E9%9D%9E%E6%9A%B4%E5%8A%9B%E6%B2%9F%E9%80%9A%E7%AC%94%E8%AE%B0/</guid>
      <description>&lt;p&gt;最近读完了《非暴力沟通》这本书，看完之后，整体感觉还好，感觉核心就下面这四点&lt;/p&gt;
&lt;h2 id=&#34;1清楚地表达观察结果&#34;&gt;1.清楚地表达观察结果&lt;/h2&gt;
&lt;p&gt;区分感受和观察，表达的时候，一定要表达清楚，不要只表达感受，即使你批评一个人，也要说清楚，你看到了什么事情，让你觉得你应该批评他，而不是一开口就是你不对，你错了。 要不带评论的冷静观察。&lt;/p&gt;
&lt;h2 id=&#34;2表达感受&#34;&gt;2.表达感受&lt;/h2&gt;
&lt;p&gt;在表达完你的观察之后，要表达感受，这个主要是为了自己，让你能观察到自己的感受，让你知道什么时候，你是什么感受，是否是正向的。如何处理，注意，“我觉得”，“我想”，这个词带有评判色彩，当你说这个的时候，请重新组织语言。&lt;/p&gt;
&lt;h2 id=&#34;3说出哪些需要导致那样的感受&#34;&gt;3.说出哪些需要导致那样的感受&lt;/h2&gt;
&lt;p&gt;说出，哪个行为，或者哪个操作让你感受这样。比如是不是冒犯了你这样。&lt;/p&gt;
&lt;h2 id=&#34;4具体的请求&#34;&gt;4.具体的请求&lt;/h2&gt;
&lt;p&gt;最后，提出具体的请求，你希望对方怎么做，才能让你好受，达到你的期望。请求的时候要具体，不能是抽象的。比如，你做的更好一点，这种对方无法决策怎么做，应该尽量具体，也避免双方理解有误。&lt;/p&gt;
&lt;p&gt;这里注意要区分请求和命令，如果你说出的请求，别人拒绝会要承担后果，那多半是命令，而不是请求。&lt;/p&gt;</description>
    </item>
    <item>
      <title>Principle Note</title>
      <link>http://blog.leaver.me/2019/09/29/principle-note/</link>
      <pubDate>Sun, 29 Sep 2019 06:04:31 +0800</pubDate>
      <guid>http://blog.leaver.me/2019/09/29/principle-note/</guid>
      <description>&lt;p&gt;最近在读一本书，《原则》，有一些感触比较深的点，分享下。这本书前半部分介绍作者在桥水的工作历程，建议直接忽略。从第二部分看起来即可。&lt;/p&gt;
&lt;h3 id=&#34;1-独立思考&#34;&gt;1. 独立思考&lt;/h3&gt;
&lt;p&gt;（1）你想要什么；
（2）事实是什么；
（3）面对事实，你如何实现自己的愿望&lt;/p&gt;
&lt;p&gt;知道自己想要什么，知道现实是什么，然后找办法实现，可以求助别人，如果还是实现不了，建议认清楚这种鸿沟。&lt;/p&gt;
&lt;h3 id=&#34;2-以可信度加权的方式做决定&#34;&gt;2. 以可信度加权的方式做决定&lt;/h3&gt;
&lt;p&gt;作者认为一个人除了自信以外，要认识到自己的弱点，做决定的时候要配合更加可信的人，以可信度加权的方式做决定。比如你去看医生，医生说你并很重，建议你住院，而你觉得自己身体并无碍，这时候你会怎么做，你当然是更相信医生才对，因为医生在这一领域更专业，如果你自己在医学上的可信度为1，那么医生就是90，所以。&lt;/p&gt;
&lt;p&gt;也就是说要经常好奇为什么其他聪明的人对事情的认识与我不同，来促使自己既从自己的视角看问题，也从别人的视角看问题。以看到很多维度，如果只从自己的视角看问题，是看不到这么多的。要懂得了如何对不同人的观点进行加权，从而选择最好的观点，&lt;/p&gt;
&lt;p&gt;那如何定义“可信”，作者认为这样的人有两个特征：曾反复地在相关领域成功找到答案（至少成功过三次，拥有过硬履历）；在被问责的情况下能对自己的观点做出很好的解释。”&lt;/p&gt;
&lt;p&gt;这个点说的非常好，告诉我们什么时候，如果做正确的决定。如果你评估对方在这方面是这个新手，那多数情况下你更应该相信自己。&lt;/p&gt;
&lt;h3 id=&#34;3-做到头脑极度开放&#34;&gt;3. 做到头脑极度开放&lt;/h3&gt;
&lt;p&gt;影响合理决策的两个最大的障碍是你的自我意识和思维盲点。这两个障碍让你难以客观地看到你和你所处环境的真相，难以通过最大限度地利用他人的帮助来做出最佳决策。&lt;/p&gt;
&lt;p&gt;自我意识指的是，要有效行事，你就绝不能允许“想要自己正确”的需求压倒“找出真相”的需求。让心里那个想要维护自己所谓尊严和正确的小人退下去，而且要保持谦逊和心胸开阔，以便你能动用自己的最佳思维，而如果你对自己掌握的知识和擅长的事情过于自豪，你学到的东西就会变少，决策质量就会变低，也将难以充分发挥自己的潜力&lt;/p&gt;
&lt;p&gt;思维盲点指的则是，一个人的能力有限，不要过于自信，起码评估在哪些方面自己比较好，但是在自己的短板上，依靠擅长者的帮助。&lt;/p&gt;
&lt;p&gt;作者还举了个例子，一个有高度创造性和目标导向性的人擅长设想新主意，但可能会低估日常生活细节的价值，而后者也很重要。他也许过度投入地追求长期目标，因而鄙视那些关注日常生活细节的人。类似地，一个任务导向的人善于处理细节，但可能会低估创造性的价值，甚至可能会为了效率而压制创造性。这两个人也许能组成一个好团队，但也有可能难以充分利用各自的优势，因为不同的思维方式让他们难以看到对方思维的价值。”&lt;/p&gt;
&lt;p&gt;在日常工作中，这两个人最好能先把自己的本职做好，比如leader，要有大局观，但是不能空想。要有合理的把控，员工如果在信息掌握不足的情况下，首先做好细节上的事情，也要积极了解做这样的意义和在全局的用处。&lt;/p&gt;
&lt;h3 id=&#34;4-合理选择&#34;&gt;4. 合理选择&lt;/h3&gt;
&lt;p&gt;这里面，我觉得久一点，最好的选择是好处多于坏处的选择，不是毫无坏处的选择。看看有些人，发现一点问题就反对某件事，而不合理权衡所有的优缺点。这样的人通常不善于决策。&lt;/p&gt;
&lt;p&gt;这个告诉我们，没有银弹，一旦有人提出一个能解决一切问题的方案，请警惕。推广到工作和生活中，就是没有完美的答案，一定会有一些妥协，但可以选择好处远远大于坏处的，并评估坏处是否可以接受。&lt;/p&gt;
&lt;h3 id=&#34;5-团队合作&#34;&gt;5. 团队合作&lt;/h3&gt;
&lt;p&gt;主持开会，要支持开会目的，开会对象，切忌胡乱跑题，绝不展开无关话题，保持高效，要允许反对意见，并充分讨论，而不是主管给结论，然后提出反对意见，并不理会，正确的应该是，会上充分讨论，会下严格执行，一旦决策，就不应该再有不同意见。否则决策多半是失败的。要么实行不下去。要么是其他的。&lt;/p&gt;
&lt;h3 id=&#34;6-不要担心个人形象&#34;&gt;6. 不要担心个人形象&lt;/h3&gt;
&lt;p&gt;不要为自身形象担心，只需关心能不能实现你的目标。也就是说不要有所谓的偶像包袱，觉得自己应该什么都自己搞定，要比别人更厉害。遇到别人更了解的，积极求援，目标是把任务完成，而不要纠结于个人形象。&lt;/p&gt;
&lt;p&gt;同时你不擅长的领域请教擅长的其他人，这也是一个你无论如何都应该培养的出色技能，这将帮助你建立起安全护栏，避免自己做错事。&lt;/p&gt;
&lt;p&gt;找到、接受，并学会如何应对你的弱点，则可以更好的进步。&lt;/p&gt;
&lt;h3 id=&#34;7-失败则反思&#34;&gt;7. 失败则反思&lt;/h3&gt;
&lt;p&gt;虽然很不喜欢如何成功类似的文章，但是作者这句话说的还是比较在理的：成功的关键在于，既知道如何努力追求很多东西，也知道如何正确地失败。“正确地失败”是指，能够在经历痛苦的失败的过程中吸取重要的教训&lt;/p&gt;
&lt;p&gt;不管是个人的失败，还是某些项目或者工作目标上的失败，一定要反思。而不能让部分的成功掩盖。&lt;/p&gt;
&lt;p&gt;另外，不要把成功的装饰误认为成功本身。有追求成就的方向感是很重要的。有的人痴迷于一双1200元的鞋或一辆时髦的汽车，这样的人很少会感到快乐，因为他们不知道自己真正想要的是什么，因而也不知道什么能满足他们&lt;/p&gt;
&lt;p&gt;这些都只是成功的装饰，并非成功本身。。&lt;/p&gt;
&lt;h3 id=&#34;8-汇总&#34;&gt;8. 汇总&lt;/h3&gt;
&lt;p&gt;作者在书中说了很多，我个人印象比较深刻的就是这么几点。总结下来，也提醒自己多多注意，能够有所提高。&lt;/p&gt;</description>
    </item>
    <item>
      <title>分析代码调用关系的利器-Flow</title>
      <link>http://blog.leaver.me/2017/04/08/%E5%88%86%E6%9E%90%E4%BB%A3%E7%A0%81%E8%B0%83%E7%94%A8%E5%85%B3%E7%B3%BB%E7%9A%84%E5%88%A9%E5%99%A8-flow/</link>
      <pubDate>Sat, 08 Apr 2017 15:10:36 +0000</pubDate>
      <guid>http://blog.leaver.me/2017/04/08/%E5%88%86%E6%9E%90%E4%BB%A3%E7%A0%81%E8%B0%83%E7%94%A8%E5%85%B3%E7%B3%BB%E7%9A%84%E5%88%A9%E5%99%A8-flow/</guid>
      <description>&lt;p&gt;今天推荐一个不错的软件.是idea 的插件.名字是Flow, 官方称:A better way to understand your Java applications,原理就是通过 java-agent 修改字节码,配置了拦截器,然后真实地跑一个测试用例,或者启动一下项目,就会生成一个真实的调用关系.官方地址:http://findtheflow.io/&lt;/p&gt;
&lt;p&gt;之前阅读源代码,对于抽象类,或者接口,静态阅读代码不太容易确定具体的调用类,因此阅读有一定的阻碍,当然 debug 也行..但是这个可以通过跑用例,或者简单的测试用例,理清调用关系,非常不错.
可以对代码结构有一个整体关系&lt;/p&gt;
&lt;h2 id=&#34;安装&#34;&gt;安装&lt;/h2&gt;
&lt;p&gt;安装比较简单:https://plugins.jetbrains.com/plugin/8362?pr=idea 直接安装idea 这个插件,然后重新启动 idea, 安装完成后的效果.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&#34;安装结果&#34; loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/flow_install.png&#34;&gt;&lt;/p&gt;
&lt;h2 id=&#34;使用&#34;&gt;使用&lt;/h2&gt;
&lt;p&gt;使用更简单,直接点击上图中的按钮,开始跑一下,即可,如果启动成功.控制台会有显示.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&#34;开始启动&#34; loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/flow_start.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;然后,会在本地开启7575的端口,来显示结果.&lt;/p&gt;
&lt;h2 id=&#34;效果&#34;&gt;效果&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&#34;结果&#34; loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/flow_common.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&#34;结果明细&#34; loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/flow_detail.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;注意,在结果页里,可以和 idea 源码交互,对着方法点右键,可以直接定位到 idea 代码中的源代码,非常方便.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&#34;跳转&#34; loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/flow_jump.png&#34;&gt;&lt;/p&gt;
&lt;h2 id=&#34;其他&#34;&gt;其他&lt;/h2&gt;
&lt;p&gt;其他,就是 可以在配置里设置根据哪些类,这样一些工具类啥的可以直接忽略了.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&#34;运行配置&#34; loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/flow_conf.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;使用了一下,还是不错的.但是这个有个问题,如果你的项目自定义了 classloader/ 或者使用了自定义的容易,这个由于没有 mvn 的 jar 包,可能会报错,类找不到.暂时没有好的办法.但是阅读开源代码基本没有问题了.&lt;/p&gt;</description>
    </item>
    <item>
      <title>jdk8_cannot_access_class_file</title>
      <link>http://blog.leaver.me/2017/03/31/jdk8_cannot_access_class_file/</link>
      <pubDate>Fri, 31 Mar 2017 13:48:50 +0000</pubDate>
      <guid>http://blog.leaver.me/2017/03/31/jdk8_cannot_access_class_file/</guid>
      <description>&lt;p&gt;之前有个项目用 jdk6跑运行正常,用 jdk8跑的时候,会报&lt;code&gt;java cannot access ....class file ...as class file not found though it exists.&lt;/code&gt;
虽然可以通过加上报错的类到依赖里解决.但是一直没想明白,为啥 jdk6下没报错.&lt;/p&gt;
&lt;p&gt;最近再次遇到,于是想一次性搞清楚.搜了一下,看 so 上有这么个说法.大意就是以前,如果 A 依赖 B,B 实现了 C 接口,编译的时候, 用 jdk8编译的时候, C 必须在 classpath 中,
&lt;a href=&#34;http://stackoverflow.com/questions/40255718/compiling-with-jdk-1-8-java-cannot-access-class-file-class-file-not-found&#34;&gt;http://stackoverflow.com/questions/40255718/compiling-with-jdk-1-8-java-cannot-access-class-file-class-file-not-found&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;给出了一个 bug 连接,但是这里跟我们的问题有差异,不过这个点提醒了我.于是我搜索了一下 jdk8的relase note&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://www.oracle.com/technetwork/java/javase/8-compatibility-guide-2156366.html&#34;&gt;http://www.oracle.com/technetwork/java/javase/8-compatibility-guide-2156366.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;注意观看这一段:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Area: Tools / javac
Synopsis
Interfaces need to be present when compiling against their implementations&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;好了.也就是说还是乖乖加依赖.但是清楚了原因了&lt;/p&gt;</description>
    </item>
    <item>
      <title>oom介绍</title>
      <link>http://blog.leaver.me/2017/02/03/oom%E4%BB%8B%E7%BB%8D/</link>
      <pubDate>Fri, 03 Feb 2017 15:04:04 +0000</pubDate>
      <guid>http://blog.leaver.me/2017/02/03/oom%E4%BB%8B%E7%BB%8D/</guid>
      <description>&lt;p&gt;oom 之前知道, 但是并不是很了解,最近遇到了由 oom 引发的问题,所以学习记录一下.&lt;/p&gt;
&lt;p&gt;OOM-killer：Out-of-Memory (OOM) Killer是一种保护机制，用于当内存严重不足时，为了系统的继续运转，内核迫不得已挑选一个进程，将其杀死，以释放内存，缓解内存不足的问题。
可以看出这种方式对进程的保护是有限的，不能完全的保护进程的运行。&lt;/p&gt;
&lt;h2 id=&#34;如何知道是否发生了-oom&#34;&gt;如何知道是否发生了 oom&lt;/h2&gt;
&lt;p&gt;两种方法,第一种,查看 /var/log/messages,会有类似&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Out of memory: Kill process 9682 (mysqld) score 9 or sacrifice child
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Killed process 9682, UID 27, (mysqld) total-vm:47388kB, anon-rss:3744kB, file-rss:80kB
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;httpd invoked oom-killer: gfp_mask=0x201da, order=0, oom_adj=0, oom_score_adj=0
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;httpd cpuset=/ mems_allowed=0
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Pid: 8911, comm: httpd Not tainted 2.6.32-279.1.1.el6.i686 #1
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这样的标识,说明发生了 oom,关键就是 kill process, 所以可以这样&lt;/p&gt;
&lt;p&gt;&lt;code&gt;sudo cat /var/log/messages | grep -i&amp;quot;killed process&amp;quot;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;另一种是通过dmesg来查看
&lt;code&gt;dmesg | egrep -i &#39;killed process&#39;&lt;/code&gt;
这个命令查看的 oom 的时间里是时间戳的形式,如果你的 dmesg 没有-T这个时间的选项,那么就需要通过&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;date -d &amp;#34;1970-01-01 UTC `echo &amp;#34;$(date +%s)-$(cat /proc/uptime|cut -f 1 -d&amp;#39; &amp;#39;)+12288812.926194&amp;#34;|bc ` seconds&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;来转换成可读的时间了.&lt;/p&gt;
&lt;h2 id=&#34;oom-的原理&#34;&gt;oom 的原理&lt;/h2&gt;
&lt;p&gt;其中涉及到有三个相关文件：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;/proc/$PID/oom_adj&lt;/li&gt;
&lt;li&gt;/proc/$PID/oom_score&lt;/li&gt;
&lt;li&gt;/proc/$PID/oom_score_adj
其中 oom_score 表示最终的分数，该分数越大，越可能被 Killer 杀掉。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;而 oom_adj 是调整分数的，可以设置为负值，会对 oom_score减分。&lt;/p&gt;
&lt;p&gt;从Linux 2.6.36开始都安装了/proc/$PID/oom_score_adj，此后将替换掉/proc/$PID/oom_adj。即使当前是对/proc/$PID/oom_adj进行的设置，在内核内部进行变换后的值也是针对/proc/$PID/oom_score_adj设置的。可以参见&lt;a href=&#34;https://github.com/tinganho/linux-kernel/blob/master/Documentation/feature-removal-schedule.txt&#34;&gt;feature-removal-schedule&lt;/a&gt;这里 171行.&lt;/p&gt;
&lt;p&gt;通过 cat /proc/$PID/oom_score 可以查看进程的得分&lt;/p&gt;
&lt;p&gt;打分算法在这里
&lt;a href=&#34;https://github.com/torvalds/linux/blob/master/mm/oom_kill.c&#34;&gt;https://github.com/torvalds/linux/blob/master/mm/oom_kill.c&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;从上面的 oom_kill.c 代码里可以看到 oom_badness() 给每个进程打分，根据 points 的高低来决定杀哪个进程，这个 points 可以根据 adj 调节，root 权限的进程通常被认为很重要，不应该被轻易杀掉，所以打分的时候可以得到 3% 的优惠（adj -= 30; 分数越低越不容易被杀掉）。我们可以在用户空间通过操作每个进程的 oom_adj 内核参数来决定哪些进程不这么容易被 OOM killer 选中杀掉。比如，如果不想 MySQL 进程被轻易杀掉的话可以找到 MySQL 运行的进程号后，调整 oom_score_adj 为 -15（注意 points 越小越不容易被杀）：范围是从-1000 到 1000,参考&lt;a href=&#34;https://github.com/torvalds/linux/commit/a63d83f427fbce97a6cea0db2e64b0eb8435cd10#include/linux/oom.h&#34;&gt;这里&lt;/a&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>graylog日记管理平台使用的那些坑</title>
      <link>http://blog.leaver.me/2016/12/10/graylog%E6%97%A5%E8%AE%B0%E7%AE%A1%E7%90%86%E5%B9%B3%E5%8F%B0%E4%BD%BF%E7%94%A8%E7%9A%84%E9%82%A3%E4%BA%9B%E5%9D%91/</link>
      <pubDate>Sat, 10 Dec 2016 18:48:17 +0000</pubDate>
      <guid>http://blog.leaver.me/2016/12/10/graylog%E6%97%A5%E8%AE%B0%E7%AE%A1%E7%90%86%E5%B9%B3%E5%8F%B0%E4%BD%BF%E7%94%A8%E7%9A%84%E9%82%A3%E4%BA%9B%E5%9D%91/</guid>
      <description>&lt;h2 id=&#34;前言&#34;&gt;前言&lt;/h2&gt;
&lt;p&gt;最近使用 graylog在部署日志平台的时候,踩到很多&amp;quot;坑&amp;quot;,记录一下&lt;/p&gt;
&lt;h2 id=&#34;日志采集nxlog&#34;&gt;日志采集(nxlog)&lt;/h2&gt;
&lt;h3 id=&#34;1客户端不要做太多的正则计算&#34;&gt;1.客户端不要做太多的正则计算&lt;/h3&gt;
&lt;p&gt;graylog 最早推荐的 nxlog 采集客户端,现在貌似有了 beats 的采集方式,不过我没了解,nxlog 采集的话,需要配置Snippets,就是定义输入,输出,处理器的地方,这个地方, Input 模块是在客户端计算的.所以,一定不要进行太多的正则计算.否则会严重影响客户端的 cpu 资源.降低应用程序的性能.&lt;/p&gt;
&lt;h3 id=&#34;2开多行一定要慎重&#34;&gt;2.开多行一定要慎重&lt;/h3&gt;
&lt;p&gt;graylog 可以通过配置&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&amp;lt;Extension multiline&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    Module    xm_multiline
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    HeaderLine    /^\d{0,2}\/\d{0,2}\/\d{0,4}/
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    EndLine    /^\d{0,2}\/\d{0,2}\/\d{0,4}/
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&amp;lt;/Extension&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&amp;lt;Input pcc-esolutions-log&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    Module            im_file
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    File            &amp;#34;*.log&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    SavePos            TRUE
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    InputType    multiline
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&amp;lt;/Input&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;来实现对于类似错误栈这样的信息,将多行采集成一行,但是一定要注意.如果这个正则写错了,或者其他原因,导致,未能正确匹配.会导致 nxlog 客户端占用内存暴涨.原因是为了实现多行采集,会再客户端内存中保存日志内容,直到匹配到行尾.如果未能正确匹配.会一直保存.导致内存泄露.&lt;/p&gt;
&lt;p&gt;这时候一般伴随着nxlog 的客户端日志中开始打印:
&lt;code&gt;2016-12-05 18:36:47 ERROR oversized string, limit is 1048576 bytes&lt;/code&gt;
这样的信息.表示单条日志超过了1m&lt;/p&gt;
&lt;p&gt;最终有一定几率影响客户端应用,被 oom 所杀.不要问我怎么知道的&amp;hellip;&lt;/p&gt;
&lt;h3 id=&#34;3-日志就是太大怎么办&#34;&gt;3 日志就是太大怎么办.&lt;/h3&gt;
&lt;p&gt;貌似没办法..只能在 Input 配置中.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Exec if $raw_event $raw_event = substr($raw_event, 0, 1040000);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;执行类似的来限制,没有尝试过,参考这里:&lt;a href=&#34;https://github.com/cityindex/LogSearchShipper/blob/master/src/LogsearchShipper.Core/NxLog/NxLogProcessManager.cs&#34;&gt;日志大小超长配置&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;服务端处理graylog&#34;&gt;服务端处理(graylog)&lt;/h2&gt;
&lt;h3 id=&#34;1服务端性能不好的情况下也不要做大量正则&#34;&gt;1.服务端性能不好的情况下也不要做大量正则&lt;/h3&gt;
&lt;p&gt;日志处理这部分主要是说 graylog 自身的处理,graylog 是 cpu 密集型的,在收到了 nxlog 经过少量计算的日志后, graylog 其实还提供了 extrator 的功能来解析字段,当时我因为部署了很多应用的日志采集,为了生成一个统一的索引字段,我在extrator写了一个正则,对于所有的消息,根据这个正则找到一个字段,来作为 key(保存成 no), 可能一个流水号,这样我就可以根据 no:xxx 来查询所有相关的日志了.&lt;/p&gt;
&lt;p&gt;结果这个正则写了以后, graylog 处理性能急剧下降.开始大量积压消息.无法发送给后端的 es 来做处理.在 graylog 的管理页面,能明显看到 in 是几千, out 是几百..很快 node 节点就废了.&lt;/p&gt;
&lt;p&gt;参考:&lt;a href=&#34;https://github.com/Graylog2/graylog2-server/issues/1334&#34;&gt;Very slow process message&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;如果是确定不是 graylog 的问题, output 还是慢,可以尝试&lt;a href=&#34;https://github.com/Graylog2/graylog2-server/issues/2313&#34;&gt;修改输出的并发量来解决&lt;/a&gt;,改改 graylog 配置中的output_batch_size值.&lt;/p&gt;
&lt;h3 id=&#34;2journal如果太多可能导致graylog-状态-dead&#34;&gt;2.journal如果太多,可能导致graylog 状态 dead&lt;/h3&gt;
&lt;p&gt;由于我前面的问题,导致 journal 中保存了太多的日志,这样会导致两个问题,1,启动的时候会尝试吧这些日志全部加载 graylog 服务端的内存中.这时候,如果应用内存不够,直接会启动不了报java 的 oom,&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; 2016-12-04T12:25:36.543+02:00 ERROR [ServiceManager] Service JournalReader [FAILED] has failed in the RUNNING state.
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;java.lang.OutOfMemoryError: Java heap space
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	at java.nio.HeapByteBuffer.&amp;lt;init&amp;gt;(HeapByteBuffer.java:57)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	at java.nio.ByteBuffer.allocate(ByteBuffer.java:331)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	at kafka.log.FileMessageSet$$anon$1.makeNext(FileMessageSet.scala:188)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;或者会报一个数组越界的错误.能解决的办法就是删..
还有就是临时加大 graylog的 jvm 内存设置.&lt;/p&gt;</description>
    </item>
    <item>
      <title>graylog中的字段解析</title>
      <link>http://blog.leaver.me/2016/10/30/graylog%E4%B8%AD%E7%9A%84%E5%AD%97%E6%AE%B5%E8%A7%A3%E6%9E%90/</link>
      <pubDate>Sun, 30 Oct 2016 14:47:01 +0000</pubDate>
      <guid>http://blog.leaver.me/2016/10/30/graylog%E4%B8%AD%E7%9A%84%E5%AD%97%E6%AE%B5%E8%A7%A3%E6%9E%90/</guid>
      <description>&lt;h2 id=&#34;关于字段解析&#34;&gt;关于字段解析&lt;/h2&gt;
&lt;p&gt;一旦 graylog 用在了一个分布式系统上,那么采集的日志格式多种多样,涉及到通过 rules.drl来解析具体的字段.之前的同学的方案是用&lt;a href=&#34;http://www.jboss.org/drools&#34;&gt;drools&lt;/a&gt; 来完成的.通过一个统一的界面,来给用户生成一些正则规则这种.然后自己写了个转换器转成 Drools 的文件.更新到 graylog 的服务器上.然后重启gralog 应用完成.&lt;/p&gt;
&lt;p&gt;实际上, graylog 2之后的版本提供了rules和 pipeline ,这种不需要重启应用,完成这个解析的动作.但是.注意.这个不完善.所以只支持一些简单的语法,无法实现原有的完全转换.所以放弃.&lt;/p&gt;
&lt;p&gt;在此过程中.这个rules 有一个比较强大的功能,自动解析 key value 对.需要添加,但是,需要你的日志文件格式里的 key value有空格,
也就是要求必须是 key=value 这样,不能紧挨着逗号这样的..比如你的打印日志是 key=value,key2=value2.那么久无法解析了..这个暂时没看到比较好的办法.估计要改代码.如果你恰好符合.那最好了.&lt;/p&gt;</description>
    </item>
    <item>
      <title>javOSize:新一代java分析工具</title>
      <link>http://blog.leaver.me/2015/07/04/javosize%E6%96%B0%E4%B8%80%E4%BB%A3java%E5%88%86%E6%9E%90%E5%B7%A5%E5%85%B7/</link>
      <pubDate>Sat, 04 Jul 2015 16:18:57 +0000</pubDate>
      <guid>http://blog.leaver.me/2015/07/04/javosize%E6%96%B0%E4%B8%80%E4%BB%A3java%E5%88%86%E6%9E%90%E5%B7%A5%E5%85%B7/</guid>
      <description>&lt;h2 id=&#34;介绍&#34;&gt;介绍&lt;/h2&gt;
&lt;p&gt;最近看到这么个工具-javOSize .&lt;a href=&#34;http://www.javosize.com/&#34;&gt;官网地址&lt;/a&gt;,去官网看了下.发现介绍很有意思,叫做 the missing sugar for your Java cup.(你的咖啡杯中缺少的那颗糖).于是感受一下这颗糖到底甜不甜&lt;/p&gt;
&lt;h2 id=&#34;安装&#34;&gt;安装&lt;/h2&gt;
&lt;p&gt;安装非常简单,从这里&lt;a href=&#34;http://www.javosize.com/download.html&#34;&gt;下载&lt;/a&gt;,其实完成之后就是一个jar包.非常简单,不用配置啥的.&lt;/p&gt;
&lt;h2 id=&#34;简单使用&#34;&gt;简单使用&lt;/h2&gt;
&lt;p&gt;使用方法就是从先附加到一个java进程上,在linux,上我直接执行
&lt;code&gt;ps aux|grep java &lt;/code&gt;
就能看到了.不废话,得到java进程的pid之后,运行 &lt;code&gt;java -jar javosize-1.0.9.jar pid&lt;/code&gt; pid就是pid的号了. 然后会看到如下图的界面&lt;img alt=&#34;启动页面&#34; loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/javosize_start_up.jpg&#34;&gt;,表示已经附加成功了.先看看都有啥.执行&lt;code&gt;ls&lt;/code&gt;.看到有这么几个命令.我比较单纯,刚开始以为是可执行文件.结果丢人了.看了下官方文档,才知道是目录.进入对应的目录.然后执行&lt;code&gt;ls&lt;/code&gt;就能看到对应的信息了.ls简直不能再万能..改目录支持的所有命令通过在对应的目录执行&lt;code&gt;help&lt;/code&gt;来查看.个人尝试觉得好的功能有.
&lt;img alt=&#34;所有功能目录&#34; loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/javosize_command_ls.jpg&#34;&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;动态修改类
进入CLASSES目录,然后通过执行
&lt;code&gt;ls|grep xxx &lt;/code&gt;
来找到需要修改的类,然后通过vi 就可以直接编辑.编辑完成后,直接保存就会动态替换.文档里说是支持jdk1.7以上,对1.6的支持估计是不行的.没有测试.
&lt;img alt=&#34;修改类demo&#34; loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/javosize_command_class_modify.jpg&#34;&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;无须重启开启jmx
直接挂载之后,执行&lt;code&gt;cd REPOSITORY&lt;/code&gt; 然后执行就好了.
&lt;code&gt;exec START_JMX_SERVER 6666&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;拦截任意代码
可以动态添加类似Spring中的aop方法.用于打印一些调用日志,排查线上问题.进入INTERCEPTOR目录.然后通过如下的方法给某个类的某个方法添加拦截器.
&lt;code&gt;create TickServlet begin mypackage.Hello doGet System.out.println(&amp;quot;Servlet invoked&amp;quot;);&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;检测内存泄漏
进入 REPOSITORY 目录,执行 &lt;code&gt;exec  TOP_FAT_STATIC_VARIABLES  5 com.apache.*&lt;/code&gt;会取出某个包下面占用大小最大的5个类.会很方便找到.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;自动检测性能问题
PROBLEMS 目录专业解决这种问题.进入目录后.执行ls命令.会看到这样的场景&lt;/p&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;Concurrency
Deadlocked: false&lt;/li&gt;
&lt;li&gt;Memory
High GC (&amp;gt;2%): false&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;这里目前只检测了死锁和频繁GC.已经很有用了.至于效果还有待观察.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;无需重启开启GC 日志
和开启jmx一样,进入JMX目录后,执行
&lt;code&gt;exec java.lang:type=Memory.setVerbose(true);&lt;/code&gt;
就开启了.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;更多文档&#34;&gt;更多文档&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&#34;http://www.javosize.com/gettingStarted.html&#34;&gt;官方文档&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;</description>
    </item>
    <item>
      <title>休假停下来反思</title>
      <link>http://blog.leaver.me/2015/07/02/%E4%BC%91%E5%81%87%E5%81%9C%E4%B8%8B%E6%9D%A5%E5%8F%8D%E6%80%9D/</link>
      <pubDate>Thu, 02 Jul 2015 21:20:19 +0000</pubDate>
      <guid>http://blog.leaver.me/2015/07/02/%E4%BC%91%E5%81%87%E5%81%9C%E4%B8%8B%E6%9D%A5%E5%8F%8D%E6%80%9D/</guid>
      <description>&lt;p&gt;项目经过一年终于告一段落.于是有了一个短暂的休假.&lt;/p&gt;
&lt;p&gt;早上照例没能睡好觉.很早就醒了.然后又躺了一会,醒来看了会订阅.然后听了一集&amp;laquo; Mr.Robot &amp;raquo;,感觉还行,再对着字幕看了一遍,以后还是有一些地方理解的有问题.以后还是要多对着无字幕版的美剧去看,才能慢慢听懂更多的,比如今天听到个&lt;code&gt;society&lt;/code&gt;,讲社交焦虑,听到很熟悉,就是没反应过来.学而不用则殆.&lt;/p&gt;
&lt;p&gt;中午给文哥寄了个快递,顺便点个饭.之前的&amp;quot;手艺&amp;quot;应该也已经忘得差不多了.到杭州之后很少做饭,工作太忙.没办法.当然这只是借口.主要还是我懒吧.&lt;/p&gt;
&lt;p&gt;下午按计划好的去浙江图书馆,从大学出来后,虽然书还是看了一些的.但是也再也没有走入图书馆.之前一直想去上海图书馆,结果一直耽搁,今天去浙江图书馆办了个证,借了几本书,看着里面的人自习的自习,借阅的借阅,想想还是有点熟悉的.遗憾的是书相同的份数有点少.想借的几本书都被人借走了,最终借了个**&amp;laquo; 七周七语言 &amp;raquo;&lt;strong&gt;,希望能给自己的编程带来不一样的思考角度.读完后争取写个书评和总结,还借了一本摄影相关的,毕竟拍照是服务妹子的技能.还有个&lt;/strong&gt;&amp;laquo; netty权威指南 &amp;raquo;** ,虽然这本书评价好像不高,但是拿来看看还是可以的.&lt;/p&gt;
&lt;p&gt;下午回家.杭州的下午还挺美的.天气凉爽.只是作为工作狗,没有下午出来的机会吧.&lt;/p&gt;
&lt;p&gt;工作忙,不过在一切自动化的指导下,(马克思没有找我),对linux 的shell操作熟悉度急剧上升,希望能写的更好,让更多的过程自动化,也希望有时间停下来想一想.当时为什么选择写代码,为什么选择当前的职业,知道自己做了什么,知道自己是否进步,想起之前看到的一个话,不知真假,&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;只是因为三轮车好学，你就要一辈子骑三轮车吗？ – Douglas Englebart&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;在职业之外,除了高效做好自己的工作外,也要学习更多的技能,英语,锻炼身体,其他编程相关的.不要安于现状.不要重复自己.还是那句话,不要让你的身份限制你的能力.&lt;/p&gt;</description>
    </item>
    <item>
      <title>SecureRandom第一次生成随机数非常慢</title>
      <link>http://blog.leaver.me/2015/06/30/securerandom%E7%AC%AC%E4%B8%80%E6%AC%A1%E7%94%9F%E6%88%90%E9%9A%8F%E6%9C%BA%E6%95%B0%E9%9D%9E%E5%B8%B8%E6%85%A2/</link>
      <pubDate>Tue, 30 Jun 2015 19:18:36 +0000</pubDate>
      <guid>http://blog.leaver.me/2015/06/30/securerandom%E7%AC%AC%E4%B8%80%E6%AC%A1%E7%94%9F%E6%88%90%E9%9A%8F%E6%9C%BA%E6%95%B0%E9%9D%9E%E5%B8%B8%E6%85%A2/</guid>
      <description>&lt;p&gt;最近发现某个系统在第一次做操作的时候非常缓慢,逐步定位打印更加详细的日志后,发现问题是使用了SecureRandom 这个类来获取随机种子,这个类第一次初始化的时候setSeed的值,非常缓慢,偶尔出现, 排查的过程就是二分,不断定位具体的代码,最终定位&lt;/p&gt;
&lt;p&gt;也就是说根本原因是SecureRandom 这个jre的工具类的问题.具体的bug搜索之后,见&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://bugs.java.com/view_bug.do?bug_id=6521844&#34;&gt;http://bugs.java.com/view_bug.do?bug_id=6521844&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;详细的解释过程:
参考: &lt;a href=&#34;http://www.websina.com/bugzero/faq/securerandom-slowness.html&#34;&gt;http://www.websina.com/bugzero/faq/securerandom-slowness.html&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Q: Why the SecureRandom generateSeed is so slow or even hang on Linux OS?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;A: When you login, it hangs or takes more than a minute to get the response.
If your server is on a Linux OS, the culprit here is SecureRandom generateSeed()
which uses /dev/random to generate the seed. However, /dev/random is a blocking
number generator and if it doesn&amp;rsquo;t have enough random data to provide, it will
simply wait until it does, which forces the JVM to wait. Keyboard and mouse input
as well as disk activity can generate the randomness or entropy needed. But on a
server that lacks such activies, the problem may arise.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;大意是说当使用SecureRandom 的时候默认使用的/dev/random 文件来生成种子,如果没有足够的种子数据,(这些数据是由键盘,鼠标,磁盘活动等产生的,如果没有这些活动,就没有足够的数据)会一直等待,导致jvm卡住,耗费比较长的时候.由于出现问题的这个环境的确是最近没什么操作,而且复现的操作也是隔个一个晚上,重新做业务才会出现.&lt;/p&gt;
&lt;p&gt;文中给出了一种解决方案.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;启动参数添加 -Djava.security.egd=file:/dev/./urandom,验证是可以的.&lt;/li&gt;
&lt;li&gt;修改随机数获取方式&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;这里urandom是啥呢,引用自&lt;a href=&#34;https://zh.wikipedia.org/wiki//dev/random&#34;&gt;维基&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;/dev/random的一个副本是/dev/urandom（“unlocked”，非阻塞的随机数发生器[4]），它会重复使用熵池中的数据以产生伪随机数据。这表示对/dev/urandom的读取操作不会产生阻塞，但其输出的熵可能小于/dev/random的。它可以作为生成较低强度密码的伪随机数生成器，不建议用于生成高强度长期密码。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;类似案例: SecureRandom 导致tomcat启动过慢.
&lt;a href=&#34;https://wiki.apache.org/tomcat/HowTo/FasterStartUp#Entropy_Source&#34;&gt;https://wiki.apache.org/tomcat/HowTo/FasterStartUp#Entropy_Source&lt;/a&gt;
从文中看到说java8已经提升了这个性能.但是一般生产环境的java版本是不会改的.&lt;/p&gt;</description>
    </item>
    <item>
      <title>关于国产的一些想法</title>
      <link>http://blog.leaver.me/2015/05/10/%E5%85%B3%E4%BA%8E%E5%9B%BD%E4%BA%A7%E7%9A%84%E4%B8%80%E4%BA%9B%E6%83%B3%E6%B3%95/</link>
      <pubDate>Sun, 10 May 2015 11:14:53 +0000</pubDate>
      <guid>http://blog.leaver.me/2015/05/10/%E5%85%B3%E4%BA%8E%E5%9B%BD%E4%BA%A7%E7%9A%84%E4%B8%80%E4%BA%9B%E6%83%B3%E6%B3%95/</guid>
      <description>&lt;p&gt;最近也没啥特殊的事情,恰好昨晚魅族云服务当机,导致本地所以联系人丢失,路上想给家里打个电话,没法打,最近又入手了国产入门机械键盘雷柏v500,写点啥呢.
##魅族##&lt;/p&gt;
&lt;p&gt;魅族mx4是我去年11月份入手的.且不说魅族搞饥饿营销.先说说我手机从去年到现在遇到的问题.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;屏幕黄边,刚入手没多久,屏幕左侧出现明显黄边,当时很无语.这质量..不过拿去直接给换了个屏幕,同事的另一台也是,入手后直接屏幕大面积坏点.&lt;/li&gt;
&lt;li&gt;通话质量,我买手机主要就是为了打电话,可是魅族这通话质量,打着打着就没声音了,电流声声音很大.尤其微信的时候.&lt;/li&gt;
&lt;li&gt;固件更新质量,有问题通过更新是好事,但是魅族的工程师每周编出那么多更新log也是蛮拼的.实际上一点问题没解决.老是改计算器,闹钟,比较著名的就是之前有人提到的滑动变点击,用了好几个月最后悄悄修复了.&lt;/li&gt;
&lt;li&gt;安全,之前对魅族的质量还算放心,结果上上周,直接整个出应用中心故障,导致很多用户手机莫名秒开始自动下载软件,自动安装,卸载完成又出现,我当时怀疑是我开了wifi下自动更新,于是关掉了.结果还真是.最后给出个这么说法.&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote&gt;
&lt;p&gt;亲爱的魅友们： Flyme应用中心于4月28日晚间服务器发生故障，部分用户出现应用名称与图标混乱，自动更新安装其他应用等情况。在发现故障之后，2个小时之内已经解决，给大家造成不便我们深表歉意。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;你特么在逗我.你确定是两小时?
5. 云服务,同上,之前很放心的把手机通讯录,联系人之类的都同步到了魅族的云服务上.结果已经出现好几次没法同步,数据本地丢失,找客服说让我再试试.服务器报错你让我再试试..
6. 诚信,我司的价值观之一诚信,现在看来真的很重要,魅族公司品质极差,之前其总设计师杨颜放狠话,说5月份公测flyme4.5 ,其官微更是转发,说不发发手机,结果,所有人等到5月份,前一天先把公告删了.然后重新发了一封,说不公测.品质极其差.&lt;/p&gt;
&lt;p&gt;综上,对魅族手机已经彻底失望.一分钱一分货,就别老是贬低别的厂商,一句话评价就是中看不中用.&lt;/p&gt;
&lt;p&gt;##雷柏v500##&lt;/p&gt;
&lt;p&gt;雷柏v500是我的第一个机械键盘,我是很喜欢80%这种键位的.不喜欢小键盘区域,有了小键盘区域,键盘太大了.于是当时是看好了filco 87圣手,poker2,race2的.最后由于前一个太贵,后两个没有F1,F2这些而告终,毕竟我是要调试程序,写代码的.没有这几个直接的键位那跟咸鱼有什么区别.用了几周下来.简单汇总下&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;便宜,219买的.这价格是真的便宜.而且是80%的键位,雷柏也还是比较出名,之前也买过个鼠标我记得.&lt;/li&gt;
&lt;li&gt;手感,和普通薄膜键盘手感差异很大.手感不错,打字的确有快感.但是你说让爱上打字这个还是有难度的.毕竟.班上多了心情不好.&lt;/li&gt;
&lt;li&gt;不方便,由于是80%,所以键盘小,但是,相当重,好像是有个钢板.非常重,比我的x1笔记本都重,整个人都不好了.自从带去公司,再也不想带回来了.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;综上,整体还是不错的,一分钱一分货,不要夸自己和cherry,flico的距离,差距肯定大大的.但是性价比高.&lt;/p&gt;
&lt;p&gt;##总结##&lt;/p&gt;
&lt;p&gt;总结就是魅族是个坑爹的公司,雷柏键盘还行吧.&lt;/p&gt;</description>
    </item>
    <item>
      <title>一键切换jdk版本</title>
      <link>http://blog.leaver.me/2014/11/07/%E4%B8%80%E9%94%AE%E5%88%87%E6%8D%A2jdk%E7%89%88%E6%9C%AC/</link>
      <pubDate>Fri, 07 Nov 2014 16:08:29 +0000</pubDate>
      <guid>http://blog.leaver.me/2014/11/07/%E4%B8%80%E9%94%AE%E5%88%87%E6%8D%A2jdk%E7%89%88%E6%9C%AC/</guid>
      <description>&lt;p&gt;工作中有时候会切换jdk版本.有时候需要用个64位的.有时候需要用32位的.频繁手动很不方便,参考了一下,写了一个bat脚本,保存为bat,运行即可切换.同理可以改改,运来切换1.7,1.8这样的版本.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    @echo off
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    :init
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    set JAVA_HOME_32=D:\5.Program\Jdk32Home
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    set JAVA_HOME_64=D:\Software\JdkHome
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    :start
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    echo.
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    echo =============================================
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    echo jdk版本列表
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    echo 32 (%JAVA_HOME_32%)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    echo 64 (%JAVA_HOME_64%)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    echo =============================================
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    :select
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    set /p opt=请选择jdk版本：
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    if %opt%==32 (
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      start  /I /WAIT /B wmic ENVIRONMENT where name=&amp;#39;JAVA_HOME&amp;#39; set     VariableValue=&amp;#34;%JAVA_HOME_32%&amp;#34; &amp;amp;gt;nul
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    rem reg add &amp;#34;HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment&amp;#34; /v JAVA_HOME /t reg_sz /d &amp;#34;%JAVA_HOME_32%&amp;#34; /f
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      goto success
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    )
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    if %opt%==64 (
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        start /I /WAIT /B wmic ENVIRONMENT where name=&amp;#39;JAVA_HOME&amp;#39; set VariableValue=&amp;#34;%JAVA_HOME_64%&amp;#34; &amp;amp;gt;nul
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    rem reg add &amp;#34;HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment&amp;#34; /v JAVA_HOME /t reg_sz /d &amp;#34;%JAVA_HOME_64%&amp;#34; /f
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        goto success
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    )
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    echo 选择的版本错误,请重新选择！
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    PAUSE
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    goto start
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    :success
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    echo.
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    echo 设置环境变了成功.
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
    </item>
    <item>
      <title>jenkins相关资料</title>
      <link>http://blog.leaver.me/2014/09/21/jenkins%E7%9B%B8%E5%85%B3%E8%B5%84%E6%96%99/</link>
      <pubDate>Sun, 21 Sep 2014 18:26:48 +0000</pubDate>
      <guid>http://blog.leaver.me/2014/09/21/jenkins%E7%9B%B8%E5%85%B3%E8%B5%84%E6%96%99/</guid>
      <description>&lt;h1 id=&#34;jenkins相关资料&#34;&gt;jenkins相关资料&lt;/h1&gt;
&lt;p&gt;jenkins的前身是hudson,是为了做持续集成测试而诞生的框架.&lt;/p&gt;
&lt;p&gt;简单说就是把代码流配置上去,然后该框架就能根据设定的时间或其他方式不间断的执行测试用例.并给出报告.这样就可以随时掌控代码质量.支持执行shell命令.支持短信通知等等.&lt;/p&gt;
&lt;p&gt;jenkins,首先从&lt;a href=&#34;http://jenkins-ci.org/%E5%AE%98%E6%96%B9%E4%B8%8B%E8%BD%BDwar%E5%8C%85,%E7%84%B6%E5%90%8E%E6%9C%89%E4%B8%A4%E7%A7%8D%E6%96%B9%E5%BC%8F%E5%8F%AF%E4%BB%A5%E6%9C%AC%E5%9C%B0%E9%83%A8%E7%BD%B2,%E4%B8%80%E7%A7%8D%E7%9B%B4%E6%8E%A5%E6%89%A7%E8%A1%8C&#34;&gt;http://jenkins-ci.org/官方下载war包,然后有两种方式可以本地部署,一种直接执行&lt;/a&gt;
&lt;code&gt;java -jar hudson.war&lt;/code&gt;,然后在本地的8080端口访问就可以了.另一种是我们希望部署在容器上,那么可以部署到tomcat,jetty等等.直接拷贝war包到对应的目录即可.&lt;/p&gt;
&lt;p&gt;部署成功后,可以新建job,然后配置svn流,配置build时间,配置一下build之前的动作,配置一下各种命令,执行完成后通知等等就可以了.&lt;/p&gt;
&lt;p&gt;最近因为有个功能感觉通过开发jenkins插件的方式会更加方便,周末大量读了一些文档,能找到的都是helloworl.摸索了一下,已经写出一个小的demo了,后面改进一下,.就ok了.先简单把这个过程中收集的资料整理一下.基本都看过觉得还不错的,官方文档不给力.下周希望可以写完,然后分享出来.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&#34;http://pan.baidu.com/s/1wBp06&#34;&gt;jenkins入门文档&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://pan.baidu.com/s/1pJySAMn&#34;&gt;The hudson book&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://pan.baidu.com/s/1bn8e5sj&#34;&gt;Writing-first-hudson-plugin&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://blog.csdn.net/littleatp2008/article/details/7001793&#34;&gt;Hudson插件开发简介&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://blog.csdn.net/yzhou86/article/details/6874144&#34;&gt;Hudson插件开发入门体验 &lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://jenkins-ci.org/maven-site/jenkins-core/jelly-taglib-ref.html&#34;&gt;插件界面设计设计的各种tag介绍&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wiki.jenkins-ci.org/display/JENKINS/Plugin+tutorial#Plugintutorial-CreatingaNewPlugin&#34;&gt;官方插件开发&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wiki.jenkins-ci.org/display/JENKINS/Basic+guide+to+Jelly+usage+in+Jenkins&#34;&gt;UI开发jelly介绍&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://pan.baidu.com/s/1qWuNags&#34;&gt;jenkins入门(itech)&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;</description>
    </item>
    <item>
      <title>蓝绿发布的整个部署过程</title>
      <link>http://blog.leaver.me/2014/09/14/%E8%93%9D%E7%BB%BF%E5%8F%91%E5%B8%83%E7%9A%84%E6%95%B4%E4%B8%AA%E9%83%A8%E7%BD%B2%E8%BF%87%E7%A8%8B/</link>
      <pubDate>Sun, 14 Sep 2014 10:01:55 +0000</pubDate>
      <guid>http://blog.leaver.me/2014/09/14/%E8%93%9D%E7%BB%BF%E5%8F%91%E5%B8%83%E7%9A%84%E6%95%B4%E4%B8%AA%E9%83%A8%E7%BD%B2%E8%BF%87%E7%A8%8B/</guid>
      <description>&lt;div&gt;
&lt;p&gt;一直听说蓝绿发布,不知道是怎么个过程.&lt;/p&gt;
&lt;p&gt;thanks to&lt;span class=&#34;Apple-converted-space&#34;&gt; &lt;/span&gt;&lt;a href=&#34;http://sunitspace.blogspot.jp/2013/10/blue-green-deployment.html&#34; title=&#34;blue green deploy&#34;&gt;blue-green-deployment&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;蓝绿发布的意义&#34;&gt;蓝绿发布的意义&lt;/h2&gt;
&lt;p&gt;整个发布过程，用户没有感受到任何宕机或者服务重启。&lt;/p&gt;
&lt;h2 id=&#34;蓝绿发布的过程&#34;&gt;蓝绿发布的过程&lt;/h2&gt;
&lt;p&gt;第0步:部署以前的配置
&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/2014/09/Blue-Green-Deployment-for-Zero-Downtime-8.png&#34;&gt;&lt;img alt=&#34;Blue Green Deployment for Zero Downtime (8)&#34; loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/640798001262d94e7dbb6e2e7c58bf456e447775.png&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;第1步: 把绿色集群的状态改为&amp;rsquo;备用&amp;rsquo;. 从负载均衡的池里把这些地址去掉,这样,绿色的集群就不再回接收到来自用户的请求了.转而进入备用负载均衡的池里.
&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/2014/09/Blue-Green-Deployment-for-Zero-Downtime-9.png&#34;&gt;&lt;img alt=&#34;Blue Green Deployment for Zero Downtime (9)&#34; loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/3f51064c7e2863de366d71673e234504f6991048.png&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;第2步:在绿色集群里部署新的代码,直到应用启动成功
&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/2014/09/Blue-Green-Deployment-for-Zero-Downtime-3.png&#34;&gt;&lt;img alt=&#34;Blue Green Deployment for Zero Downtime (3)&#34; loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/d4b51b6ce1a44b5cbaa11da5e8c1aa1d5eeea056.png&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;第3步:使用备用负载均衡简单测试一下备用集群的部署情况.理想状态下是全自动的.&lt;/p&gt;
&lt;p&gt;第4步:把绿色备用集群的状态改成存货,于是进入了存活负载均衡的池里
&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/2014/09/Blue-Green-Deployment-for-Zero-Downtime-4.png&#34;&gt;&lt;img alt=&#34;Blue Green Deployment for Zero Downtime (4)&#34; loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/19b275c22c2540d4cd4c8e6f28f6c90e474fd0ad.png&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;看到 蓝色运行v1版本,绿色运行v2版本,都连接的是相同的数据库.这意味着v2版本也要在老的数据模型上运行.如果数据库有变更,要等到所有的集群升级到新的代码上.&lt;/p&gt;
&lt;p&gt;第5步: 对蓝色集群也进行同样的操作.
&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/2014/09/Blue-Green-Deployment-for-Zero-Downtime-5.png&#34;&gt;&lt;img alt=&#34;Blue Green Deployment for Zero Downtime (5)&#34; loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/d40415aeafd0197ad5408a7d9bcf17e99b2b8d64.png&#34;&gt;&lt;/a&gt;
&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/2014/09/Blue-Green-Deployment-for-Zero-Downtime-6.png&#34;&gt;&lt;img alt=&#34;Blue Green Deployment for Zero Downtime (6)&#34; loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/6d403f2fcd75c1dcacab86ef6447f837018aaf5e.png&#34;&gt;&lt;/a&gt;
最终v2代码完成部署.
&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/2014/09/Blue-Green-Deployment-for-Zero-Downtime-7.png&#34;&gt;&lt;img alt=&#34;Blue Green Deployment for Zero Downtime (7)&#34; loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/6f2592793b9517521e14b4aae09696e30d708ae6.png&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;第6步:根据情况.运行数据库迁移&lt;/p&gt;
&lt;/div&gt;
&amp;nbsp;
&lt;p&gt; &lt;/p&gt;</description>
    </item>
    <item>
      <title>第一次给Spring-Framework贡献代码</title>
      <link>http://blog.leaver.me/2014/08/21/%E7%AC%AC%E4%B8%80%E6%AC%A1%E7%BB%99spring-framework%E8%B4%A1%E7%8C%AE%E4%BB%A3%E7%A0%81/</link>
      <pubDate>Thu, 21 Aug 2014 07:46:26 +0000</pubDate>
      <guid>http://blog.leaver.me/2014/08/21/%E7%AC%AC%E4%B8%80%E6%AC%A1%E7%BB%99spring-framework%E8%B4%A1%E7%8C%AE%E4%BB%A3%E7%A0%81/</guid>
      <description>&lt;p&gt;鲁肃说建议去看Spring框架的代码,之前其实我想看来着,不过一看到还要gradlew,换jdk就好麻烦.这次各种折腾把代码fork下来,然后安装&lt;code&gt;gradlew &lt;/code&gt;,然后转换成eclipse支持的,期间升级了eclipse版本和jdk版本到8.否则会有个方法不支持,&lt;/p&gt;
&lt;p&gt;流程很简单,先fork一下代码,然后自己改好提交上去,再去Spring框架的pull request请求一下.等大牛合并就行了.&lt;/p&gt;
&lt;p&gt;刚开始看测试用例,我当时看到这个方法调用了一个下线的方法.于是改了一下.提交上去之后,**&lt;a href=&#34;https://github.com/sbrannen&#34;&gt;sbrannen&lt;/a&gt; ** 回复说:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;while you&amp;rsquo;re at it, why don&amp;rsquo;t you go ahead fix the related deprecated issues in all of the test classes in &lt;code&gt;spring-jdbc&lt;/code&gt;
于是我把spring-jbdc包下面的几个方法调用都改掉了.记得谁说过,任何事情都不是别人的事情,你发现了你就要去做,不要等着别人去做,不会就去学.于是再次修改提交,sbrannen 问我有没有签&lt;a href=&#34;https://support.springsource.com/spring_committer_signup.&#34;&gt;CLA&lt;/a&gt;,这个坑爹的网站挂了.等了几天,昨天终于ok了.今天代码已经合并.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;截图留念:&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/2014/08/spring.png&#34;&gt;&lt;img alt=&#34;spring&#34; loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/56d25e223f79e6ffdb3162ac7658124363f1d82e.png&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/spring-projects/spring-framework/commits?author=leizhiyuan&#34;&gt;https://github.com/spring-projects/spring-framework/commits?author=leizhiyuan&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;今天要吃两个煎饼果子.&lt;/p&gt;</description>
    </item>
    <item>
      <title>8583报文相关</title>
      <link>http://blog.leaver.me/2014/06/27/8583%E6%8A%A5%E6%96%87%E7%9B%B8%E5%85%B3/</link>
      <pubDate>Fri, 27 Jun 2014 15:28:46 +0000</pubDate>
      <guid>http://blog.leaver.me/2014/06/27/8583%E6%8A%A5%E6%96%87%E7%9B%B8%E5%85%B3/</guid>
      <description>&lt;p&gt;以下是我在学习的时候发现的好的资料，都是非常有帮助的。&lt;/p&gt;
&lt;p&gt;如果你想知道原理，看完下面这篇就会了&lt;/p&gt;
&lt;h2 id=&#34;heading&#34;&gt;&lt;a href=&#34;http://leaver.me/archives/3663.html&#34;&gt;[藏]轻松掌握ISO8583报文协议原理&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;看了原理之后还想知道怎么来的。手工联系一下&lt;/p&gt;
&lt;h2 id=&#34;谈谈8583报文的使用及测试&#34;&gt;&lt;a href=&#34;http://blog.sina.com.cn/s/blog_4c925dca010178pt.html&#34;&gt;谈谈8583报文的使用及测试&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;这篇文章不错&lt;/p&gt;
&lt;p&gt;看完了想写代码了，可以看看这篇文章，基本上不能直接拿来用，但是可以参考实现&lt;/p&gt;
&lt;h2 id=&#34;iso8583报文工具类组装和解析报文&#34;&gt;&lt;span class=&#34;link_title&#34;&gt;&lt;a href=&#34;http://blog.csdn.net/lushuaiyin/article/details/14390725&#34;&gt; ISO8583报文工具类（组装和解析报文） &lt;/a&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p&gt;看完之后这里还有一些补充&lt;/p&gt;
&lt;h2 id=&#34;iso-8583协议的简要说明&#34;&gt;&lt;a href=&#34;http://blog.sina.com.cn/s/blog_6182547f01014p02.html&#34;&gt;ISO-8583协议的简要说明&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;最后，http://www.jpos.org/这个库基本可以用来做这个事情。&lt;/p&gt;
&lt;p&gt;Jimmy写了一个例子非常好，&lt;a href=&#34;http://jimmod.com/blog/2011/07/jimmys-blog-iso-8583-tutorial-build-and-parse-iso-message-using-jpos-library/&#34;&gt;iso-8583-tutorial-build-and-parse-iso-message-using-jpos-library&lt;/a&gt;，至于银联的那个规范搜一下。&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</description>
    </item>
    <item>
      <title>[藏]轻松掌握ISO8583报文协议原理</title>
      <link>http://blog.leaver.me/2014/06/27/%E8%97%8F%E8%BD%BB%E6%9D%BE%E6%8E%8C%E6%8F%A1iso8583%E6%8A%A5%E6%96%87%E5%8D%8F%E8%AE%AE%E5%8E%9F%E7%90%86/</link>
      <pubDate>Fri, 27 Jun 2014 14:30:53 +0000</pubDate>
      <guid>http://blog.leaver.me/2014/06/27/%E8%97%8F%E8%BD%BB%E6%9D%BE%E6%8E%8C%E6%8F%A1iso8583%E6%8A%A5%E6%96%87%E5%8D%8F%E8%AE%AE%E5%8E%9F%E7%90%86/</guid>
      <description>&lt;div id=&#34;article_content&#34; class=&#34;article_content&#34;&gt;
&lt;p&gt;感谢@&lt;span style=&#34;font-size: 14px;&#34;&gt;&lt;span id=&#34;text2969839&#34; class=&#34;javascript&#34;&gt;&lt;a href=&#34;http://blog.csdn.net/lysheng/archive/2005/03/03/309914.aspx&#34;&gt;&lt;span style=&#34;font-family: Verdana;&#34;&gt;lysheng&lt;/span&gt;&lt;/a&gt;&lt;span style=&#34;font-family: Verdana;&#34;&gt;，&lt;/span&gt;&lt;span style=&#34;font-family: Verdana;&#34;&gt;可惜原文已经删除了，因此全文备份。作者提到的&lt;span style=&#34;font-size: 14px;&#34;&gt;&lt;span id=&#34;text2969839&#34; class=&#34;javascript&#34;&gt;&lt;span style=&#34;font-family: Verdana;&#34;&gt;“全面掌握ISO8583报文”和“符合CEN/XFS（即WOSA/XFS）规范的SP编写&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;，这两篇文章我能找到的话也会备份在本博客。&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&#34;font-size: 14px;&#34;&gt;&lt;span id=&#34;text2969839&#34; class=&#34;javascript&#34;&gt;&lt;span style=&#34;font-family: Verdana;&#34;&gt;我 刚进入金融行业时，就知道了IS08583报文协议，我想可能我还没进入这个行业都已经听过了，可知ISO8583的影响力有多大了。最初刚接触它时，确 实对其中的一些细节概念不是很清晰，对有些地方比较迷惑。鉴于此，我想很多同行也必然会经历同样得阶段，所以我写下本文，以便大家能够少走一些弯路。同 时，我在网上&lt;/span&gt;&lt;span style=&#34;font-family: Verdana;&#34;&gt;写下我要写“全面掌握ISO8583报文”和“符合CEN/XFS（即WOSA/XFS）规范的SP编写”两篇文章时，很多人都询问我什么时候能够写出来，可知许多人是需要了解这方面的知识的，即使我时间不是很多，也得尽量将这两篇文章写出来，给需要的人提供一些参考。&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;如果单纯的讲IS08583那些字段的定义，我觉得没有什么意思，标准中已经对每个字段解释的非常详细了，如果你觉得理解英文版的ISO8583规范有些 困难，网上也有同行为我们翻译好的中文版ISO8583规范，所以我的目的是达到阅读本文后能够对ISO8583知其然，亦知其所以然，使以前基本没有接 触它的人也能够达到掌握ISO8583报文规范。&lt;span style=&#34;font-size: 14px;&#34;&gt;
&lt;span style=&#34;font-family: Verdana;&#34;&gt;好了，我们该转入正题了。&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;最开始时，金融系统只有IBM这些大的公司来提供设备，象各种主机与终端等。在各个计算机设备之间，需要交换数据。我们知道数据是通过网络来传送的，而在 网络上传送的数据都是基于0或1这样的二进制数据，如果没有对数据进行编码，则这些数据没有人能够理解，属于没有用的数据。起初的X.25、SDLC以及 现在流行的TCP/IP网络协议都提供底层的通讯编码协议，它们解决了最底层的通讯问题，能够将一串字符从一个地方传送到另一个地方。但是，仅仅传送字符 串是没有太大意义的，怎样来解析字符串代表什么内容是非常重要的，否则传送一些“0123abcd”的字符串也是无用的乱码。&lt;/p&gt;
&lt;p&gt;让我们随着时光回到几十年前的某个时刻，假设我们被推到历史的舞台上，由我们来设计一个通用报文协议，来解决金融系统之间的报文交换，暂且称该协议叫做 ISO8583协议。此时，技术是在不断的前行，当初IBM一支独秀的局面好像已经不妙了，各种大小不一的公司都进入金融行业以求能有所斩获，呈一片百花 齐放的局面。我们怎样来设计一个报文协议，能够将这些如雨后春笋般出现的所有公司都纳入进来，其实也不是一件很简单的事。&lt;/p&gt;
&lt;p&gt;我们还是先一步步的来考虑吧。金融行业其实涉及到的数据内容并不是成千上万，无法统计，恰恰相反，是比较少的。我们都可以在心底数得过来，象交易类型、帐 号、帐户类型、密码、交易金额、交易手续费、日期时间、商户代码、2磁3磁数据、交易序列号等，把所有能够总结出来的都总结起来不过100个左右的数据。 那我们可以首先简单的设计ISO8583，定义128个字段，将所有能够考虑到的类似上面提到的“帐号”等金融数据类型，按照一个顺序排起来，分别对应 128个字段中的一个字段。每个数据类型占固定的长度，这个顺序和长度我们都事先定义好。这样就简单了，要发送一个报文时，就将128个字段按照顺序接起 来，然后将接起来的整串数据包发送出去。&lt;/p&gt;
&lt;p&gt;任何金融软件收到ISO8583包后，直接按照我们定义的规范解包即可，因为整个报文的128个字段从哪一位到哪一位代表什么，大家都知道，只要知道你的 数据包是ISO8583包即可，我们都已经定义好了。比如第1个字段是“交易类型”，长度为4位，第2个字段位是“帐号”，为19位等等。接收方就可以先 取4位，再取接着的19位，依次类推，直到整个数据包128个字段都解完为止。&lt;/p&gt;
&lt;p&gt;其实这种做法真是简单直接，基本上就可以满足需要了。不过我们有几个问题要思考下：
1、 我怎么知道每个字段的数据类型呢，是数字还是字符？
2、 每个传送的报文都把128个字段都传过去，那网络带宽能够承受得了，有时候我可能只需要其中5个字段，结果多收到了123个无用的字段。
3、 如果我某些字段的长度不固定，属于变长怎么办，因为你现在解包是当作数据包每个字段都是固定的，用C语言解包时直接依靠指针取固定长度的一串字符做为一个字段。&lt;/p&gt;
&lt;p&gt;我们来一一解决这些问题。&lt;/p&gt;
&lt;p&gt;第一个问题简单，我在定义ISO8583时除了定义每个字段表示什么，还规定其内容是数字或是字符等即可。考虑可能出现的类型不过有以下几种：字母、数 字、特殊字符、年月日等时间、二进制数据。比如我对128个字段中的“商户类型”字段定义其长度是15，同时定义其类型为字母。再精细点，如果“商户类 型”里面的数据同时包括数字和字母呢？那我们就定义其类型为字母也可，为数字也可，即一个字段可以同时属于多个类型。&lt;/p&gt;
&lt;p&gt;第二个问题稍微复杂点。其本质就是如果我只传128个字段的5个字段，接收方怎么知道我传了哪几个字段给它了。要是我们把剩下的123全部填成0或其他特殊标识，标明该字段不需要使用？这种处理方法没有半点用处，没有解决网络带宽的本质问题，还是要传128个字段。&lt;/p&gt;
&lt;p&gt;换个思路，我在报文前面加上个包头，包头里面包含的信息能够让别人知道只传了5个字段。怎样设计这个包头，可以这样，我们用16个字节，即128个 bit（一个字节等于8bit）来表示128个字段中的某个字段是否存在。每个bit在计算机的二进制里面不是1就是0，如果是1就表示对应的字段在本次 报文中存在，如果是0就是不存在。这样好了，如果别人接收到了ISO8583报文，可以先根据最前面的报文头，就知道紧接着报文头后面的报文有哪些字段， 没有哪些字段了。比如，我要发送5个字段，分别属于128个字段中的第2、3、6、8、9字段，我就可以将128bit的报文头填成 011001011000000000………..，一共128个bit，后面就全是0了。注意其中第2、3、6、8、9位为1，其他都为0。&lt;/p&gt;
&lt;p&gt;有了这个128bit的报文头，我们就可以只发送需要的5个字段了。怎样组织报文？先放上这128bit，即16个字节的头，然后在头后面放2、3、6、 8、9字段，这些字段紧挨在一起，3和6之间也不需要填上4、5这两个字段了。接收方收到这个报文，它会根据128bit的报文头来解包，它自然知道把第 3个字段取出后，就直接在第3字段的后面取第6个字段，每个字段的长度在ISO8583里面都定义好了，很轻松就把数据包解出来了。&lt;/p&gt;
&lt;p&gt;这下好了，为了解决上面的第二问题，我们只是在报文中增加了16个字节的数据，就轻松搞定了，我们把这16个字节称为bit map，即位图，用来表示某个位是否存在。不过我们再稍微优化一下，考虑到很多时候报文不需要128个字段这么多，其一半64个字段都不一定能够用完。那 我可以将报文头由128bit减到64bit，只有在需要的时候才把剩下的64bit放到报文里面，这样报文长度不又少了8个字节吗？&lt;/p&gt;
&lt;p&gt;是个好主意。我们把ISO8583的128个字段中最常见的都放到前64个字段中，那我们可以将处理缩小一倍。这样我一般发送报文时只需发送64bit， 即一个字节的报文头，再加上需要的几个字段就可以了。如果有些报文用到64到128之间的字段呢？这个也好办，我把64bit报文头的第一位bit用来代 表特殊含义，如果该bit为1，则表示64bit后面跟了剩下的64bit报文头；如果第一位bit为0，则表示64bit后面没有跟剩下的64bit报 文头，直接是128个字段中的报文了。那们，接收方会判断一下报头的第一个bit是1还是0，从而知道报文头是64bit还是128bit了，就可以做相 应处理。因为报文头第二个64bit属于有时候有，所以我们叫它Extended bit map扩展位图，相应的报文头最开始的64bit我们叫它Primary bit map主位图。我们直接把扩展位图固定放到128个字段的第一个字段，而主位图每个数据包都有，就强制性放在所有128个字段的前面，并不归入128个字 段中去。&lt;/p&gt;
&lt;p&gt;第三个问题可以考虑这样解决。比如第2个字段是“帐号”，是不定长的，可能有的银行帐号是19位，有的是17位等。我们定ISO8583规范时可以规定第 2个字段是25位，这下足够将19和17的情况都包含进来，但是如果以后出现了30位的怎么办？那我们现在将字段定为100位。以后超过100位怎么办， 况且如果你只有19位的帐号，我们定义了100位，那81位的数据不是浪费了网络的带宽。看来预先定义一个我们认为比较大的位数是不太好的。&lt;/p&gt;
&lt;p&gt;我们这样，对于第2个字段“帐号”，在字段的开头加上“帐号”的长度。比如帐号是0123456789，一共10位，我们变成100123456789， 注意前面多了个10，表示后面的10位为帐号。如果你接触过COM里面的BSTR，应该对这种处理比较熟悉了。接收方收到该字段后，它知道ISO8583 规定第2个字段“帐号”是变长的，所以会先取前面的2位出来，获取其值，此时为长度，然后根据该长度值知道应该拷贝该字段后面哪几位数据，才是真正的帐 号。如果你觉得长度如果只有两位最多只能表示99位长，不太够，我们也定义可以允许前面3位都为长度的变长字段，这样就有999位长，应该够了吧。在规范 里面如果我定义某个字段的属性是“LLVAR”，你注意了，其中的LL表示长度，VAR表示后面的数据，两个LL表示两位长，最大是99，如果是三位就是 “LLLVAR”，最大是999。这样看我们定义的ISO8583规范文档时直接根据这几个字母就理解某个变长字段的意思了。&lt;/p&gt;
&lt;p&gt;该解决的几个问题到这里都解决了，我们来回顾下自己设计的ISO8583规范。其实没有什么，无非是把金融行业可能出现的数据分门别类，排好顺序，接着把 它们连接起来，组成一个报文发送出去而已。其中针对该报文的设计进行了一些优化，引入了bit map位图的概念，也算是一个不错的想法。&lt;/p&gt;
&lt;p&gt;剩下的工作就简单了，我们就直接收集金融行业可能出现的数据字段类型，分成128个字段类型，如果没有到128个这么多就先保留一些下来，另外考虑到有些人有特殊的要求，我们规定可以将128个字段中的几个字段你自己来定义其内容，也算是一种扩展了。&lt;/p&gt;
&lt;p&gt;这样，最后我们就得到了ISO8583规范的那张字段描述表了。想要详细的知道每个字段的含义直接对着表看就可以，比较简单。&lt;/p&gt;
&lt;/div&gt;</description>
    </item>
    <item>
      <title>构建数据库连接的配置方法</title>
      <link>http://blog.leaver.me/2014/04/26/%E6%9E%84%E5%BB%BA%E6%95%B0%E6%8D%AE%E5%BA%93%E8%BF%9E%E6%8E%A5%E7%9A%84%E9%85%8D%E7%BD%AE%E6%96%B9%E6%B3%95/</link>
      <pubDate>Sat, 26 Apr 2014 16:56:41 +0000</pubDate>
      <guid>http://blog.leaver.me/2014/04/26/%E6%9E%84%E5%BB%BA%E6%95%B0%E6%8D%AE%E5%BA%93%E8%BF%9E%E6%8E%A5%E7%9A%84%E9%85%8D%E7%BD%AE%E6%96%B9%E6%B3%95/</guid>
      <description>&lt;p&gt;以前我在写数据库连接的时候，都是在文件里写死的，或者一个简单地配置文件，只有一个数据库连接嘛，但是最近写一个测试工具的时候，需要很多数据库，而且有些还有分库规则，于是查找资料，完善了两个类，和xml的定义规则，分享出来。仅供参考，有任何指教请回复。不胜感谢&lt;/p&gt;
&lt;p&gt;首先xml的配置格式定义如下&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;&amp;lt;?xml version=&#34;1.0&#34; encoding=&#34;UTF-8&#34;?&amp;gt;  
&amp;lt;config&amp;gt;  
	 &amp;lt;db-info&amp;gt;
        &amp;lt;id&amp;gt;oracle-test&amp;lt;/id&amp;gt;  
        &amp;lt;driver-name&amp;gt;oracle.jdbc.driver.OracleDriver&amp;lt;/driver-name&amp;gt;  
        &amp;lt;url&amp;gt;jdbc:oracle:thin:@127.0.0.1:1521:test&amp;lt;/url&amp;gt;  
        &amp;lt;user-name&amp;gt;admin&amp;lt;/user-name&amp;gt;  
        &amp;lt;password&amp;gt;admin&amp;lt;/password&amp;gt;  
    &amp;lt;/db-info&amp;gt;  
	 &amp;lt;db-info&amp;gt;
        &amp;lt;id&amp;gt;mysql-test&amp;lt;/id&amp;gt;  
        &amp;lt;driver-name&amp;gt;com.mysql.jdbc.Driver&amp;lt;/driver-name&amp;gt;  
        &amp;lt;url&amp;gt;jdbc:mysql://127.0.0.1:3306&amp;lt;/url&amp;gt;  
        &amp;lt;user-name&amp;gt;root&amp;lt;/user-name&amp;gt;  
        &amp;lt;password&amp;gt;root&amp;lt;/password&amp;gt;  
    &amp;lt;/db-info&amp;gt;
&amp;lt;/config&amp;gt;&lt;/pre&gt;
&lt;p&gt;然后我们有XmlConfigReader类，用来读取这个配置文件，并且返回对应的jdbcConfig对象。&lt;/p&gt;
&lt;p&gt;这个对象就是一个model类，对应xml的属性&lt;/p&gt;
&lt;p&gt;然后我们的DBUtil类会调用XmlConfigReader，通用的一般是传个&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt; &amp;lt;id&amp;gt;mysql-test&amp;lt;/id&amp;gt;&lt;/pre&gt;
&lt;p&gt;值，然后XmlConfigReader来读取返回，对象，然后在DBUtil里用这个对象得知来构造连接，我添加了一个简单的方法&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true &#34;&gt;public static Connection getConnection(String dbId,String dbName) throws ClassNotFoundException
	{
		Connection conn = null;

		try {
			//新建jdbc配置类。
			XmlConfigReader xcr=new XmlConfigReader();
			JdbcConfig jdbcconfig = xcr.getConnection(dbId,dbName);
			Class.forName(jdbcconfig.getDriverName());
			//取得连接对象。
			conn = DriverManager.getConnection(jdbcconfig.getUrl(), jdbcconfig.getUserName(), jdbcconfig.getPassword());

		} catch (ClassNotFoundException e) {
			// 抛出 exception
			e.printStackTrace();
		}catch(SQLException e)
		{
			e.printStackTrace();
		}

		return conn;

	}&lt;/pre&gt;
&lt;p&gt;就是多传一个数据库名&lt;/p&gt;
&lt;p&gt;然后XmlConfigReader哩对应有这个方法&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;//分库分表使用
		public  JdbcConfig getConnection(String dbId,String dbName) {
			SAXReader reader = new SAXReader();

			// 拿到当前线程。
			InputStream in = Thread.currentThread().getContextClassLoader()
					.getResourceAsStream(&#34;sys-config.xml&#34;);
			try {
				Document doc = reader.read(in);
				Element rootElt = doc.getRootElement(); // 获取根节点
				Iterator&amp;lt;?&amp;gt; iter = rootElt.elementIterator(&#34;db-info&#34;);
				while (iter.hasNext()) {
					Element recordEle = (Element) iter.next();
					String title: = recordEle.elementTextTrim(&#34;id&#34;);
					if (title.equalsIgnoreCase(dbId)) {
						jdbcconfig.setDriverName(recordEle
								.elementTextTrim(&#34;driver-name&#34;));
						jdbcconfig.setUrl(recordEle.elementTextTrim(&#34;url&#34;)+&#34;/&#34;+dbName);
						jdbcconfig.setUserName(recordEle
								.elementTextTrim(&#34;user-name&#34;));
						jdbcconfig.setPassword(recordEle
								.elementTextTrim(&#34;password&#34;));
					}
				}

			} catch (DocumentException e) {
				// 打印错误
				e.printStackTrace();
			}
			return jdbcconfig;

		}&lt;/pre&gt;
&lt;p&gt; &lt;/p&gt;</description>
    </item>
    <item>
      <title>Google输入法和Java不兼容</title>
      <link>http://blog.leaver.me/2014/03/29/google%E8%BE%93%E5%85%A5%E6%B3%95%E5%92%8Cjava%E4%B8%8D%E5%85%BC%E5%AE%B9/</link>
      <pubDate>Sat, 29 Mar 2014 12:13:25 +0000</pubDate>
      <guid>http://blog.leaver.me/2014/03/29/google%E8%BE%93%E5%85%A5%E6%B3%95%E5%92%8Cjava%E4%B8%8D%E5%85%BC%E5%AE%B9/</guid>
      <description>&lt;p&gt;一直发现自己写的Swing界面无法关闭，症状是点击了界面的关闭按钮后程序会卡住，然后点击无响应最后就挂掉了。&lt;/p&gt;
&lt;p&gt;最开始以为是自己的资源没释放，但是没理由呀，应该在关闭的时候会自动释放，而且改了代码也没用。&lt;/p&gt;
&lt;p&gt;今天再执行另一个Swing的时候，eclipse报错了&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;#
# A fatal error has been detected by the Java Runtime Environment:
#
#  EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x6d986cc3, pid=700, tid=2280
#
# JRE version: Java(TM) SE Runtime Environment (7.0_45-b18) (build 1.7.0_45-b18)
# Java VM: Java HotSpot(TM) Client VM (24.45-b08 mixed mode, sharing windows-x86 )
# Problematic frame:
# C  [GOOGLEPINYIN2.IME+0x96cc3]
#
# Failed to write core dump. Minidumps are not enabled by default on client versions of Windows&lt;/pre&gt;
&lt;p&gt;看问题说是Google拼音输入法冲突，导致访问禁止，在PChunder里卸载掉javaw的Google拼音模块，javaw马上就关闭了，于是修改系统的默认输入法为其他输入法问题解决。&lt;/p&gt;
&lt;p&gt;我了个去，纠结了我好长时间。我说为啥公司电脑和我的电脑都会关不了呢&amp;hellip;&lt;/p&gt;</description>
    </item>
    <item>
      <title>linux编写定时任务</title>
      <link>http://blog.leaver.me/2014/03/29/linux%E7%BC%96%E5%86%99%E5%AE%9A%E6%97%B6%E4%BB%BB%E5%8A%A1/</link>
      <pubDate>Sat, 29 Mar 2014 10:31:31 +0000</pubDate>
      <guid>http://blog.leaver.me/2014/03/29/linux%E7%BC%96%E5%86%99%E5%AE%9A%E6%97%B6%E4%BB%BB%E5%8A%A1/</guid>
      <description>&lt;p&gt;linux中定时任务用来执行一些周期性的自动化的任务，比如有些人可能用来定期备份，也可能是定期检查一下特殊文件的签名，如果不一致，就报警，检测入侵。&lt;/p&gt;
&lt;p&gt;cron是linux下的定时执行工具&lt;/p&gt;
&lt;p&gt;这个工具的几个命令是这样的&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;/sbin/service crond start //启动服务

/sbin/service crond stop //关闭服务

/sbin/service crond restart //重启服务

/sbin/service crond reload //重新载入配置&lt;/pre&gt;
&lt;p&gt;注意，这几个服务都是要以root权限才能运行的，很多时候，只要我们可能只是一个低权限的用户，那么我们要执行一些定时任务的时候，可以这样做&lt;/p&gt;
&lt;p&gt;直接通过这个命令来编辑，无需root用户&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;crontab&lt;/pre&gt;
&lt;p&gt;首先添加定时任务&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;crontab -e&lt;/pre&gt;
&lt;p&gt;打开之后按如下的格式编写&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;*/1 * * * * ls &amp;gt;&amp;gt; /tmp/ls.txt&lt;/pre&gt;
&lt;p&gt;从左到右一次表示&lt;/p&gt;
&lt;p&gt;分钟 一小时的第几分 0-59
小时 一天的第几小时 0-23
日期 一个月的的第几天 1-31
月份 一年的第几个月 1-12
周几 一周的第几天 0-6&lt;/p&gt;
&lt;p&gt;/1表示每一天 /2表示每两天，直接*的话就表示每天/每小时这样&lt;/p&gt;
&lt;p&gt;写完之后，wq保存退出&lt;/p&gt;
&lt;p&gt;然后&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;crontab -l //列出当前的所有调度任务&lt;/pre&gt;
&lt;p&gt;可以看到自己的定时任务了，然后就不要做什么操作了，操作系统定时会读取配置的，编辑完成之后，我们的定时任务过一会就会生效了。&lt;/p&gt;
&lt;p&gt;有时候，可能还要把结果信息和一些错误信息也写入&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;30 5 * * * ls &amp;gt;&amp;gt;/result/test 2&amp;gt;&amp;amp;1

注：2&amp;gt;&amp;amp;1 表示执行结果及错误信息。&lt;/pre&gt;
&lt;p&gt;这里就是说明天的5点50执行一次ls命令，并把结果追加到文件&lt;/p&gt;
&lt;p&gt;如果我想每天5点30和17点30都执行一次呢，使用逗号隔开就行了&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;30 5,17 * * * ls &amp;gt;&amp;gt;/result/test 2&amp;gt;&amp;amp;1&lt;/pre&gt;
&lt;p&gt;如果是某个时间段呢&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;30 5-17 * * * ls &amp;gt;&amp;gt;/result/test 2&amp;gt;&amp;amp;1&lt;/pre&gt;
&lt;p&gt;这样5-17点钟的每个30分到会执行&lt;/p&gt;
&lt;p&gt;如果是一些特殊的时间点，那么有更简单的方法，比如每月0点或者每天0点执行一次&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;@monthly ls &amp;gt;&amp;gt;/result/test 2&amp;gt;&amp;amp;1&lt;/pre&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;@daily ls &amp;gt;&amp;gt;/result/test 2&amp;gt;&amp;amp;1&lt;/pre&gt;
&lt;p&gt;使用如上的关键字&lt;/p&gt;</description>
    </item>
    <item>
      <title>linux的CPU负载均值</title>
      <link>http://blog.leaver.me/2014/03/08/linux%E7%9A%84cpu%E8%B4%9F%E8%BD%BD%E5%9D%87%E5%80%BC/</link>
      <pubDate>Sat, 08 Mar 2014 17:19:30 +0000</pubDate>
      <guid>http://blog.leaver.me/2014/03/08/linux%E7%9A%84cpu%E8%B4%9F%E8%BD%BD%E5%9D%87%E5%80%BC/</guid>
      <description>&lt;p&gt;当运行在Linux上的程序有问题之后，我们通常要看一下当前CPU和内存的使用情况来分析一下问题&lt;/p&gt;
&lt;p&gt;对于CPU的使用率，通常用Load Average，也就是负载均值来度量&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;负载均值是啥？&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;负载是啥，负载就是对CPU使用率的一个计量，均值就是某一段时间内的一个平均值。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;怎么看啊？&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;直接输入w命令&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;# w
20:02:51 up 23 days, 8:10, 2 users, load average: 1.20, 1.28, 1.29&lt;/pre&gt;
&lt;p&gt;第一位1.20：表示最近1分钟平均负载
第二位1.28：表示最近5分钟平均负载
第三位1.29：表示最近15分钟平均负载&lt;/p&gt;
&lt;p&gt;或者uptime命令&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;$ uptime
09:50:21 up 200 days, 15:07, 1 user, load average: 0.27, 0.33, 0.37&lt;/pre&gt;
&lt;p&gt;我们一般认为0.00表示无负载，可以理解为CPU空闲，1.00表示CPU满负载，但是注意，1.00是对于单cpu来说的，也就是说，如果是双核，那么这个满负载显示的值应该是2.00，以此类推。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;怎么看我是几核啊&lt;/strong&gt;&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true &#34;&gt;grep &#39;model name&#39; /proc/cpuinfo | wc -l&lt;/pre&gt;
&lt;p&gt;通过统计cpuinfo的model name信息来算的&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;这三个值哪个重要？&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;一分钟内突然负载很大没关系，当然如果你要排查也没人拦着，如果15分钟的负载均值超过cpu的数目，就要关注了。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;那什么就是理想负载呢？&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;以单个cpu为例，1.00表示cpu满负载运行，没有一点点浪费，实际上，有些管理员认为0.7也许是理想的状态。如果你的经常超过0.7，那么最好查一查。&lt;/p&gt;</description>
    </item>
    <item>
      <title>eclipse管理多个workplace</title>
      <link>http://blog.leaver.me/2014/03/08/eclipse%E7%AE%A1%E7%90%86%E5%A4%9A%E4%B8%AAworkplace/</link>
      <pubDate>Sat, 08 Mar 2014 16:34:34 +0000</pubDate>
      <guid>http://blog.leaver.me/2014/03/08/eclipse%E7%AE%A1%E7%90%86%E5%A4%9A%E4%B8%AAworkplace/</guid>
      <description>&lt;p&gt;由于eclipse用的比较多，管理多个workplace很麻烦，经常需要打开以后再切换，简单介绍个方法。&lt;/p&gt;
&lt;p&gt;一&lt;/p&gt;
&lt;p&gt;1.进入Eclipse的安装目录，鼠标点击eclipse.exe，右键菜单&amp;ndash;&amp;gt;发送到&amp;ndash;&amp;gt;桌面快捷方式&lt;/p&gt;
&lt;p&gt;2.到桌面上找到“eclipse.exe - 快捷方式”，鼠标右键点击查看属性，弹出菜单中选择“快捷方式”标签，然后在“目标”中增加内容：-data e:\workspace，保存后即可&lt;/p&gt;
&lt;p&gt;3.双击这个快捷方式，eclipse就会使用e:\workspace作为工作空间启动。&lt;/p&gt;
&lt;p&gt;这样你多复制几个，就好了。&lt;/p&gt;
&lt;p&gt;二&lt;/p&gt;
&lt;p&gt;1.找个目录，新建一个文件夹，名称为workspace_aaa&lt;/p&gt;
&lt;p&gt;2.然后在当前目录下新建一个txt文件&lt;/p&gt;
&lt;p&gt;3.输入内容为：&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;start E:\eclipse\eclipse.exe -data workspace1&lt;/pre&gt;
&lt;p&gt;说明：前面是eclipse的路径，中间加上&amp;quot;-data” ，后面为工作空间的路径，start要有，不然打开eclipse之后，命令行窗口不会自动消失的，很是碍眼。&lt;/p&gt;
&lt;p&gt;4.将这个txt保存为workspace1.bat&lt;/p&gt;
&lt;p&gt;5.双击这个workspace1.bat，eclipse就会使用workspace1.bat 作为工作空间启动。&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;对launchy党来说，新建个目录，然后创建好多个bat，以后直接快速启动真是太方便了&lt;/p&gt;</description>
    </item>
    <item>
      <title>[译]使用Mockito简单mock入门</title>
      <link>http://blog.leaver.me/2014/03/01/%E8%AF%91%E4%BD%BF%E7%94%A8mockito%E7%AE%80%E5%8D%95mock%E5%85%A5%E9%97%A8/</link>
      <pubDate>Sat, 01 Mar 2014 10:57:33 +0000</pubDate>
      <guid>http://blog.leaver.me/2014/03/01/%E8%AF%91%E4%BD%BF%E7%94%A8mockito%E7%AE%80%E5%8D%95mock%E5%85%A5%E9%97%A8/</guid>
      <description>&lt;p&gt;我们在写单元测试的时候，面临的一个挑战就是要测试的内容总是依赖于其他组件，要是我们还得先配置好其他组件，未免有点不如意，那么我们可以使用Mocks来代替那些依赖的组件&lt;/p&gt;
&lt;p&gt;本文问了展示这个过程，我会创建一个DAL，数据访问层，这是一个类，提供了一个通用的api来访问和修改数据仓库的数据，然后，我们要测试这个api，而不用配置连接某个本地的数据库，，或者一个远程的数据库，或者是一个文件系统，反正就是任何放数据的东西，DAL层的好处就是隔离开了数据访问和应用程序代码&lt;/p&gt;
&lt;p&gt;首先使用maven来创建一个工程&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;mvn archetype:generate -DgroupId=info.sanaulla -DartifactId=MockitoDemo -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false&lt;/pre&gt;
&lt;p&gt;执行之后，本地生成MockitoDemo 文件夹，然后整个工程的目录结构与生成好了。&lt;/p&gt;
&lt;p&gt;然后，我们写这样一个model类，表示book类型&lt;/p&gt;
&lt;pre class=&#34;lang:java decode:true&#34;&gt;package info.sanaulla.models;

import java.util.List;

/**
* Model class for the book details.
*/
public class Book {

  private String isbn;
  private String title;
  private List&amp;lt;String&amp;gt; authors;
  private String publication;
  private Integer yearOfPublication;
  private Integer numberOfPages;
  private String image;

  public Book(String isbn,
              String title,
              List&amp;lt;String&amp;gt; authors,
              String publication,
              Integer yearOfPublication,
              Integer numberOfPages,
              String image){

    this.isbn = isbn;
    this.title: = title;
    this.authors = authors;
    this.publication = publication;
    this.yearOfPublication = yearOfPublication;
    this.numberOfPages = numberOfPages;
    this.image = image;

  }

  public String getIsbn() {
    return isbn;
  }

  public String getTitle() {
    return title;
  }

  public List&amp;lt;String&amp;gt; getAuthors() {
    return authors;
  }

  public String getPublication() {
    return publication;
  }

  public Integer getYearOfPublication() {
    return yearOfPublication;
  }

  public Integer getNumberOfPages() {
    return numberOfPages;
  }

  public String getImage() {
    return image;
  }
}&lt;/pre&gt;
&lt;p&gt;然后，我们访问Book model的DAL类会如下&lt;/p&gt;
&lt;pre class=&#34;lang:java decode:true&#34;&gt;package info.sanaulla.dal;

import info.sanaulla.models.Book;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

/**
* API layer for persisting and retrieving the Book objects.
*/
public class BookDAL {

  private static BookDAL bookDAL = new BookDAL();

  public List&amp;lt;Book&amp;gt; getAllBooks(){
      return Collections.EMPTY_LIST;
  }

  public Book getBook(String isbn){
      return null;
  }

  public String addBook(Book book){
      return book.getIsbn();
  }

  public String updateBook(Book book){
      return book.getIsbn();
  }

  public static BookDAL getInstance(){
      return bookDAL;
  }
}&lt;/pre&gt;
&lt;p&gt;DAL层现在还没啥功能，我们要通过TDD来测试，实际中，DAL可能和ORM来交互，也可能和数据库API交互，但是我们设计DAL的时候，不用关心&lt;/p&gt;</description>
    </item>
    <item>
      <title>尝试JavaFX开发</title>
      <link>http://blog.leaver.me/2014/02/11/%E5%B0%9D%E8%AF%95javafx%E5%BC%80%E5%8F%91/</link>
      <pubDate>Tue, 11 Feb 2014 20:40:12 +0000</pubDate>
      <guid>http://blog.leaver.me/2014/02/11/%E5%B0%9D%E8%AF%95javafx%E5%BC%80%E5%8F%91/</guid>
      <description>&lt;p&gt;曾经有报道说JavaFX将使java在桌面开发上大有作为，感觉好像是很高端的样子，今天尝试了一下，界面对于自用的工具来说，本来也不多重要，只是一个简单的尝试&lt;/p&gt;
&lt;p&gt;简单说下大致的步骤和一些思路，可能有错误。&lt;/p&gt;
&lt;p&gt;javafx需要sdk支持，java7之后的都有的。设计思路是数据和代码分离，界面通过xml或json数据来描述，这样就把业务逻辑代码和界面实现代码分开了&lt;/p&gt;
&lt;p&gt;一个简单的开发过程应该是这样的&lt;/p&gt;
&lt;p&gt;1.使用JavaFX Scene Builder来绘制界面，保存为xml/json格式&lt;/p&gt;
&lt;p&gt;画的话没啥要说的，了解一下基本的整体概念就行。&lt;/p&gt;
&lt;p&gt;2.在eclipse里新建工程，可以是普通工程，将1中的文件放到资源目录，在代码里加载，然后界面就加载成功了。&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;Node topNode = FXMLLoader.load(AFI.class.getResource(&#34;/afimain.fxml&#34;));&lt;/pre&gt;
&lt;p&gt;逻辑代码，比如一个简单的按钮事件可以通过&lt;/p&gt;
&lt;pre&gt;Node node = topNode.lookup(&#34;#paneRightBottom&#34;);&lt;/pre&gt;
&lt;p&gt;来查找到id为paneRightBottom的元素，然后就可以通过对node添加事件监听器来完成一些功能了&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;主要想说的是：&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;JavaFX和WPF其实思路是一模一样的，恰好WPF我也用过，感觉两个都没搞起来，虽然界面炫，然后我去维基看了下：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;该产品于2007年5月在JavaOne大会上首次对外公布。JavaFX技术主要应用于创建Rich Internet application（&lt;a href=&#34;http://zh.wikipedia.org/wiki/RIA&#34; title=&#34;RIA&#34;&gt;RIAs&lt;/a&gt;）。JavaFX期望能够在桌面应用的开发领域与Adobe公司的AIR、&lt;a href=&#34;http://zh.wikipedia.org/w/index.php?title=OpenLaszlo&amp;amp;action=edit&amp;amp;redlink=1&#34; title=&#34;OpenLaszlo（页面不存在）&#34;&gt;OpenLaszlo&lt;/a&gt;以及&lt;a href=&#34;http://zh.wikipedia.org/wiki/%E5%BE%AE%E8%BD%AF&#34; title=&#34;微软&#34;&gt;微软&lt;/a&gt;公司的&lt;a href=&#34;http://zh.wikipedia.org/wiki/Silverlight&#34; title=&#34;Silverlight&#34;&gt;Silverlight&lt;/a&gt;相竞争
已经7年了，用户数应该是非常少的，&lt;strong&gt;成熟的商业型产品也没几个&lt;/strong&gt;，在尝试的过程中，我在stackoverflow，以及一些很不错的java博客上，大量查找基本也没有太多的信息，都是一些很浅的应用，包括stackoverflow上的回答数，基本还是能反映出来的，主要应用于RIA，而当前RIA已经出html5的天下了。SL早都不更新了，这种坑爹的所谓新技术。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;Oracle还是好好把Swing搞好吧。。不建议尝试。&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</description>
    </item>
    <item>
      <title>[笔记]写代码遇到的一些问题汇总下</title>
      <link>http://blog.leaver.me/2014/02/08/%E7%AC%94%E8%AE%B0%E5%86%99%E4%BB%A3%E7%A0%81%E9%81%87%E5%88%B0%E7%9A%84%E4%B8%80%E4%BA%9B%E9%97%AE%E9%A2%98%E6%B1%87%E6%80%BB%E4%B8%8B/</link>
      <pubDate>Sat, 08 Feb 2014 11:06:51 +0000</pubDate>
      <guid>http://blog.leaver.me/2014/02/08/%E7%AC%94%E8%AE%B0%E5%86%99%E4%BB%A3%E7%A0%81%E9%81%87%E5%88%B0%E7%9A%84%E4%B8%80%E4%BA%9B%E9%97%AE%E9%A2%98%E6%B1%87%E6%80%BB%E4%B8%8B/</guid>
      <description>&lt;p&gt;本篇是用来填&lt;a href=&#34;http://leaver.me/archives/3454.html&#34;&gt;上一篇 &lt;/a&gt;挖下的坑的。&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;1.java调用webservice&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;有一些已有的webservice服务，由xfire生成发布，有些有参数，有些无参数，无参数的直接我直接使用org.codehaus.xfire这个包里的Client来动态生成客户端。然后调用就可以了。非常简单&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;Client client = null;
		try {
			client = new Client(
					new URL(
							&#34;http://leaver.me/testService?wsdl&#34;));
			client.invoke(&#34;refreshAllCache&#34;, new Object[0]);

		} catch (MalformedURLException e) {

			e.printStackTrace();
		} catch (Exception e) {

			e.printStackTrace();
		}&lt;/pre&gt;
&lt;p&gt;但对于有参的，且是服务器自定义的类作为参数的时候，实在是搞不定。。不管是把自定义的类放到本地，包名一致，在invoke的时候生成这个对象还是其他什么方法。都无法完成。&lt;/p&gt;
&lt;p&gt;最终换了直接发送soap报文来完成。dirty hack啊。如果你有一些好的方法希望不吝赐教。&lt;/p&gt;
&lt;p&gt;解决方案来源自&lt;a href=&#34;http://stackoverflow.com/a/15942217/764869&#34;&gt;stackoverflow&lt;/a&gt;，因为stackoverflow现在国内好像有时候打不开。因此把代码贴过来。有疑问的话留言讨论。&lt;/p&gt;
&lt;pre class=&#34;lang:java decode:true&#34;&gt;import javax.xml.soap.*;
import javax.xml.transform.*;
import javax.xml.transform.stream.*;

public class SOAPClientSAAJ {

    /**
     * Starting point for the SAAJ - SOAP Client Testing
     */
    public static void main(String args[]) {
        try {
            // Create SOAP Connection
            SOAPConnectionFactory soapConnectionFactory = SOAPConnectionFactory.newInstance();
            SOAPConnection soapConnection = soapConnectionFactory.createConnection();

            // Send SOAP Message to SOAP Server
            String url = &#34;http://ws.cdyne.com/emailverify/Emailvernotestemail.asmx&#34;;
            SOAPMessage soapResponse = soapConnection.call(createSOAPRequest(), url);

            // Process the SOAP Response
            printSOAPResponse(soapResponse);

            soapConnection.close();
        } catch (Exception e) {
            System.err.println(&#34;Error occurred while sending SOAP Request to Server&#34;);
            e.printStackTrace();
        }
    }

    private static SOAPMessage createSOAPRequest() throws Exception {
        MessageFactory messageFactory = MessageFactory.newInstance();
        SOAPMessage soapMessage = messageFactory.createMessage();
        SOAPPart soapPart = soapMessage.getSOAPPart();

        String serverURI = &#34;http://ws.cdyne.com/&#34;;

        // SOAP Envelope
        SOAPEnvelope envelope = soapPart.getEnvelope();
        envelope.addNamespaceDeclaration(&#34;example&#34;, serverURI);

        /*
        Constructed SOAP Request Message:
        &amp;lt;SOAP-ENV:Envelope xmlns:SOAP-ENV=&#34;http://schemas.xmlsoap.org/soap/envelope/&#34; xmlns:example=&#34;http://ws.cdyne.com/&#34;&amp;gt;
            &amp;lt;SOAP-ENV:Header/&amp;gt;
            &amp;lt;SOAP-ENV:Body&amp;gt;
                &amp;lt;example:VerifyEmail&amp;gt;
                    &amp;lt;example:email&amp;gt;mutantninja@gmail.com&amp;lt;/example:email&amp;gt;
                    &amp;lt;example:LicenseKey&amp;gt;123&amp;lt;/example:LicenseKey&amp;gt;
                &amp;lt;/example:VerifyEmail&amp;gt;
            &amp;lt;/SOAP-ENV:Body&amp;gt;
        &amp;lt;/SOAP-ENV:Envelope&amp;gt;
         */

        // SOAP Body
        SOAPBody soapBody = envelope.getBody();
        SOAPElement soapBodyElem = soapBody.addChildElement(&#34;VerifyEmail&#34;, &#34;example&#34;);
        SOAPElement soapBodyElem1 = soapBodyElem.addChildElement(&#34;email&#34;, &#34;example&#34;);
        soapBodyElem1.addTextNode(&#34;mutantninja@gmail.com&#34;);
        SOAPElement soapBodyElem2 = soapBodyElem.addChildElement(&#34;LicenseKey&#34;, &#34;example&#34;);
        soapBodyElem2.addTextNode(&#34;123&#34;);

        MimeHeaders headers = soapMessage.getMimeHeaders();
        headers.addHeader(&#34;SOAPAction&#34;, serverURI  + &#34;VerifyEmail&#34;);

        soapMessage.saveChanges();

        /* Print the request message */
        System.out.print(&#34;Request SOAP Message = &#34;);
        soapMessage.writeTo(System.out);
        System.out.println();

        return soapMessage;
    }

    /**
     * Method used to print the SOAP Response
     */
    private static void printSOAPResponse(SOAPMessage soapResponse) throws Exception {
        TransformerFactory transformerFactory = TransformerFactory.newInstance();
        Transformer transformer = transformerFactory.newTransformer();
        Source sourceContent = soapResponse.getSOAPPart().getContent();
        System.out.print(&#34;\nResponse SOAP Message = &#34;);
        StreamResult result = new StreamResult(System.out);
        transformer.transform(sourceContent, result);
    }

}&lt;/pre&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;2.Access restriction on class due to restriction on required library rt.jar? 报错&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>[藏]跨行清算系统的实现原理</title>
      <link>http://blog.leaver.me/2013/12/14/%E8%97%8F%E8%B7%A8%E8%A1%8C%E6%B8%85%E7%AE%97%E7%B3%BB%E7%BB%9F%E7%9A%84%E5%AE%9E%E7%8E%B0%E5%8E%9F%E7%90%86/</link>
      <pubDate>Sat, 14 Dec 2013 18:24:12 +0000</pubDate>
      <guid>http://blog.leaver.me/2013/12/14/%E8%97%8F%E8%B7%A8%E8%A1%8C%E6%B8%85%E7%AE%97%E7%B3%BB%E7%BB%9F%E7%9A%84%E5%AE%9E%E7%8E%B0%E5%8E%9F%E7%90%86/</guid>
      <description>&lt;p&gt;本文来自&lt;a href=&#34;http://www.cnblogs.com/aigongsi/p/3439766.html&#34;&gt;God Is Coder&lt;/a&gt;，通过这篇文章我算是理解了跨行清算系统逻辑，非常非常好。&lt;/p&gt;
&lt;p&gt;最近看了很多银联方面的清算系统的设计原理，对于跨行清算系统有了很大的了解，写这篇文章的目的是在于从一个程序员的角度去思考一个跨行清算系统的架构是如何实现的以及整个过程中我们有哪些思想是可以借鉴的。由于金融里面涉及到太多的专业名词，包括借贷，备付金，头寸，调拨等等，这里不会涉及到这些，取而代之的是以大家可以理解的概念去解释。&lt;/p&gt;
&lt;p&gt;下面简单的介绍一下两种跨行清算系统的实现原理以及特点。一种跨清算系统是我们最熟悉的银联，还有一种是越来越流行的第三方支付系统，比较典型的是快钱。&lt;/p&gt;
&lt;p&gt;首先来拿生活中的一个非常常见的例子来说明跨行清算的整个过程，这里面不涉及交易费等其他概念。&lt;/p&gt;
&lt;h2 id=&#34;跨行取款流程&#34;&gt;&lt;strong&gt;跨行取款流程&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;张三是工行的持卡人，他需要取现金，但是找不到工行的ATM机器，发现附近有建行的ATM机器，他只能去建行取款，整个过程就是跨行清算的过程，我们以这个场景为例，分析一下业务流程，具体交互流程见下面一张图。&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/2013/12/%E5%9B%BE1-21B3CB2A3-1863-403C-AA5A-F1F49E7EF416.png&#34;&gt;&lt;img alt=&#34;%E5%9B%BE1-21B3CB2A3-1863-403C-AA5A-F1F49E7EF416&#34; loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/2128716c2c0bc979bd671885c0cb16e5ee93d09e.png&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;工行持卡人张三在建行ATM机器取款100，ATM请求建行主机，由于是工行的卡，建行不识别，只能请求工行去处理，工行识别持卡人账户并扣款100，然后通知建行，建行则通知atm吐钱。&lt;/p&gt;
&lt;p&gt;这里整个系统要解决两个问题：&lt;/p&gt;
&lt;p&gt;1 建行如何与工行通信&lt;/p&gt;
&lt;p&gt;2 建行和工行之间如何清算，如上图结果，工行欠建行100.&lt;/p&gt;
&lt;p&gt;整个系统的分析基于以上两个问题，下面首先解决是通信问题&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2 id=&#34;跨行通信的两种模式&#34;&gt;跨行通信的两种模式&lt;/h2&gt;
&lt;p&gt;我们先假设工行提供接口，只需要建行发送指约定格式的报文，即可于工行通信，这种相当于建行直接通过接口方式与工行通信。如果是这种方式，只能解决建行和工行的单向通信，如果工行和建行通信，则工行要发送建行指定的通信报文格式。可是大家想想，如果银行更多怎么办，下面是三家银行间的通信&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/2013/12/%E5%9B%BE1-239A9848E-13A0-4F15-ABEB-F1CE91BBAD73.png&#34;&gt;&lt;img alt=&#34;%E5%9B%BE1-239A9848E-13A0-4F15-ABEB-F1CE91BBAD73&#34; loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/bf16b6e107e301f75d8484ce0e0f98ed3f685027.png&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;当有三家银行的时候，通信链路就有3*2=6条，当银行越来越多的时候，这种点对点的通信变的越来越复杂，每新增一家银行，他要做之前银行都要做的很多重复性的劳动，这样的成本非常高，也不经济，那么必须出现一个网络，它能够接入所有的银行，新的银行只需要接入这个网络，就可以和其他所有的银行进行通信。&lt;/p&gt;
&lt;p&gt;先把这个网络成为通信网络，这种通信网络有两种方式可以连接所有的银行&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;1 这个通信网络定义标准接口，所有的银行都必须实现这个通信网络定义的api，新的银行如果想要接入这个通信网络，必须实现通信接口约定的协议。简称公共接口模式&lt;/li&gt;
&lt;li&gt;2 这个通信网络主动去连接所有的银行的接口，把所有银行的接口信息都接入里面，就像一个适配器，新的银行如果想要接入这个通信网络，这个通信网络必须主动联系银行，按照银行的接口协议实现通信，简称适配器模式。
下面一幅图演示了这两种模式的不同：&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/2013/12/%E5%9B%BE1-27BDB9C58-65C9-4F58-B9B0-EA37D977317E.png&#34;&gt;&lt;img alt=&#34;%E5%9B%BE1-27BDB9C58-65C9-4F58-B9B0-EA37D977317E&#34; loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/11ace11b09acce70d8eaead337a87ebb868513a8.png&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;对于这两模式，主要博弈就在于谁强谁弱。显然第三方支付公司属于适配器模式，需要一家一家银行去接入，至于银联，个人认为应该是第一种模式，这种对于银联这种需要稳定的系统来说是最具有优势的。&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2 id=&#34;跨行清算保证金模式&#34;&gt;跨行清算保证金模式&lt;/h2&gt;
&lt;p&gt;解决了通信问题，下面就看如何解决资金的清算问题。一种简单的方案就是工行在建行里面开设一个保证金账户，用这个账户去偿还在整个跨行交易中应付给建行的资金。&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/2013/12/%E5%9B%BE1-288169047-B15D-422F-828E-685ADF9207D7.png&#34;&gt;&lt;img alt=&#34;%E5%9B%BE1-288169047-B15D-422F-828E-685ADF9207D7&#34; loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/ee7b5387f30e0221c9366cf68d72d03cca9fa2fb.png&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;从上图来看，这种方案确实可行。只需要工行在建行里面放足额的保证金，就可以满足跨行的费用。但是这里面实际上存在非常多的问题，&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;1 如果银行越来也多，每个银行都要在其他银行存钱，太不经济了&lt;/li&gt;
&lt;li&gt;2 保证金需要放多少资金？如果一直都没有发生跨行交易，工行就亏大发了&lt;/li&gt;
&lt;li&gt;3 如果保证金不够怎么办？交易失败还是记应收款？
对于第一个问题假设银行越来越多，会导致工行需要在其他每个银行里面都开设保证金账户（见下图），是一个很不经济的方案。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/2013/12/%E5%9B%BE1-266D7CC71-8C84-4621-B234-3E06FAC5856F.png&#34;&gt;&lt;img alt=&#34;%E5%9B%BE1-266D7CC71-8C84-4621-B234-3E06FAC5856F&#34; loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/07c21a5d4f416fa7b3b34b4667bcb02a08a452fd.png&#34;&gt;&lt;/a&gt;说明这个在其他银行存保证金的方案是不可行的，和之前通信的问题一样，是不是可以把所有的银行保证金账户单独管理起来，统一放置在一起，方便各个银行之间的清算。我们暂时把这个系统称之为保证金系统。&lt;/p&gt;
&lt;h2 id=&#34;保证金系统&#34;&gt;保证金系统&lt;/h2&gt;
&lt;p&gt;保证金就是方便各个银行之间的清算，需要单独由一个系统进行管理，解决了跨行之间保证金存放的问题。每个银行只需要在保证金系统中存点钱就可以了。保证金系统也有两种模式。先看看比较好理解的第一种模式：&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/2013/12/%E5%9B%BE1-2EB1C0D6C-C30F-4B7D-A120-7CB46AC33DD3.png&#34;&gt;&lt;img alt=&#34;%E5%9B%BE1-2EB1C0D6C-C30F-4B7D-A120-7CB46AC33DD3&#34; loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/b420275350a8aa8888110b745a1426787f9a750d.png&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;在这种模式下，银行先把一部分钱存放在保证金系统里面，同时银行内部建立一个虚拟账户，记录存放了多少钱，主要是方便对账，万一这个保证金系统钱算错了怎么办。你可以想象一下，银行是很小气的，为啥愿意把钱存放到这保证金系统里面，这部分钱干啥不好，能够银行这么干的只有国家了，这个系统就是央行的备付金管理系统。每个新增的银行都要存一份钱在这里。&lt;/p&gt;
&lt;p&gt;另外一种方案是倒过来思考，既然没有牛逼的央行作支撑，那可以在每个商业银行都建立一个账户，用这个账户负责和银行进行清算。每新增一家银行，就在那个银行里面开一个保证金账户。&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/2013/12/%E5%9B%BE1-2EBA5972D-06C6-4DC7-A7E4-4CC68455988B.png&#34;&gt;&lt;img alt=&#34;%E5%9B%BE1-2EBA5972D-06C6-4DC7-A7E4-4CC68455988B&#34; loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/2ed236969650d9d6c981c7a933ca69a0b0aa982a.png&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;这两种方式有本质的不同，一个是银行把资金的一部分转出到保证金，银行建立虚拟账户和保证金里面真实的资金映射。一个是保证金系统把资金转出到各个银行，自己内部建立一个虚拟账户和银行中真实的资金账户进行映射。这个间接的银行了后续的对账机制，这里先不叙述。&lt;/p&gt;
&lt;p&gt;所有的第三方支付公司跨行清算的流程都是第二种方式，只有国家级清算公司（比如银联）是第一种方式，这是一种资源和权力上的不平等，不过是可以理解的。&lt;/p&gt;
&lt;h2 id=&#34;清算系统&#34;&gt;清算系统&lt;/h2&gt;
&lt;p&gt;保证金系统解决了保证金存放的问题，接下来就是解决如何清算的问题。假设保证金转账是实时的，就要面对上面说的问题，保证金不够的情况下，跨行交易是成功还是失败。这是一个业务上问题，有很多种解决方案，我们暂不说。从技术上来讲，如果每一笔交易都要保证金实时记账，那么保证金系统的负载太大，事务如何保证等等一些列的问题。所以一个最简单的方案就是：一天结算一次。&lt;/p&gt;
&lt;p&gt;每天由一个系统记录这些跨行交易信息，汇总出来，统一记账。这样一天只需要调用一次保证金系统即可。那么整个清算过程则是下面的流程：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;1 系统T日发生建行和工行的跨行交易100
&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/2013/12/%E5%9B%BE1-208F9F26D-11BC-4BCA-9FAD-F5C9F7B9691C.png&#34;&gt;&lt;img alt=&#34;%E5%9B%BE1-208F9F26D-11BC-4BCA-9FAD-F5C9F7B9691C&#34; loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/4c745f5c7b8a40a840d975f5ac5a0e0871e8a2dc.png&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;2 清算系统T+1日汇总T日工行和建行之间发生的交易明细数据，并且发这些数据发给建行和工行进行确认
&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/2013/12/%E5%9B%BE1-2111356A9-ECA8-490A-977A-1FCD613F054F.png&#34;&gt;&lt;img alt=&#34;%E5%9B%BE1-2111356A9-ECA8-490A-977A-1FCD613F054F&#34; loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/1982182c16c49a40f6f81c9839c260a0b599296c.png&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt; &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;3 工行建行分别对明细对账确认之后，通知清算系统确认交易明细无误，清算系统开始清算，调用保证金支付系统转账。&lt;/li&gt;
&lt;li&gt;4 清算完成之后，工行和建行分别获取保证金系统的真实金额和自身系统内部的映射账户进行余额对账。
&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/2013/12/%E5%9B%BE1-2C84544CD-AE52-4D98-999C-C8B587B3E6AE.png&#34;&gt;&lt;img alt=&#34;%E5%9B%BE1-2C84544CD-AE52-4D98-999C-C8B587B3E6AE&#34; loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/c6fbba7cf0732085b9fc6a72eac7df350c736d08.png&#34;&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;清算中心最主要干得事情就是统计谁欠谁多少钱，以及触发保证金系统的调拨操作。&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2 id=&#34;对账流程&#34;&gt;对账流程&lt;/h2&gt;
&lt;p&gt;对账包括两个部分，一个是跨行交易明细的对账以及保证金余额的对账。&lt;/p&gt;
&lt;p&gt;首先要思考的是：对账是谁发起的 ？ 这个是了解对账的本质。&lt;/p&gt;
&lt;p&gt;我们举生活中的一个例子，我们把钱投资到一个人，那个人负责公司的日常运作。你肯定会主动了解公司的账务，因为那个是你的钱。对账的发起人也是如此，对于银联的清算过程，对账的发起者是商业银行，因为你把钱放在保证金系统里面，这是你的钱，你需要去关心这个的，银联可不关心这个。&lt;/p&gt;
&lt;p&gt;对于另外一种保证金系统，把钱放在各个银行里面了，那么对账的发起者就是这个保证金系统维护者了。目前普遍的第三方支付公司都是这个模式，所以他要找各个银行要结果明细进行对账，确认自己的资金安全无误。&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;以上就是一个简单的跨行清算系统的雏形，从一个就简单的例子入手，说明一个清算过程。目前银联的第三方支付公司的清算过程大致如此，但是实现细节远比这个复杂。但是一个基本的清算系统的本质模型大体上是不会变的。当然这个只是对于同币种的清算，不同币种或者虚拟货币的清算会涉及到汇率的问题，这些就很复杂，有机会在研究一下，后续在分享。&lt;/p&gt;
&lt;p&gt;PS：以上很多名词都是自己的随意写的，里面很多专业名词这里不提及，有兴趣的可以自己去了解。&lt;/p&gt;</description>
    </item>
    <item>
      <title>[藏]Class.getResource和ClassLoader.getResource不同点</title>
      <link>http://blog.leaver.me/2013/12/14/%E8%97%8Fclass.getresource%E5%92%8Cclassloader.getresource%E4%B8%8D%E5%90%8C%E7%82%B9/</link>
      <pubDate>Sat, 14 Dec 2013 18:18:53 +0000</pubDate>
      <guid>http://blog.leaver.me/2013/12/14/%E8%97%8Fclass.getresource%E5%92%8Cclassloader.getresource%E4%B8%8D%E5%90%8C%E7%82%B9/</guid>
      <description>&lt;p&gt;有一次遇到了，查了查。&lt;a href=&#34;http://www.cnblogs.com/yejg1212/p/3270152.html&#34;&gt;原文地址&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Java中取资源时，经常用到Class.getResource和ClassLoader.getResource，这里来看看他们在取资源文件时候的路径问题。&lt;/p&gt;
&lt;h2 id=&#34;classgetresourcestring-path&#34;&gt;Class.getResource(String path)&lt;/h2&gt;
&lt;div&gt;
&lt;pre&gt;path不以’/&#39;开头时，默认是从此类所在的包下取资源；
path  以’/&#39;开头时，则是从ClassPath根下获取；&lt;/pre&gt;
&lt;/div&gt;
什么意思呢？看下面这段代码的输出结果就明白了：
&lt;div&gt;
&lt;pre&gt;package testpackage;
public class TestMain {
    public static void main(String[] args) {
        System.out.println(TestMain.class.getResource(&#34;&#34;));
        System.out.println(TestMain.class.getResource(&#34;/&#34;));
    }
}&lt;/pre&gt;
&lt;/div&gt;
输出结果：
&lt;div&gt;
&lt;pre&gt;file:/E:/workspace/Test/bin/testpackage/
file:/E:/workspace/Test/bin/&lt;/pre&gt;
&lt;/div&gt;
上面说到的【path以’/&#39;开头时，则是从ClassPath根下获取；】在这里就是相当于bin目录(Eclipse环境下)。
&lt;p&gt;再来一个实例，假设有如下Project结构：&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/2013/12/o_PackageStructure1.png&#34;&gt;&lt;img alt=&#34;o_PackageStructure1&#34; loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/94eb328bce2cf9ff32430cc4075af46091202a22.png&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;如果我们想在TestMain.java中分别取到1~3.properties文件，该怎么写路径呢？代码如下：&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;package testpackage;

public class TestMain {

    public static void main(String[] args) {
        // 当前类(class)所在的包目录
        System.out.println(TestMain.class.getResource(&#34;&#34;));
        // class path根目录
        System.out.println(TestMain.class.getResource(&#34;/&#34;));

        // TestMain.class在&amp;lt;bin&amp;gt;/testpackage包中
        // 2.properties  在&amp;lt;bin&amp;gt;/testpackage包中
        System.out.println(TestMain.class.getResource(&#34;2.properties&#34;));

        // TestMain.class在&amp;lt;bin&amp;gt;/testpackage包中
        // 3.properties  在&amp;lt;bin&amp;gt;/testpackage.subpackage包中
        System.out.println(TestMain.class.getResource(&#34;subpackage/3.properties&#34;));

        // TestMain.class在&amp;lt;bin&amp;gt;/testpackage包中
        // 1.properties  在bin目录（class根目录）
        System.out.println(TestMain.class.getResource(&#34;/1.properties&#34;));
    }
}&lt;/pre&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;※Class.getResource和Class.getResourceAsStream在使用时，路径选择上是一样的。&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2 id=&#34;classgetclassloadergetresourcestring-path&#34;&gt;Class.getClassLoader（）.getResource(String path)&lt;/h2&gt;
&lt;div&gt;
&lt;pre&gt;path不能以’/&#39;开头时；
path是从ClassPath根下获取；&lt;/pre&gt;
&lt;/div&gt;
还是先看一下下面这段代码的输出：
&lt;div&gt;
&lt;pre&gt;package testpackage;
public class TestMain {
    public static void main(String[] args) {
        TestMain t = new TestMain();
        System.out.println(t.getClass());
        System.out.println(t.getClass().getClassLoader());
        System.out.println(t.getClass().getClassLoader().getResource(&#34;&#34;));
        System.out.println(t.getClass().getClassLoader().getResource(&#34;/&#34;));//null
    }
}&lt;/pre&gt;
&lt;/div&gt;
输出结果：
&lt;div&gt;
&lt;pre&gt;class testpackage.TestMain
sun.misc.Launcher$AppClassLoader@1fb8ee3
file:/E:/workspace/Test/bin/
null&lt;/pre&gt;
&lt;/div&gt;
从结果来看【TestMain.class.getResource(&#34;/&#34;) == t.getClass().getClassLoader().getResource(&#34;&#34;)】
&lt;p&gt;如果有同样的Project结构&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/2013/12/o_PackageStructure.png&#34;&gt;&lt;img alt=&#34;o_PackageStructure&#34; loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/46e184c9601d96bbb9fbb19e475c7909c85fe52c.png&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;使用Class.getClassLoader（）.getResource(String path)可以这么写：&lt;/p&gt;
&lt;div&gt;
&lt;pre&gt;package testpackage;
&lt;p&gt;public class TestMain {
public static void main(String[] args) {
TestMain t = new TestMain();
System.out.println(t.getClass().getClassLoader().getResource(&amp;quot;&amp;quot;));&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    System.out.println(t.getClass().getClassLoader().getResource(&amp;quot;1.properties&amp;quot;));
    System.out.println(t.getClass().getClassLoader().getResource(&amp;quot;testpackage/2.properties&amp;quot;));
    System.out.println(t.getClass().getClassLoader().getResource(&amp;quot;testpackage/subpackage/3.properties&amp;quot;));
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;}&lt;/pre&gt;&lt;/p&gt;
&lt;/div&gt;
&amp;nbsp;
&lt;p&gt;※Class.getClassLoader（）.getResource和Class.getClassLoader（）.getResourceAsStream在使用时，路径选择上也是一样的。&lt;/p&gt;</description>
    </item>
    <item>
      <title>Java动态代理实例</title>
      <link>http://blog.leaver.me/2013/11/24/java%E5%8A%A8%E6%80%81%E4%BB%A3%E7%90%86%E5%AE%9E%E4%BE%8B/</link>
      <pubDate>Sun, 24 Nov 2013 18:16:31 +0000</pubDate>
      <guid>http://blog.leaver.me/2013/11/24/java%E5%8A%A8%E6%80%81%E4%BB%A3%E7%90%86%E5%AE%9E%E4%BE%8B/</guid>
      <description>&lt;p&gt;首先什么是代理？&lt;/p&gt;
&lt;div&gt;所谓代理呢也就是在调用实现类的方法时，可以在方法执行前后做额外的工作，这个就是代理。&lt;/div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;div&gt;那动态代理呢，官方解释是：&lt;/div&gt;
&lt;div&gt;
&lt;pre class=&#34;lang:default decode:true &#34;&gt;Java 动态代理机制的出现，使得 Java 开发人员不用手工编写代理类，只要简单地指定一组接口及委托类对象，便能动态地获得代理类。代理类会负责将所有的方法调用分派到委托对象上反射执行，在分派执行的过程中，开发人员还可以按需调整委托类对象及其功能，这是一套非常灵活有弹性的代理框架。&lt;/pre&gt;
老湿，你说的是个毛啊，完全没看懂啊！
&lt;p&gt;我更喜欢另一种通俗的解释，官方的解释总是高度抽象的，等用了一段时间才能理解体会&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;动态代理实现了日志和业务的分开，也就是某个类只是要提供了某些业务，比如银行取款业务。这个类实现了取款业务的同时也需要实现日志功能，如果不用动态代理的话，那么由此一来该类代码里面已经额外地添加了自己不该添加的日志功能能代码。所以我们就得使用动态代理把它的业务代码和日志功能代码分开。所以用到了动态代理概念，spring里面的AOP就是一个很好的例子。&lt;/div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;div&gt;不直观啊，老湿，能再给力一点不？&lt;/div&gt;
&lt;div&gt;额，这样的话，我们来看一个例子，要用到的两个类
&lt;div&gt;实现java.lang.reflect.InvocationHandler接口提供一个执行处理器，也就是真正做事的，然后通过java.lang.reflect.Proxy得到一个代理对象，通过这个代理对象来执行业务方法,在业务方法被调用的同时，执行处理器会被自动调用。   记住，动态代理只能对接口&lt;/div&gt;
&lt;div&gt;首先业务接口：&lt;/div&gt;
&lt;div&gt;
&lt;pre class=&#34;lang:default decode:true &#34;&gt;public interface HelloWorld {
	public void sayHelloWorld();
}&lt;/pre&gt;
然后我们是这样写的实现
&lt;pre class=&#34;lang:default decode:true&#34;&gt;public class HelloWorldImpl implements HelloWorld {
	public void sayHelloWorld() {
		System.out.println(&#34;Hello World!&#34;);
	}
}&lt;/pre&gt;
后来我们觉得执行这个方法前能不能做点其他啥事呢，比如写个日志？见个妹子？啥，这段代码不让改了，改了的话，业务方法和日志混合的一塌糊涂啊，以后想改个日志格式你来写啊
&lt;p&gt;那我们就得定义一个拦截器/执行处理器了。&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;public class HelloWorldHandler implements InvocationHandler {
	//目标对象
	private Object targetObject;

	public HelloWorldHandler(Object targetObject){
		this.targetObject = targetObject;
	}

	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		System.out.println(&#34;方法调用前&#34;);

		Object result = method.invoke(this.targetObject, args);

		System.out.println(&#34;方法调用结束&#34;);

		return result;
	}
}&lt;/pre&gt;
&lt;p&gt;这客户端咋用啊，老湿&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;public class HelloWorldTest {
	public static void main(String[] args) {
		//业务对象
		HelloWorld obj = new HelloWorldImpl();

		//拦截器对象
		HelloWorldHandler handler = new HelloWorldHandler(obj);

		//返回业务对象的代理对象
		HelloWorld proxy = (HelloWorld)Proxy.newProxyInstance(
				obj.getClass().getClassLoader(), 
				obj.getClass().getInterfaces(), 
				handler);

		//通过代理对象执行业务对象的方法
		proxy.sayHelloWorld();
	}
}&lt;/pre&gt;
&lt;p&gt;看到没，通过Proxy类的newProxyInstance方法，传入类加载器，类接口，和这个处理器，我们就获得一个代理&lt;/p&gt;
&lt;p&gt;执行结果是这样的&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;方法调用前
Hello World!
方法调用结束&lt;/pre&gt;
&lt;p&gt;恩，电脑没死机，是这样的&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;/div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;</description>
    </item>
    <item>
      <title>[译]Java中的CountDownLatch和CyclicBarrier</title>
      <link>http://blog.leaver.me/2013/09/15/%E8%AF%91java%E4%B8%AD%E7%9A%84countdownlatch%E5%92%8Ccyclicbarrier/</link>
      <pubDate>Sun, 15 Sep 2013 08:03:09 +0000</pubDate>
      <guid>http://blog.leaver.me/2013/09/15/%E8%AF%91java%E4%B8%AD%E7%9A%84countdownlatch%E5%92%8Ccyclicbarrier/</guid>
      <description>&lt;p&gt;本文译自官方文档，有细微改动，Java多线程的时候，看了好多文档，还是官方说的最清楚。结合自己的理解，译之。&lt;/p&gt;
&lt;h2 id=&#34;countdownlatch&#34;&gt;CountDownLatch&lt;/h2&gt;
&lt;p&gt;字面意思就是倒计数闩，后面会讲到，这里的同步允许一个或多个线程等待，，知道其他线程进行的一系列操作完成。而CountDownLatch通过一个参数count（数目）来构造，而await（）则阻塞当前线程，直到countDown()将count减为了0，然后，所有的阻塞线程被释放，也就是那些调用了await方法的线程立即返回，注意，这是一次性的，也就是说count不能被自动重置，如果你想这么做，CyclicBarrier是可以的。&lt;/p&gt;
&lt;p&gt;CountDownLatch用处很多，当用count=1来构造的时候，这就相当于一个开关，所有调用了await方法的线程都在等待，直到有一个线程调用了countDown()，CountDownLatch通过count=N构造的话，就可以使一个线程等待其他N个线程完成操作，或者一个操作被做N次。&lt;/p&gt;
&lt;p&gt;简单的demo：&lt;/p&gt;
&lt;p&gt;一组worker（工人）线程使用两个CountDownLatch&lt;/p&gt;
&lt;p&gt;第一个是开始信号，用来阻止工人提前操作，直到(driver)传送带准备好了才允许开始&lt;/p&gt;
&lt;p&gt;第二个是完成信号，他使传送带等待直到所有的worker都完成&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt; class Driver { // ...
   void main() throws InterruptedException {
     CountDownLatch startSignal = new CountDownLatch(1);
     CountDownLatch doneSignal = new CountDownLatch(N);

     for (int i = 0; i &amp;lt; N; ++i) // 创建并启动线程
       new Thread(new Worker(startSignal, doneSignal)).start();

     doSomethingElse();            // 传送带做点准备工作
     startSignal.countDown();      // 减为0，工人可以开始了
     doSomethingElse();
     doneSignal.await();           // 等待直到所有的工人完成任务
   }
 }

 class Worker implements Runnable {
   private final CountDownLatch startSignal;
   private final CountDownLatch doneSignal;
   Worker(CountDownLatch startSignal, CountDownLatch doneSignal) {
      this.startSignal = startSignal;
      this.doneSignal = doneSignal;
   }
   public void run() {
      try {
        startSignal.await();//工人们等待开关打开
        doWork();              //做事
        doneSignal.countDown(); //做完了就给countdownlatch 减去1
      } catch (InterruptedException ex) {} // return;
   }

   void doWork() { ... }
 }&lt;/pre&gt;
&lt;p&gt;另一个典型的例子就是把问题分成N部分，通过线程执行每一部分，具体的话是将线程入队到一个Executor对象里。然后调用execute方法。当执行完毕一部分，就并给latch 减去1，当减到0的时候调用await的方法就可以继续运行了，当需要重复计数的话，用CyclicBarrier代替&lt;/p&gt;
&lt;pre&gt;class Driver2 { // ...
   void main() throws InterruptedException {
     CountDownLatch doneSignal = new CountDownLatch(N);
     Executor e = ...

     for (int i = 0; i &amp;lt; N; ++i) // 创建并开始线程
       e.execute(new WorkerRunnable(doneSignal, i));

     doneSignal.await();           // 等待所有的线程完成
   }
 }

 class WorkerRunnable implements Runnable {
   private final CountDownLatch doneSignal;
   private final int i;
   WorkerRunnable(CountDownLatch doneSignal, int i) {
      this.doneSignal = doneSignal;
      this.i = i;
   }
   public void run() {
      try {
        doWork(i);
        doneSignal.countDown();
      } catch (InterruptedException ex) {} // 返回;
   }

   void doWork() { ... }
 }&lt;/pre&gt;
&lt;p&gt; &lt;/p&gt;</description>
    </item>
    <item>
      <title>阿里巴巴5月5日综合算法题详解</title>
      <link>http://blog.leaver.me/2013/06/02/%E9%98%BF%E9%87%8C%E5%B7%B4%E5%B7%B45%E6%9C%885%E6%97%A5%E7%BB%BC%E5%90%88%E7%AE%97%E6%B3%95%E9%A2%98%E8%AF%A6%E8%A7%A3/</link>
      <pubDate>Sun, 02 Jun 2013 15:44:22 +0000</pubDate>
      <guid>http://blog.leaver.me/2013/06/02/%E9%98%BF%E9%87%8C%E5%B7%B4%E5%B7%B45%E6%9C%885%E6%97%A5%E7%BB%BC%E5%90%88%E7%AE%97%E6%B3%95%E9%A2%98%E8%AF%A6%E8%A7%A3/</guid>
      <description>&lt;p&gt;之前参加了阿里的笔试和电面，让后天那个敏感的日子去参加现场面，就去看了一下那天笔试的最后一道综合题，看着网上清一色最后一道题不知道从哪转的答案，不忍直视，一看代码就是错的，最直接的就是求中位数连奇偶性都不判断，直接处以2..这，另外当在无法整除的情况下，数据结果错误。&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;这道题的大意是：有一个淘宝商户，在某城市有n个仓库，每个仓库的储货量不同，现在要通过货物运输，将每次仓库的储货量变成一致的，n个仓库之间的运输线路围城一个圈，即1-&amp;gt;2-&amp;gt;3-&amp;gt;4-&amp;gt;&amp;hellip;-&amp;gt;n-&amp;gt;1-&amp;gt;&amp;hellip;，货物只能通过连接的仓库运输，设计最小的运送成本（运货量*路程）达到淘宝商户的要求，并写出代码。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;解题思路：&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;假设n个仓库的初始储货量分别为warehouse[1],warehouse[2],&amp;hellip;,warehouse[n]
计算平均储货量&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt; average = （warehouse[1]+warehouse[2]+...+warehouse[n])/n&lt;/pre&gt;
&lt;p&gt;就算出来了最终的结果中，每个仓库应该有的存量
首先，从仓库1向仓库n运送k；
然后，从1到n-1，依次向下运送某一特定值，使得每一个仓库的余量都为average，剩下的问题就是求总代价的最小值了。&lt;/p&gt;
&lt;p&gt;设第0步从1仓库向n仓库（注意因为是圆圈，所以路径长度是1）运出k存量，k可以为负，如果为负数，意味着从n向1运输|k|存量，然后从循环，从（1到n-1）,从i仓库向i+1仓库运输，运输的量需要保证i仓库在运输完毕后等于average&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;第0步（从仓库1向仓库n运送k）:花费代价为 |k|，&lt;/li&gt;
&lt;li&gt;第1步（确保仓库1的余量为average）：需要花费代价为&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;|warehouse[1]-average-k|&lt;/pre&gt;
&lt;p&gt;也就是从1向2伙从2向1运输
3.  第2步（确保仓库2的余量为average）：代价为&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;|warehouse[2]+warehouse[1]-average-k-average|=|warehouse[1]+warehouse[2]-2*average-k|&lt;/pre&gt;
&lt;p&gt;&amp;hellip;
n-1.第n-1步：代价为&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;|warehouse[1]+warehouse[2]+...+warehouse[n-1]-(n-1)*average-k|&lt;/pre&gt;
&lt;p&gt;此时，仓库n剩下的货物量：&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;(warehouse[n]+k)+warehouse[1]+warehouse[2]+...+warehouse[n-1]-(n-1)*average-k=(warehouse[1]+warehouse[2]+...+warehouse[n])-(n-1)*average=average&lt;/pre&gt;
&lt;p&gt;刚好也满足，其实这里不用推导，因为平均值是算好的，所以最胡一定是刚好完成的。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;总的代价为&lt;/strong&gt;：&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;|k|+|warehouse[1]-average-k|+|warehouse[1]+a[2]-2*average-k|+...+|warehouse[1]+warehouse[2]+...+warehouse[n-1]-(n-1)*average-k|&lt;/pre&gt;
&lt;p&gt;不妨令sum[i] = warehouse[1]+warehouse[2]+&amp;hellip;+warehouse[i]-i*average
则，总代价可表示为：|k|+|sum[1]-k|+|sum[2]-k|+&amp;hellip;+|sum[n-1]-k|
这个式子可以看成在水平数轴上寻找一个点k，使得点k到点0,sum[1],sum[2],sum[3],&amp;hellip;,sum[n-1]的距离之和最小，显然k应该取这n个数的中位数。至此问题解决。&lt;/p&gt;
&lt;p&gt;给出详细注释代码：&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;#include &#34;stdafx.h&#34;
#include &amp;lt;iostream&amp;gt;
#include &amp;lt;algorithm&amp;gt;
#include&amp;lt;string&amp;gt;

using namespace std;

const int X = 100000;
double sum[X],warehouse[X];
int n;

double Abs(double x)
{
	return max(x,-x);
}

int _tmain(int argc, _TCHAR* argv[])
{
	while(true)
	{
		double total = 0;
		double mid=0;
		cout&amp;lt;&amp;lt;&#34;请输入仓库数目：&#34;;
		cin&amp;gt;&amp;gt;n;
		//读入n个仓库的值，并计算总数
		for(int i=1;i&amp;lt;=n;i++)
		{
			cout&amp;lt;&amp;lt;&#34;请输入第&#34;&amp;lt;&amp;lt;i&amp;lt;&amp;lt;&#34;个仓库的存量：&#34;;
			cin&amp;gt;&amp;gt;warehouse[i];
			total += warehouse[i];
		}
		//计算每个仓库应该最终存储的值
		double average = total/n;
		//计算sum数组
		for(int i=1;i&amp;lt;n;i++)
			sum[i] = warehouse[i]+sum[i-1]-average;
		//排序后打算去中位数
		//sort采用半开半闭区间，所以排序为0～n-1
		sort(sum,sum+n);
		//这个可以自己举个数字就知道了
		if(n%2!=0)
		{	
			mid = sum[n/2];
		}
		else
		{
			mid=(sum[n/2]+sum[n/2-1])/2;
		}
		cout&amp;lt;&amp;lt;&#34;应该从1开始,运输&#34;&amp;lt;&amp;lt;mid&amp;lt;&amp;lt;&#34;货物,然后依次保证符合条件即可&#34;&amp;lt;&amp;lt;endl;
		double ans = Abs(mid);
		for(int i=1;i&amp;lt;n;i++)
			ans += Abs(sum[i]-mid);
		cout&amp;lt;&amp;lt;&#34;总成本花费是:&#34;&amp;lt;&amp;lt;ans&amp;lt;&amp;lt;endl;
		cout&amp;lt;&amp;lt;&#34;----------------------------------------------------------------------&#34;&amp;lt;&amp;lt;endl;
	}
	return 0;
}&lt;/pre&gt;
&lt;p&gt;思路借鉴了：&lt;a href=&#34;http://hi.baidu.com/hujunjiehit/item/54204f01931ee6c49157184c&#34;&gt;http://hi.baidu.com/hujunjiehit/item/54204f01931ee6c49157184c&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;错误之处欢迎留言指出..&lt;/p&gt;</description>
    </item>
    <item>
      <title>[藏]社交网络，电子时代的人生绑架者</title>
      <link>http://blog.leaver.me/2013/05/13/%E8%97%8F%E7%A4%BE%E4%BA%A4%E7%BD%91%E7%BB%9C%E7%94%B5%E5%AD%90%E6%97%B6%E4%BB%A3%E7%9A%84%E4%BA%BA%E7%94%9F%E7%BB%91%E6%9E%B6%E8%80%85/</link>
      <pubDate>Mon, 13 May 2013 06:31:43 +0000</pubDate>
      <guid>http://blog.leaver.me/2013/05/13/%E8%97%8F%E7%A4%BE%E4%BA%A4%E7%BD%91%E7%BB%9C%E7%94%B5%E5%AD%90%E6%97%B6%E4%BB%A3%E7%9A%84%E4%BA%BA%E7%94%9F%E7%BB%91%E6%9E%B6%E8%80%85/</guid>
      <description>&lt;p&gt;作者:&lt;a href=&#34;http://www.zhihu.com/people/fu-er&#34;&gt;负二&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;bystander:本文回答了你刷社交网络的内在因素.希望读到的人不只是读到那么简单.&lt;/p&gt;
&lt;p&gt;大家在互相打招呼之前，先各自拿出手机，其中几个人用手机“签到”，然后把“签到”信息转发给在场的每一个人，而另一些人则用手机给饭桌上的菜肴拍照，然后同样转发给在场的每一个人，直到各种提示音消失之后，大家开始一边动筷子，一边心不在焉地聊八卦，如果没有爆炸性的话题出现，吸引在场的每一个人的注意力，那么大家的注意力都会被自己的手机虏获——比如我会收到坐在对面的那人发来的一张用手指画的拙劣的涂鸦，然后让我根据此图猜一个单词。&lt;/p&gt;
&lt;p&gt;现在，一次聚餐的情景差不多就是这样，把一盘菜的照片转发给就坐在你身边和你一起吃饭的那个人，这种事说起来真是要多蠢有多蠢，但人们仍是乐此不疲——当一台饮水机都拥有一个微博账号时，我们意识到任何事情都已经无法阻止网络社交了，无论是美食还是同学聚会。&lt;/p&gt;
&lt;p&gt;大多数热衷于用手机刷新SNS网站的人并不认为对网络社交上瘾是什么问题——他们有种幻觉：需要的时候，我肯定能够克制自己，那肯定比戒烟容易。但事实并非如此，网络社交上瘾与烟瘾截然不同，如果你对它背后的机制有所了解，一定会对它能够利用人类心理的弱点到如此地步深感惊讶——一个正常人只要掉进这个圈套，就几乎不可能不对这玩意上瘾。&lt;/p&gt;
&lt;p&gt;如果你有过在泡论坛时不断刷新页面的经历，你就会明白社交网站的通知系统是一个多么精巧的引人上钩的设计——人们难以容忍等待，他们需要新状态的刺激，现代化的机场都将下飞机口到取行李处的距离设计得要多漫长有多漫长，就是为了避免旅客在取行李处叉着双手等行李，因为“走”比“等”更容易让人接受——而创造通知系统的产品经理们显然深谙此道，只要通知系统不断地给出状态更新的通知，就能够让人每天乖乖地登录，然后长时间地留在你的社交网站上，这一招就像用香肠逗狗一样好用。&lt;/p&gt;
&lt;p&gt;许多人认为社交网站降低了人与人之间交流的成本，促进了信息流动和世界大同——他们显然是被Facebook、新浪微薄之类的网站给蒙骗了；而对人类社会的本质有所了解的人则会同意窥私欲是支撑社交网站的动力之一——有一定道理，人们总是有无穷的动力想去瞧瞧多年不见的老朋友、老同学，或是初恋情人，看他们是不是过得比自己更差，我的表弟曾向我坦白，在他听说前女友离婚的消息后，他曾连续一个月关注她的微博和开心网账号，并且觉得很爽——巴菲特说，竞争并不是推动人类前进的动力，嫉妒才是。&lt;/p&gt;
&lt;p&gt;但实际上，窥私欲在社交网络这盘大菜中顶多只能算是几滴酱油——如果你对人性有更透彻的认识，你会从“把一盘菜的照片转发给和你一起吃饭的每一个人”这一举动上看到更深层次的动机。只有够自恋的人才会认为“我在吃这盘菜”这件事很重要，重要到有必要让每个人知道的地步——不幸的是，这世界上除了抑郁症患者，每个人都够自恋，你只要稍加注意就会发现，社交网络中的大多数信息都与“交流”没半毛钱关系，只是某人发布的“自以为很重要”的自我推销信息而已。根据“人类自我表现理论”，人们的自我表现往往根据相互关系中对方的特点而采取某种相应的对策，人们会不断地调节和控制呈现给其他人的信息，特别是有关自我的信息，以便建立起有利于自己的形象——所以人们会狂热地维护自己的微博形象，对隐私泄露视而不见，而对爱你的家人恶言相向。&lt;/p&gt;
&lt;p&gt;最新的研究表明，热衷社交网络，也很有可能是你不够成功的表现——美国人4个中有3个是Facebook用户，但在可支配财产超过100万美元的人群中，这一比例只有26%，而百万富翁中上Twitter的比例更是只有可怜的3%——心理学家指出，原因可能是财富给予人更多的独立意识，对他人的依赖越少，对他人就越少在意，产生自我关注的倾向。想必扎克伯格自己也不会一天到晚泡在自己的网站上——而这世界上大多数人都“不够成功”，毫无疑问。&lt;/p&gt;
&lt;p&gt;只要看透这一切，你就会明白，社交网络热潮，根本不是什么科技革命，它只不过是人性弱点的一次集中爆发而已，并且在它不为人所见的屁股后面，多多少少都能闻出一丝阴谋家的味道——自由软件基金会主席Richard Stallman认为，基于实名制的Facebook是一个国际寄生项目，而Jonathan Nolan（《盗梦空间》编剧）则在他的新剧中直接说，Facebook的幕后金主其实是CIA，自从全世界的人们都那么乐意泄露隐私后，CIA的工作简单了不少。&lt;/p&gt;
&lt;p&gt;现在看来，远离通知提示音的诱惑，从社交网络那里为自己“赎身”，才是人生正途。&lt;/p&gt;</description>
    </item>
    <item>
      <title>分享几个电子书资源站点</title>
      <link>http://blog.leaver.me/2012/10/18/%E5%88%86%E4%BA%AB%E5%87%A0%E4%B8%AA%E7%94%B5%E5%AD%90%E4%B9%A6%E8%B5%84%E6%BA%90%E7%AB%99%E7%82%B9/</link>
      <pubDate>Thu, 18 Oct 2012 11:12:01 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/10/18/%E5%88%86%E4%BA%AB%E5%87%A0%E4%B8%AA%E7%94%B5%E5%AD%90%E4%B9%A6%E8%B5%84%E6%BA%90%E7%AB%99%E7%82%B9/</guid>
      <description>&lt;p&gt;看到书签里有好些电子书的资源站。今天心情不错。遂起了分享的念头。。&lt;/p&gt;
&lt;p&gt;对于计算机相关专业人隆重推荐&lt;a href=&#34;http://www.xiaoshuwu.in/&#34;&gt;小书屋&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;作者很认真的在分享技术/安全/心理学/技术PPT方面的书籍。算是国内技术书籍比较好的分享站点了。&lt;/p&gt;
&lt;p&gt;如果你没有找到自己喜欢的书。那么试试&lt;a href=&#34;http://forfrigg.com/&#34;&gt;forfrigg&lt;/a&gt;，是一个电子书籍整合站点。使用该网站。不只可以下载kindle书籍。更是能够搜索新浪，doukan等诸多网盘内容。实乃书籍下载必备引擎啊。&lt;/p&gt;
&lt;p&gt;什么？你只想下载百度文库的？没积分？好吧。那我告诉你一个类似的镜像站点&amp;ndash;&lt;a href=&#34;http://www.wenkudaquan.com/&#34;&gt;文库大全&lt;/a&gt;，这个站和百度文库差不多。资源很丰富。想下什么。就去下吧。。&lt;/p&gt;
&lt;p&gt;如果在这里没找到。。而你发现百度文科的积分是0 1 2 5那么试试&lt;a href=&#34;http://www.bangshouwang.com/&#34;&gt;帮手&lt;/a&gt;吧。免费下载。原版哦。稍多一点的积分就不可以了。如果你和博主私交不错。我帮你搞定。&lt;/p&gt;
&lt;p&gt;如果你是大牛。。只喜欢看英文原版的。。那么先去&lt;a href=&#34;http://www.qcenglish.com/&#34;&gt;七彩英语&lt;/a&gt;看看吧，优秀的英文电子书下载站。从技术到小说应有尽有。界面也漂亮。&lt;/p&gt;
&lt;p&gt;还嫌少？那去国外溜达吧。&lt;a href=&#34;http://www.ebook-downloader.com/&#34;&gt;ebook-downloader&lt;/a&gt; 随时欢迎你的光临。全球最大电子书下载平台。。尽情享受阅读的快感吧。。&lt;/p&gt;
&lt;p&gt;update:感谢@Shiyao Yu的推荐-&lt;a href=&#34;http://www.ppurl.com&#34;&gt;皮皮书屋&lt;/a&gt;。很小众。但资源很全。需注册。注册用户每天可下三本。最喜欢小众什么的了。我试着搜了一下计算机的。确实挺全。&lt;/p&gt;
&lt;p&gt;ps:如果你收藏了其他的站点。不妨留言回复。&lt;/p&gt;</description>
    </item>
    <item>
      <title>C#调用Matlab引擎</title>
      <link>http://blog.leaver.me/2012/08/09/c%23%E8%B0%83%E7%94%A8matlab%E5%BC%95%E6%93%8E/</link>
      <pubDate>Thu, 09 Aug 2012 22:39:57 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/08/09/c%23%E8%B0%83%E7%94%A8matlab%E5%BC%95%E6%93%8E/</guid>
      <description>&lt;p&gt;　　最近在使用matlab的时候。求多元函数取得最小值的时候。变量的值。于是就用到了sym符号。结果在C#中调用时总是出错。后来Google了N久发现是符号工具箱是无法编译的。。后来找到了替代方法。就是调用matlab 引擎。当然要稍微麻烦一点。因为调用引擎这种方法参数传递比较麻烦。我只想到了通过C#把需要计算的值保存到文本中。然后matlab中load进来。计算完成后 save出去。。&lt;/p&gt;
&lt;p&gt;　　调用matlab引擎类似于在C#中新开了一个进程。然后执行一些命令。之前需要引用Matlab Application Type Library。这是个com组件&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/25657_o.jpg&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/b938768405ede59db17f36bdc27e700bf3cbf1dc.jpg&#34; title=&#34;type&#34;&gt;&lt;/a&gt;
然后在程序里使用 using语句&lt;/p&gt;
&lt;pre class=&#34;lang:c# decode:true &#34; &gt;using MLApp;&lt;/pre&gt; 
&lt;p&gt;然后就可以正常使用了。使用我试过的有两种方法&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true &#34; &gt;MLApp.MLAppClass matlab = new MLApp.MLAppClass();  
matlab.Visible = 1;  
string command=&#34;figure(1)&#34;;
matlab.Execute(command);  
matlab.Quit();&lt;/pre&gt; 
&lt;p&gt;很简单。Visible设置可见性。。command表示要执行的命令。&lt;/p&gt;
&lt;p&gt;另一种是&lt;/p&gt;
&lt;pre class=&#34;lang:c# decode:true &#34; &gt;MLApp.DIMLApp matlab = null;  
Type matlabAppType = System.Type.GetTypeFromProgID(&#34;Matlab.Application&#34;);  
matlab = System.Activator.CreateInstance(matlabAppType) as MLApp.DIMLApp;  
matlab.Visible = 1;  
string command=&#34;figure(2)&#34;;
matlab.Execute(command);  
matlab.Quit();&lt;/pre&gt; 
&lt;p&gt;不知什么原因，第一种方法我没有调用成功。第二种调用成功。欢迎讨论。&lt;/p&gt;</description>
    </item>
    <item>
      <title>SQLServer超时时间已到解决和一套控件库</title>
      <link>http://blog.leaver.me/2012/07/13/sqlserver%E8%B6%85%E6%97%B6%E6%97%B6%E9%97%B4%E5%B7%B2%E5%88%B0%E8%A7%A3%E5%86%B3%E5%92%8C%E4%B8%80%E5%A5%97%E6%8E%A7%E4%BB%B6%E5%BA%93/</link>
      <pubDate>Fri, 13 Jul 2012 08:36:56 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/07/13/sqlserver%E8%B6%85%E6%97%B6%E6%97%B6%E9%97%B4%E5%B7%B2%E5%88%B0%E8%A7%A3%E5%86%B3%E5%92%8C%E4%B8%80%E5%A5%97%E6%8E%A7%E4%BB%B6%E5%BA%93/</guid>
      <description>&lt;p&gt;　　在最近的一个程序中，因为频繁的操作数据库，莫名的出现了如下的错误：&lt;/p&gt;
&lt;p&gt;　　超时时间已到。超时时间已到，但是尚未从池中获取连接。出现这种情况可能是因为所有池连接均在使用，并且达到了最大池大小。&lt;/p&gt;
&lt;p&gt;　　说明: 执行当前 Web 请求期间，出现未处理的异常。请检查堆栈跟踪信息，以了解有关该错误以及代码中导致错误的出处的详细信息。&lt;/p&gt;
&lt;p&gt;　　异常详细信息: System.InvalidOperationException: 超时时间已到。超时时间已到，但是尚未从池中获取连接。出现这种情况可能是因为所有池连接均在使用，并且达到了最大池大小。&lt;/p&gt;
&lt;p&gt;　　按理说这应该是没有关闭数据库连接或者dataset，可是查了一下。发现都关了啊。遂可以表述为原因不明，但是通过在数据库连接字符串中添加max pool size=512  这个数字可以自己设。就可以了&lt;/p&gt;
&lt;p&gt;　　这篇文章短是短了点。。好吧。那顺带分享一套非常精美的C#控件。
&lt;a href=&#34;http://115.com/file/dptqnr63#RadControls-WinForms-2012-2-608-Dev.msi&#34;&gt;RadControls-For-WinForms 控件2012&lt;/a&gt;
&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/24794_o.jpg&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/35b3a6023ad34c4bab5564678dffabbcdd53a5da.jpg&#34; title=&#34;wpf&#34;&gt;&lt;/a&gt;
&lt;a href=&#34;http://115.com/file/e79q6pju#RadControls-for-WPF-2012-2-0607-Dev.msi&#34;&gt;RadControls-for-WPF控件2012&lt;/a&gt;
&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/24793_o.jpg&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/c3f1eeb8b01e38643d7ce0d2e2716bba20285943.jpg&#34; title=&#34;winform&#34;&gt;&lt;/a&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>降级论</title>
      <link>http://blog.leaver.me/2012/07/07/%E9%99%8D%E7%BA%A7%E8%AE%BA/</link>
      <pubDate>Sat, 07 Jul 2012 22:37:11 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/07/07/%E9%99%8D%E7%BA%A7%E8%AE%BA/</guid>
      <description>&lt;p&gt;　　相当精彩的一篇文章『&lt;a href=&#34;http://meditic.com/degrading-for-success/&#34;&gt;降级论&lt;/a&gt;』，收藏分享。精彩的部分突出显示了。&lt;/p&gt;
&lt;p&gt;　　几乎一年没有写博客了，说没时间那是借口，唯一的原因是，年纪越大越发觉自己肤浅。有些想法还没提笔，就发现很幼稚，就不敢发出来贻笑大方了。这次先给大家说个小故事：&lt;/p&gt;
&lt;p&gt;　　从前有三个屌丝，聚在一起做网络，提供免费的网络服务，砸锅卖铁，通宵达旦，除了卖肾啥都做了。3年后终于做到了五百万用户，对于年轻人来说，能把五百万人玩弄于鼓掌之间，已经是很牛逼轰轰的事了，不过用户越多，成本越高，每年服务器、带宽租金、房租水电、广告运营等成本，已经达到了十七八万，屌丝们不得不面对一个终极问题：如何盈利？&lt;/p&gt;
&lt;p&gt;　　屌丝们定了三盘沙县水饺，围着一箱子的冰啤酒开始计算：按照最近一月的登陆情况来看，四百万个账号已经不活跃了，真正有商业价值的只有一百万人，如 果开通xx功能，收点高级会员费，让其中1%的人升级为高级会员，每年付30块钱年费，那么每年收入就是100万x1%x30元=30万元！不错嘛， 扣除十七八万的运营成本，还剩毛利润12万，每个屌丝年底能分到4万大洋，如果按照打工者的算法，这三个人每人月薪3333元，木有奖金，木有津贴、木有任何福利，上班还得带自家的电脑。&lt;/p&gt;
&lt;p&gt;　　尽管如此，屌丝们还是激动得热泪盈眶：老子有钱啦！老子有钱啦！！！那一夜，人们看到三个发疯的屌丝在屋顶翩翩起舞。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;韩寒说，中国人民是最有忍耐力的族群，一点好处就感激涕零。他一定不知道，IT创业界里的屌丝，才是这群傻逼中的战斗机。他们可以平静地忍受每年都持续亏钱，而且还能信心十足的对所有人说公司的状态非常好，如果有一天居然收支平衡了，他们会激动的趁夜难眠，比北朝鲜倒掉还开心。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;　　本文开头的三个屌丝，其实是非常幸运的，至少能做到月薪3333元。大部分的屌丝在第一年做到几万用户的时候就会挂掉，原因众多，最主要要的是意志太弱，受不了最初的寂寞；意志稍微坚强点的会在第二年第三年慢慢挂掉，原因主要是资金断裂、团队分裂；能成功熬到第四年还没饿死、还没被口水淹死、还没被肠胃病颈椎病腰肌劳损折磨死的，甚至员工不减反增的，基本上属于神仙级别了。&lt;/p&gt;
&lt;p&gt;　　我为什么要说三个屌丝的故事呢。首先是因为这是身边每天都在发生的故事，其次是因为感到可惜，&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;IT界在我眼里一直是一个无比高级的职业，聚集着全球最聪明、最富有的人类精英。以IT创业界的青年们的智商，他们可以做成任何一件事情，包括改造银行到制造汽车到发射航天飞机 。结果这帮人却整天在蓬头垢面得为3k的月薪而挣扎，太悲催了。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;　　为什么用悲催这个词？ 如果一个人生下来就在山沟沟里，一辈子都没机会去见什么好东西，这不叫悲催，这只叫苦难；&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;而如果一个人生出来有一个奇怪的特异功能：皮肤出来的汗水会凝结成昂贵的水晶，本来只靠出汗就能赚钱，结果这傻逼居然觉得出汗这个行为太低级，做手术把自己的汗腺全给切了，而且丝毫没有意识到他做了什么傻事，这才叫真的悲催。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;　　我们IT界中的很多人，生下来就是有这个出汗成水晶的特异功能的，正是因为这种与众不同，这群人能混入牛逼的大学，整天打网游还能写出像样的毕业论文， 拿到学位，进外企，考CPA，做咨询、做证券分析，研究高分子材料，做电子商务，做云计算。。。一级一级的上升，直到有一天，发现身边的人里，已经没有一个不是CPA，不是咨询师，不是高级研究员了，身边的人全是业界精英，个个都超级强悍。在这个所谓的高级圈子里，自己并没有任何过人之处，只不过是just another analyst而已。在高级圈子里拼的头破血流，最后也只能混到给台湾人整理数据而已。莫然回首，发现当年的血气方刚、年少时的无限梦想，进化成了一身肥胖的赘肉。这个时候，有个旁观者说：“升级到头了，该降级了”&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;当一个社会疯狂鼓吹快节奏的时候，一定需要有人来宣扬慢生活；当全社会跟打了鸡血似的吹捧升级的时候，一定需要有人来说说降级论。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;　　IT青年们喜欢打游戏，喜欢升级。他们的人生也和游戏一样，沉醉于不停的升级中，不仅喜欢升级自己手上的技术，把MySql改成MongoDB，把Apache升级为Nginx，在Mac上装Ubuntu，Ubuntu里再装个虚拟机去跑Mac OS。。。IT青年们也喜欢升级自己的人生，从程序员升级到项目经理，再升级到技术总监或产品总监，再升级到合伙人。。。&lt;/p&gt;
&lt;p&gt;　　在不断追求升级的过程中，所面临的一个很大事实是：当一个人从A刚升级到A+级的时候，其实这个人的能力层级依然只是A的层级，还未胜任A+的层级，他必须要到A+的后期，才可以胜任A+。就好像一个高中生，高考完之后，虽然理论上已经属于大学生了，但是他的实际能力依然只是高三毕业的水平，除非他全部pass了大一的期末考试。同样的道理，&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;这个世界上有很多人的身份和称谓，都是在描述“未来的自己”，而不是现在的自己。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;当你从销售员升级为销售经理的时候，你自我感觉很好：“我现在是销售经理了”，但是这个时候 ，你并未通过公司对你作为销售经理这一年的工作成果的考核，你只是一个“未来可能是合格的销售经理”的前身。如果年终考核你失败了，那么这一年最准确的描述是：一个销售员，占了整整一年销售经理的位子，最后失败了。而且这一年一定会过的很累，因为通过考核的其他销售经理，才是真正胜任这个层级的人，跟一帮真正属于这个圈子的人厮杀，就好像拳击馆里当陪练的小角色，去和泰森比了一年的武，怎么可能不累呢？&lt;/p&gt;
&lt;p&gt;　　当我07年进入互联网行业的时候，就是那个拳击馆里陪练的小角色，我被迫去跟全国各地的泰森比拼，结果累的半死。后来我开始反思最初的目标，为什么要在自己身上挂一个“拳击高手”的招牌，被那么多泰森追着打？ 我把这块招牌卸了，找个完全没练武的人去比拼，不是更容易赢么？于是果断照做，去找了一个没人懂拳击的小乡村，做了纯英文的Tucia.com(需翻墙)，只做国外的业务。在那个地方，作为一个知名武馆的拳击小陪练，我成了村子里拳击技术最高超的人，受人仰慕，还开武馆教人拳击，活的非常滋润，而且在教人拳击的过程中，自己的拳术也比以前提高了很多，发展出一套属于自己的拳法，我虽然进不了泰森们的大圈子，但他们也进不了我的小圈子。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;关于圈子，有一个很赤裸裸的现实：不会是你进入圈子，只能是圈子进入你。很多人会四处找关系，“帮我介绍给xxx吧，我想进入你们的圈子”，这样的人是永远进不去这个圈子的，因为圈子的天性是，永远追求更高一个层级的人。而我们的大部分人，其实都在以低一级的属性，占着更高一级的位子，徘徊在更高一级的圈子边缘，与更高一级的人竞争，幻想着自己可以升级到那个圈子里去。也许永远进不去，悲催的努力一辈子；也许运气好，某一天真的进入这个圈子了，但那个时候又会有下一个目标，希望进入更高级的圈子，这是一场没有终点的战斗。永远的追求升级，永远的累。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;　　有没有想过降级呢？&lt;/p&gt;
&lt;p&gt;　　如果一个来自微软的高级工程师，辞职去一个养猪场做开放平台经理，那么他的到来不仅会让养猪圈感到无比荣幸，更是意味着，利用他在IT界训练出来的高效工作方式和逻辑思维能力，他可以掀起一场养猪行业的革命，使得20年后才会出现的人性、高效、开放、协作、健康的养殖方式提前到达。在这场革命中，他会活的非常有价值。这种价值，在原先的圈子里，是完全体验不到的，因为他此前的所有工作，只是在满身疮痍的windows系统上不停的打补丁，无论打多少都逃不开产品衰落、被人鄙视的命运。&lt;/p&gt;
&lt;p&gt;　　很多人的命运，都像是上面那个微软工程师。只需要降级，就能创造更大的价值，也能获得更大的满足。那为什么不呢？为什么要死死抱着那个所谓的“高级职业”不放呢？&lt;/p&gt;
&lt;p&gt;　　去年我曾犯贱去趟了移动互联网的浑水，做了个手机app，刚开始的时候感觉很高级，但很快，铺天盖地的竞争对手就出现了，我又发现自己陷入了07年一样的场景：作为一个小小陪练，我他妈的又被一帮泰森们给围住了。当泰森中的战斗机&amp;mdash;微信，变得无比牛逼之后，我就知道，战胜这群泰森是绝对不可能的事情了。于是我再次投靠了“降级论”，把自己从牛逼哄哄的移动互联网行业，降级到了一个被人不齿的低级项目：Tucia Baby。&lt;/p&gt;
&lt;p&gt;　　这个项目虽然是传统行业，但是我们基本上是按照互联网产品的思路去做的，除了拍摄需要来店里以外，其他一切，包括营销、预约、客服、后期、选片、取片、客户关系等，所有环节都放在网络上，尤其是微博（@tuciababy官网）。当然，最重要的是，作为一个脑残的果粉，我按照iPhone的做工和品质去要求每一张作品，必须达到我们能力可以做到的最好水准，不计成本的最好水准，才允许送给客户。正式接客不到两个月时间，虽然还远未达到成功，但目前已做到每天都有客户订单，财务上已实现盈利，未来相信一定会比大部分app开发者更光明。（ps:我们没有请工商、税务、城管去吃饭喝酒泡桑拿，也没有塞钱给任何政府机关。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;当你的产品真的用心做到很好的时候，其实你不需要讨好任何人的。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;）&lt;/p&gt;
&lt;p&gt;　　这个项目让我沉思了很久：07年我曾把一个纯纯的web2.0网站做到了alexa中国区前1000名（如有质疑，请查询2010年附近的tucia.com排名），结果一路亏损，到最后只剩下一个员工；11年我把那个纯纯的app做到苹果官方推荐区免费榜的第一位（点此看截图），那段时间每天四五千iPhone安装量，结果一路烧钱，到最后濒临关闭；而如今，我只需把自己从纯纯的互联网降级下来，做一些看起来有些“低级”的项目，居然就能立即实现收支平衡。&lt;/p&gt;
&lt;p&gt;　　除此以外，我还发现一个现象，&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;中国消费者在与奸商们的长期斗争中，已经培养出了一种非常苦B的品质：只要不被坑，他就谢天谢地。如果商家严格做到了承诺的每一件事情，客户就会感动的泪如泉涌。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;如果商家不仅做到了所有承诺的事情，还很贴心的提供了一些额外的服务（比如我们给每位客户赠送非常好吃的樱桃和昂贵的进口巧克力作为甜点），那么客户就会激动的哭天喊地、奔走相告，推荐给他认识的每一个人。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;其实这片肮脏的国土，就是上天赐予IT青年们的最好机会。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;　　在一个不会练武的村子里，只要你会打两拳，你就是拳术最厉害的人；在一个没有服务意识、忽视产品质量的土地上，只要你用心做服务，用最高的标准去要求自己，你就会成为这块土地上最出色的商家；在一个没有现代管理意识，不懂网络、不懂微博、不懂用户体验、不懂口碑传播的粗犷社会里，你只需要把之前花在IT产品上的心思的10%拿过来用，就可以秒杀一切天朝对手。&lt;/p&gt;
&lt;p&gt;　　所以，&lt;/p&gt;
&lt;p&gt;　　IT青年们，当你在为网站的转化率苦苦思索的时候，当你在为app的活跃度辗转反侧的时候，当你在为融资计划苦苦哀求各界大佬引荐的时候，也许犯了一个错误，也许你们的脑子最值得闪光的地方，不是去悲催的IT界当炮灰，而应该是去按摩界、餐饮界、烧烤界、早餐界、理发界、家政界、按摩界、送花界、纺织界、成人用品界、现代化养殖界、有机蔬果界、个人护理界、汽车修理界。。。。与IT界相比，这些行业的确无比低级，他们的老板连qq都会发音成“抠抠”，他们的员工一辈子都没用过Email；跟他们解释什么是SEO，什么是用户体验，什么是数据挖掘，他们会在听你说完之前就开枪自杀掉。正是因为如此，这些行业才是如此的不堪一击。正是因为如此，当智商高达147的IT青年还在为3k薪水拼命、而智商不到50的烧烤店老板正坐在porsche里玩着前面那位青年开发的app的时候，我就忍不住仰望星空。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;这些原始而纯粹的行业，正在等待IT精英们的降级，如同蒲公英一般的伞兵，在黑夜里从天而降，长驱直入，用最智慧的产品、最优质的服务拯救这些早就该死的行业，屌丝的生命将会绽放出银色的羽翼，无比丰满，无比性感。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;　　最后注意，请珍惜生命，远离我的微博：@meditic&lt;/p&gt;</description>
    </item>
  </channel>
</rss>
