<?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/%E4%B8%8A%E6%B5%B7/</link>
    <description>Recent content in 上海 on bystander&#39;s blog</description>
    <generator>Hugo</generator>
    <language>zh-CN</language>
    <lastBuildDate>Tue, 11 Mar 2014 08:28:38 +0000</lastBuildDate>
    <atom:link href="http://blog.leaver.me/tags/%E4%B8%8A%E6%B5%B7/rss.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>[藏]深入理解Java内存模型</title>
      <link>http://blog.leaver.me/2014/03/11/%E8%97%8F%E6%B7%B1%E5%85%A5%E7%90%86%E8%A7%A3java%E5%86%85%E5%AD%98%E6%A8%A1%E5%9E%8B/</link>
      <pubDate>Tue, 11 Mar 2014 08:28:38 +0000</pubDate>
      <guid>http://blog.leaver.me/2014/03/11/%E8%97%8F%E6%B7%B1%E5%85%A5%E7%90%86%E8%A7%A3java%E5%86%85%E5%AD%98%E6%A8%A1%E5%9E%8B/</guid>
      <description>&lt;ol&gt;
&lt;li&gt;&lt;a href=&#34;http://ifeve.com/java-memory-model-1/&#34;&gt;深入理解java内存模型（一）——基础&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://ifeve.com/java-memory-model-2/&#34;&gt;深入理解java内存模型（二）——重排序&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://ifeve.com/java-memory-model-3/&#34;&gt;深入理解java内存模型（三）——顺序一致性&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://ifeve.com/java-memory-model-4/&#34;&gt;深入理解java内存模型（四）——volatile&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://ifeve.com/java-memory-model-5/&#34;&gt;深入理解java内存模型（五）——锁&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://ifeve.com/java-memory-model/&#34;&gt;深入理解java内存模型（六）——final&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://ifeve.com/java-memory-model-7/&#34;&gt;深入理解java内存模型（七）——总结&lt;/a&gt;&lt;/li&gt;
&lt;/ol&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>尝试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>[藏]隐藏在PNG图像元数据中的新iFrame注入攻击</title>
      <link>http://blog.leaver.me/2014/02/09/%E8%97%8F%E9%9A%90%E8%97%8F%E5%9C%A8png%E5%9B%BE%E5%83%8F%E5%85%83%E6%95%B0%E6%8D%AE%E4%B8%AD%E7%9A%84%E6%96%B0iframe%E6%B3%A8%E5%85%A5%E6%94%BB%E5%87%BB/</link>
      <pubDate>Sun, 09 Feb 2014 09:23:12 +0000</pubDate>
      <guid>http://blog.leaver.me/2014/02/09/%E8%97%8F%E9%9A%90%E8%97%8F%E5%9C%A8png%E5%9B%BE%E5%83%8F%E5%85%83%E6%95%B0%E6%8D%AE%E4%B8%AD%E7%9A%84%E6%96%B0iframe%E6%B3%A8%E5%85%A5%E6%94%BB%E5%87%BB/</guid>
      <description>&lt;p&gt;这个攻击方式很旧了，但手法相当不错，来自&lt;a href=&#34;http://www.lembed.com/new-iframe-injections-leverage-png-image-metadata/&#34;&gt;乐嵌网&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;我们一直在努力保持领先的最新趋势，今天我们发现了一个非常有趣的事，这或者是我们之前没有发现，或者是刚发生的。 我们只能说这是新发现的。&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;我们都了解的iFrame注入攻击，对吧？&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;了解一个iFrame注入&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;今天的iFrame 是非常标准的HTML标记，它是在自己网页中嵌入其他网站内容的简单方式。 被几乎所有的浏览器支持和百万计的网站使用，使用AdSense吗？ 那么你的网站中就有一个iFrame。&lt;/p&gt;
