<?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>Java on bystander&#39;s blog</title>
    <link>http://blog.leaver.me/tags/java/</link>
    <description>Recent content in Java on bystander&#39;s blog</description>
    <generator>Hugo</generator>
    <language>zh-CN</language>
    <lastBuildDate>Sat, 08 Apr 2017 15:10:36 +0000</lastBuildDate>
    <atom:link href="http://blog.leaver.me/tags/java/rss.xml" rel="self" type="application/rss+xml" />
    <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>mac日志批量查询配置</title>
      <link>http://blog.leaver.me/2016/10/05/mac%E6%97%A5%E5%BF%97%E6%89%B9%E9%87%8F%E6%9F%A5%E8%AF%A2%E9%85%8D%E7%BD%AE/</link>
      <pubDate>Wed, 05 Oct 2016 10:13:05 +0000</pubDate>
      <guid>http://blog.leaver.me/2016/10/05/mac%E6%97%A5%E5%BF%97%E6%89%B9%E9%87%8F%E6%9F%A5%E8%AF%A2%E9%85%8D%E7%BD%AE/</guid>
      <description>&lt;p&gt;由于公司线下机器非常多,导致每次查日志变得非常痛苦.线下的trace平台大部分时候还是可用的.但是有时候需要本机来批量查询.方案就是批量分发ssh key,实现免登.然后luit实现编码转换,这个主要是公司的机器编码有差异.历史原因.&lt;/p&gt;
&lt;h2 id=&#34;0-准备&#34;&gt;0. 准备&lt;/h2&gt;
&lt;p&gt;先要安装pssh,expect,ssh-copy-id.&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; brew install pssh
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; brew install homebrew/dupes/expect
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; brew install ssh-copy-id
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;另外安装luit的安装参考这里&lt;a href=&#34;http://www.jianshu.com/p/69382cb499db&#34;&gt;luit安装&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;1-生成ssh-key-并批量copy&#34;&gt;1. 生成ssh key ,并批量copy&lt;/h2&gt;
&lt;p&gt;生成ssh key比较简单.&lt;code&gt;ssh-keygen -t rsa -C &amp;quot;your_email@example.com&amp;quot;&lt;/code&gt;,直接使用git的ssh key也是可以的.然后保存下面这个脚本为pscopy.sh,&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-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;#!/bin/bash
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;FILE&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;sb&#34;&gt;`&lt;/span&gt;cat ~/host.txt&lt;span class=&#34;sb&#34;&gt;`&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; ip in &lt;span class=&#34;nv&#34;&gt;$FILE&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;expect -c &lt;span class=&#34;s2&#34;&gt;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;spawn ssh-copy-id &lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$ip&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;   expect {
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;       \&amp;#34;*yes/no*\&amp;#34; {send \&amp;#34;yes\r\&amp;#34;;exp_continue}
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;       \&amp;#34;*password*\&amp;#34; {send \&amp;#34;pass\r\&amp;#34;;exp_continue}
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;       \&amp;#34;*password*\&amp;#34; {send \&amp;#34;pass\r\&amp;#34;;}
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;done&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;然后执行一下sh pscopy.sh,注意,host.txt要保证存在.格式是user@address.一行一个,中间的paas要改成user的密码,这样就会使用指定的用户密码,自动copy ssh key了.
完成上面的步骤之后,ssh user@address 就可以免登了.&lt;/p&gt;
&lt;h2 id=&#34;2-写一个简单的pssh脚本&#34;&gt;2. 写一个简单的pssh脚本&lt;/h2&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;#!/bin/bash
&lt;/span&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;&lt;span class=&#34;nv&#34;&gt;encoding&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;key&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;command&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;file&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;usage&lt;span class=&#34;o&#34;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;Usage: `basename &lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$0&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;` [-f filename]  [-c encoding] [-k keyword]&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nb&#34;&gt;exit&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;}&lt;/span&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;&lt;span class=&#34;k&#34;&gt;while&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;getopts&lt;/span&gt; :f:c:k: opt
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;do&lt;/span&gt;  
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;case&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;$opt&lt;/span&gt; in
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        c&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;  
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;nv&#34;&gt;encoding&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$OPTARG&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;p&#34;&gt;;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        :&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;-&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$OPTARG&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt; needs an argument&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;p&#34;&gt;;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        k&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;  
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;nv&#34;&gt;key&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$OPTARG&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;p&#34;&gt;;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        f&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;nv&#34;&gt;file&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$OPTARG&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;p&#34;&gt;;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        *&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;  
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;-&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$opt&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt; not recognized&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            usage
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;p&#34;&gt;;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;esac&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;done&lt;/span&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;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt; -z &lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$encoding&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;then&lt;/span&gt;   &lt;span class=&#34;c1&#34;&gt;#该脚本必须提供-d选项&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nv&#34;&gt;encoding&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;gbk&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;fi&lt;/span&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;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt; -z &lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$file&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;then&lt;/span&gt;   &lt;span class=&#34;c1&#34;&gt;#该脚本必须提供-d选项&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nv&#34;&gt;file&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;~/hosts.txt&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt; -z &lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$key&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;then&lt;/span&gt;   &lt;span class=&#34;c1&#34;&gt;#该脚本必须提供-d选项&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  usage
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;command&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;pssh -h &lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$file&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt; -P \&amp;#34;find /home/admin/logs/ -name &amp;#39;*.log&amp;#39;|xargs grep &lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$key&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt; --col\&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;luit -encoding &lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;encoding&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;command&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;保存这个脚本为pssh.sh,然后用法如上.之后就可以通过 pssh.sh -f host.txt -c gbk -k keyword来批量查询了&lt;/p&gt;</description>
    </item>
    <item>
      <title>motan源码阅读-客户端服务引用</title>
      <link>http://blog.leaver.me/2016/05/31/motan%E6%BA%90%E7%A0%81%E9%98%85%E8%AF%BB-%E5%AE%A2%E6%88%B7%E7%AB%AF%E6%9C%8D%E5%8A%A1%E5%BC%95%E7%94%A8/</link>
      <pubDate>Tue, 31 May 2016 20:00:45 +0000</pubDate>
      <guid>http://blog.leaver.me/2016/05/31/motan%E6%BA%90%E7%A0%81%E9%98%85%E8%AF%BB-%E5%AE%A2%E6%88%B7%E7%AB%AF%E6%9C%8D%E5%8A%A1%E5%BC%95%E7%94%A8/</guid>
      <description>&lt;p&gt;一旦服务器启动,服务开始提供,并且在配置中心注册了(配置中心可以是本地的地址,也可以是zk,也可以是其他的实现),那么客户端就要开始调用了&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://blog.leaver.me/images/service_ref.png&#34;&gt;点击看大图&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&#34;服务引用&#34; loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/service_ref.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;服务引用 RefererConfig.getRef()&lt;/p&gt;
&lt;p&gt;先是获取集群支持(先忽略,主要是配置中心相关的)&lt;/p&gt;
&lt;p&gt;configHandler.refer(interfaceClass, clusters, proxy)
开始获取接口代理&lt;/p&gt;
&lt;p&gt;1.一旦知道接口名,Class.forName加载接口类,就开始通过proxy工厂来为服务端接口创建代理了&lt;/p&gt;
&lt;p&gt;2.jdk的Proxy类,直接来创建代理.同时代理要传入RefererInvocationHandler
这个类可以看错是真正的stub,封装了rpc调用请求.当在客户端获取到服务接口的bean的时候,实际上调用过程被这个类拦截,进行封装发送rpc&lt;/p&gt;
&lt;p&gt;1.当接口被调用的时候,这个拦截器险根据拦截到的请求构造一个rpc请求&lt;/p&gt;
&lt;p&gt;2.这里就会存在一个策略.该调用哪个,以FailoverHaStrategy为例&lt;/p&gt;
&lt;p&gt;1.选择一个服务提供方&lt;/p&gt;
&lt;p&gt;1.如果是jvm服务,那么直接从本地的服务map中取出一个调用就行&lt;/p&gt;
&lt;p&gt;2.如果是真正的远程服务,这时候就进入nettyClient部分了&lt;/p&gt;
&lt;p&gt;把请求向netty的Channel中写就行了.服务端会从Channel中取进行处理,然后放回来.这样客户端就拿到结果了&lt;/p&gt;</description>
    </item>
    <item>
      <title>motan源码阅读-服务的发布</title>
      <link>http://blog.leaver.me/2016/05/30/motan%E6%BA%90%E7%A0%81%E9%98%85%E8%AF%BB-%E6%9C%8D%E5%8A%A1%E7%9A%84%E5%8F%91%E5%B8%83/</link>
      <pubDate>Mon, 30 May 2016 20:42:06 +0000</pubDate>
      <guid>http://blog.leaver.me/2016/05/30/motan%E6%BA%90%E7%A0%81%E9%98%85%E8%AF%BB-%E6%9C%8D%E5%8A%A1%E7%9A%84%E5%8F%91%E5%B8%83/</guid>
      <description>&lt;p&gt;这一篇继续从这个demo开始,分析一下这个服务是怎么发布出去的.关键的代码从&lt;code&gt;motanDemoService.export();&lt;/code&gt;开始.&lt;/p&gt;
&lt;p&gt;一图胜千言.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://blog.leaver.me/images/serviceConfig_export.png&#34;&gt;点击看大图&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&#34;服务发布&#34; loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/serviceConfig_export.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;服务发布ServiceConfig.export()&lt;/p&gt;
&lt;p&gt;1.加载有的配置中心url列表/新建&lt;/p&gt;
&lt;p&gt;2.doExport(ProtocolConfig,port,registryURLs) //配置中心地址列表&lt;/p&gt;
&lt;p&gt;2.1导出的时候,会先判断是否存在.其实就是根据协议名,ip,接口,参数来生成一个唯一key.&lt;/p&gt;
&lt;p&gt;2.2ConfigHandler.export(Class&lt;T&gt; interfaceClass, T ref, List&lt;URL&gt; registryUrls) //接口.实现.配置中心url列表&lt;/p&gt;
&lt;p&gt;2.2.1.根据协议名创建协议,这里ProtocolFilterDecorator&lt;/p&gt;
&lt;p&gt;2.2.2.根据接口,实现类,serviceUrl,构造一个Provider,用来提供服务&lt;/p&gt;
&lt;p&gt;2.2.3.使用协议进行导出Provider,  export(Provider&lt;T&gt; provider, URL url)&lt;/p&gt;
&lt;p&gt;2.2.3.1创建一个Exporter&lt;/p&gt;
&lt;p&gt;2.2.3.1.1.创建的时候会将服务提供方Provider和url有个映射关系,这样当一个url请求过来的时候,就知道改调用谁了.ProviderMessageRouter,讲一个请求路由注册到server上,同时包装了一个心跳包&lt;/p&gt;
&lt;p&gt;2.2.3.2进行导出 导出就是一个服务器打开的过程/server.open();&lt;/p&gt;
&lt;p&gt;2.2.3.2.1进入nettyServer初始化,主要就是添加handler,编码解码.和一个rpc处理的
相当于一个请求过来的时候,先进行解码,然后调用业务处理handler进行处理,处理完成后,进行编码,然后返回给客户端&lt;/p&gt;
&lt;p&gt;服务器启动后,相当于这个服务就发布了&lt;/p&gt;
&lt;p&gt;2.2.4.注册register(registryUrls, serviceUrl) //这一步就是将serviceUrl,向对应的jvm/rpc服务中心注册url,本地注册就是LocalRegistryService类里一个map..zk的.就是向zk写node.等等&lt;/p&gt;</description>
    </item>
    <item>
      <title>motan源码阅读-入门和运行demo</title>
      <link>http://blog.leaver.me/2016/05/29/motan%E6%BA%90%E7%A0%81%E9%98%85%E8%AF%BB-%E5%85%A5%E9%97%A8%E5%92%8C%E8%BF%90%E8%A1%8Cdemo/</link>
      <pubDate>Sun, 29 May 2016 15:13:48 +0000</pubDate>
      <guid>http://blog.leaver.me/2016/05/29/motan%E6%BA%90%E7%A0%81%E9%98%85%E8%AF%BB-%E5%85%A5%E9%97%A8%E5%92%8C%E8%BF%90%E8%A1%8Cdemo/</guid>
      <description>&lt;p&gt;工作中一直在使用rpc,但是只是对简单的原理比较熟悉.最近看到有motan的一个介绍,代码拉下来看了看,除了测试用例比较少之外.其他还是不错的,和阿里的rpc框架比起来,还是弱了一些,好处就是方便用来学习.
&lt;a href=&#34;https://github.com/weibocom/motan&#34;&gt;motan&lt;/a&gt; 是weibo的一个rpc框架,据说已经在线上使用了.&lt;/p&gt;
&lt;p&gt;在学习rpc框架之前,建议看一个hello world级别的文章&lt;a href=&#34;http://javatar.iteye.com/blog/1123915&#34;&gt;RPC框架几行代码就够了&lt;/a&gt;,写的非常好,看完基本就知道rpc的核心了.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://www.cs.rutgers.edu/~pxk/417/notes/08-rpc.html&#34;&gt;Remote Procedure Calls&lt;/a&gt;中最关键的那个图,就能说明了.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&#34;rpc的flow&#34; loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/rpc-flow.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;本地client调用本地client stub,stub对消息进行封装,通过socket发送,服务端的server stub接收到,然后解包,将里面传递的方法名,方法参数.等等信息,识别出来,调用服务端对应的服务,然后得到结果后,又通过socket返回,本地client又进行解包.就行了.&lt;/p&gt;
&lt;p&gt;这里面会涉及到,封装,封装就是吧对象序列化,这样才能在网络中传递.&lt;/p&gt;
&lt;p&gt;而生产环境的rpc框架需要考虑的有:&lt;/p&gt;
&lt;p&gt;stub怎么生成,序列化怎么最高效,如何统一不同机器之前的调用,(大小端的机器等),如何识别该调用哪个机器,负载均衡.socket通信.等等.&lt;/p&gt;
&lt;p&gt;先跑个demo熟悉一下.&lt;/p&gt;
&lt;p&gt;下载motan源码,导入ide,然后先启动服务端,MotanApiExportDemo,这个类,然后控制台会打出服务已经启动.然后运行MotanApiClientDemo,会发现一个控制台打出motan,服务端打出hello motan.就说明跑起来了.&lt;/p&gt;
&lt;p&gt;如果控制台日志没有.修改对应resources下面的log4j.properties文件.首行添加&lt;code&gt;log4j.rootLogger=debug,stdout&lt;/code&gt; ,会设置默认日志级别为debug,并且在控制台输出.
或者直接fork&lt;a href=&#34;https://github.com/leizhiyuan/motan&#34;&gt;我这个&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;后面会逐步分析,希望坚持下来.&lt;/p&gt;</description>
    </item>
    <item>
      <title>python3.5 安装 Paramiko</title>
      <link>http://blog.leaver.me/2015/12/28/python3.5-%E5%AE%89%E8%A3%85-paramiko/</link>
      <pubDate>Mon, 28 Dec 2015 19:17:25 +0000</pubDate>
      <guid>http://blog.leaver.me/2015/12/28/python3.5-%E5%AE%89%E8%A3%85-paramiko/</guid>
      <description>&lt;p&gt;最近由于一些需求,要搞一下python,于是周末搞了搞.要连接服务器,进行一些服务器的操作,于是安装这个Paramiko包,&lt;/p&gt;