&lt;p&gt;我知道这东西很好，然而总是福祸相惜。&lt;/p&gt;
&lt;p&gt;今天的攻击，特别是当我们谈论路过式下载，首选是利用IFRAME标记。 它简单方便，只需简单的属性修改，攻击者可以稳妥的从另一个站点嵌入代码，并通过客户的浏览器不知不觉的加载。&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/2014/02/iframe-sample.png&#34;&gt;&lt;img alt=&#34;iframe-sample&#34; loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/3da10af5e9e3a897cf39927ee28a0106f297880a.png&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;攻击者通常从其他网站嵌入的恶意文件，通常是一个PHP文件或类似的形式。 当然，这并不是唯一的方法，但是是最普遍的。 从检测和修复的角度来看，这往往很容易修复。&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;新的iFrame注入法&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;然而今天，我们发现一个有趣的iFrame注入类型。&lt;/p&gt;
&lt;p&gt;它的特殊之处不是在iframe标签中嵌入的内容，而是它分发恶意软件的方式。 你会看到，攻击者将威胁隐藏在PNG文件中。&lt;/p&gt;
&lt;p&gt;我几乎可以听到很多你的窃笑，PFF .. 这不是新的…. 但问题是在细节上我的朋友。&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;如下，iFrame加载了一个有效的文件，没有什么恶意，一个叫jquery.js的JavaScript文件。这一切看上去都很好。你要细细的找：&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/2014/02/blog_injection1-494x650.png&#34;&gt;&lt;img alt=&#34;blog_injection1-494x650&#34; loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/7f64ba23d5fd4d5763ff921134e11beede62faeb.png&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;起初，很多人会说我们傻。 这些代码很好，没看见什么问题，对不对？ 然后，我们注意到了这个小函数，loadFile（）。 函数本身并不奇怪，但事实上，它是装载一个PNG-&lt;strong&gt;var strFile = ‘./dron.png&lt;/strong&gt;。 你会被它惊讶良久，它才是一个真正的黑手。&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;自然，下一步就是好奇的打开dron.png文件。 会有什么可怕的事情发生吗？&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/2014/02/Sucuri-iframe-png.png&#34;&gt;&lt;img alt=&#34;Sucuri-iframe-png&#34; loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/0d8a2bcd6d6e5a6ac87f8858fe8f0a81878d6bbc.png&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;但是，请等一下，我发现这里有个有趣的小循环。&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/2014/02/Sucuri-PNG-Decoding-Loop.png&#34;&gt;&lt;img alt=&#34;Sucuri-PNG-Decoding-Loop&#34; loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/8c17a78234586bebb89f023d8023b6b69d9f574b.png&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;嗯，这是确实挺奇怪的，这是一个解码循环。 为什么要一个循环的解码PNG文件呢？&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;作为一个优秀的研究人员，采取最简单的方式，我可以将它加载到简单的测试页上 并提取图像内容。搞定！&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;测试页上加载它之后这，我们获得了strData变量：&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/2014/02/sucuri-png-iframe-payload.png&#34;&gt;&lt;img alt=&#34;sucuri-png-iframe-payload&#34; loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/4a1a1266a40ff50c6d0328eea9c9e849e043ae05.png&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;看到它在干嘛了吗？&lt;/p&gt;
&lt;p&gt;它做了个iFrame注入，并把它嵌入到PNG的元数据中，像一个新的分配机制。&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;有两点需要特别注意了，它使用&lt;strong&gt;createElement&lt;/strong&gt;做了一个&lt;strong&gt;iFrame&lt;/strong&gt;标签**，&lt;strong&gt;然后设置&lt;/strong&gt;elm.style.position.left 和 elm.style.position.top **属性的值为-1000px，把iframe放到可视区域之外。这些值都是负值，在浏览器中根本看不到。但是你知道谁能看到吗？只有浏览器和Google能看到。这就是下载驱动和搜索引擎感染（SEP)攻击的小伎俩。&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;最后我们在&lt;strong&gt;elm.src&lt;/strong&gt;元素中发现了真正的威胁**。**&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;做的这么独特到底有什么用呢？&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;它尽力隐藏真正的威胁的水平是独特的。现在的杀毒软件不会解码图像元数据，直到JavaScript文件加载完毕就停止扫描。不会追踪cookie文件，对于攻击者来说，这太好了，使它们很难被发现。&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;记住一点，尽管我们这里谈论的是PNG文件，这些方法和概念也可以应用到其他类型图像中。重要的一点是：留意你的web 服务状态，了解哪些修改和未修改的文件并确保漏洞未被利用。&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;a href=&#34;http://blog.sucuri.net/2014/02/new-iframe-injections-leverage-png-image-metadata.html&#34;&gt;new-iframe-injections-leverage-png-image-metadata&lt;/a&gt; by Peter Gramantik&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/2014/02/04/%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%8A/</link>
      <pubDate>Tue, 04 Feb 2014 19:13:26 +0000</pubDate>
      <guid>http://blog.leaver.me/2014/02/04/%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%8A/</guid>
      <description>&lt;p&gt;今天大雪，天冷，不能出去玩了。把保存在pocket里的一些记录总结一下，太懒了。。下篇等我去了上海用我电脑写吧&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;1.java模拟https登陆&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;首先我要登陆，然后保存cookie，然后利用cookie来访问后续的网页，发包，处理包这样，然后，为了方便，我选择了 org.apache.http 这个库，典型的一个登陆场景应该是这样的，以后遇到问题一定先要去看官方的例子，别人给出的例子一般要么是不能用，要么是用的方法都是一些过时的，虽然能用，但看到警告还是不舒服。&lt;/p&gt;
&lt;pre class=&#34;lang:java decode:true&#34;&gt;public static BasicCookieStore cookieStore;
//整个过程用一个client
public static CloseableHttpClient httpclient;
cookieStore = new BasicCookieStore();
httpclient = HttpClients.custom().setDefaultCookieStore(cookieStore).build();
//先访问一下首页，然后cookie、会填充进来
HttpGet httpget = new HttpGet(&#34;https://leaver.me/index.htm&#34;);
httpclient.execute(httpget);
CloseableHttpResponse responseCookie = null;
//然后post请求登陆
HttpPost httpost = new HttpPost(&#34;https://leaver.me/login.htm&#34;);
//通过键值对来作为post参数
List &amp;lt; NameValuePair &amp;gt; nameValuePairs = new ArrayList &amp;lt; NameValuePair &amp;gt; (1);
nameValuePairs.add(new BasicNameValuePair(&#34;loginType&#34;, &#34;1&#34;));
nameValuePairs.add(new BasicNameValuePair(&#34;loginName&#34;, username));
nameValuePairs.add(new BasicNameValuePair(&#34;Password&#34;, password));
httpost.setEntity(new UrlEncodedFormEntity(nameValuePairs, Consts.UTF_8));
CloseableHttpResponse responLogin = null;
responLogin = httpclient.execute(httpost);&lt;/pre&gt;
&lt;p&gt;但是，这个过程报了如下的错&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;e: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target&lt;/pre&gt;
&lt;p&gt;google之，发现时访问https的原因。需要先安装对应站点的证书。这里要用到一个通用的java类，我贴下&lt;a href=&#34;http://pan.baidu.com/s/1sjMyvgx&#34;&gt;链接&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;编译这个工具类，然后执行java InstallCert &amp;lt;host&amp;gt;[:port] 会生成一个证书文件&lt;/p&gt;
&lt;p&gt;然后在项目里通过&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;System.setProperty(&#34;javax.net.ssl.trustStore&#34;,
				&#34;证书路径&#34;);&lt;/pre&gt;
&lt;p&gt;设置即可，你可以吧证书文件放到资源目录，就更好了。&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;2.java正则替换反斜线&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;我在某个地方需要把字符串里的所有反斜线替换成两个，我就写了&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;str.replaceAll(&#34;\\&#34;,&#34;\\\\&#34;)&lt;/pre&gt;
&lt;p&gt;结果发现我还是too young,实际上，&lt;/p&gt;
&lt;p&gt;java replaceAll() 方法要用 4 个反斜杠,表示一个反斜杠 例如&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;str1=&#34;aa\bbb&#34;;&lt;/pre&gt;
&lt;p&gt;要想替换成&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;str1=&#34;aa\\bbb&#34;;&lt;/pre&gt;
&lt;p&gt;必须这样替换：&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;str1 = str1.replaceAll(&#34;\\\\&#34;, &#34;\\\\\\\\&#34;);&lt;/pre&gt;
&lt;p&gt;原因如下： String 的 replaceAll（） 方法，实际是采用正则表达式的规则去匹配的， \\ ，java解析为\交给正则表达式， 正则表达式再经过一次转换，把\转换成为\ 也就是java里面要用正则来表示一个. 必须写成4个\ 如果要表示\，那就要写8个\ 所以如果写成： str1 = str1.replaceAll(&amp;quot;\&amp;quot;, &amp;ldquo;\\&amp;rdquo;); 就会报正则表达式的错误。&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;3.httpClient如何模拟表单上传文件&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;这个还是要去看官方例子，网上没找到，需要添加&lt;/p&gt;
&lt;p&gt;org.apache.http.entity包&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;//文件部分
FileBody csvFile = null;
//表单的其他部分
StringBody filelog = null;
StringBody dataItemDefine = null;
csvFile = new FileBody(new File(file));
filelog = new StringBody(&#34;ADD&#34;, ContentType.TEXT_PLAIN);
dataItemDefine = new StringBody(GlobalSetting.getValueOfKey(type), ContentType.TEXT_PLAIN);
//关键代码,此处来构造请求数据
HttpEntity reqEntity = MultipartEntityBuilder.create().addPart(&#34;filelog&#34;, changeLogAction).addPart(&#34;dataItemDefine&#34;, dataItemDefine).addPart(&#34;fileName&#34;, csvFile).build();
HttpPost httppost = new HttpPost(&#34;https://leaver.me/uploadFile.action&#34;);
httppost.setEntity(reqEntity);
CloseableHttpResponse response = null;
response = httpclient.execute(httppost);&lt;/pre&gt;
&lt;p&gt;其他都和普通的post请求没啥区别了&lt;/p&gt;</description>
    </item>
    <item>
      <title>前路月光</title>
      <link>http://blog.leaver.me/2014/01/28/%E5%89%8D%E8%B7%AF%E6%9C%88%E5%85%89/</link>
      <pubDate>Tue, 28 Jan 2014 15:35:43 +0000</pubDate>
      <guid>http://blog.leaver.me/2014/01/28/%E5%89%8D%E8%B7%AF%E6%9C%88%E5%85%89/</guid>
      <description>&lt;p&gt;火影片头曲想知道中文，没找到翻译，于是译之，感谢&lt;a href=&#34;http://weibo.com/u/1095659682&#34;&gt;@sepith &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;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;很多时候，伤痕累累
忘掉了痛苦
流过血泪，
王者归来是使命所及
哪管一路秋叶萧萧&lt;/p&gt;
&lt;p&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>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>
  </channel>
</rss>