&lt;p&gt;直接&lt;code&gt;pip install paramiko&lt;/code&gt; 结果.报错,最关键的一句是:&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-gdscript3&#34; data-lang=&#34;gdscript3&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;error&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Unable&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;to&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;find&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;vcvarsall&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;bat&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;google一圈.最终找到一种最简单地方法.其他的安装vs.安装MinGW都太复杂了.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;安装PyCrypto 第三方版
因为paramiko依赖PyCrypto,上面那个错就是他报错出来的.安装&lt;a href=&#34;https://github.com/sfbahr/PyCrypto-Wheels&#34;&gt;PyCrypto第三方版&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;pip&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;install&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;--&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;use&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;wheel&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;--&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;no&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;index&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;--&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;find&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;links&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;https&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;//github.com/sfbahr/PyCrypto-Wheels/raw/master/pycrypto-2.6.1-cp35-none-win_amd64.whl pycrypto&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;安装完成后,再次安装paramiko即可.
2.修改nt.py&lt;/p&gt;
&lt;p&gt;安装完上面的步骤,写一个简单的程序测试下&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-java&#34; data-lang=&#34;java&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;#&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-*-&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;coding&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;utf&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;8&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-*-&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;#&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;!/&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;usr&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;bin&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;python&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nn&#34;&gt;paramiko&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nn&#34;&gt;threading&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;def&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;ssh2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ip&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;username&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;passwd&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;cmd&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;try&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ssh&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;paramiko&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;SSHClient&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ssh&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;set_missing_host_key_policy&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;paramiko&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;AutoAddPolicy&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;())&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ssh&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;connect&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ip&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;22&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;username&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;passwd&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;timeout&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;5&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;m&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;in&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;cmd&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;            &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;stdin&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;stdout&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;stderr&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ssh&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;exec_command&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;m&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;            &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;out&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;stdout&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;readlines&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;            &lt;/span&gt;&lt;span class=&#34;err&#34;&gt;#&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;屏幕输出&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;            &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;o&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;in&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;out&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;                &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;o&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;%&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;s&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;\&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;tOK&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;\&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;n&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;%&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ip&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ssh&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;close&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;except&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;%&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;s&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;\&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;tError&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;\&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;n&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;%&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ip&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;__name__&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;==&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;__main__&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;cmd&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;find&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;home&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;admin&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;logs&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;mtime&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;3&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;err&#34;&gt;\&amp;#39;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;log&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;\&amp;#39;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;exec&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;rm&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;rf&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;err&#34;&gt;\&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;#&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;你要执行的命令列表&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;username&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;admin&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;err&#34;&gt;#&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;用户名&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;passwd&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;password&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;err&#34;&gt;#&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;密码&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;threads&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;[]&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;   &lt;/span&gt;&lt;span class=&#34;err&#34;&gt;#&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;多线程&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ip&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;127.0.0.1&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;Begin......&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;threading&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;Thread&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;target&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ssh2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;args&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ip&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;username&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;passwd&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;cmd&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;start&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;input&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;运行报错.
&lt;code&gt;ImportError: No module named &#39;winrandom&#39;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;so一下..找到一个办法
&lt;a href=&#34;http://stackoverflow.com/questions/24804829/another-one-about-pycrypto-and-paramiko&#34;&gt;http://stackoverflow.com/questions/24804829/another-one-about-pycrypto-and-paramiko&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;找到python3.5的安装目录的
&lt;code&gt;Lib\site-packages\Crypto\Random\OSRNG&lt;/code&gt;的nt.py文件将&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-java&#34; data-lang=&#34;java&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nn&#34;&gt;winrandom&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;改成&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-java&#34; data-lang=&#34;java&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;from&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nn&#34;&gt;winrandom&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;再次运行ok.非常简单&lt;/p&gt;</description>
    </item>
    <item>
      <title>json-lib反序列化精度丢失问题</title>
      <link>http://blog.leaver.me/2015/11/25/json-lib%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E7%B2%BE%E5%BA%A6%E4%B8%A2%E5%A4%B1%E9%97%AE%E9%A2%98/</link>
      <pubDate>Wed, 25 Nov 2015 21:30:58 +0000</pubDate>
      <guid>http://blog.leaver.me/2015/11/25/json-lib%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E7%B2%BE%E5%BA%A6%E4%B8%A2%E5%A4%B1%E9%97%AE%E9%A2%98/</guid>
      <description>&lt;p&gt;最近在工作中,遇到一个问题,项目中某处使用了json-lib的2.4-jdk15版本.问题最终简化为&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;double amount = 6264583.33;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;String jsonString = &amp;#34;{\&amp;#34;pi\&amp;#34;:&amp;#34; + amount + &amp;#34;}&amp;#34;;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;JSONObject jsonObject = JSONObject.fromObject(jsonString);
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;System.out.println(&amp;#34;转换前:&amp;#34; + jsonString);
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;System.out.println(&amp;#34;转换后:&amp;#34; + jsonObject);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这个值输出的将会是6264583.5 这个值.这个问题.先google一下,很快赵到了
&lt;a href=&#34;http://sourceforge.net/p/json-lib/bugs/116/&#34;&gt;http://sourceforge.net/p/json-lib/bugs/116/&lt;/a&gt; 于是,大概问题知道了.是json-lib的一个bug,但是这个bug怎么来的呢.结合这个bug下面的评论和debug代码,先以pi这个例子,很快走到了.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&#34;json_create&#34; loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/json_create.jpg&#34;&gt;&lt;/p&gt;
&lt;p&gt;可以看到json-lib走到了apache common-lang(2.5这个版本) 的&lt;code&gt;NumberUtils.createNumber&lt;/code&gt;处,此时String的还是对的.
继续单步,来到这个方法里面&lt;/p&gt;
&lt;p&gt;&lt;img alt=&#34;json_mant_dec&#34; loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/json_mant_dec.jpg&#34;&gt;&lt;/p&gt;
&lt;p&gt;可以看到这里小数部分,整数部分也都还是对的.继续向下走.我擦.画风不太对.居然采用了先尝试float,发现没问题.然后就继续尝试double,我擦.直接数据就丢失了呀..&lt;/p&gt;
&lt;p&gt;&lt;img alt=&#34;json_float&#34; loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/json_float.jpg&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&#34;json_float_fluent&#34; loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/json_float_fluent.jpg&#34;&gt;&lt;/p&gt;
&lt;p&gt;好吧..那么现在问题就便成了更简单的一个问题.&lt;/p&gt;
&lt;p&gt;使用NumberUtils.createNumber 的bug.在bug issue里,有人提到.这个bug,apache官方已知.好的.
&lt;a href=&#34;https://issues.apache.org/jira/browse/LANG-693&#34;&gt;https://issues.apache.org/jira/browse/LANG-693&lt;/a&gt;
然后在这里有官方的一次修复,修复记录在这里.3.2版本已经修复.
&lt;a href=&#34;http://svn.apache.org/viewvc?view=revision&amp;amp;revision=1484263&#34;&gt;http://svn.apache.org/viewvc?view=revision&amp;amp;revision=1484263&lt;/a&gt;
可以看到是对小数部分的长度进行了判断.如果小于7位,就用float转换,如果大于7,小于16,就用double,如果还大,就用BigDecimal.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&#34;json_common_lang3_fix&#34; loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/json_common_lang3_fix.jpg&#34;&gt;&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;n = org.apache.commons.lang3.math.NumberUtils.createNumber(&amp;#34;3.14159265358&amp;#34;);
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;System.out.println(&amp;#34;lang3_createNumber_3.14159265358----&amp;gt;&amp;#34; + n + &amp;#34;-&amp;gt;精度正常&amp;#34;);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;于是我继续debug,看common-lang3的修复情况,好像确实是修复了.但是对于我出现的问题1.6264583.33 这个数字,还是出现了精度丢失,因为这里小数部分小于7位,所以尝试使用float转换,直接丢失精度&lt;/p&gt;
&lt;p&gt;&lt;img alt=&#34;lang3_float_loss&#34; loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/lang3_float_loss.jpg&#34;&gt;&lt;/p&gt;
&lt;p&gt;修复不完善..&lt;/p&gt;
&lt;p&gt;于是提个bug :https://issues.apache.org/jira/browse/LANG-1187 等回复.&lt;/p&gt;
&lt;p&gt;继续.公司内部一般使用fastjson,那么如果我使用fastjson,有问题吗? 发现没有问题.&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;Object o = com.alibaba.fastjson.JSONObject.parse(&amp;#34;3.14159265358&amp;#34;);
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;System.out.println(&amp;#34;fastjson_createNumber_3.14159265358----&amp;gt;&amp;#34; + o + &amp;#34;-&amp;gt;精度正常&amp;#34;);
&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;o = com.alibaba.fastjson.JSONObject.parse(&amp;#34;6264583.33&amp;#34;);
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;System.out.println(&amp;#34;fastjson_createNumber_6264583.33----&amp;gt;&amp;#34; + o + &amp;#34;-&amp;gt;精度正常&amp;#34;);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img alt=&#34;fastjson_decimal&#34; loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/fastjson_decimal.jpg&#34;&gt;&lt;/p&gt;
&lt;p&gt;可以看到,这里做转换的时候传递了一个是否是bigdecimal的标识.而这个标识默认是开启的.而且即使不开启..&lt;/p&gt;
&lt;p&gt;&lt;img alt=&#34;fastjson_first_decimal&#34; loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/fastjson_first_decimal.jpg&#34;&gt;&lt;/p&gt;
&lt;p&gt;最坏的情况也是个double.所以数据不会丢失.&lt;/p&gt;
&lt;p&gt;再顺便说一下,double的6264583.33 为什么转换到float会精度丢失,先看一下浮点数在计算机中怎么表示的
&lt;img alt=&#34;double_present&#34; loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/double_present.jpg&#34;&gt;
找到一张图,这是double的标识和浮点数的计算.&lt;/p&gt;
&lt;p&gt;而浮点数则是32位,1位符号位,8位幂,23位尾数,看测试代码&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;//double标识测试
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;double d = 6264583.33d;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;long l = Double.doubleToLongBits(d);
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;System.out.println(Long.toBinaryString(l));
&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;//float想要表示这个数字
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;float f = 6264583.33f;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;int value = Float.floatToIntBits(f);
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;System.out.println(Integer.toBinaryString(value));
&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;//double表示这个值
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;d = 6264583.5d;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;l = Double.doubleToLongBits(d);
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;System.out.println(Long.toBinaryString(l));
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;输出结果(做一下分割对齐)&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;1 00000101010    111111001011100000111010101000111101011100001010010
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;1    00101010    1111110010111000001111
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;1 00000101010    111111001011100000111100000000000000000000000000000
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;注意看,第一行是6264583.33的double表示.而同样想要用float表示这个数字,发现幂,符号位,都是对的.但是因为尾数只有23位,所以四舍五入,将完整double的后几位进位1,变成了这个二进制表示法,这时候已经不准确了,
而这个数字呢.看第三行,会发现实际上是6264583.5的精确值表示.尾数位0都是可以省略的,因为按照公式计算也没啥作用.&lt;/p&gt;
&lt;p&gt;如有问题,欢迎评论讨论.&lt;/p&gt;
&lt;p&gt;附录:
完整的测试代码&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;public class App {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    public static void main(String[] args) {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;//http://sourceforge.net/p/json-lib/bugs/116/
&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;//2.4版本有问题
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;double pi = 3.14159265358;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;String jsonString = &amp;#34;{\&amp;#34;pi\&amp;#34;:&amp;#34; + pi + &amp;#34;}&amp;#34;;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;JSONObject jsonObject = JSONObject.fromObject(jsonString);
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;System.out.println(&amp;#34;转换前:&amp;#34; + jsonString);
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;System.out.println(&amp;#34;转换后:&amp;#34; + jsonObject);
&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;double amount = 6264583.33;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;jsonString = &amp;#34;{\&amp;#34;pi\&amp;#34;:&amp;#34; + amount + &amp;#34;}&amp;#34;;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;jsonObject = JSONObject.fromObject(jsonString);
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;System.out.println(&amp;#34;转换前:&amp;#34; + jsonString);
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;System.out.println(&amp;#34;转换后:&amp;#34; + jsonObject);
&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;//测试2.4版本引入的lang,这里面
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Number n = org.apache.commons.lang.math.NumberUtils.createNumber(&amp;#34;3.14159265358&amp;#34;);
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;System.out.println(&amp;#34;lang2_createNumber_3.14159265358----&amp;gt;&amp;#34; + n + &amp;#34;-&amp;gt;精度丢失&amp;#34;);
&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;n = org.apache.commons.lang.math.NumberUtils.createNumber(&amp;#34;6264583.33&amp;#34;);
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;System.out.println(&amp;#34;lang2_createNumber_6264583.33----&amp;gt;&amp;#34; + n + &amp;#34;-&amp;gt;精度丢失&amp;#34;);
&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;//测试3.4版本,里面是根据小数部分的长度,选择是否使用float还是double,当小数部分大于7的时候,就会使用double
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;n = org.apache.commons.lang3.math.NumberUtils.createNumber(&amp;#34;3.14159265358&amp;#34;);
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;System.out.println(&amp;#34;lang3_createNumber_3.14159265358----&amp;gt;&amp;#34; + n + &amp;#34;-&amp;gt;精度正常&amp;#34;);
&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;//这种情况就会有问题,虽然小数部分是33,两位,但是实际上是个浮点数.所以还会丢失精度
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;n = org.apache.commons.lang3.math.NumberUtils.createNumber(&amp;#34;6264583.33&amp;#34;);
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;System.out.println(&amp;#34;lang3_createNumber_6264583.33----&amp;gt;&amp;#34; + n + &amp;#34;-&amp;gt;精度丢失&amp;#34;);
&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;//测试fastjson
&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;Object o = com.alibaba.fastjson.JSONObject.parse(&amp;#34;3.14159265358&amp;#34;);
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;System.out.println(&amp;#34;fastjson_createNumber_3.14159265358----&amp;gt;&amp;#34; + o + &amp;#34;-&amp;gt;精度正常&amp;#34;);
&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;o = com.alibaba.fastjson.JSONObject.parse(&amp;#34;6264583.33&amp;#34;);
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;System.out.println(&amp;#34;fastjson_createNumber_6264583.33----&amp;gt;&amp;#34; + o + &amp;#34;-&amp;gt;精度正常&amp;#34;);
&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;//double标识测试
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;double d = 6264583.33d;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;long l = Double.doubleToLongBits(d);
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;System.out.println(Long.toBinaryString(l));
&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;//float想要表示这个数字
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;float f = 6264583.33f;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;int value = Float.floatToIntBits(f);
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;System.out.println(Integer.toBinaryString(value));
&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;//double表示这个值
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;d = 6264583.5d;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;l = Double.doubleToLongBits(d);
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;System.out.println(Long.toBinaryString(l));
&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;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
    </item>
    <item>
      <title>zookeeper伪集群部署</title>
      <link>http://blog.leaver.me/2015/11/22/zookeeper%E4%BC%AA%E9%9B%86%E7%BE%A4%E9%83%A8%E7%BD%B2/</link>
      <pubDate>Sun, 22 Nov 2015 16:06:43 +0000</pubDate>
      <guid>http://blog.leaver.me/2015/11/22/zookeeper%E4%BC%AA%E9%9B%86%E7%BE%A4%E9%83%A8%E7%BD%B2/</guid>
      <description>&lt;p&gt;zookeeper是用来管理分布式环境的系统主要用来服务发现,配置管理,同步.大致原理是zookeeper 自身集群的每个节点都维护这一个目录树,内容相同,每个节点的数据一致性由zookeeper自身的算法来解决.下篇尝试.zookeeper本篇主要说明如果部署zookeeper的分布式环境.&lt;/p&gt;
&lt;h2 id=&#34;下载&#34;&gt;下载&lt;/h2&gt;
&lt;p&gt;zookeeper由apache在管理,下载地址:&lt;a href=&#34;http://www.apache.org/dyn/closer.cgi/zookeeper/&#34;&gt;http://www.apache.org/dyn/closer.cgi/zookeeper/&lt;/a&gt;.下载完成后,随便放个目录好了..&lt;/p&gt;
&lt;h2 id=&#34;配置&#34;&gt;配置&lt;/h2&gt;
&lt;p&gt;本次创建3个节点.
1 . 存储目录准备
首先给每个伪节点创建一个目录.用来存储每个节点保存的目录信息.真实的分布式环境将对应在不同的机器上.
这里我在D:\zookeeper,创建三个目录,分别是zk1,zk2,zk3.
然后为每个集群编写一个myid文件,标识集群id&lt;/p&gt;
&lt;p&gt;2 . 启动配置文件
下载完成后,在conf目录会看到由一个zoo_sample.cfg实例配置文件,我们可以以这个为模板.来为分布式环境的每个zookeeper节点配置一个节点的数据目录,端口.其他节点的信息等.&lt;/p&gt;
&lt;p&gt;我们在conf目录例创建三个配置文件,分别为zk1.cfg,zk2.cfg,zk3.cfg;
里面的值
zk1.cfg&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;tickTime=2000 
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;initLimit=10 
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;syncLimit=5 
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;dataDir=D:/zookeeper/zk1 
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;clientPort=2181 
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;server.1=127.0.0.1:2888:3888 
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;server.2=127.0.0.1:2889:3889 
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;server.3=127.0.0.1:2890:3890
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;zk2.cfg&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;tickTime=2000 
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;initLimit=10 
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;syncLimit=5 
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;dataDir=D:/zookeeper/zk2 
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;clientPort=2182 
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;server.1=127.0.0.1:2888:3888 
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;server.2=127.0.0.1:2889:3889 
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;server.3=127.0.0.1:2890:3890
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;zk1.cfg&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;tickTime=2000 
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;initLimit=10 
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;syncLimit=5 
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;dataDir=D:/zookeeper/zk3
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;clientPort=2183 
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;server.1=127.0.0.1:2888:3888 
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;server.2=127.0.0.1:2889:3889 
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;server.3=127.0.0.1:2890:3890
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这里的server.1.2.3这就是每个机器对应的myid的值.
server.1=127.0.0.1:2888:3888解释一下这条配置.前面的2888是各个节点用来互相交流.选取leader的端口.后面这个端口,3888是各个节点用来和leader沟通的节点.而clientPort 是开放出去,等待客户端连接的端口.&lt;/p&gt;
&lt;h2 id=&#34;启动&#34;&gt;启动&lt;/h2&gt;
&lt;p&gt;分别启动三个实例,在zookeeper的安装目录下.进如bin目录,复制三个zkServer.cmd 文件,要是linux就不用这么麻烦了..&lt;/p&gt;
&lt;p&gt;分别加上一行&lt;/p&gt;
&lt;p&gt;set ZOOCFG=../conf/zk1.cfg&lt;/p&gt;
&lt;p&gt;最终这个文件像这样&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;setlocal
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;call &amp;#34;%~dp0zkEnv.cmd&amp;#34;
&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;set ZOOMAIN=org.apache.zookeeper.server.quorum.QuorumPeerMain
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;set ZOOCFG=../conf/zk1.cfg
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;echo on
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;java &amp;#34;-Dzookeeper.log.dir=%ZOO_LOG_DIR%&amp;#34; &amp;#34;-Dzookeeper.root.logger=%ZOO_LOG4J_PROP%&amp;#34; -cp &amp;#34;%CLASSPATH%&amp;#34; %ZOOMAIN% &amp;#34;%ZOOCFG%&amp;#34; %*
&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;endlocal
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;然后直接双击启动zkServer1.cmd,zkServer2.cmd,zkServer3.cmd&lt;/p&gt;
&lt;p&gt;刚启动第一个之后,你会看到有报错,是zookeeper进行选举的时候报错的.因为第一个zk节点.从自己的启动配置里,知道还有两个节点,于是尝试连接.但是连接不上,再启动另外两个.都启动后,报错消失&lt;/p&gt;
&lt;p&gt;然后在D:\zookeeper中可以看到由数据写入.
&lt;img alt=&#34;zk数据目录&#34; loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/zk_result.jpg&#34;&gt;&lt;/p&gt;
&lt;h2 id=&#34;测试&#34;&gt;测试&lt;/h2&gt;
&lt;p&gt;启动bin目录的zkCli.cmd,自动连接本机的2181端口.也可以自己指定
zkCli.cmd –server 127.0.0.1:2181,127.0.0.1:2182,127.0.0.1:2183
对客户端来说.连接上了一个列表之后,如果一台挂了,并不会影响.系统依旧可以运行.&lt;/p&gt;
&lt;p&gt;然后执行一些简单的操作
&lt;img alt=&#34;zk测试结果&#34; loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/zk_operation_test.jpg&#34;&gt;&lt;/p&gt;
&lt;p&gt;显示根目录下、文件： ls / 使用 ls 命令来查看当前 ZooKeeper 中所包含的内容。
显示根目录下、文件： ls2 / 查看当前节点数据并能看到更新次数等数据。
创建文件，并设置初始内容： create /zktest &amp;ldquo;test&amp;rdquo; 创建一个新的 znode节点“ zk ”以及与它关联的字符串。
获取文件内容： get /zktest 确认 znode 是否包含我们所创建的字符串。
修改文件内容： set /zktest &amp;ldquo;zkbak&amp;rdquo; 对 zk 所关联的字符串进行设置。
删除文件： delete /zktest 将刚才创建的 znode 删除。
退出客户端： quit
帮助命令： help&lt;/p&gt;
&lt;p&gt;可以关掉一个服务器,会发现客户端依然正常.可以执行get set等操作.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Java可重入锁学习笔记</title>
      <link>http://blog.leaver.me/2015/11/20/java%E5%8F%AF%E9%87%8D%E5%85%A5%E9%94%81%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/</link>
      <pubDate>Fri, 20 Nov 2015 20:51:25 +0000</pubDate>
      <guid>http://blog.leaver.me/2015/11/20/java%E5%8F%AF%E9%87%8D%E5%85%A5%E9%94%81%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/</guid>
      <description>&lt;p&gt;前几天被前辈问到这个可重入锁,结果忘掉了.于是抽空整个了解一下&lt;/p&gt;
&lt;h2 id=&#34;目录&#34;&gt;目录&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;什么是可重入锁&lt;/li&gt;
&lt;li&gt;为什么要可重入&lt;/li&gt;
&lt;li&gt;如何实现可重入锁&lt;/li&gt;
&lt;li&gt;有不可重入锁吗&lt;/li&gt;
&lt;li&gt;demo代码展示&lt;/li&gt;
&lt;li&gt;参考文章&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;1--什么是可重入锁&#34;&gt;1 . 什么是可重入锁&lt;/h2&gt;
&lt;p&gt;锁的概念就不用多解释了,当某个线程A已经持有了一个锁,当线程B尝试进入被这个锁保护的代码段的时候.就会被阻塞.而锁的操作粒度是&amp;quot;线程&amp;quot;,而不是调用(至于为什么要这样,下面解释).同一个线程再次进入同步代码的时候.可以使用自己已经获取到的锁,这就是可重入锁
java里面内置锁(synchronize)和Lock(ReentrantLock)都是可重入的&lt;/p&gt;
&lt;h2 id=&#34;2--为什么要可重入&#34;&gt;2 . 为什么要可重入&lt;/h2&gt;
&lt;p&gt;如果线程A继续再次获得这个锁呢?比如一个方法是synchronized,递归调用自己,那么第一次已经获得了锁,第二次调用的时候还能进入吗? 直观上当然需要能进入.这就要求必须是可重入的.可重入锁又叫做递归锁,再举个例子.&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-gdscript3&#34; data-lang=&#34;gdscript3&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;public&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;class&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Widget&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;public&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;synchronized&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;void&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;doSomething&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;o&#34;&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&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;&lt;span class=&#34;n&#34;&gt;public&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;class&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;LoggingWidget&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;extends&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Widget&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;public&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;synchronized&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;void&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;doSomething&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;n&#34;&gt;System&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;out&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;println&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;toString&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;: calling doSomething&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;n&#34;&gt;super&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;doSomething&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;//&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;若内置锁是不可重入的，则发生死锁&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这个例子是java并发编程实战中的例 子.synchronized 是父类Widget的内置锁,当执行子 类的方法的时候,先获取了一次Widget的锁,然后在执行super的时候,就要获取一次,如果不可重入,那么就跪了.&lt;/p&gt;
&lt;h2 id=&#34;3--如何实现可重入锁&#34;&gt;3 . 如何实现可重入锁&lt;/h2&gt;
&lt;p&gt;为每个锁关联一个获取计数器和一个所有者线程,当计数值为0的时候,这个所就没有被任何线程只有.当线程请求一个未被持有的锁时,JVM将记下锁的持有者,并且将获取计数值置为1,如果同一个线程再次获取这个锁,技术值将递增,退出一次同步代码块,计算值递减,当计数值为0时,这个锁就被释放.
ReentrantLock里面有实现&lt;/p&gt;
&lt;h2 id=&#34;4--有不可重入锁吗&#34;&gt;4 . 有不可重入锁吗&lt;/h2&gt;
&lt;p&gt;这个还真有.Linux下的pthread_mutex_t锁是默认是非递归的。可以通过设置PTHREAD_MUTEX_RECURSIVE属性，将pthread_mutex_t锁设置为递归锁。如果要自己实现不可重入锁,同可重入锁,这个计数器只能为1.或者0,再次进入的时候,发现已经是1了,就进行阻塞.jdk里面没有默认的实现类.&lt;/p&gt;
&lt;h2 id=&#34;5--demo代码展示&#34;&gt;5 . demo代码展示&lt;/h2&gt;
&lt;p&gt;5.1 内置锁的可重入&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;public class ReentrantTest {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    public void method1() {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        synchronized (ReentrantTest.class) {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            System.out.println(&amp;#34;方法1获得ReentrantTest的内置锁运行了&amp;#34;);
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            method2();
&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;    }
&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;    public void method2() {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        synchronized (ReentrantTest.class) {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            System.out.println(&amp;#34;方法1里面调用的方法2重入内置锁,也正常运行了&amp;#34;);
&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;    }
&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;    public static void main(String[] args) {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        new ReentrantTest().method1();
&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;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;5.2 lock对象的可重入&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;import java.util.concurrent.locks.Lock;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;import java.util.concurrent.locks.ReentrantLock;
&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;public class ReentrantLockTest {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    private Lock lock = new ReentrantLock();
&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;    public void method1() {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        lock.lock();
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        try {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            System.out.println(&amp;#34;方法1获得ReentrantLock锁运行了&amp;#34;);
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            method2();
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        } finally {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            lock.unlock();
&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;    }
&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;    public void method2() {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        lock.lock();
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        try {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            System.out.println(&amp;#34;方法1里面调用的方法2重入ReentrantLock锁,也正常运行了&amp;#34;);
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        } finally {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            lock.unlock();
&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;    }
&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;    public static void main(String[] args) {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        new ReentrantLockTest().method1();
&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;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;5.3 不同线程不可访问同一锁&lt;/p&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>Spring揭秘-23章，Spring MVC初体验</title>
      <link>http://blog.leaver.me/2014/07/13/spring%E6%8F%AD%E7%A7%98-23%E7%AB%A0spring-mvc%E5%88%9D%E4%BD%93%E9%AA%8C/</link>
      <pubDate>Sun, 13 Jul 2014 11:26:24 +0000</pubDate>
      <guid>http://blog.leaver.me/2014/07/13/spring%E6%8F%AD%E7%A7%98-23%E7%AB%A0spring-mvc%E5%88%9D%E4%BD%93%E9%AA%8C/</guid>
      <description>&lt;p&gt; 鸟瞰Spring MVC&lt;div&gt;与其他请求驱动的Web框架思路类似。org.springframework.web.servlet.DispatcherServlet就是Spring mvC中的Front Controller。负责处理请求，但是不针对具体的处理逻辑。而是委派给下一级的控制器，也就是&lt;span style=&#34;font-size: 10.5pt; line-height: 1.5;&#34;&gt;org.springframework.web.servlet.mvc.Controller&lt;/span&gt;&lt;span style=&#34;font-size: 10.5pt; line-height: 1.5;&#34;&gt;去执行。&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&#34;font-size: 10.5pt; line-height: 1.5;&#34;&gt;
&lt;/span&gt;&lt;/div&gt;&lt;div&gt;DispatcherServlet的处理流程如下：&lt;/div&gt;&lt;div&gt;1.HandlerMapping&lt;/div&gt;&lt;div&gt;DispathcherServlet是FrontController，所以他服务于一组Web请求，需要在web.xml中配置。&lt;/div&gt;&lt;div&gt;DispathcherServlet需要自己处理请求和处理之前的对应关系，比如根据参数对应到不同的Controller上。为了更加方便的处理映射的匹配，引入&lt;span style=&#34;font-size: 10.5pt; line-height: 1.5;&#34;&gt;HandlerMapping用来获取需要处理请求的对应的Controller类。&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;&lt;div&gt;&lt;span style=&#34;font-size: 10.5pt; line-height: 1.5;&#34;&gt;2.Controller&lt;/span&gt;&lt;/div&gt;&lt;div&gt;对应于&lt;span style=&#34;font-size: 10.5pt; line-height: 1.5;&#34;&gt;DispathcherServlet的次级控制器，本身实现了对应某个具体Web请求的处理逻辑，当&lt;/span&gt;&lt;span style=&#34;font-size: 10.5pt; line-height: 1.5;&#34;&gt;HandlerMapping查到了Controller之后，&lt;/span&gt;&lt;span style=&#34;font-size: 10.5pt; line-height: 1.5;&#34;&gt;DispathcherServlet获得了&lt;/span&gt;&lt;span style=&#34;font-size: 10.5pt; line-height: 1.5;&#34;&gt;HandlerMapping的返回结果。然后调用Controller处理请求，处理完成后，返回一个ModelAndView实例，里面包含两部分内容&lt;/span&gt;&lt;/div&gt;&lt;div&gt;视图的逻辑名称，&lt;span style=&#34;font-size: 10.5pt; line-height: 1.5;&#34;&gt;DispathcherServlet根据名称决定显示哪个视图&lt;/span&gt;&lt;/div&gt;&lt;div&gt;模型数据，渲染过程中需要将这些模型数据并入视图的显示中&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;div&gt;ViewResolver和View&lt;/div&gt;&lt;div&gt;我们已经来到了最后一步，要转成最终的JSP视图文件。由于模板引擎很多，Spring提供了一套基于ViewResolver和View的抽象层。&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;div&gt;![](/images/fc45dedeba68b31c39383776fc7a7a35eba30a5a.jpg)
&lt;/div&gt;
&lt;div&gt;[来自为知笔记(Wiz)](http://www.wiz.cn/i/e0140d75 &#34;来自为知笔记(Wiz)&#34;)&lt;/div&gt;</description>
    </item>
    <item>
      <title>Spring揭秘-22章，迈向Spring MVC的旅程</title>
      <link>http://blog.leaver.me/2014/07/13/spring%E6%8F%AD%E7%A7%98-22%E7%AB%A0%E8%BF%88%E5%90%91spring-mvc%E7%9A%84%E6%97%85%E7%A8%8B/</link>
      <pubDate>Sun, 13 Jul 2014 11:25:39 +0000</pubDate>
      <guid>http://blog.leaver.me/2014/07/13/spring%E6%8F%AD%E7%A7%98-22%E7%AB%A0%E8%BF%88%E5%90%91spring-mvc%E7%9A%84%E6%97%85%E7%A8%8B/</guid>
      <description>&lt;p&gt;Spring揭秘-22章，迈向Spring MVC的旅程&lt;div&gt;&lt;/p&gt;
&lt;/div&gt;&lt;div&gt;Servlet导致数据访问逻辑和业务处理逻辑和对应的视图渲染逻辑相互混杂。之后，JSP出现，通过将输出渲染以模板的形式抽取到jsp后缀的模板文件中，jsp开始繁盛，同时要注意，Servlet处理web请求的时候，要在web.xml中，注册相应的请求url和具体的Serlet的映射关系。于是，jsp有开始混合着写代码&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;div&gt;于是，我们引入了JavaBean,来封装相关业务逻辑，经过一次升级后，&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;div&gt;![](/images/e6af173baae0c480b8dddc398ce8dd3078b260e4.jpg)
&lt;/div&gt;&lt;div&gt;这个模型就比较清楚了。但是和MVC还是有点差别&lt;/div&gt;&lt;div&gt;一个典型的mvc模式应该是这样的&lt;/div&gt;&lt;div&gt;![](/images/4bcce41a42b7cc021f4b726da1c3533cc5371a21.jpg)
&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;div&gt;控制器处理请求，模型封装逻辑和状态，视图给用户，&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;div&gt;Structs以请求/响应框架为基础。&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;div&gt;Spring MVC属于请求渠道的WEb框架。框架引入Front Controller做分发之后，就更加好管理了。&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;div&gt;![](/images/131d593fd9a36cfc8180a4b86495208a356ae563.jpg)
&lt;/div&gt;
&lt;div&gt;[来自为知笔记(Wiz)](http://www.wiz.cn/i/e0140d75 &#34;来自为知笔记(Wiz)&#34;)&lt;/div&gt;</description>
    </item>
    <item>
      <title>Spring揭秘-第13章 统一的数据访问异常层次体系</title>
      <link>http://blog.leaver.me/2014/07/13/spring%E6%8F%AD%E7%A7%98-%E7%AC%AC13%E7%AB%A0-%E7%BB%9F%E4%B8%80%E7%9A%84%E6%95%B0%E6%8D%AE%E8%AE%BF%E9%97%AE%E5%BC%82%E5%B8%B8%E5%B1%82%E6%AC%A1%E4%BD%93%E7%B3%BB/</link>
      <pubDate>Sun, 13 Jul 2014 11:25:13 +0000</pubDate>
      <guid>http://blog.leaver.me/2014/07/13/spring%E6%8F%AD%E7%A7%98-%E7%AC%AC13%E7%AB%A0-%E7%BB%9F%E4%B8%80%E7%9A%84%E6%95%B0%E6%8D%AE%E8%AE%BF%E9%97%AE%E5%BC%82%E5%B8%B8%E5%B1%82%E6%AC%A1%E4%BD%93%E7%B3%BB/</guid>
      <description>&lt;p&gt;Spring揭秘-第13章 统一的数据访问异常层次体系&lt;/p&gt;
&lt;div&gt;&lt;/div&gt;
&lt;div&gt;DAO可以分离数据哭的访问和存储，屏蔽各种数据访问方式的差异性，下面以访问顾客信息为例，使用DAO模式&lt;/div&gt;
&lt;div&gt;首先定义一个数据访问对象接口，如下&lt;/div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;div&gt;
&lt;div class=&#34;kwd&#34;&gt;
&lt;pre class=&#34;lang:default decode:true &#34;&gt;    public interrface ICustomerDao{
    Customer findCustomerByPK(String customerId);
    void updateCustomerStatus(Customer customer);&lt;/pre&gt;
&amp;nbsp;
&lt;/div&gt;
&lt;div class=&#34;kwd&#34;&gt;之后，所有的数据访问都通过该接口进行，不论底层存储机制如何改变，DAO的实现因此会扩展，但客户端代码不需要调整&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;pre class=&#34;lang:default decode:true &#34;&gt;    publicclassCustomerService
    {
    privateICustomerDao customerDao;
    publicvoid disableCustomerCampain(String customerId)
    {
    Customer customer=getCustomerDao().findCustomerByPK(customerId);
    customer.setCampainStatus(CampainStatus.DISABLE);
    getCustomerDao().updateCustomerStatus(customer);
    }
    publicICustomerDao getCustomerDao()
    {
    return customerDao;
    }
    publicvoid setCustomerDao(ICustomerDao customerDao)
    {
    this.customerDao=customerDao;
    }&lt;/pre&gt;
&amp;nbsp;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;我们只要针对不同的数据存储方式实现不同的Dao类即可。&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;    publicCustomer findCustomerByPK(String customerId)
    {
    Connection con=null;
    try{
    con=getDataSource().getConnection();
    Customer cust=..;
    return cust;
    }
    catch(SQLException e){
    //这里咋办，直接抛出还是直接处理？
    }
    finally{
    releaseConnection(con);
    }
    }
    privatevoid releaseConnection(Connection con){
    }&lt;/pre&gt;
&amp;nbsp;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&lt;span class=&#34;typ&#34; style=&#34;font-family: Consolas, &#39;Liberation Mono&#39;, Menlo, Courier, monospace; line-height: 18px; white-space: pre; background-color: #f7f7f9;&#34;&gt;SQLException&lt;/span&gt;&lt;span class=&#34;pln&#34; style=&#34;font-family: Consolas, &#39;Liberation Mono&#39;, Menlo, Courier, monospace; line-height: 18px; white-space: pre; background-color: #f7f7f9;&#34;&gt; 是checked exception，如果在DAO的实现类里直接处理掉，那么客户端怎么知道发生了问题，&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span class=&#34;pln&#34; style=&#34;font-family: Consolas, &#39;Liberation Mono&#39;, Menlo, Courier, monospace; line-height: 18px; white-space: pre; background-color: #f7f7f9;&#34;&gt; &lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span class=&#34;pln&#34; style=&#34;font-family: Consolas, &#39;Liberation Mono&#39;, Menlo, Courier, monospace; line-height: 18px; white-space: pre; background-color: #f7f7f9;&#34;&gt;于是，只能处理，那么客户端的签名就要改了&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;span class=&amp;quot;typ&amp;quot;&amp;gt;Customer&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;pln&amp;quot;&amp;gt; findCustomerByPK&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;pun&amp;quot;&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;typ&amp;quot;&amp;gt;String&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;pln&amp;quot;&amp;gt; customerId&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;pun&amp;quot;&amp;gt;)&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;kwd&amp;quot;&amp;gt;throws&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;typ&amp;quot;&amp;gt;SQLExcepiton&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;pun&amp;quot;&amp;gt;;&amp;lt;/span&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;div&gt;ICustomerDao也要改了，可是这样的话&lt;/div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;div&gt;如果数据在其他方式存储，那么其他类型的异常捕获就要继续添加到方法签名。由于数据访问机制的不同，导致这个接口签名不断在变化。&lt;/div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;div&gt;那怎么办呢？DAO如此美好的远景。&lt;/div&gt;
&lt;div&gt;直接抛出，的话，因此，可以根据发生的异常信息封装成不同的unchecked exception，然后抛出，这样方法签名不用改。因为unchecked不需要编译器检查。&lt;/div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;div&gt;要开始写了？Spring的数据访问异常层次体系已经给我们做完了&lt;/div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;div&gt;该体系下面所有的异常类型均以DataAccessException为统领，然后划分成不同的子类型&lt;/div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;div&gt;![](/images/3ab324530a8c3d0b0216d3f7549ebbfa6b7869f4.jpg)&lt;/div&gt;
&lt;div&gt;这些类是啥搜索一下，或者根据名字猜一下，之后我们就可以&lt;/div&gt;
&lt;/div&gt;</description>
    </item>
    <item>
      <title>Spring揭秘-第四章BeanFactory笔记</title>
      <link>http://blog.leaver.me/2014/07/13/spring%E6%8F%AD%E7%A7%98-%E7%AC%AC%E5%9B%9B%E7%AB%A0beanfactory%E7%AC%94%E8%AE%B0/</link>
      <pubDate>Sun, 13 Jul 2014 11:20:09 +0000</pubDate>
      <guid>http://blog.leaver.me/2014/07/13/spring%E6%8F%AD%E7%A7%98-%E7%AC%AC%E5%9B%9B%E7%AB%A0beanfactory%E7%AC%94%E8%AE%B0/</guid>
      <description>&lt;div&gt;&lt;/div&gt;
&lt;div&gt;之前说了，IoC容器就是一个IoC Service Provider，但是容器是个啥意思？![](/images/d4d1615a6c1a06895088631c37e3fca7692f0b8a.png)&lt;/div&gt;
&lt;div&gt;可以看到IoC容器提供了更多的内容，&lt;/div&gt;
&lt;div&gt;Spring的IoC容器又分成两种，&lt;/div&gt;
&lt;div&gt;1.BeanFactory&lt;/div&gt;
&lt;div&gt;。基础类型IoC容器，提供完整的IoC服务支持。如果没有特殊指定，默认采用延 迟初始化策略（lazy-load）。只有当客户端对象需要访问容器中的某个受管对象的时候，才对 该受管对象进行初始化以及依赖注入操作。所以，相对来说，容器启动初期速度较快，所需 要的资源有限。对于资源有限，并且功能要求不是很严格的场景，BeanFactory是比较合适的 IoC容器选择。&lt;/div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;div&gt;2.ApplicationContext。ApplicationContext在BeanFactory的基础上构建，是相对比较高 级的容器实现，除了拥有BeanFactory的所有支持，ApplicationContext还提供了其他高级&lt;span style=&#34;font-size: 10.5pt; line-height: 1.5;&#34;&gt;特性，比如事件发布、国际化信息支持等，这些会在后面详述。ApplicationContext所管理 的对象，在该类型容器启动之后，默认全部初始化并绑定完成。所以，相对于BeanFactory来 说，ApplicationContext要求更多的系统资源，同时，因为在启动时就完成所有初始化，容 器启动时间较之BeanFactory也会长一些。在那些系统资源充足，并且要求更多功能的场景中， ApplicationContext类型的容器是比较合适的选择。 &lt;/span&gt;&lt;/div&gt;
&lt;div&gt; 通过 图4-2，我们可以对BeanFactory和ApplicationContext之间的关系有一个更清晰的认识。&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;&lt;/div&gt;
&lt;div&gt;![](/images/f531ea3e11bb391453eb5f763283398c938634b2.png)&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;Bean工长，就是生成Bean的嘛，每个业务对象被看成Javabean,我们与工厂打交道就简单得多，我们只要告诉他我要什么对象，至于怎么组装，那是他的事情。&lt;/div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;div&gt;工厂提供了一些对外的接口，比如获取Bean，渠道Bean的状态等等。&lt;/div&gt;
&lt;div&gt;以xml为例&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;&amp;lt;?xml version=&#34;1.0&#34; encoding=&#34;UTF-8&#34;?&amp;gt; 
&amp;lt;!DOCTYPE beans PUBLIC &#34;-//SPRING//DTD BEAN//EN&#34; &#34;http://www.springframework.org/dtd/spring-beans.dtd&#34;&amp;gt;  
&amp;lt;beans&amp;gt;  
 &amp;lt;bean id=&#34;djNewsProvider&#34; class=&#34;..FXNewsProvider&#34;&amp;gt;   
    &amp;lt;constructor-arg index=&#34;0&#34;&amp;gt;    
       &amp;lt;ref bean=&#34;djNewsListener&#34;/&amp;gt;   
     &amp;lt;/constructor-arg&amp;gt;   
   &amp;lt;constructor-arg index=&#34;1&#34;&amp;gt;    
       &amp;lt;ref bean=&#34;djNewsPersister&#34;/&amp;gt;   
   &amp;lt;/constructor-arg&amp;gt;  
 &amp;lt;/bean&amp;gt;    
 &amp;lt;bean id=&#34;djNewsListener&#34; class=&#34;..impl.DowJonesNewsListener&#34;&amp;gt;  
 &amp;lt;/bean&amp;gt;  
 &amp;lt;bean id=&#34;djNewsPersister&#34; class=&#34;..impl.DowJonesNewsPersister&#34;&amp;gt;  
 &amp;lt;/bean&amp;gt; 
&amp;lt;/beans&amp;gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;然后&lt;/div&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;public static void main(String[] args)  {
   DefaultListableBeanFactory beanRegistry = new DefaultListableBeanFactory();     
   BeanFactory container = (BeanFactory)bindViaXMLFile(beanRegistry);  
   FXNewsProvider newsProvider = (FXNewsProvider)container.getBean(&#34;djNewsProvider&#34;); 
   newsProvider.getAndPersistNews(); 
}  
public static BeanFactory bindViaXMLFile(BeanDefinitionRegistry registry)  
{  
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(registry);  
reader.loadBeanDefinitions(&#34;classpath:../news-config.xml&#34;);   
return (BeanFactory)registry;  // 或者直接  
//return new XmlBeanFactory(new ClassPathResource(&#34;../news-config.xml&#34;));
 }&lt;/pre&gt;
&lt;div&gt;&lt;/div&gt;
&lt;div&gt;人生好像就美好&lt;/div&gt;</description>
    </item>
    <item>
      <title>Spring揭秘-第三章IoC Service Provider读书笔记</title>
      <link>http://blog.leaver.me/2014/07/13/spring%E6%8F%AD%E7%A7%98-%E7%AC%AC%E4%B8%89%E7%AB%A0ioc-service-provider%E8%AF%BB%E4%B9%A6%E7%AC%94%E8%AE%B0/</link>
      <pubDate>Sun, 13 Jul 2014 11:18:02 +0000</pubDate>
      <guid>http://blog.leaver.me/2014/07/13/spring%E6%8F%AD%E7%A7%98-%E7%AC%AC%E4%B8%89%E7%AB%A0ioc-service-provider%E8%AF%BB%E4%B9%A6%E7%AC%94%E8%AE%B0/</guid>
      <description>&lt;p&gt;&lt;span style=&#34;color: #000000; font-family: &#39;Microsoft YaHei UI&#39;, &#39;Microsoft YaHei&#39;, SimSun, &#39;Segoe UI&#39;, Tahoma, Helvetica, sans-serif, &#39;Microsoft YaHei&#39;, Georgia, Helvetica, Arial, sans-serif, 宋体, PMingLiU, serif; font-size: 14.399999618530273px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 16.799999237060547px; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; display: inline !important; float: none;&#34;&gt;我们虽然已经通过IoC声明了相应的依赖，但是最终总要有个啥东西将这些依赖对象绑定在一起，这里而IoC Service Provider, 来啦，表示一种绑定的实现方式，可以使一段代码，也可以是一组相关的泪，甚至是框架或容器。&lt;/span&gt;&lt;/p&gt;
&lt;div style=&#34;color: #000000; font-family: &#39;Microsoft YaHei UI&#39;, &#39;Microsoft YaHei&#39;, SimSun, &#39;Segoe UI&#39;, Tahoma, Helvetica, sans-serif, &#39;Microsoft YaHei&#39;, Georgia, Helvetica, Arial, sans-serif, 宋体, PMingLiU, serif; font-size: 14.399999618530273px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 16.799999237060547px; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;&#34;&gt;&lt;/div&gt;
&lt;div style=&#34;color: #000000; font-family: &#39;Microsoft YaHei UI&#39;, &#39;Microsoft YaHei&#39;, SimSun, &#39;Segoe UI&#39;, Tahoma, Helvetica, sans-serif, &#39;Microsoft YaHei&#39;, Georgia, Helvetica, Arial, sans-serif, 宋体, PMingLiU, serif; font-size: 14.399999618530273px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 16.799999237060547px; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;&#34;&gt;比如前一篇提到的&lt;/div&gt;
&lt;div style=&#34;color: #000000; font-family: &#39;Microsoft YaHei UI&#39;, &#39;Microsoft YaHei&#39;, SimSun, &#39;Segoe UI&#39;, Tahoma, Helvetica, sans-serif, &#39;Microsoft YaHei&#39;, Georgia, Helvetica, Arial, sans-serif, 宋体, PMingLiU, serif; font-size: 14.399999618530273px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 16.799999237060547px; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;&#34;&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;IFXNewsListener newsListener = new DowJonesNewsListener(); 
IFXNewsPersister newsPersister = new DowJonesNewsPersister(); 
FXNewsProvider newsProvider = new FXNewsProvider(newsListener,newsPersister); 
newsProvider.getAndPersistNews();&lt;/pre&gt;
&amp;nbsp;
&lt;/div&gt;
&lt;div style=&#34;color: #000000; font-family: &#39;Microsoft YaHei UI&#39;, &#39;Microsoft YaHei&#39;, SimSun, &#39;Segoe UI&#39;, Tahoma, Helvetica, sans-serif, &#39;Microsoft YaHei&#39;, Georgia, Helvetica, Arial, sans-serif, 宋体, PMingLiU, serif; font-size: 14.399999618530273px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 16.799999237060547px; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;&#34;&gt;就是一个容器，只不过太简单了，不适用于更多的场景，&lt;/div&gt;
&lt;div style=&#34;color: #000000; font-family: &#39;Microsoft YaHei UI&#39;, &#39;Microsoft YaHei&#39;, SimSun, &#39;Segoe UI&#39;, Tahoma, Helvetica, sans-serif, &#39;Microsoft YaHei&#39;, Georgia, Helvetica, Arial, sans-serif, 宋体, PMingLiU, serif; font-size: 14.399999618530273px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 16.799999237060547px; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;&#34;&gt;&lt;/div&gt;
&lt;div style=&#34;color: #000000; font-family: &#39;Microsoft YaHei UI&#39;, &#39;Microsoft YaHei&#39;, SimSun, &#39;Segoe UI&#39;, Tahoma, Helvetica, sans-serif, &#39;Microsoft YaHei&#39;, Georgia, Helvetica, Arial, sans-serif, 宋体, PMingLiU, serif; font-size: 14.399999618530273px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 16.799999237060547px; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;&#34;&gt;IoC容器就是Spring提供依赖注入服务的Provider&lt;/div&gt;
&lt;div style=&#34;color: #000000; font-family: &#39;Microsoft YaHei UI&#39;, &#39;Microsoft YaHei&#39;, SimSun, &#39;Segoe UI&#39;, Tahoma, Helvetica, sans-serif, &#39;Microsoft YaHei&#39;, Georgia, Helvetica, Arial, sans-serif, 宋体, PMingLiU, serif; font-size: 14.399999618530273px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 16.799999237060547px; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;&#34;&gt;&lt;/div&gt;
&lt;div style=&#34;color: #000000; font-family: &#39;Microsoft YaHei UI&#39;, &#39;Microsoft YaHei&#39;, SimSun, &#39;Segoe UI&#39;, Tahoma, Helvetica, sans-serif, &#39;Microsoft YaHei&#39;, Georgia, Helvetica, Arial, sans-serif, 宋体, PMingLiU, serif; font-size: 14.399999618530273px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 16.799999237060547px; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;&#34;&gt;I&lt;span style=&#34;font-size: 10.5pt; line-height: 1.5;&#34;&gt;oC Service Provider 是干嘛？&lt;/span&gt;&lt;/div&gt;
&lt;div style=&#34;color: #000000; font-family: &#39;Microsoft YaHei UI&#39;, &#39;Microsoft YaHei&#39;, SimSun, &#39;Segoe UI&#39;, Tahoma, Helvetica, sans-serif, &#39;Microsoft YaHei&#39;, Georgia, Helvetica, Arial, sans-serif, 宋体, PMingLiU, serif; font-size: 14.399999618530273px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 16.799999237060547px; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;&#34;&gt;&lt;span style=&#34;font-size: 10.5pt; line-height: 1.5;&#34;&gt;1.业务对象的构建管理，剥离客户端对象的构建的依赖逻辑，比如A引用B，那么A是B的客户端对象，容器需要理清这种关系。&lt;/span&gt;&lt;/div&gt;
&lt;div style=&#34;color: #000000; font-family: &#39;Microsoft YaHei UI&#39;, &#39;Microsoft YaHei&#39;, SimSun, &#39;Segoe UI&#39;, Tahoma, Helvetica, sans-serif, &#39;Microsoft YaHei&#39;, Georgia, Helvetica, Arial, sans-serif, 宋体, PMingLiU, serif; font-size: 14.399999618530273px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 16.799999237060547px; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;&#34;&gt;&lt;span style=&#34;font-size: 10.5pt; line-height: 1.5;&#34;&gt;2.业务对象之间的依赖绑定，通过1的实现， 识别各个对象的依赖关系，然后将这些对象依赖的对象注入绑定，用的时候就有了。&lt;/span&gt;&lt;/div&gt;
&lt;div style=&#34;color: #000000; font-family: &#39;Microsoft YaHei UI&#39;, &#39;Microsoft YaHei&#39;, SimSun, &#39;Segoe UI&#39;, Tahoma, Helvetica, sans-serif, &#39;Microsoft YaHei&#39;, Georgia, Helvetica, Arial, sans-serif, 宋体, PMingLiU, serif; font-size: 14.399999618530273px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 16.799999237060547px; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;&#34;&gt;&lt;span style=&#34;font-size: 10.5pt; line-height: 1.5;&#34;&gt; &lt;/span&gt;&lt;/div&gt;
&lt;div style=&#34;color: #000000; font-family: &#39;Microsoft YaHei UI&#39;, &#39;Microsoft YaHei&#39;, SimSun, &#39;Segoe UI&#39;, Tahoma, Helvetica, sans-serif, &#39;Microsoft YaHei&#39;, Georgia, Helvetica, Arial, sans-serif, 宋体, PMingLiU, serif; font-size: 14.399999618530273px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 16.799999237060547px; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;&#34;&gt;&lt;span style=&#34;font-size: 10.5pt; line-height: 1.5;&#34;&gt; &lt;/span&gt;&lt;/div&gt;
&lt;div style=&#34;color: #000000; font-family: &#39;Microsoft YaHei UI&#39;, &#39;Microsoft YaHei&#39;, SimSun, &#39;Segoe UI&#39;, Tahoma, Helvetica, sans-serif, &#39;Microsoft YaHei&#39;, Georgia, Helvetica, Arial, sans-serif, 宋体, PMingLiU, serif; font-size: 14.399999618530273px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 16.799999237060547px; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;&#34;&gt;那你要问了，这怎么管理对象间的依赖关系呢&lt;/div&gt;
&lt;div style=&#34;color: #000000; font-family: &#39;Microsoft YaHei UI&#39;, &#39;Microsoft YaHei&#39;, SimSun, &#39;Segoe UI&#39;, Tahoma, Helvetica, sans-serif, &#39;Microsoft YaHei&#39;, Georgia, Helvetica, Arial, sans-serif, 宋体, PMingLiU, serif; font-size: 14.399999618530273px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 16.799999237060547px; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;&#34;&gt;&lt;/div&gt;
&lt;div style=&#34;color: #000000; font-family: &#39;Microsoft YaHei UI&#39;, &#39;Microsoft YaHei&#39;, SimSun, &#39;Segoe UI&#39;, Tahoma, Helvetica, sans-serif, &#39;Microsoft YaHei&#39;, Georgia, Helvetica, Arial, sans-serif, 宋体, PMingLiU, serif; font-size: 14.399999618530273px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 16.799999237060547px; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;&#34;&gt;IoC Service Provider怎么就能完全领会代码的意图呢？他怎么记住这么多的依赖关系等等，他要这么做&lt;/div&gt;
&lt;div style=&#34;color: #000000; font-family: &#39;Microsoft YaHei UI&#39;, &#39;Microsoft YaHei&#39;, SimSun, &#39;Segoe UI&#39;, Tahoma, Helvetica, sans-serif, &#39;Microsoft YaHei&#39;, Georgia, Helvetica, Arial, sans-serif, 宋体, PMingLiU, serif; font-size: 14.399999618530273px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 16.799999237060547px; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;&#34;&gt;1.元数据方式&lt;/div&gt;
&lt;div style=&#34;color: #000000; font-family: &#39;Microsoft YaHei UI&#39;, &#39;Microsoft YaHei&#39;, SimSun, &#39;Segoe UI&#39;, Tahoma, Helvetica, sans-serif, &#39;Microsoft YaHei&#39;, Georgia, Helvetica, Arial, sans-serif, 宋体, PMingLiU, serif; font-size: 14.399999618530273px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 16.799999237060547px; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;&#34;&gt;2.通过描述性较强的xml来记录对应信息&lt;/div&gt;
&lt;div style=&#34;color: #000000; font-family: &#39;Microsoft YaHei UI&#39;, &#39;Microsoft YaHei&#39;, SimSun, &#39;Segoe UI&#39;, Tahoma, Helvetica, sans-serif, &#39;Microsoft YaHei&#39;, Georgia, Helvetica, Arial, sans-serif, 宋体, PMingLiU, serif; font-size: 14.399999618530273px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 16.799999237060547px; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;&#34;&gt;3.通过编写代码的方式注册这些信息&lt;/div&gt;
&lt;div style=&#34;color: #000000; font-family: &#39;Microsoft YaHei UI&#39;, &#39;Microsoft YaHei&#39;, SimSun, &#39;Segoe UI&#39;, Tahoma, Helvetica, sans-serif, &#39;Microsoft YaHei&#39;, Georgia, Helvetica, Arial, sans-serif, 宋体, PMingLiU, serif; font-size: 14.399999618530273px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 16.799999237060547px; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;&#34;&gt;&lt;/div&gt;
&lt;div style=&#34;color: #000000; font-family: &#39;Microsoft YaHei UI&#39;, &#39;Microsoft YaHei&#39;, SimSun, &#39;Segoe UI&#39;, Tahoma, Helvetica, sans-serif, &#39;Microsoft YaHei&#39;, Georgia, Helvetica, Arial, sans-serif, 宋体, PMingLiU, serif; font-size: 14.399999618530273px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 16.799999237060547px; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;&#34;&gt;&lt;/div&gt;
&lt;div style=&#34;color: #000000; font-family: &#39;Microsoft YaHei UI&#39;, &#39;Microsoft YaHei&#39;, SimSun, &#39;Segoe UI&#39;, Tahoma, Helvetica, sans-serif, &#39;Microsoft YaHei&#39;, Georgia, Helvetica, Arial, sans-serif, 宋体, PMingLiU, serif; font-size: 14.399999618530273px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 16.799999237060547px; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;&#34;&gt;3.直接编码方式，&lt;/div&gt;
&lt;div style=&#34;color: #000000; font-family: &#39;Microsoft YaHei UI&#39;, &#39;Microsoft YaHei&#39;, SimSun, &#39;Segoe UI&#39;, Tahoma, Helvetica, sans-serif, &#39;Microsoft YaHei&#39;, Georgia, Helvetica, Arial, sans-serif, 宋体, PMingLiU, serif; font-size: 14.399999618530273px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 16.799999237060547px; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;&#34;&gt;明确了依赖关系&lt;/div&gt;
&lt;div style=&#34;color: #000000; font-family: &#39;Microsoft YaHei UI&#39;, &#39;Microsoft YaHei&#39;, SimSun, &#39;Segoe UI&#39;, Tahoma, Helvetica, sans-serif, &#39;Microsoft YaHei&#39;, Georgia, Helvetica, Arial, sans-serif, 宋体, PMingLiU, serif; font-size: 14.399999618530273px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 16.799999237060547px; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;&#34;&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;IoContainer container = ...; 
container.register(FXNewsProvider.class,new FXNewsProvider()); 
container.register(IFXNewsListener.class,new DowJonesNewsListener());
 ... 
FXNewsProvider newsProvider = (FXNewsProvider)container.get(FXNewsProvider.class); 
newProvider.getAndPersistNews();&lt;/pre&gt;
&amp;nbsp;
&lt;/div&gt;
&lt;div style=&#34;color: #000000; font-family: &#39;Microsoft YaHei UI&#39;, &#39;Microsoft YaHei&#39;, SimSun, &#39;Segoe UI&#39;, Tahoma, Helvetica, sans-serif, &#39;Microsoft YaHei&#39;, Georgia, Helvetica, Arial, sans-serif, 宋体, PMingLiU, serif; font-size: 14.399999618530273px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 16.799999237060547px; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;&#34;&gt;&lt;/div&gt;
&lt;div style=&#34;color: #000000; font-family: &#39;Microsoft YaHei UI&#39;, &#39;Microsoft YaHei&#39;, SimSun, &#39;Segoe UI&#39;, Tahoma, Helvetica, sans-serif, &#39;Microsoft YaHei&#39;, Georgia, Helvetica, Arial, sans-serif, 宋体, PMingLiU, serif; font-size: 14.399999618530273px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 16.799999237060547px; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;&#34;&gt;2.配置文件方式&lt;/div&gt;
&lt;div style=&#34;color: #000000; font-family: &#39;Microsoft YaHei UI&#39;, &#39;Microsoft YaHei&#39;, SimSun, &#39;Segoe UI&#39;, Tahoma, Helvetica, sans-serif, &#39;Microsoft YaHei&#39;, Georgia, Helvetica, Arial, sans-serif, 宋体, PMingLiU, serif; font-size: 14.399999618530273px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 16.799999237060547px; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;&#34;&gt;&lt;/div&gt;
&lt;div style=&#34;color: #000000; font-family: &#39;Microsoft YaHei UI&#39;, &#39;Microsoft YaHei&#39;, SimSun, &#39;Segoe UI&#39;, Tahoma, Helvetica, sans-serif, &#39;Microsoft YaHei&#39;, Georgia, Helvetica, Arial, sans-serif, 宋体, PMingLiU, serif; font-size: 14.399999618530273px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 16.799999237060547px; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;&#34;&gt;最常见的还是xml方式，&lt;/div&gt;
&lt;div style=&#34;color: #000000; font-family: &#39;Microsoft YaHei UI&#39;, &#39;Microsoft YaHei&#39;, SimSun, &#39;Segoe UI&#39;, Tahoma, Helvetica, sans-serif, &#39;Microsoft YaHei&#39;, Georgia, Helvetica, Arial, sans-serif, 宋体, PMingLiU, serif; font-size: 14.399999618530273px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 16.799999237060547px; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;&#34;&gt;&lt;/div&gt;
&lt;div style=&#34;color: #000000; font-family: &#39;Microsoft YaHei UI&#39;, &#39;Microsoft YaHei&#39;, SimSun, &#39;Segoe UI&#39;, Tahoma, Helvetica, sans-serif, &#39;Microsoft YaHei&#39;, Georgia, Helvetica, Arial, sans-serif, 宋体, PMingLiU, serif; font-size: 14.399999618530273px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 16.799999237060547px; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;&#34;&gt;
&lt;pre class=&#34;lang:xhtml decode:true&#34;&gt;&amp;lt;bean id=&#34;newsProvider&#34; class=&#34;..FXNewsProvider&#34;&amp;gt;  
 &amp;lt;property name=&#34;newsListener&#34;&amp;gt;   
  &amp;lt;ref bean=&#34;djNewsListener&#34;/&amp;gt;  
 &amp;lt;/property&amp;gt;  
 &amp;lt;property name=&#34;newPersistener&#34;&amp;gt;   
  &amp;lt;ref bean=&#34;djNewsPersister&#34;/&amp;gt;  
 &amp;lt;/property&amp;gt; 
&amp;lt;/bean&amp;gt;  
&amp;lt;bean id=&#34;djNewsListener&#34;   class=&#34;..impl.DowJonesNewsListener&#34;&amp;gt; 
&amp;lt;/bean&amp;gt; 
&amp;lt;bean id=&#34;djNewsPersister&#34;   class=&#34;..impl.DowJonesNewsPersister&#34;&amp;gt; 
&amp;lt;/bean&amp;gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div style=&#34;color: #000000; font-family: &#39;Microsoft YaHei UI&#39;, &#39;Microsoft YaHei&#39;, SimSun, &#39;Segoe UI&#39;, Tahoma, Helvetica, sans-serif, &#39;Microsoft YaHei&#39;, Georgia, Helvetica, Arial, sans-serif, 宋体, PMingLiU, serif; font-size: 14.399999618530273px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 16.799999237060547px; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;&#34;&gt;&lt;/div&gt;
&lt;div style=&#34;color: #000000; font-family: &#39;Microsoft YaHei UI&#39;, &#39;Microsoft YaHei&#39;, SimSun, &#39;Segoe UI&#39;, Tahoma, Helvetica, sans-serif, &#39;Microsoft YaHei&#39;, Georgia, Helvetica, Arial, sans-serif, 宋体, PMingLiU, serif; font-size: 14.399999618530273px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 16.799999237060547px; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;&#34;&gt;然后我们要用的时候&lt;/div&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;container.readConfigurationFiles(...); 
FXNewsProvider newsProvider = (FXNewsProvider)container.getBean(&#34;newsProvider&#34;); 
newsProvider.getAndPersistNews();&lt;/pre&gt;
&lt;div style=&#34;color: #000000; font-family: &#39;Microsoft YaHei UI&#39;, &#39;Microsoft YaHei&#39;, SimSun, &#39;Segoe UI&#39;, Tahoma, Helvetica, sans-serif, &#39;Microsoft YaHei&#39;, Georgia, Helvetica, Arial, sans-serif, 宋体, PMingLiU, serif; font-size: 14.399999618530273px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 16.799999237060547px; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;&#34;&gt;&lt;/div&gt;
&lt;div style=&#34;color: #000000; font-family: &#39;Microsoft YaHei UI&#39;, &#39;Microsoft YaHei&#39;, SimSun, &#39;Segoe UI&#39;, Tahoma, Helvetica, sans-serif, &#39;Microsoft YaHei&#39;, Georgia, Helvetica, Arial, sans-serif, 宋体, PMingLiU, serif; font-size: 14.399999618530273px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 16.799999237060547px; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;&#34;&gt;容器读取配置文件，然后取到其中的两个类，注入进来。&lt;/div&gt;
&lt;div style=&#34;color: #000000; font-family: &#39;Microsoft YaHei UI&#39;, &#39;Microsoft YaHei&#39;, SimSun, &#39;Segoe UI&#39;, Tahoma, Helvetica, sans-serif, &#39;Microsoft YaHei&#39;, Georgia, Helvetica, Arial, sans-serif, 宋体, PMingLiU, serif; font-size: 14.399999618530273px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 16.799999237060547px; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;&#34;&gt;&lt;/div&gt;
&lt;div style=&#34;color: #000000; font-family: &#39;Microsoft YaHei UI&#39;, &#39;Microsoft YaHei&#39;, SimSun, &#39;Segoe UI&#39;, Tahoma, Helvetica, sans-serif, &#39;Microsoft YaHei&#39;, Georgia, Helvetica, Arial, sans-serif, 宋体, PMingLiU, serif; font-size: 14.399999618530273px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 16.799999237060547px; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;&#34;&gt;&lt;/div&gt;
&lt;div style=&#34;color: #000000; font-family: &#39;Microsoft YaHei UI&#39;, &#39;Microsoft YaHei&#39;, SimSun, &#39;Segoe UI&#39;, Tahoma, Helvetica, sans-serif, &#39;Microsoft YaHei&#39;, Georgia, Helvetica, Arial, sans-serif, 宋体, PMingLiU, serif; font-size: 14.399999618530273px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 16.799999237060547px; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;&#34;&gt;1.元数据方式&lt;/div&gt;
&lt;div style=&#34;color: #000000; font-family: &#39;Microsoft YaHei UI&#39;, &#39;Microsoft YaHei&#39;, SimSun, &#39;Segoe UI&#39;, Tahoma, Helvetica, sans-serif, &#39;Microsoft YaHei&#39;, Georgia, Helvetica, Arial, sans-serif, 宋体, PMingLiU, serif; font-size: 14.399999618530273px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 16.799999237060547px; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;&#34;&gt;代表实现Java Guide，基于java注解，在类中直接使用元数据信息来标注 各个对象之间的依赖关系。然后框架根据信息组装之后交给客户端对象使用&lt;/div&gt;
&lt;div style=&#34;color: #000000; font-family: &#39;Microsoft YaHei UI&#39;, &#39;Microsoft YaHei&#39;, SimSun, &#39;Segoe UI&#39;, Tahoma, Helvetica, sans-serif, &#39;Microsoft YaHei&#39;, Georgia, Helvetica, Arial, sans-serif, 宋体, PMingLiU, serif; font-size: 14.399999618530273px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 16.799999237060547px; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;&#34;&gt;&lt;/div&gt;
&lt;div style=&#34;color: #000000; font-family: &#39;Microsoft YaHei UI&#39;, &#39;Microsoft YaHei&#39;, SimSun, &#39;Segoe UI&#39;, Tahoma, Helvetica, sans-serif, &#39;Microsoft YaHei&#39;, Georgia, Helvetica, Arial, sans-serif, 宋体, PMingLiU, serif; font-size: 14.399999618530273px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 16.799999237060547px; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;&#34;&gt;这种方式重写我们的例子就是&lt;/div&gt;
&lt;div style=&#34;color: #000000; font-family: &#39;Microsoft YaHei UI&#39;, &#39;Microsoft YaHei&#39;, SimSun, &#39;Segoe UI&#39;, Tahoma, Helvetica, sans-serif, &#39;Microsoft YaHei&#39;, Georgia, Helvetica, Arial, sans-serif, 宋体, PMingLiU, serif; font-size: 14.399999618530273px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 16.799999237060547px; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;&#34;&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;public class FXNewsProvider {  
private IFXNewsListener  newsListener;  
private IFXNewsPersister newPersistener;  
@Inject  
public FXNewsProvider(IFXNewsListener listener,IFXNewsPersister persister)  {   this.newsListener   = listener;   
this.newPersistener = persister;   
}  
... 
}&lt;/pre&gt;
&lt;/div&gt;
&lt;div style=&#34;color: #000000; font-family: &#39;Microsoft YaHei UI&#39;, &#39;Microsoft YaHei&#39;, SimSun, &#39;Segoe UI&#39;, Tahoma, Helvetica, sans-serif, &#39;Microsoft YaHei&#39;, Georgia, Helvetica, Arial, sans-serif, 宋体, PMingLiU, serif; font-size: 14.399999618530273px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 16.799999237060547px; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;&#34;&gt;&lt;/div&gt;
&lt;div style=&#34;color: #000000; font-family: &#39;Microsoft YaHei UI&#39;, &#39;Microsoft YaHei&#39;, SimSun, &#39;Segoe UI&#39;, Tahoma, Helvetica, sans-serif, &#39;Microsoft YaHei&#39;, Georgia, Helvetica, Arial, sans-serif, 宋体, PMingLiU, serif; font-size: 14.399999618530273px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 16.799999237060547px; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;&#34;&gt;通过 @Inject，我们指明需要IoC Service Provider通过构造方法注入方&lt;/div&gt;
&lt;div style=&#34;color: #000000; font-family: &#39;Microsoft YaHei UI&#39;, &#39;Microsoft YaHei&#39;, SimSun, &#39;Segoe UI&#39;, Tahoma, Helvetica, sans-serif, &#39;Microsoft YaHei&#39;, Georgia, Helvetica, Arial, sans-serif, 宋体, PMingLiU, serif; font-size: 14.399999618530273px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 16.799999237060547px; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;&#34;&gt;&lt;/div&gt;
&lt;div style=&#34;color: #000000; font-family: &#39;Microsoft YaHei UI&#39;, &#39;Microsoft YaHei&#39;, SimSun, &#39;Segoe UI&#39;, Tahoma, Helvetica, sans-serif, &#39;Microsoft YaHei&#39;, Georgia, Helvetica, Arial, sans-serif, 宋体, PMingLiU, serif; font-size: 14.399999618530273px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 16.799999237060547px; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;&#34;&gt;余下的部分由Guide提供的Module完成，我们继承一下。&lt;/div&gt;
&lt;div style=&#34;color: #000000; font-family: &#39;Microsoft YaHei UI&#39;, &#39;Microsoft YaHei&#39;, SimSun, &#39;Segoe UI&#39;, Tahoma, Helvetica, sans-serif, &#39;Microsoft YaHei&#39;, Georgia, Helvetica, Arial, sans-serif, 宋体, PMingLiU, serif; font-size: 14.399999618530273px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 16.799999237060547px; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;&#34;&gt;&lt;/div&gt;
&lt;div style=&#34;color: #000000; font-family: &#39;Microsoft YaHei UI&#39;, &#39;Microsoft YaHei&#39;, SimSun, &#39;Segoe UI&#39;, Tahoma, Helvetica, sans-serif, &#39;Microsoft YaHei&#39;, Georgia, Helvetica, Arial, sans-serif, 宋体, PMingLiU, serif; font-size: 14.399999618530273px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 16.799999237060547px; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;&#34;&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;public class NewsBindingModule extends AbstractModule  {  
@Override  
protected void configure() {  
bind(IFXNewsListener.class) .to(DowJonesNewsListener.class).in(Scopes.SINGLETON);   
bind(IFXNewsPersister.class).to(DowJonesNewsPersister.class).in(Scopes.SINGLETON);  
} 
}&lt;/pre&gt;
&lt;/div&gt;
&lt;div style=&#34;color: #000000; font-family: &#39;Microsoft YaHei UI&#39;, &#39;Microsoft YaHei&#39;, SimSun, &#39;Segoe UI&#39;, Tahoma, Helvetica, sans-serif, &#39;Microsoft YaHei&#39;, Georgia, Helvetica, Arial, sans-serif, 宋体, PMingLiU, serif; font-size: 14.399999618530273px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 16.799999237060547px; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;&#34;&gt;&lt;/div&gt;
&lt;div style=&#34;color: #000000; font-family: &#39;Microsoft YaHei UI&#39;, &#39;Microsoft YaHei&#39;, SimSun, &#39;Segoe UI&#39;, Tahoma, Helvetica, sans-serif, &#39;Microsoft YaHei&#39;, Georgia, Helvetica, Arial, sans-serif, 宋体, PMingLiU, serif; font-size: 14.399999618530273px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 16.799999237060547px; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;&#34;&gt;最后，要用的时候，直接来拿吧。&lt;/div&gt;
&lt;div style=&#34;color: #000000; font-family: &#39;Microsoft YaHei UI&#39;, &#39;Microsoft YaHei&#39;, SimSun, &#39;Segoe UI&#39;, Tahoma, Helvetica, sans-serif, &#39;Microsoft YaHei&#39;, Georgia, Helvetica, Arial, sans-serif, 宋体, PMingLiU, serif; font-size: 14.399999618530273px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 16.799999237060547px; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;&#34;&gt;&lt;/div&gt;
&lt;div style=&#34;color: #000000; font-family: &#39;Microsoft YaHei UI&#39;, &#39;Microsoft YaHei&#39;, SimSun, &#39;Segoe UI&#39;, Tahoma, Helvetica, sans-serif, &#39;Microsoft YaHei&#39;, Georgia, Helvetica, Arial, sans-serif, 宋体, PMingLiU, serif; font-size: 14.399999618530273px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 16.799999237060547px; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;&#34;&gt;&lt;/div&gt;
&lt;div style=&#34;color: #000000; font-family: &#39;Microsoft YaHei UI&#39;, &#39;Microsoft YaHei&#39;, SimSun, &#39;Segoe UI&#39;, Tahoma, Helvetica, sans-serif, &#39;Microsoft YaHei&#39;, Georgia, Helvetica, Arial, sans-serif, 宋体, PMingLiU, serif; font-size: 14.399999618530273px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 16.799999237060547px; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;&#34;&gt;
&lt;div&gt;
&lt;pre class=&#34;lang:default decode:true &#34;&gt;Injector injector = Guice.createInjector(new NewsBindingModule()); 
FXNewsProvider newsProvider = injector.getInstance(FXNewsProvider.class); 
newsProvider.getAndPersistNews();&lt;/pre&gt;
&amp;nbsp;
&lt;/div&gt;
&lt;/div&gt;
&lt;div style=&#34;color: #000000; font-family: &#39;Microsoft YaHei UI&#39;, &#39;Microsoft YaHei&#39;, SimSun, &#39;Segoe UI&#39;, Tahoma, Helvetica, sans-serif, &#39;Microsoft YaHei&#39;, Georgia, Helvetica, Arial, sans-serif, 宋体, PMingLiU, serif; font-size: 14.399999618530273px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 16.799999237060547px; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;&#34;&gt;&lt;/div&gt;
&lt;div style=&#34;color: #000000; font-family: &#39;Microsoft YaHei UI&#39;, &#39;Microsoft YaHei&#39;, SimSun, &#39;Segoe UI&#39;, Tahoma, Helvetica, sans-serif, &#39;Microsoft YaHei&#39;, Georgia, Helvetica, Arial, sans-serif, 宋体, PMingLiU, serif; font-size: 14.399999618530273px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 16.799999237060547px; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;&#34;&gt;&lt;/div&gt;</description>
    </item>
    <item>
      <title>《Spring揭秘》读书笔记-第二章IoC的基本概念</title>
      <link>http://blog.leaver.me/2014/07/01/spring%E6%8F%AD%E7%A7%98%E8%AF%BB%E4%B9%A6%E7%AC%94%E8%AE%B0-%E7%AC%AC%E4%BA%8C%E7%AB%A0ioc%E7%9A%84%E5%9F%BA%E6%9C%AC%E6%A6%82%E5%BF%B5/</link>
      <pubDate>Tue, 01 Jul 2014 18:54:17 +0000</pubDate>
      <guid>http://blog.leaver.me/2014/07/01/spring%E6%8F%AD%E7%A7%98%E8%AF%BB%E4%B9%A6%E7%AC%94%E8%AE%B0-%E7%AC%AC%E4%BA%8C%E7%AB%A0ioc%E7%9A%84%E5%9F%BA%E6%9C%AC%E6%A6%82%E5%BF%B5/</guid>
      <description>&lt;p&gt;&lt;span style=&#34;font-family: 宋体; font-size: 10pt;&#34;&gt;理念就是让别人为你服务，中文名控制反转，也叫依赖注入DI&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;public class FXNewsProvider

{

  private IFXNewsListener newsListener;

  private IFXNewsPersister newPersistener;

  public void getAndPersistNews()

{

String[] newsIds = newsListener.getAvailableNewsIds();

if(ArrayUtils.isEmpty(newsIds))

{
   return;
} 

for(String newsId : newsIds)

{ FXNewsBean newsBean = newsListener.getNewsByPK(newsId); 

newPersistener.persistNews(newsBean);

newsListener.postProcessIfNecessary(newsId);

}

}

}&lt;/pre&gt;
&lt;p&gt; &lt;span style=&#34;font-family: 宋体; font-size: 10pt;&#34;&gt;假设这个类用来处理新闻，&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&#34;font-family: Courier; font-size: 8pt;&#34;&gt;IFXNewsListener &lt;/span&gt;&lt;span style=&#34;font-family: 宋体; font-size: 8pt;&#34;&gt;用来获取新闻，&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&#34;font-family: Courier; font-size: 8pt;&#34;&gt;IFXNewsPersister  &lt;/span&gt; &lt;span style=&#34;font-family: 宋体; font-size: 8pt;&#34;&gt;用来把获取的新闻持久化&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&#34;font-family: 宋体; font-size: 10pt;&#34;&gt;当我们需要获取不同的新闻源，比如道琼斯的新闻时，我们会写一个&lt;/span&gt; &lt;span style=&#34;font-family: Courier; font-size: 8pt;&#34;&gt;DowJonesNewsListener&lt;/span&gt; &lt;span style=&#34;font-family: 宋体; font-size: 8pt;&#34;&gt;类和&lt;/span&gt; &lt;span style=&#34;font-family: Courier; font-size: 8pt;&#34;&gt;DowJonesNewsPersister&lt;/span&gt; &lt;span style=&#34;font-family: 宋体; font-size: 8pt;&#34;&gt;类，然后实例化&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;public FXNewsProvider()

{

  newsListener = new DowJonesNewsListener();

  newPersistener = new DowJonesNewsPersister();

}&lt;/pre&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;span style=&#34;font-family: SimSun; font-size: 9pt;&#34;&gt;如果我们依赖于某个类或服务，最简单而有效的方式就是直接&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&#34;font-family: SimSun; font-size: 9pt;&#34;&gt;在类的构造函数中新建相应的依赖类。&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&#34;font-family: 宋体; font-size: 10pt;&#34;&gt;注意看，&lt;/span&gt; &lt;span style=&#34;font-family: SimSun; font-size: 9pt;&#34;&gt;，我们都是自己主动地去获&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&#34;font-family: SimSun; font-size: 9pt;&#34;&gt;取依赖的对象！&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&#34;font-family: SimSun; font-size: 9pt;&#34;&gt;可是回头想想，我们自己每次用到什么依赖对象都要主动地去获取，这是否真的必要？我们最终&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&#34;font-family: SimSun; font-size: 9pt;&#34;&gt;所要做的，其实就是直接调用依赖对象所提供的某项服务而已&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&#34;font-family: SimSun; font-size: 9pt;&#34;&gt;能不能我们用的时候自动送过来呢？&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&#34;font-family: SimSun; font-size: 9pt;&#34;&gt;。现在是用什么，让别人直接送过来就成。所以，简单点儿说，&lt;/span&gt; &lt;span style=&#34;font-family: &#39;Times New Roman&#39;; font-size: 9pt;&#34;&gt;IoC&lt;/span&gt; &lt;span style=&#34;font-family: SimSun; font-size: 9pt;&#34;&gt;的理念就是，&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&#34;font-family: SimSun; font-size: 9pt;&#34;&gt;让别人为你服务！在图&lt;/span&gt; &lt;span style=&#34;font-family: &#39;Times New Roman&#39;; font-size: 9pt;&#34;&gt;2-1&lt;/span&gt; &lt;span style=&#34;font-family: SimSun; font-size: 9pt;&#34;&gt;中，也就是让&lt;/span&gt; &lt;span style=&#34;font-family: &#39;Times New Roman&#39;; font-size: 9pt;&#34;&gt;IoC Service Provider&lt;/span&gt; &lt;span style=&#34;font-family: SimSun; font-size: 9pt;&#34;&gt;来为你服务！&lt;/span&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>《Spring揭秘》读书笔记-第一章Spring框架的由来</title>
      <link>http://blog.leaver.me/2014/06/30/spring%E6%8F%AD%E7%A7%98%E8%AF%BB%E4%B9%A6%E7%AC%94%E8%AE%B0-%E7%AC%AC%E4%B8%80%E7%AB%A0spring%E6%A1%86%E6%9E%B6%E7%9A%84%E7%94%B1%E6%9D%A5/</link>
      <pubDate>Mon, 30 Jun 2014 20:40:40 +0000</pubDate>
      <guid>http://blog.leaver.me/2014/06/30/spring%E6%8F%AD%E7%A7%98%E8%AF%BB%E4%B9%A6%E7%AC%94%E8%AE%B0-%E7%AC%AC%E4%B8%80%E7%AB%A0spring%E6%A1%86%E6%9E%B6%E7%9A%84%E7%94%B1%E6%9D%A5/</guid>
      <description>&lt;p&gt;1.框架的由来&lt;/p&gt;
&lt;p&gt;倡导J2EE轻量级应用解决方案&lt;/p&gt;
&lt;p&gt;框架总结结构&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/2014/06/Spring-Framework.jpg&#34;&gt;&lt;img alt=&#34;Spring Framework&#34; loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/8775d9e40dbc29240061edd2b9b6f76990f39cad.jpg&#34;&gt;&lt;/a&gt;
整个Spring架构建立在Core核心模块上，是基础，该模块中，有一个IoC容器的实现，用来以依赖注入的方式管理对象之间的依赖关系。Core中还有一些气筒工具类，比如IO工具类&lt;/p&gt;
&lt;p&gt;从图中看到，AOP模块，提供了轻便二强大的AOP框架，一AOP的形式增强POJO的能力，弥补OOP/OOSD的不足，采用Proxy模式，与IoC容器相结合&lt;/p&gt;
&lt;p&gt;继续向上看，在Core和AOP之上，提供了完毕的数据访问和事务管理的抽象，其中，对JDBC API的最佳实践简化了API的使用，还未ORM产品提供了统一的支持，&lt;/p&gt;
&lt;p&gt;为了简化Java EE的服务，比如JNDI，JMS等等，Spring还提供了这些的集成服务，&lt;/p&gt;
&lt;p&gt;最后就是Web模块，提供了一套自己的Web MVC框架，上层模块依赖于下层模块，水平之间的模块彼此基本可以认为独立。&lt;/p&gt;
&lt;p&gt;Spring不仅仅是容器，更是开发任何Java应用的框架，&lt;/p&gt;
&lt;p&gt;Spring 框架之上衍生的产品包括不限于Spring Web Flow,Spring Web Services,Spring Security,Spring Integration，Spring Rich Client 等等等等&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>构建数据库连接的配置方法</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>[藏]深入理解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>[藏]运用 BoxLayout 进行 Swing 控件布局</title>
      <link>http://blog.leaver.me/2014/03/03/%E8%97%8F%E8%BF%90%E7%94%A8-boxlayout-%E8%BF%9B%E8%A1%8C-swing-%E6%8E%A7%E4%BB%B6%E5%B8%83%E5%B1%80/</link>
      <pubDate>Mon, 03 Mar 2014 21:17:20 +0000</pubDate>
      <guid>http://blog.leaver.me/2014/03/03/%E8%97%8F%E8%BF%90%E7%94%A8-boxlayout-%E8%BF%9B%E8%A1%8C-swing-%E6%8E%A7%E4%BB%B6%E5%B8%83%E5%B1%80/</guid>
      <description>&lt;p&gt;写的非常非常好的一个教程，感谢&lt;a href=&#34;http://www.ibm.com/developerworks/cn/java/j-lo-boxlayout/&#34;&gt;陈 怡平&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;引言&#34;&gt;引言&lt;/h2&gt;
&lt;p&gt;在用户使用 Java Swing 进行用户界面开发过程中，会碰到如何对 Java Swing 的控件进行布局的问题。Swing 的控件放置在容器 (Container) 中，容器就是能够容纳控件或者其它容器的类，容器的具体例子有 Frame、Panel 等等。容器需要定义一个布局管理器来对控件进行布局管理，Swing 当中提供的主要的布局管理器有 FlowLayout、BorderLayout、BoxLayout、GridLayout 和 GridBaglayout, 它们的主要特点如表 1 所示：&lt;/p&gt;
&lt;h5 id=&#34;表-1-swing-中的一些主要布局管理器的比较&#34;&gt;表 1. Swing 中的一些主要布局管理器的比较&lt;/h5&gt;
&lt;table summary=&#34;Swing 中的一些主要布局管理器的比较&#34; border=&#34;0&#34; cellspacing=&#34;0&#34; cellpadding=&#34;0&#34;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;**布局管理器**&lt;/th&gt;
&lt;th&gt;**特点**&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;FlowLayout&lt;/td&gt;
&lt;td&gt;把控件按照顺序一个接一个由左向右的水平放置在容器中，一行放不下，就放到下一行&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;BorderLayout&lt;/td&gt;
&lt;td&gt;将整个容器划分成东南西北中五个方位来放置控件，放置控件时需要指定控件放置的方位&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;BoxLayout&lt;/td&gt;
&lt;td&gt;可以指定在容器中是否对控件进行水平或者垂直放置，比 FlowLayout 要更为灵活&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GridLayout&lt;/td&gt;
&lt;td&gt;将整个容器划分成一定的行和一定的列，可以指定控件放在某行某列上&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GridBagLayout&lt;/td&gt;
&lt;td&gt;是 Swing 当中最灵活也是最复杂的布局管理器，可对控件在容器中的位置进行比较灵活的调整&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
本文主要关注在 BoxLayout 布局管理器的使用上。我们首先对 BoxLayout 作一下介绍。
&lt;h2 id=&#34;boxlayout-介绍&#34;&gt;BoxLayout 介绍&lt;/h2&gt;
&lt;p&gt;如前所述，BoxLayout 可以把控件依次进行水平或者垂直排列布局，这是通过参数 X_AXIS、Y_AXIS 来决定的。X_AXIS 表示水平排列，而 Y_AXIS 表示垂直排列。BoxLayout 的构造函数有两个参数，一个参数定义使用该 BoxLayout 的容器，另一个参数是指定 BoxLayout 是采用水平还是垂直排列。下面是一个创建 BoxLayout 实例的例子：&lt;/p&gt;
&lt;div&gt;
&lt;pre&gt; JPanel panel=new JPanel(); 
 BoxLayout layout=new BoxLayout(panel, BoxLayout.X_AXIS); 
 panel.setLayout(layoout);&lt;/pre&gt;
&lt;/div&gt;
在这个例子中，一个 BoxLayout 布局管理器的实例 layout 被创建，这个实例被设置为 panel 的布局管理器，该布局管理器采用了水平排列来排列控件。
&lt;p&gt;当 BoxLayout 进行布局时，它将所有控件依次按照控件的优先尺寸按照顺序的进行水平或者垂直放置，假如布局的整个水平或者垂直空间的尺寸不能放下所有控件，那么 BoxLayout 会试图调整各个控件的大小来填充整个布局的水平或者垂直空间。&lt;/p&gt;
&lt;p&gt;BoxLayout 往往和 Box 这个容器结合在一起使用，这么做的理由是，BoxLayout 是把控件以水平或者垂直的方向一个接一个的放置，如果要调整这些控件之间的空间，就会需要使用 Box 容器提供的透明的组件作为填充来填充控件之间的空间，从而达到调整控件之间的间隔空间的目的。Box 容器提供了 4 种透明的组件，分别是 rigid area、strut、glue、filler。Box 容器分别提供了不同的方法来创建这些组件。这四个组件的特点如下：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Rigid area 是一种用户可以定义水平和垂直尺寸的透明组件；&lt;/li&gt;
&lt;li&gt;strut 与 rigid area 类似，但是用户只能定义一个方向的尺寸，即水平方向或者垂直方向，不能同时定义水平和垂直尺寸；&lt;/li&gt;
&lt;li&gt;当用户将 glue 放在两个控件之间时，它会尽可能的占据两个控件之间的多余空间，从而将两个控件挤到两边；&lt;/li&gt;
&lt;li&gt;Filler 是 Box 的内部类，它与 rigid area 相似，都可以指定水平或者垂直的尺寸，但是它可以设置最小，最大和优先尺寸。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;用-boxlayout-进行布局&#34;&gt;用 BoxLayout 进行布局&lt;/h2&gt;
&lt;p&gt;在了解了 BoxLayout 和 Box 容器的基本特点后，我们来看一下 BoxLayout 的优点，首先 BoxLayout 可以进行对控件进行垂直或者水平布局，同时 BoxLayout 使用起来较为简单，然而把它和 Box 容器相结合，就可以进行较为复杂的布局，达到同使用 GridBagLayout 的一样的效果，但是使用起来要简单方便多了。我们用按钮的布局作为例子来看怎样运用 BoxLayout 和 Box 容器进行布局：&lt;/p&gt;
&lt;h5 id=&#34;图-1-应用-boxlayout-进行按钮布局例子-1&#34;&gt;图 1. 应用 BoxLayout 进行按钮布局例子 1&lt;/h5&gt;
&lt;p&gt;&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/2014/03/image003.jpg&#34;&gt;&lt;img alt=&#34;image003&#34; loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/3f7f662b57a56e94f2e43da95973ee61d0735286.jpg&#34;&gt;&lt;/a&gt;&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/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>[藏]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>[藏]图文并茂详解Eclipse断点</title>
      <link>http://blog.leaver.me/2013/11/16/%E8%97%8F%E5%9B%BE%E6%96%87%E5%B9%B6%E8%8C%82%E8%AF%A6%E8%A7%A3eclipse%E6%96%AD%E7%82%B9/</link>
      <pubDate>Sat, 16 Nov 2013 14:21:11 +0000</pubDate>
      <guid>http://blog.leaver.me/2013/11/16/%E8%97%8F%E5%9B%BE%E6%96%87%E5%B9%B6%E8%8C%82%E8%AF%A6%E8%A7%A3eclipse%E6%96%AD%E7%82%B9/</guid>
      <description>&lt;p&gt;本文转自：&lt;a href=&#34;http://my.oschina.net/colorleaf/blog/176569&#34;&gt;http://my.oschina.net/colorleaf/blog/176569&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;这个算说的比较清楚的了，虽然简单但是很有用。收藏一下。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;详解Eclipse断点&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;大家肯定都用过Eclipse的调试的功能，在调试的过程中自然也无法避免要使用断点(breakpoint)，但不知是否对Eclipse中各类断点都有所了解。本篇图文并茂地介绍了Eclipse中全部类型的断点，及其设置，希望对大家有所帮助。(2011.11.20)&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1. 示例程序&lt;/strong&gt;
BreakpointDemo是一个臆造的应用程序，只是为了便于讲解Eclipse中各类断点的使用罢了。其代码如下图所示，
&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/2013/11/15153245_BTUJ.png&#34;&gt;&lt;img alt=&#34;15153245_BTUJ&#34; loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/abd1d53612eeef8d1feccdf17a894d3e71d41941.png&#34;&gt;&lt;/a&gt;
BreakpointDemo主要包含两个方法：
[1]setValue，该方法根据指定的次数(count)，对成员变量value进行赋值，值的范围为0-9的随机整数。
[2]printValue，该方法会调用setValue()对value进行赋值，并打印出value的值；但，如果value能被3整除，那么就会抛出IllegalArgumentException异常。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2. Line Breakpoint&lt;/strong&gt;
Line Breakpoin是最简单的Eclipse断点，只要双击某行代码对应的左侧栏，就对该行设置上断点。此处，对第20行代码设置上Line Breakpoint，如下图所示，
&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/2013/11/15153245_zkOp.png&#34;&gt;&lt;img alt=&#34;15153245_zkOp&#34; loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/ca7da4e9038334e0603072298cbaf834326da937.png&#34;&gt;&lt;/a&gt;
可以为Line Breakpoint设置一个条件，那么当程序运行到该断点时，只有满足设定的条件，才会被中断。右键点击第20行的断点，选择&amp;quot;Breakpoint Properties&amp;hellip;&amp;quot;
&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/2013/11/15153245_I2Pe.png&#34;&gt;&lt;img alt=&#34;15153245_I2Pe&#34; loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/ff95dcb0130a35d3e293a52487e4109316cba1f8.png&#34;&gt;&lt;/a&gt;
在弹出的属性对话框中，勾选上&amp;quot;Conditional&amp;quot;，然后在文本框中输入&amp;quot;count % 2 == 0&amp;quot;。
&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/2013/11/15153246_rJtm.png&#34;&gt;&lt;img alt=&#34;15153246_rJtm&#34; loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/4f5d2d716473a55f1e3b96a59ac07f700657452a.png&#34;&gt;&lt;/a&gt;
该条件表示，当程序运行到第20行时，只有当count为偶数时，程序才会被中断。细心地话，你会发现该断点的图标发生了改变，多了一个问号。
&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/2013/11/15153246_5APe.png&#34;&gt;&lt;img alt=&#34;15153246_5APe&#34; loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/e3d69e5d5b31edbf729ce4522f9b21e2f5024f17.png&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;3. Watchpoint&lt;/strong&gt;
Line Breakpoint关注于程序运行的&amp;quot;过程&amp;quot;，大家也常把使用这种断点的调试称为单步调试。但有时候，我们对程序的运行过程不太了解，可能也不太关心，不能确定在什么地方设置断点比较合适，而可能比较关注某个关键变量的变化或使用。此时，就可以为该变量设置一种特殊的断点&amp;ndash;Watchpoint。在此示例，我们最关心的就是成员变量value的值，那么就可以为它设置一个Watchpoint，双击第9行代码对应的左侧栏就可以了。
&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/2013/11/15153246_zzEM.png&#34;&gt;&lt;img alt=&#34;15153246_zzEM&#34; loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/082e1647ca341b0f3549dcfc136ce278d73f4acb.png&#34;&gt;&lt;/a&gt;
使用在2中所提及的方法，查看该断点的属性，
&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/2013/11/15153246_e1gH.png&#34;&gt;&lt;img alt=&#34;15153246_e1gH&#34; loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/f268f9ed80a672eeb51d164658a971d6777989b9.png&#34;&gt;&lt;/a&gt;
默认地，当该变量被访问或它的值被修改时，程序都会被中断。但在本示例中，只希望当对value的值进行修改时程序才需要被中断，所以取消对&amp;quot;Access&amp;quot;的勾选。
&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/2013/11/15153246_evtw.png&#34;&gt;&lt;img alt=&#34;15153246_evtw&#34; loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/1deb043f0baa72b61a76e794f7acf9d25762112c.png&#34;&gt;&lt;/a&gt;
这时，我们会发现原来的Watchpoin图标也有变化了。
&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/2013/11/15153246_Sw8K.png&#34;&gt;&lt;img alt=&#34;15153246_Sw8K&#34; loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/d2dff57a03768ac00b84dd9bb651e99031d94cdc.png&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;4. Method Breakpoint&lt;/strong&gt;
与关注对某个变量的访问与修改一样，我们也可以关注程序对某个方法的调用情况，即，可以设置Method Breakpoint。在此处，设置针对方法setValue的Method Breakpoint。同理，双击第11行代码对应的左侧栏即可。
&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/2013/11/15153247_xdH4.png&#34;&gt;&lt;img alt=&#34;15153247_xdH4&#34; loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/bd49da0a82d0dc044a917e5b53107b05b36f6378.png&#34;&gt;&lt;/a&gt;
仍然要查看该断点的属性。默认地，只勾选了&amp;quot;Entry&amp;quot;，而没有勾选&amp;quot;Exit&amp;quot;。
&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/2013/11/15153247_W1oy.png&#34;&gt;&lt;img alt=&#34;15153247_W1oy&#34; loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/7294186aaa782865383feb3a4e375a5a3b628c27.png&#34;&gt;&lt;/a&gt;
这表示，当刚进入该方法(调用开始)时，程序会被中断；而，离开该方法(调用结束)时，程序并不会被中断。在本示例中，需要同时勾选上&amp;quot;Exit&amp;quot;。
&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/2013/11/15153247_QVwz.png&#34;&gt;&lt;img alt=&#34;15153247_QVwz&#34; loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/39f23217e1d0ead7061f1d636b97f52b6ee886fd.png&#34;&gt;&lt;/a&gt;
点击OK之后，可以看到该断点的图标也有所改变。
&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/2013/11/15153247_YRMh.png&#34;&gt;&lt;img alt=&#34;15153247_YRMh&#34; loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/bdeda47c131aefb575366c4d23b16b3e0ee59321.png&#34;&gt;&lt;/a&gt;
根据这里的设置，当程序运行到第20行后会在第12行被中断，尽管这里没有显式的断点，但这就是setValue()方法的入口(Entry)。必须注意地是，程序在运行到第16行时不会被中断，尽管它看起来像是setValue()方法的出口(Exit)。实际上，程序会在第17行被中断，这里才是setValue()调用结束的地方。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;5. Exception Breakpoint&lt;/strong&gt;
如果，我们期望某个特定异常发生时程序能够被中断，以方便查看当时程序所处的状态。通过设置Exception Breakpoint就能达到这一目标。本示例故意在第23行抛出了IllegalArgumentException异常，我们期望程序运行到此处时会被中断。但我们不直接为此行代码设置Line Breakpoint，而是为IllegalArgumentException设置Exception Breakpoint。设置Exception Breakpoint的方法与其它类型断点都不同，它不能通过双击左侧栏的方式在代码编辑器上直接进行设置。点击Breakpoints视图右上角形如Ji的图标，
&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/2013/11/15153247_Wm2U.png&#34;&gt;&lt;img alt=&#34;15153247_Wm2U&#34; loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/d4f298befa3d1c0100aef36797c56bbc1d2a423c.png&#34;&gt;&lt;/a&gt;
会弹出如下所示的对话框，
&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/2013/11/15153248_WgLd.png&#34;&gt;&lt;img alt=&#34;15153248_WgLd&#34; loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/04e45e47d1e4248fd2ec8db8b13252e1c196e525.png&#34;&gt;&lt;/a&gt;
在其中选中IllegalArgumentException，并点击OK，这时一个Exception Breakpoint就设置好了。
&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/2013/11/15153248_kE2O.png&#34;&gt;&lt;img alt=&#34;15153248_kE2O&#34; loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/fd555622458bbb34ad01929c6a7483768f6b37a8.png&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div&gt;当value为3的倍数时，程序会在第23行被中断，这时我们就能使用调试器来看看value具体是等于0，3或6。&lt;/div&gt;
**6\. Class Load Breakpoint**
还有一种大家平时可能不太用的断点--Class Load Breakpoint，即当某个类被加载时，通过该断点可以中断程序。
[![15153248_2UA6](/images/8158c897f4e784042063a484c7256901902b6c20.png)](http://leaverimage.b0.upaiyun.com/2013/11/15153248_2UA6.png)
&lt;p&gt;&lt;strong&gt;小结&lt;/strong&gt;
上述的Eclipse断点，我们在现实工作中肯定都有意或无意地使用过其中的几种，只是不一定十分了解内情罢了。使用好Eclipse的各种断点，可以把很好地帮助我们分析程序，定位问题。&lt;/p&gt;</description>
    </item>
    <item>
      <title>Spring依赖注入</title>
      <link>http://blog.leaver.me/2013/09/20/spring%E4%BE%9D%E8%B5%96%E6%B3%A8%E5%85%A5/</link>
      <pubDate>Fri, 20 Sep 2013 19:06:00 +0000</pubDate>
      <guid>http://blog.leaver.me/2013/09/20/spring%E4%BE%9D%E8%B5%96%E6%B3%A8%E5%85%A5/</guid>
      <description>&lt;p&gt;在Spring框架中，依赖注入设计模式主要用来定义对象之间的依赖，存在两种主要类型&lt;/p&gt;
&lt;p&gt;1)setter注入(设置器)&lt;/p&gt;
&lt;p&gt;2)constructor注入(构造器)&lt;/p&gt;
&lt;h2 id=&#34;1setter注入&#34;&gt;1.Setter注入&lt;/h2&gt;
&lt;p&gt;是最流行最简单的DI方法，通过一个setter方法来完成依赖。&lt;/p&gt;
&lt;p&gt;例子：&lt;/p&gt;
&lt;p&gt;一个有一个setter方法的Helper类&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;package com.mkyong.output;

import com.mkyong.output.IOutputGenerator;

public class OutputHelper
{
	IOutputGenerator outputGenerator;

	public void setOutputGenerator(IOutputGenerator outputGenerator){
		this.outputGenerator = outputGenerator;
	}

}&lt;/pre&gt;
&lt;p&gt;再写一个bean配合iwenjianshengming这些bean，并且通过property(属性)标签来设置依赖&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;&amp;lt;beans xmlns=&#34;http://www.springframework.org/schema/beans&#34;
xmlns:xsi=&#34;http://www.w3.org/2001/XMLSchema-instance&#34;
xsi:schemaLocation=&#34;http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd&#34;&amp;gt;

	&amp;lt;bean id=&#34;OutputHelper&#34; class=&#34;com.mkyong.output.OutputHelper&#34;&amp;gt;
		&amp;lt;property name=&#34;outputGenerator&#34;&amp;gt;
			&amp;lt;ref bean=&#34;CsvOutputGenerator&#34; /&amp;gt;
		&amp;lt;/property&amp;gt;
	&amp;lt;/bean&amp;gt;

&amp;lt;bean id=&#34;CsvOutputGenerator&#34; class=&#34;com.mkyong.output.impl.CsvOutputGenerator&#34; /&amp;gt;
&amp;lt;bean id=&#34;JsonOutputGenerator&#34; class=&#34;com.mkyong.output.impl.JsonOutputGenerator&#34; /&amp;gt;

&amp;lt;/beans&amp;gt;&lt;/pre&gt;
&lt;p&gt;看到了把。我们只需要一个setter方法把CsvOutputGenerator注入进去就行了&lt;/p&gt;
&lt;h2 id=&#34;2constructor注入&#34;&gt;2.Constructor注入&lt;/h2&gt;
&lt;p&gt;这种方式是通过一个构造函数来完成依赖设置的&lt;/p&gt;
&lt;p&gt;例子：&lt;/p&gt;
&lt;p&gt;一个有着一个构造函数的Helper类&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;package com.mkyong.output;

import com.mkyong.output.IOutputGenerator;

public class OutputHelper
{
	IOutputGenerator outputGenerator;

        OutputHelper(IOutputGenerator outputGenerator){
		this.outputGenerator = outputGenerator;
	}
}&lt;/pre&gt;
&lt;p&gt;然后当然是一个bean配置文件了。通过constructor-arg标签来写依赖&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;&amp;lt;beans xmlns=&#34;http://www.springframework.org/schema/beans&#34;
xmlns:xsi=&#34;http://www.w3.org/2001/XMLSchema-instance&#34;
xsi:schemaLocation=&#34;http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd&#34;&amp;gt;

	&amp;lt;bean id=&#34;OutputHelper&#34; class=&#34;com.mkyong.output.OutputHelper&#34;&amp;gt;
		&amp;lt;constructor-arg&amp;gt;
                     &amp;lt;ref bean=&#34;JsonOutputGenerator&#34; /&amp;gt;
                 &amp;lt;/constructor-arg&amp;gt; 
       &amp;lt;/bean&amp;gt; 
       &amp;lt;bean id=&#34;CsvOutputGenerator&#34; class=&#34;com.mkyong.output.impl.CsvOutputGenerator&#34; /&amp;gt; 
       &amp;lt;bean id=&#34;JsonOutputGenerator&#34; class=&#34;com.mkyong.output.impl.JsonOutputGenerator&#34; /&amp;gt; 
&amp;lt;/beans&amp;gt;&lt;/pre&gt;
&lt;h2 id=&#34;该选哪个&#34;&gt;该选哪个？&lt;/h2&gt;
&lt;p&gt;没有硬性规定，哪个合适就用那个，由于setter的简单性，一般还是setter用得多。&lt;/p&gt;</description>
    </item>
    <item>
      <title>Spring松耦合示例</title>
      <link>http://blog.leaver.me/2013/09/20/spring%E6%9D%BE%E8%80%A6%E5%90%88%E7%A4%BA%E4%BE%8B/</link>
      <pubDate>Fri, 20 Sep 2013 15:50:46 +0000</pubDate>
      <guid>http://blog.leaver.me/2013/09/20/spring%E6%9D%BE%E8%80%A6%E5%90%88%E7%A4%BA%E4%BE%8B/</guid>
      <description>&lt;p&gt;面向对象设计的理念是把整个系统分成一组可重用的组件，然而，当系统变得越大的时候，尤其是在java中，这最大的对象依赖将会紧紧耦合，以至于非常难以管理和修改，而现在，你可以使用Spring框架扮演一个中间模块的角色，方便高效地管理其他组件依赖&lt;/p&gt;
&lt;h2 id=&#34;输出生成的例子&#34;&gt;输出生成的例子&lt;/h2&gt;
&lt;p&gt;看个例子，假设你的项目有一个方法可以输出内容到csv或者json格式，你可能写出这样的代码&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34; title=&#34;IOutputGenerator.java 输出生成器接口&#34;&gt;package com.mkyong.output;

public interface IOutputGenerator
{
	public void generateOutput();
}&lt;/pre&gt;
&lt;p&gt;，然后是实现接口的类&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34; title=&#34;CsvOutputGenerator.java csv生成类&#34;&gt;package com.mkyong.output.impl;

import com.mkyong.output.IOutputGenerator;

public class CsvOutputGenerator implements IOutputGenerator
{
	public void generateOutput(){
		System.out.println(&#34;Csv Output Generator&#34;);
	}
}&lt;/pre&gt;
&lt;p&gt;再写个Json生成的类&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34; title=&#34;JsonOutputGenerator.java json生成类&#34;&gt;package com.mkyong.output.impl;

import com.mkyong.output.IOutputGenerator;

public class JsonOutputGenerator implements IOutputGenerator
{
	public void generateOutput(){
		System.out.println(&#34;Json Output Generator&#34;);
	}
}&lt;/pre&gt;
&lt;p&gt;有好几种方法来调用IOutputGenerator接口，以及我们如何使用Spring来避免对象的过度耦合。&lt;/p&gt;
&lt;h2 id=&#34;方法1-直接调用&#34;&gt;方法1-直接调用&lt;/h2&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;package com.mkyong.common;

import com.mkyong.output.IOutputGenerator;
import com.mkyong.output.impl.CsvOutputGenerator;

public class App 
{
    public static void main( String[] args )
    {
    	IOutputGenerator output = new CsvOutputGenerator();
    	output.generateOutput();
    }
}&lt;/pre&gt;
&lt;p&gt;问题：&lt;/p&gt;
&lt;p&gt;这种方法，output这个对象和CsvOutputGenerator耦合在了一起，每次要改变输出格式的话都要修改代码，如果这类代码遍布项目，那么改起来就跪了&lt;/p&gt;
&lt;h2 id=&#34;方法2-通过帮助类调用&#34;&gt;方法2-通过帮助类调用&lt;/h2&gt;
&lt;p&gt;也许你会想创建一个Helper类吧所有的output实现都移进去&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;package com.mkyong.output;

import com.mkyong.output.IOutputGenerator;
import com.mkyong.output.impl.CsvOutputGenerator;

public class OutputHelper
{
	IOutputGenerator outputGenerator;

	public OutputHelper(){
		outputGenerator = new CsvOutputGenerator();
	}

	public void generateOutput(){
		outputGenerator.generateOutput();
	}

}&lt;/pre&gt;
&lt;p&gt;然后可以这样调用&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;package com.mkyong.common;

import com.mkyong.output.OutputHelper;

public class App 
{
    public static void main( String[] args )
    {
    	OutputHelper output = new OutputHelper();
    	output.generateOutput(); 
    }
}&lt;/pre&gt;
&lt;p&gt;问题：&lt;/p&gt;
&lt;p&gt;看起来似乎更加优雅了，你仅仅需要管理这个Helper类就可以实现不同格式的输出需求改变了，然而，Helper还是和CvsOutputGenerator耦合，每一次要改变输出格式的时候，都要对Helper类做一下微调。&lt;/p&gt;
&lt;h2 id=&#34;方法3-spring&#34;&gt;方法3-Spring&lt;/h2&gt;
&lt;p&gt;Spring依赖注入很合适，可以使不同的格式生成类分离开来&lt;/p&gt;</description>
    </item>
    <item>
      <title>Spring3实例入门-Hello World</title>
      <link>http://blog.leaver.me/2013/09/20/spring3%E5%AE%9E%E4%BE%8B%E5%85%A5%E9%97%A8-hello-world/</link>
      <pubDate>Fri, 20 Sep 2013 13:14:39 +0000</pubDate>
      <guid>http://blog.leaver.me/2013/09/20/spring3%E5%AE%9E%E4%BE%8B%E5%85%A5%E9%97%A8-hello-world/</guid>
      <description>&lt;p&gt;每次看到hello world,都有一种说不出的赶脚，想起了一个程序员，退休后写毛笔字，取笔研磨铺纸，大笔一挥，写下了“hello world”。&lt;/p&gt;
&lt;h2 id=&#34;1使用maven生成项目结构&#34;&gt;1.使用Maven生成项目结构&lt;/h2&gt;
&lt;pre class=&#34;lang:default decode:true &#34;&gt;mvn archetype:generate -DgroupId=com.mkyong.core -DartifactId=Spring3Example 
	-DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false&lt;/pre&gt;
&lt;h2 id=&#34;2转换成eclipse项目&#34;&gt; 2.转换成Eclipse项目&lt;/h2&gt;
&lt;pre class=&#34;lang:default decode:true &#34;&gt;mvn eclipse:eclipse&lt;/pre&gt;
&lt;h2 id=&#34;3添加spring30-依赖&#34;&gt; 3.添加Spring3.0 依赖&lt;/h2&gt;
&lt;p&gt;在pom.xml文件里添加Spring 3.0 依赖，然后依赖会从Maven中央仓库自动下载&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34; title=&#34;pom.xml&#34;&gt;&amp;lt;project xmlns=&#34;http://maven.apache.org/POM/4.0.0&#34; 
	xmlns:xsi=&#34;http://www.w3.org/2001/XMLSchema-instance&#34;
	xsi:schemaLocation=&#34;http://maven.apache.org/POM/4.0.0 
	http://maven.apache.org/maven-v4_0_0.xsd&#34;&amp;gt;
	&amp;lt;modelVersion&amp;gt;4.0.0&amp;lt;/modelVersion&amp;gt;
	&amp;lt;groupId&amp;gt;com.mkyong.core&amp;lt;/groupId&amp;gt;
	&amp;lt;artifactId&amp;gt;Spring3Example&amp;lt;/artifactId&amp;gt;
	&amp;lt;packaging&amp;gt;jar&amp;lt;/packaging&amp;gt;
	&amp;lt;version&amp;gt;1.0-SNAPSHOT&amp;lt;/version&amp;gt;
	&amp;lt;name&amp;gt;Spring3Example&amp;lt;/name&amp;gt;
	&amp;lt;url&amp;gt;http://maven.apache.org&amp;lt;/url&amp;gt;

	&amp;lt;properties&amp;gt;
		&amp;lt;spring.version&amp;gt;3.0.5.RELEASE&amp;lt;/spring.version&amp;gt;
	&amp;lt;/properties&amp;gt;

	&amp;lt;dependencies&amp;gt;

		&amp;lt;!-- Spring 3 dependencies --&amp;gt;
		&amp;lt;dependency&amp;gt;
			&amp;lt;groupId&amp;gt;org.springframework&amp;lt;/groupId&amp;gt;
			&amp;lt;artifactId&amp;gt;spring-core&amp;lt;/artifactId&amp;gt;
			&amp;lt;version&amp;gt;${spring.version}&amp;lt;/version&amp;gt;
		&amp;lt;/dependency&amp;gt;

		&amp;lt;dependency&amp;gt;
			&amp;lt;groupId&amp;gt;org.springframework&amp;lt;/groupId&amp;gt;
			&amp;lt;artifactId&amp;gt;spring-context&amp;lt;/artifactId&amp;gt;
			&amp;lt;version&amp;gt;${spring.version}&amp;lt;/version&amp;gt;
		&amp;lt;/dependency&amp;gt;

	&amp;lt;/dependencies&amp;gt;
&amp;lt;/project&amp;gt;&lt;/pre&gt;
&lt;h2 id=&#34;4spring-bean&#34;&gt; 4.Spring bean&lt;/h2&gt;
&lt;p&gt;写个简单的bean&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34; title=&#34;HelloWorld&#34;&gt;package com.mkyong.core;

/**
 * Spring bean
 * 
 */
public class HelloWorld {
	private String name;

	public void setName(String name) {
		this.name = name;
	}

	public void printHello() {
		System.out.println(&#34;Spring 3 : Hello ! &#34; + name);
	}
}&lt;/pre&gt;
&lt;h2 id=&#34;5spring-bean配置文件&#34;&gt; 5.Spring bean配置文件&lt;/h2&gt;
&lt;p&gt;创建一个配置文件，在里面声明所有可用的Spring beans&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34; title=&#34;SpringBeans.xml&#34;&gt;&amp;lt;beans xmlns=&#34;http://www.springframework.org/schema/beans&#34;
	xmlns:xsi=&#34;http://www.w3.org/2001/XMLSchema-instance&#34;
	xsi:schemaLocation=&#34;http://www.springframework.org/schema/beans
	http://www.springframework.org/schema/beans/spring-beans-3.0.xsd&#34;&amp;gt;

	&amp;lt;bean id=&#34;helloBean&#34; class=&#34;com.mkyong.core.HelloWorld&#34;&amp;gt;
		&amp;lt;property name=&#34;name&#34; value=&#34;Mkyong&#34; /&amp;gt;
	&amp;lt;/bean&amp;gt;

&amp;lt;/beans&amp;gt;&lt;/pre&gt;
&lt;h2 id=&#34;6最终的目录结构&#34;&gt; 6.最终的目录结构&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/2013/09/Spring3-hello-world-example.png&#34;&gt;&lt;img alt=&#34;Spring3-hello-world-example&#34; loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/bbe4d8f74c9337766eb4a368bb71c6c0d09a248b.png&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2 id=&#34;7运行&#34;&gt;7.运行&lt;/h2&gt;
&lt;pre class=&#34;lang:default decode:true&#34; title=&#34;App.java&#34;&gt;package com.mkyong.core;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class App {
	public static void main(String[] args) {
		ApplicationContext context = new ClassPathXmlApplicationContext(
				&#34;SpringBeans.xml&#34;);

		HelloWorld obj = (HelloWorld) context.getBean(&#34;helloBean&#34;);
		obj.printHello();
	}
}&lt;/pre&gt;
&lt;h2 id=&#34;8输出&#34;&gt; 8.输出&lt;/h2&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;Spring 3 : Hello ! Mkyong&lt;/pre&gt;
&lt;h2 id=&#34;9demo下载&#34;&gt; 9.Demo下载&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;http://pan.baidu.com/share/link?shareid=2464458395&amp;amp;uk=1493685990&#34;&gt;Spring3-hello-world-example.zip &lt;/a&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>使用Maven创建Web项目</title>
      <link>http://blog.leaver.me/2013/09/20/%E4%BD%BF%E7%94%A8maven%E5%88%9B%E5%BB%BAweb%E9%A1%B9%E7%9B%AE/</link>
      <pubDate>Fri, 20 Sep 2013 08:44:11 +0000</pubDate>
      <guid>http://blog.leaver.me/2013/09/20/%E4%BD%BF%E7%94%A8maven%E5%88%9B%E5%BB%BAweb%E9%A1%B9%E7%9B%AE/</guid>
      <description>&lt;p&gt;本文通过Maven完成一个简单的Web项目（注意，Spring配置不是重点，看看就行）&lt;/p&gt;
&lt;h2 id=&#34;1从maven模板创建web应用程序&#34;&gt;1.从Maven模板创建Web应用程序&lt;/h2&gt;
&lt;p&gt;命令格式如下：&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;mvn archetype:generate -DgroupId={project-packaging} -DartifactId={project-name} -DarchetypeArtifactId=maven-archetype-webapp -DinteractiveMode=false&lt;/pre&gt;
&lt;p&gt;这就告诉Maven从**maven-archetype-webapp **这个模板来创建&lt;/p&gt;
&lt;p&gt;友情提示：是不是太难记了..好吧，直接输入&lt;/p&gt;
&lt;pre&gt;mvn archetype:generate&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;&amp;gt; mvn archetype:generate -DgroupId=com.mkyong -DartifactId=CounterWebApp -DarchetypeArtifactId=maven-archetype-webapp -DinteractiveMode=false
[INFO] Scanning for projects...
[INFO]                                                                         
[INFO] ------------------------------------------------------------------------
[INFO] Building Maven Stub Project (No POM) 1
[INFO] ------------------------------------------------------------------------
[INFO] 
[INFO] Generating project in Batch mode
[INFO] ----------------------------------------------------------------------------
[INFO] Using following parameters for creating project from Old (1.x) Archetype: maven-archetype-webapp:1.0
[INFO] ----------------------------------------------------------------------------
[INFO] Parameter: groupId, Value: com.mkyong
[INFO] Parameter: packageName, Value: com.mkyong
[INFO] Parameter: package, Value: com.mkyong
[INFO] Parameter: artifactId, Value: CounterWebApp
[INFO] Parameter: basedir, Value: /Users/mkyong/Documents/workspace
[INFO] Parameter: version, Value: 1.0-SNAPSHOT
[INFO] project created from Old (1.x) Archetype in dir: /Users/mkyong/Documents/workspace/CounterWebApp
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 3.147s
[INFO] Finished at: Thu Dec 20 20:35:19 MYT 2012
[INFO] Final Memory: 12M/128M
[INFO] ------------------------------------------------------------------------&lt;/pre&gt;
&lt;p&gt;就创建了一个包名为com.mkyong,类名为CounterWebApp的项目了&lt;/p&gt;
&lt;h2 id=&#34;2maven的web程序目录结构&#34;&gt;2.Maven的Web程序目录结构&lt;/h2&gt;
&lt;p&gt;标准的web.xml部署描述文件生成了&lt;/p&gt;
&lt;pre&gt;CounterWebApp
   |-src
   |---main
   |-----resources
   |-----webapp
   |-------index.jsp
   |-------WEB-INF
   |---------web.xml
   |-pom.xml&lt;/pre&gt;
&lt;p&gt;对结构有疑问的去&lt;a href=&#34;http://maven.apache.org/guides/introduction/introduction-to-the-standard-directory-layout.html&#34;&gt;这里&lt;/a&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>Maven库依赖机制及添加自定义库</title>
      <link>http://blog.leaver.me/2013/09/19/maven%E5%BA%93%E4%BE%9D%E8%B5%96%E6%9C%BA%E5%88%B6%E5%8F%8A%E6%B7%BB%E5%8A%A0%E8%87%AA%E5%AE%9A%E4%B9%89%E5%BA%93/</link>
      <pubDate>Thu, 19 Sep 2013 22:49:42 +0000</pubDate>
      <guid>http://blog.leaver.me/2013/09/19/maven%E5%BA%93%E4%BE%9D%E8%B5%96%E6%9C%BA%E5%88%B6%E5%8F%8A%E6%B7%BB%E5%8A%A0%E8%87%AA%E5%AE%9A%E4%B9%89%E5%BA%93/</guid>
      <description>&lt;h1 id=&#34;一maven库依赖机制&#34;&gt;一.Maven库依赖机制&lt;/h1&gt;
&lt;p&gt;Maven的库依赖机制可以帮助我们自动下载依赖的库文件，并且还能更新版本。。&lt;/p&gt;
&lt;p&gt;考虑一个情境来理解机制的工作原理，假设我们要使用Log4J库作为项目的日志记录。以下是我们要做的&lt;/p&gt;
&lt;h2 id=&#34;1传统的方式&#34;&gt;1.传统的方式&lt;/h2&gt;
&lt;p&gt;1）访问Log4J网站&lt;a href=&#34;http://logging.apache.org/log4j/2.x/&#34;&gt;http://logging.apache.org/log4j/2.x/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;2）下载Log4J的jar包&lt;/p&gt;
&lt;p&gt;3）复制进项目的classpath里&lt;/p&gt;
&lt;p&gt;4）手工包含到项目的依赖里&lt;/p&gt;
&lt;p&gt;看到没，你要从头做到尾，如果Log4J更新了，你得再来一遍。。&lt;/p&gt;
&lt;h2 id=&#34;2maven的方式&#34;&gt;2.Maven的方式&lt;/h2&gt;
&lt;p&gt;1）需要知道Log4J的Maven坐标(coordinates,这个暂时没想到好名字)，就是这样的东西&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;&amp;lt;groupId&amp;gt;log4j&amp;lt;/groupId&amp;gt;
	&amp;lt;artifactId&amp;gt;log4j&amp;lt;/artifactId&amp;gt;
	&amp;lt;version&amp;gt;1.2.14&amp;lt;/version&amp;gt;&lt;/pre&gt;
&lt;p&gt;然后Maven就会自动下载1.2.14版本的Log4J了。如果version这个元素没有，那么如果有了新版本，Maven会自动下载新版本的。&lt;/p&gt;
&lt;p&gt;2）在pom.xml里声明这个Maven坐标&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;&amp;lt;dependencies&amp;gt;
    &amp;lt;dependency&amp;gt;
	&amp;lt;groupId&amp;gt;log4j&amp;lt;/groupId&amp;gt;
	&amp;lt;artifactId&amp;gt;log4j&amp;lt;/artifactId&amp;gt;
	&amp;lt;version&amp;gt;1.2.14&amp;lt;/version&amp;gt;
    &amp;lt;/dependency&amp;gt;
&amp;lt;/dependencies&amp;gt;&lt;/pre&gt;
&lt;p&gt;3）当Maven编译或者build的时候，Log4J会自动下载，放入本地仓库里&lt;/p&gt;
&lt;p&gt;4）Maven全部接管&lt;/p&gt;
&lt;h2 id=&#34;3解释&#34;&gt;3.解释&lt;/h2&gt;
&lt;p&gt;搜索顺序前面说过了。本地-》中央-》远程仓库&lt;/p&gt;
&lt;p&gt;Maven坐标咋来的，当然去&lt;a href=&#34;http://search.maven.org/&#34;&gt;中央仓库搜索&lt;/a&gt;之了，搜索结果清晰的令人发指&lt;/p&gt;
&lt;h1 id=&#34;二添加自定义库到本地仓库&#34;&gt;二.添加自定义库到本地仓库&lt;/h1&gt;
&lt;p&gt;有两个情况，需要我们包含自定义的库到本地仓库里&lt;/p&gt;
&lt;p&gt;1是你想使用的jar文件不再中央仓库&lt;/p&gt;
&lt;p&gt;2是你创建了一个自定义的jar包，需要另一个项目使用这个jar&lt;/p&gt;
&lt;p&gt;比如，&lt;a href=&#34;http://code.google.com/p/kaptcha/&#34;&gt;kaptche&lt;/a&gt;，一个第三方的java库，生成验证码，现在中央仓库没有了。&lt;/p&gt;
&lt;p&gt;我们想要加到本地仓库里&lt;/p&gt;
&lt;h2 id=&#34;1mvn安装&#34;&gt;1.mvn安装&lt;/h2&gt;
&lt;p&gt;下载&lt;a href=&#34;http://code.google.com/p/kaptcha/&#34;&gt;kaptche&lt;/a&gt;，解压并且拷贝kaptcha-version.jar到其他任何你喜欢的地方，比如c盘，然后输入如下格式的命令&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;mvn install:install-file -Dfile=c:\kaptcha-{version}.jar -DgroupId=com.google.code 
-DartifactId=kaptcha -Dversion={version} -Dpackaging=jar&lt;/pre&gt;
&lt;p&gt;这里我这样输入&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;D:\&amp;gt;mvn install:install-file -Dfile=c:\kaptcha-2.3.jar -DgroupId=com.google.code 
-DartifactId=kaptcha -Dversion=2.3 -Dpackaging=jar
[INFO] Scanning for projects...
[INFO] Searching repository for plugin with prefix: &#39;install&#39;.
[INFO] ------------------------------------------------------------------------
[INFO] Building Maven Default Project
[INFO]    task-segment: [install:install-file] (aggregator-style)
[INFO] ------------------------------------------------------------------------
[INFO] [install:install-file]
[INFO] Installing c:\kaptcha-2.3.jar to 
D:\maven_repo\com\google\code\kaptcha\2.3\kaptcha-2.3.jar
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ------------------------------------------------------------------------
[INFO] Total time: &amp;lt; 1 second
[INFO] Finished at: Tue May 12 13:41:42 SGT 2009
[INFO] Final Memory: 3M/6M
[INFO] ------------------------------------------------------------------------&lt;/pre&gt;
&lt;p&gt;这样完成了。kaptcha已经存在本地库了&lt;/p&gt;
&lt;h2 id=&#34;2pomxml配置一下&#34;&gt;2.pom.xml配置一下&lt;/h2&gt;
&lt;pre&gt;&amp;lt;dependency&amp;gt;
      &amp;lt;groupId&amp;gt;com.google.code&amp;lt;/groupId&amp;gt;
      &amp;lt;artifactId&amp;gt;kaptcha&amp;lt;/artifactId&amp;gt;
      &amp;lt;version&amp;gt;2.3&amp;lt;/version&amp;gt;
 &amp;lt;/dependency&amp;gt;&lt;/pre&gt;
&lt;p&gt;这个前面说过了，Maven坐标嘛&lt;/p&gt;</description>
    </item>
    <item>
      <title>Maven仓库详解</title>
      <link>http://blog.leaver.me/2013/09/19/maven%E4%BB%93%E5%BA%93%E8%AF%A6%E8%A7%A3/</link>
      <pubDate>Thu, 19 Sep 2013 22:05:10 +0000</pubDate>
      <guid>http://blog.leaver.me/2013/09/19/maven%E4%BB%93%E5%BA%93%E8%AF%A6%E8%A7%A3/</guid>
      <description>&lt;p&gt;本文由我翻译合并了多篇文章，整理成一篇。&lt;/p&gt;
&lt;h1 id=&#34;一本地仓库local-repository&#34;&gt;一.本地仓库(Local Repository)&lt;/h1&gt;
&lt;p&gt;本地仓库就是一个本机的目录，这个目录被用来存储我们项目的所有依赖（插件的jar包还有一些其他的文件），简单的说，当你build一个Maven项目的时候，所有的依赖文件都会放在本地仓库里，仓库供所有项目都可以使用&lt;/p&gt;
&lt;p&gt;默认情况下，本地仓库在.m2目录，windows下的话就是你的用户名目录下的.m2目录&lt;/p&gt;
&lt;h2 id=&#34;1更新本地仓库目录&#34;&gt;1.更新本地仓库目录&lt;/h2&gt;
&lt;p&gt;找到你的MAVEN_HOME目录下的conf/setting.xml文件，更新localRepository节点&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34; title=&#34;maven_home/conf/setting.xml&#34;&gt;&amp;lt;settings&amp;gt;
  &amp;lt;!-- localRepository
   | The path to the local repository maven will use to store artifacts.
   |
   | Default: ~/.m2/repository
  &amp;lt;localRepository&amp;gt;/path/to/local/repo&amp;lt;/localRepository&amp;gt;
  --&amp;gt;

&amp;lt;localRepository&amp;gt;D:/maven/repo&amp;lt;/localRepository&amp;gt;&lt;/pre&gt;
&lt;h2 id=&#34;2保存一下&#34;&gt; 2.保存一下&lt;/h2&gt;
&lt;p&gt;完成了。新的本地仓库被放在了D:/maven/repo&lt;/p&gt;
&lt;p&gt;看一下这个目录&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/2013/09/maven-local-repo.png&#34;&gt;&lt;img alt=&#34;maven-local-repo&#34; loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/4bc19a12bd7d869d840c872a9c3bdbfbd55d339c.png&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h1 id=&#34;二中央仓库central-repository&#34;&gt; 二.中央仓库(central repository)&lt;/h1&gt;
&lt;p&gt;当我们build一个Maven项目的时候，Maven会检查我们的pom.xml文件，来定义项目的依赖，然后Maven会在本地仓库里查找，如果没有找到，就去maven的中央库去下载，地址是&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://search.maven.org/#browse&#34;&gt;http://search.maven.org/#browse&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;看起来是这样的&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/2013/09/maven-center-repository-search.png&#34;&gt;&lt;img alt=&#34;maven-center-repository-search&#34; loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/1b90bc7c3b841d566a18777d661d40b159a29b16.png&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;注意啊，虽然这个是新的中央仓库，但有时候还是会从_“&lt;strong&gt;&lt;a href=&#34;http://repo1.maven.org/maven/&#34;&gt;http://repo1.maven.org/maven/&lt;/a&gt;&lt;/strong&gt;_这个旧仓库下载东西，不过不要紧，理解就行了&lt;/p&gt;
&lt;h1 id=&#34;三远程仓库remote-respository&#34;&gt;三.远程仓库(Remote Respository)&lt;/h1&gt;
&lt;p&gt;在Maven中，当你在pom.xml中生命的依赖既不在本地库，也不在中央库的时候，就会报错。&lt;/p&gt;
&lt;h2 id=&#34;1例子&#34;&gt;1.例子&lt;/h2&gt;
&lt;p&gt;org.jvnet.localizer这个包仅在&lt;a href=&#34;https://maven.java.net/content/repositories/public/&#34;&gt;java.net的仓库里&lt;/a&gt;有(以前是，现在中央仓库也有了。但理解就行)&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34; title=&#34;pom.xml&#34;&gt;   &amp;lt;dependency&amp;gt;
        &amp;lt;groupId&amp;gt;org.jvnet.localizer&amp;lt;/groupId&amp;gt;
        &amp;lt;artifactId&amp;gt;localizer&amp;lt;/artifactId&amp;gt;
        &amp;lt;version&amp;gt;1.8&amp;lt;/version&amp;gt;
    &amp;lt;/dependency&amp;gt;&lt;/pre&gt;
&lt;p&gt;当我们build的时候，会失败，并输出未找到错误信息&lt;/p&gt;
&lt;h2 id=&#34;2声明javanet仓库&#34;&gt;2.声明java.net仓库&lt;/h2&gt;
&lt;p&gt;为了告诉Maven从远程仓库里获取依赖，我们需要声明一个远程仓库，在pom.xml里这样写&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;  &amp;lt;repositories&amp;gt;
	&amp;lt;repository&amp;gt;
	    &amp;lt;id&amp;gt;java.net&amp;lt;/id&amp;gt;
	    &amp;lt;url&amp;gt;https://maven.java.net/content/repositories/public/&amp;lt;/url&amp;gt;
	&amp;lt;/repository&amp;gt;
    &amp;lt;/repositories&amp;gt;&lt;/pre&gt;
&lt;p&gt;这样，Maven搜索依赖的顺序就是：&lt;/p&gt;
&lt;p&gt;1）搜索本地仓库，没有找到，就去第2步，否则退出&lt;/p&gt;
&lt;p&gt;2）搜索中央仓库，没有找到，就去第3步，否则退出&lt;/p&gt;
&lt;p&gt;3）去java.net远程仓库获取，没有找到，就报错，否则退出&lt;/p&gt;
&lt;p&gt;补充：JBoss也有个远程仓库，可以如下配置：&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;&amp;lt;project ...&amp;gt;
    &amp;lt;repositories&amp;gt;
      &amp;lt;repository&amp;gt;
	&amp;lt;id&amp;gt;JBoss repository&amp;lt;/id&amp;gt;
	&amp;lt;url&amp;gt;http://repository.jboss.org/nexus/content/groups/public/&amp;lt;/url&amp;gt;
      &amp;lt;/repository&amp;gt;
    &amp;lt;/repositories&amp;gt;
&amp;lt;/project&amp;gt;&lt;/pre&gt;</description>
    </item>
    <item>
      <title>Maven安装教程</title>
      <link>http://blog.leaver.me/2013/09/19/maven%E5%AE%89%E8%A3%85%E6%95%99%E7%A8%8B/</link>
      <pubDate>Thu, 19 Sep 2013 21:15:09 +0000</pubDate>
      <guid>http://blog.leaver.me/2013/09/19/maven%E5%AE%89%E8%A3%85%E6%95%99%E7%A8%8B/</guid>
      <description>&lt;p&gt;Maven不需要作为服务组件安装到windows上，仅仅需要下载，解压，然后配置一下环境变量就行了&lt;/p&gt;
&lt;h2 id=&#34;1jdk和java_home&#34;&gt;1.JDK和JAVA_HOME&lt;/h2&gt;
&lt;p&gt;确保JDK已经安装，同时JAVA_HOME变量已经添加到了windows环境变量里，指向jdk目录&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/2013/09/maven-java-home.png&#34;&gt;&lt;img alt=&#34;maven-java-home&#34; loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/3161766919fb6fd118699cc45753f0740be3a6b4.png&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2 id=&#34;2下载maven&#34;&gt;2.下载Maven&lt;/h2&gt;
&lt;p&gt;去&lt;a href=&#34;http://maven.apache.org/download.html&#34;&gt;Maven主页&lt;/a&gt;,选个版本，点击下载&lt;/p&gt;
&lt;h2 id=&#34;3解压&#34;&gt;3.解压&lt;/h2&gt;
&lt;p&gt;解压下载的zip文件，重命名，比如我放到D盘的Maven目录&lt;/p&gt;
&lt;h2 id=&#34;4添加maven_home环境变量&#34;&gt;4.添加MAVEN_HOME环境变量&lt;/h2&gt;
&lt;p&gt;添加一个新的环境变量MAVEN_HOME到环境变量，指向Maven目录&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/2013/09/maven-maven-home.png&#34;&gt;&lt;img alt=&#34;maven-maven-home&#34; loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/5a2878c27f389f27afa72040040a0cc54312b388.png&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2 id=&#34;5添加path变量&#34;&gt;5.添加path变量&lt;/h2&gt;
&lt;p&gt;更新Path变量，把Maven的bin目录添加进去，这样就可以在任何地方执行mvn命令了&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/2013/09/Maven-Path.png&#34;&gt;&lt;img alt=&#34;Maven-Path&#34; loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/ec2bd24fcc118b64cb10405acb807c59490c10d6.png&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2 id=&#34;6验证&#34;&gt;6.验证&lt;/h2&gt;
&lt;p&gt;打开命令行，输入&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;mvn -version&lt;/pre&gt;
&lt;p&gt;如果看到类似下面的&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;C:\Documents and Settings\mkyong&amp;gt;mvn -version
Apache Maven 2.2.1 (r801777; 2009-08-07 03:16:01+0800)
Java version: 1.6.0_13
Java home: C:\Program Files\Java\jdk1.6.0_13\jre
Default locale: en_US, platform encoding: Cp1252
OS name: &#34;windows xp&#34; version: &#34;5.1&#34; arch: &#34;x86&#34; Family: &#34;windows&#34;&lt;/pre&gt;
&lt;p&gt;Maven已经成功的安装配置了。&lt;/p&gt;
&lt;p&gt;老外写的太详细了。。。&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</description>
    </item>
    <item>
      <title>Maven实例入门-随机数生成</title>
      <link>http://blog.leaver.me/2013/09/19/maven%E5%AE%9E%E4%BE%8B%E5%85%A5%E9%97%A8-%E9%9A%8F%E6%9C%BA%E6%95%B0%E7%94%9F%E6%88%90/</link>
      <pubDate>Thu, 19 Sep 2013 20:50:23 +0000</pubDate>
      <guid>http://blog.leaver.me/2013/09/19/maven%E5%AE%9E%E4%BE%8B%E5%85%A5%E9%97%A8-%E9%9A%8F%E6%9C%BA%E6%95%B0%E7%94%9F%E6%88%90/</guid>
      <description>&lt;p&gt;看了很多个例子，发现这个最好，译文中会带有我的一些了理解，有问题欢迎指出。&lt;/p&gt;
&lt;h2 id=&#34;0maven是什么&#34;&gt;0.Maven是什么？&lt;/h2&gt;
&lt;p&gt;Apache Maven，是一个软件（特别是Java软件）项目管理及自动构建工具，由Apache软件基金会所提供。基于项目对象模型（缩写：POM）概念，Maven利用一个中央信息片断能管理一个项目的构建、报告和文档等步骤。&lt;/p&gt;
&lt;p&gt;可以看到，核心就是项目管理和自动构建了，从例子中将会体会更深。本例创建一个随机数生成程序。&lt;/p&gt;
&lt;h2 id=&#34;1从maven模板创建项目&#34;&gt;1.从Maven模板创建项目&lt;/h2&gt;
&lt;p&gt;Maven的环境变量配置和java类似，直接添加系统变量MAVEN_HOME指向你下载的maven目录，然后将bin目录添加到path环境变量里。&lt;/p&gt;
&lt;p&gt;在命令行下，进入到你想存储项目的位置，比如，我自己有个叫work的目录，那么我就cd到work目录，然后按下面的格式输入命令&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;mvn archetype:generate -DgroupId={project-packaging} -DartifactId={project-name} -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false&lt;/pre&gt;
&lt;p&gt;这是告诉Maven从**maven-archetype-quickstart **创建一个java项目，如果你这个参数不填，那么会列出一个列表，让你选择你想创建什么类型，比如web项目啊，啥的。&lt;/p&gt;
&lt;p&gt;友情提示：是不是太难记了..好吧，直接输入&lt;/p&gt;
&lt;pre&gt;mvn archetype:generate&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;&amp;gt;mvn archetype:generate -DgroupId=com.mkyong -DartifactId=NumberGenerator -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false
[INFO] Scanning for projects...
[INFO]                                                                         
[INFO] -- omitted for readability
[INFO] ----------------------------------------------------------------------------
[INFO] Using following parameters for creating project from Old (1.x) Archetype: maven-archetype-quickstart:1.0
[INFO] ----------------------------------------------------------------------------
[INFO] Parameter: groupId, Value: com.mkyong
[INFO] Parameter: packageName, Value: com.mkyong
[INFO] Parameter: package, Value: com.mkyong
[INFO] Parameter: artifactId, Value: NumberGenerator
[INFO] Parameter: basedir, Value: /Users/mkyong/Documents/workspace
[INFO] Parameter: version, Value: 1.0-SNAPSHOT
[INFO] project created from Old (1.x) Archetype in dir: /Users/mkyong/Documents/workspace/NumberGenerator
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 3.917s
[INFO] Finished at: Mon Dec 17 18:53:58 MYT 2012
[INFO] Final Memory: 9M/24M
[INFO] ------------------------------------------------------------------------&lt;/pre&gt;
&lt;p&gt;这里的groupId就是包名，artifactId就是类名，以后具体的一些其他参数我希望有时间可以跟大家分享。&lt;/p&gt;
&lt;h2 id=&#34;2maven目录结构&#34;&gt;2.Maven目录结构&lt;/h2&gt;
&lt;p&gt;上面的命令第一次执行的时候会从apache网站下载maven的一些其他东西，所以务必保持联网。执行成功后，会生成一个这样的目录结构&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;NumberGenerator
   |-src
   |---main
   |-----java
   |-------com
   |---------mkyong
   |-----------App.java
   |---test
   |-----java
   |-------com
   |---------mkyong
   |-----------AppTest.java
   |-pom.xml&lt;/pre&gt;
&lt;p&gt;这里main目录是我们的程序住代码目录。源代码会放在/src/main/java/包名 目录里，而单元测试代码会放在/src/test/java/包名 目录里。当然还有一个标准的pom.xml文件会生成。这个pom文件其实类似于Ant的build.xml文件，它包含了项目的信息，从目录结构到项目插件到项目依赖，都有了。。&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34; title=&#34;pom.xml&#34;&gt;&amp;lt;project xmlns=&#34;http://maven.apache.org/POM/4.0.0&#34; 
	xmlns:xsi=&#34;http://www.w3.org/2001/XMLSchema-instance&#34;
  	xsi:schemaLocation=&#34;http://maven.apache.org/POM/4.0.0 
	http://maven.apache.org/maven-v4_0_0.xsd&#34;&amp;gt;
  &amp;lt;modelVersion&amp;gt;4.0.0&amp;lt;/modelVersion&amp;gt;
  &amp;lt;groupId&amp;gt;com.mkyong&amp;lt;/groupId&amp;gt;
  &amp;lt;artifactId&amp;gt;NumberGenerator&amp;lt;/artifactId&amp;gt;
  &amp;lt;packaging&amp;gt;jar&amp;lt;/packaging&amp;gt;
  &amp;lt;version&amp;gt;1.0-SNAPSHOT&amp;lt;/version&amp;gt;
  &amp;lt;name&amp;gt;NumberGenerator&amp;lt;/name&amp;gt;
  &amp;lt;url&amp;gt;http://maven.apache.org&amp;lt;/url&amp;gt;
  &amp;lt;dependencies&amp;gt;
    &amp;lt;dependency&amp;gt;
      &amp;lt;groupId&amp;gt;junit&amp;lt;/groupId&amp;gt;
      &amp;lt;artifactId&amp;gt;junit&amp;lt;/artifactId&amp;gt;
      &amp;lt;version&amp;gt;3.8.1&amp;lt;/version&amp;gt;
      &amp;lt;scope&amp;gt;test&amp;lt;/scope&amp;gt;
    &amp;lt;/dependency&amp;gt;
  &amp;lt;/dependencies&amp;gt;
&amp;lt;/project&amp;gt;&lt;/pre&gt;
&lt;h2 id=&#34;3用eclipse写代码&#34;&gt;3.用Eclipse写代码&lt;/h2&gt;
&lt;p&gt;maven已经生成了一个完整的工程了，为了能够导入到eclipse里来编辑代码，我们可以把这个项目转换成eclipse可用的。&lt;/p&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>等物体填充问题</title>
      <link>http://blog.leaver.me/2013/06/29/%E7%AD%89%E7%89%A9%E4%BD%93%E5%A1%AB%E5%85%85%E9%97%AE%E9%A2%98/</link>
      <pubDate>Sat, 29 Jun 2013 18:14:08 +0000</pubDate>
      <guid>http://blog.leaver.me/2013/06/29/%E7%AD%89%E7%89%A9%E4%BD%93%E5%A1%AB%E5%85%85%E9%97%AE%E9%A2%98/</guid>
      <description>&lt;p&gt;那天在群里，rich大牛提了一个问题，一个直径为10cm的球内最多能够填充直径为1cm的球多少个.&lt;/p&gt;
&lt;p&gt;之前看到过一个类似的简单说明，就像是在一个盒子里装乒乓球，如果装满了，想继续装，如何办？经验告诉我们，摇一摇盒子。。这个问题看上去简单，其实是个NP难问题&amp;hellip;于是，查找了一些资料，比较有意思，分享一下。&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;首先是stetson大学efriedma教授的网页，收集了各类填充（英文是packing）问题的图示，欢迎移步：&lt;a href=&#34;http://www2.stetson.edu/~efriedma/packing.html&#34;&gt;packing center&lt;/a&gt; ，不过这里面恰好没有球体填充（SpherePacking）的问题，然后继续查找，进入了一个可以演示球体填充问题的页面：&lt;a href=&#34;http://www.randomwalk.de/sphere/insphr/ylspheresinsphr.html&#34;&gt;sphere packing demo&lt;/a&gt; 感谢网站作者&lt;a href=&#34;http://www.pfoertner.org/&#34;&gt;Hugo Pfoertner&lt;/a&gt;，这里作者解出了1-72个球的问题，但是，作者说对于n&amp;gt;10的情况无法证明最优化.不过这个页面的演示太帅了，推荐看看。&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/37791_o.png&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/b6b2a692820197a3aab3f59f8e9b8e6821acf744.png&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;可以鼠标拖动旋转3D视角。&lt;/p&gt;
&lt;p&gt;然后在数学世界看到了一球体填充问题的证明结果，见：&lt;a href=&#34;http://mathworld.wolfram.com/SpherePacking.html&#34;&gt;SpherePacking&lt;/a&gt;，当然，下面一大堆引用我都没看..看文章里的意思是说这个填充问题填充率已经被证明最大是77.9%，但是这个上限可能还能提高，因为貌似根据这个情况，rich大牛提出的这个问题应该数量在779左右..&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</description>
    </item>
    <item>
      <title>Eclipse安装JavaCC</title>
      <link>http://blog.leaver.me/2012/09/17/eclipse%E5%AE%89%E8%A3%85javacc/</link>
      <pubDate>Mon, 17 Sep 2012 18:26:35 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/09/17/eclipse%E5%AE%89%E8%A3%85javacc/</guid>
      <description>&lt;p&gt;　　今年的编译原理课程上机实践是讲这个的。。要求用JavaCC来做一个简单的解释器。今天总算是有点时间找找文档先把这个安装了。安装过程很简单。。&lt;/p&gt;
&lt;p&gt;　　1.希望你已经安装了Eclipse。。。&lt;/p&gt;
&lt;p&gt;　　2.去&lt;a href=&#34;http://sourceforge.net/projects/eclipse-javacc/&#34;&gt;sourceforge&lt;/a&gt;该项目主页下载javaCC压缩包&lt;/p&gt;
&lt;p&gt;　　3.下载完成后解压到你的Eclipse根目录。会提示覆盖plugins和features。直接覆盖即可。&lt;/p&gt;
&lt;p&gt;　　4.测试一下是否成功。具体步骤就是，打开eclipse，新建一个空java项目。然后对着项目点击右键new-&amp;gt;other-&amp;gt;javaCC-&amp;gt;javaCC template file。然后选择命名空间。包名。和文件名就可以了。这个地方的什么的是由你建立的java项目决定的。所以你可以先把java项目设置好，然后直接选就可以了。。&lt;/p&gt;
&lt;p&gt;　　5.点击运行。选择java application。控制台输出　　
　　&lt;pre class=&#34;lang:java decode:true &#34; &gt;Reading from standard input&amp;hellip;　　
　　Enter an expression like &amp;ldquo;1+(2+3)*4;&amp;rdquo;:&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;　　完成。。。&lt;/p&gt;
&lt;p&gt;Update:其实吧。这里安装的是JavaCC的插件。但是已经可以进行开发了。可能你需要一个例子来开始。或者你不喜欢eclipse。那么去&lt;a href=&#34;http://javacc.java.net&#34;&gt;JavaCC&lt;/a&gt;的项目下载你喜欢的即可。我下的是javacc-5.0.zip 里面有例子。可以参考。&lt;/p&gt;</description>
    </item>
    <item>
      <title>andorid 实现拖动滑动效果</title>
      <link>http://blog.leaver.me/2012/04/12/andorid-%E5%AE%9E%E7%8E%B0%E6%8B%96%E5%8A%A8%E6%BB%91%E5%8A%A8%E6%95%88%E6%9E%9C/</link>
      <pubDate>Thu, 12 Apr 2012 11:05:43 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/04/12/andorid-%E5%AE%9E%E7%8E%B0%E6%8B%96%E5%8A%A8%E6%BB%91%E5%8A%A8%E6%95%88%E6%9E%9C/</guid>
      <description>&lt;p&gt;这个大家都有过体会，就是当你左右拖动的时候，能够做到向左向右翻页。代码我写了很详细的注释。包括xml的注释，所以就不怎么解释了。先测试下代码高亮能用不.我当前用的是&lt;strong&gt;WP-Syntax&lt;/strong&gt;插件。将就着还行吧。如果你知道更好的话。不妨给我推荐一下。&lt;/p&gt;
&lt;pre lang=&#34;java&#34;&gt;package com.android.flip;

import android.app.Activity;
import android.os.Bundle;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import android.view.GestureDetector.OnGestureListener;
import android.view.animation.AnimationUtils;
import android.widget.ImageView;
import android.widget.ViewFlipper;

/**
 * Android实现左右滑动效果
 * @author byStander
 *
 */&lt;/pre&gt;</description>
    </item>
  </channel>
</rss>
