﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>语源科技BlogJava-溪石的博客</title><link>http://www.blogjava.net/jonenine/</link><description>建立中......</description><language>zh-cn</language><lastBuildDate>Sun, 12 Apr 2026 11:42:45 GMT</lastBuildDate><pubDate>Sun, 12 Apr 2026 11:42:45 GMT</pubDate><ttl>60</ttl><item><title>移植jQuery deferred到java，基于java的promise编程模型</title><link>http://www.blogjava.net/jonenine/archive/2017/07/23/432679.html</link><dc:creator>溪石</dc:creator><author>溪石</author><pubDate>Sun, 23 Jul 2017 03:59:00 GMT</pubDate><guid>http://www.blogjava.net/jonenine/archive/2017/07/23/432679.html</guid><wfw:comment>http://www.blogjava.net/jonenine/comments/432679.html</wfw:comment><comments>http://www.blogjava.net/jonenine/archive/2017/07/23/432679.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jonenine/comments/commentRss/432679.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jonenine/services/trackbacks/432679.html</trackback:ping><description><![CDATA[<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<span style="font-family:宋体;Segoe UI&quot;;Segoe UI&quot;;Segoe UI&quot;; color:#24292E;background:white">移植</span><span style="font-family: &quot;Segoe UI&quot;,&quot;sans-serif&quot;;color:#24292E;background:white">jQuery deferred</span><span style="font-family:宋体;Segoe UI&quot;;Segoe UI&quot;;Segoe UI&quot;;color:#24292E;background:white">到</span><span style="font-family:&quot;Segoe UI&quot;,&quot;sans-serif&quot;;color:#24292E;background: white">java</span><span style="font-family:宋体;Segoe UI&quot;;Segoe UI&quot;;Segoe UI&quot;;color:#24292E;background:white">，基于</span><span style="font-family:&quot;Segoe UI&quot;,&quot;sans-serif&quot;;color:#24292E;background: white">java</span><span style="font-family:宋体;Segoe UI&quot;;Segoe UI&quot;;Segoe UI&quot;;color:#24292E;background:white">的</span><span style="font-family:&quot;Segoe UI&quot;,&quot;sans-serif&quot;;color:#24292E;background: white">promise</span><span style="font-family:宋体;Segoe UI&quot;;Segoe UI&quot;;Segoe UI&quot;;color:#24292E;background:white">编程模型</span></p>  <p>&nbsp;</p>  <p style="text-indent:21.0pt"><span style="font-family:宋体;">很多语言都支持</span>promise<span style="font-family:宋体;">编程模型，像是</span>scala<span style="font-family:宋体;">中</span>promise<span style="font-family:宋体;">类和</span>jquery<span style="font-family:宋体;">（</span>javascript<span style="font-family:宋体;">）中的</span>deferred<span style="font-family:宋体;">对象等，在</span>java<span style="font-family:宋体;">中好像缺少相关实现。笔者不得以，只能自己动手弄了一个。最后选择将</span>jquery<span style="font-family:宋体;">中的</span>deferred<span style="font-family:宋体;">对象移植到</span>java<span style="font-family:宋体;">中来的方案。目前已经应用在企业级项目的高性能服务器和</span>android<span style="font-family:宋体;">客户端等项目中。</span></p>  <p style="text-indent:21.0pt">Promise<span style="font-family:宋体;">编程模型的概念这里也不再赘述，大家自己上网查找即可。这种编程模型主要解决的问题就是&#8220;同步调用变异步的问题&#8221;，通常解决异步调用的方式是使用&#8220;回调&#8221;。但普通回调的使用在代码书写，返回值传递和&#8220;异步方法编排上&#8221;非常的不方便。所以才会有</span>Promise<span style="font-family:宋体;">模型的诞生。</span></p>  <p style="text-indent:21.0pt"><span style="font-family:宋体;">这次会介绍</span>java<span style="font-family:宋体;">版的</span>deferred<span style="font-family:宋体;">对象的使用方法，以及用</span>jquery<span style="font-family:宋体;">版之间的变化和改进。目前开放的版本是基于线程池的版本，正在开发基于</span>akka<span style="font-family:宋体;">的版本。在</span>jquery<span style="font-family:宋体;">的实现中，因为</span>javascript<span style="font-family:宋体;">是单线程的，所以不用考虑线程同步的问题。在</span>java<span style="font-family:宋体;">线程池的版的</span>deferred<span style="font-family:宋体;">里，基于多线程环境做了很多测试，保证了线程安全及可靠性。</span></p>  <p style="text-indent:21.0pt">&nbsp;</p>  <p style="margin-left:42.0pt;text-indent:-21.0pt;">一．<span style="font-variant-numeric: normal; font-stretch: normal; font-size: 7pt; line-height: normal; font-family: &quot;Times New Roman&quot;;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-family:宋体;">基本调用形式</span></p>  <p style="margin-left:42.0pt;text-indent:0cm;"><span style="font-size:9.0pt">final Deferred &nbsp;def = new Deferred (App. executor);</span></p>  <p style="margin-left:42.0pt;text-indent:0cm;"><span style="font-size:9.0pt;font-family:宋体;">执行某个异步调用，比如某个基于网络的异步服务</span></p>  <p style="margin-left:42.0pt;text-indent:0cm;"><span style="font-size:9.0pt">callService(new Response(){</span></p>  <p style="margin-left:42.0pt;text-indent:0cm;"><span style="font-size:9.0pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public void onMessage(Object message){</span></p>  <p style="margin-left:42.0pt;"><span style="font-size:9.0pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; def.resolve(message);</span></p>  <p style="margin-left:42.0pt;"><span style="font-size:9.0pt">}</span></p>  <p style="margin-left:63.0pt;text-indent:0cm;"><span style="font-size:9.0pt">Public void onFail(Exception e){</span></p>  <p style="margin-left:63.0pt;text-indent:0cm;"><span style="font-size:9.0pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; def.reject(e);</span></p>  <p style="margin-left:42.0pt;"><span style="font-size:9.0pt">}</span></p>  <p style="margin-left:42.0pt;text-indent:0cm;"><span style="font-size:9.0pt">});</span></p>  <p style="margin-left:42.0pt;text-indent:0cm;"><span style="font-size:9.0pt;font-family:宋体;">你可以在构造</span><span style="font-size:9.0pt">Deferred </span><span style="font-size:9.0pt; font-family:宋体;">对象后的任意时候，使用</span><span style="font-size:9.0pt">def</span><span style="font-size:9.0pt;font-family: 宋体;">的</span><span style="font-size: 9.0pt">then</span><span style="font-size:9.0pt;font-family:宋体;">方法。比如</span></p>  <p align="left" style="margin-left: 42.5pt; text-indent: -42.5pt;"><span style="font-size:9.0pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; def.then(</span><strong><span style="font-size:9.0pt;font-family:Consolas;color:#7F0055;">new</span></strong><span style="font-size: 9pt; font-family: Consolas;"> Reply(){</span></p>  <p align="left" style="margin-left: 42.5pt; text-indent: -42.5pt;"><span style="font-size: 9pt; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><strong><span style="font-size:9.0pt;font-family:Consolas;color:#7F0055;">public</span></strong><span style="font-size: 9pt; font-family: Consolas;"> Object done(Object d) {</span></p>  <p align="left" style="margin-left: 42.5pt; text-indent: -42.5pt;"><span style="font-size: 9pt; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.</span><em><span style="font-size:9.0pt;font-family:Consolas;color:#0000C0;">out</span></em><span style="font-size: 9pt; font-family: Consolas;">.println(</span><span style="font-size:9.0pt;font-family:Consolas;color:#2A00FF;">"response:"</span><span style="font-size: 9pt; font-family: Consolas;">+d);</span></p>  <p align="left" style="margin-left: 42.5pt; text-indent: -42.5pt;"><span style="font-size: 9pt; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><strong><span style="font-size:9.0pt;font-family:Consolas;color:#7F0055;">return</span></strong><span style="font-size: 9pt; font-family: Consolas;"> d;</span></p>  <p align="left" style="margin-left: 42.5pt; text-indent: -42.5pt;"><span style="font-size: 9pt; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</span></p>  <p align="left" style="margin-left: 42.5pt; text-indent: -42.5pt;"><span style="font-size: 9pt; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><strong><span style="font-size:9.0pt;font-family:Consolas;color:#7F0055;">public</span></strong> <strong><span style="font-size:9.0pt;font-family:Consolas;color:#7F0055;">void</span></strong><span style="font-size: 9pt; font-family: Consolas;"> fail(Object f) {</span></p>  <p align="left" style="margin-left: 42.5pt; text-indent: -42.5pt;"><span style="font-size: 9pt; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.</span><em><span style="font-size:9.0pt;font-family:Consolas;color:#0000C0;">out</span></em><span style="font-size: 9pt; font-family: Consolas;">.println(</span><span style="font-size:9.0pt;font-family:Consolas;color:#2A00FF;">"error:"</span><span style="font-size: 9pt; font-family: Consolas;">+f);</span></p>  <p align="left" style="margin-left: 42.5pt; text-indent: -42.5pt;"><span style="font-size: 9pt; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</span></p>  <p style="margin-left:21.35pt;text-indent:20.65pt"><span style="font-size: 9pt; font-family: Consolas;">}</span><span style="font-size:9.0pt">);</span></p>  <p style="margin-left:42.0pt;text-indent:18.0pt"><span style="font-size:9.0pt;font-family:宋体;">一个经常遇到的场景是</span><span style="font-size:9.0pt">callService</span><span style="font-size: 9.0pt;font-family:宋体;">后将</span><span style="font-size:9.0pt">def</span><span style="font-size:9.0pt;font-family: 宋体;">作为参数传递到其他方法，在其他方法内部再决定</span><span style="font-size:9.0pt">def</span><span style="font-size:9.0pt; font-family:宋体;">要绑定什么样的后续动作，也就是绑定什么样的</span><span style="font-size:9.0pt">then</span><span style="font-size:9.0pt; font-family:宋体;">。</span></p>  <p align="left" style="margin-left: 42.5pt; text-indent: -42.5pt;"><span style="font-size:9.0pt">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;</span><span style="font-size:9.0pt; font-family:宋体;">注意</span><span style="font-size:9.0pt">then</span><span style="font-size:9.0pt;font-family: 宋体;">方法的定义</span><strong><span style="font-size:9.0pt;font-family:Consolas;color:#7F0055;">public</span></strong><span style="font-size: 9pt; font-family: Consolas;"> Object done(Object d)</span><span style="font-size: 9pt; font-family: 宋体;">，在实际使用中</span><span style="font-size: 9pt; font-family: Consolas;">done</span><span style="font-size: 9pt; font-family: 宋体;">通常是以&#8220;处理链&#8221;的方式来使用的，即你会看到</span><span style="font-size: 9pt; font-family: Consolas;">def.then().then().then()&#8230;</span><span style="font-size: 9pt; font-family: 宋体;">这样的方式，每一个</span><span style="font-size: 9pt; font-family: Consolas;">then</span><span style="font-size: 9pt; font-family: 宋体;">的</span><span style="font-size: 9pt; font-family: Consolas;">done</span><span style="font-size: 9pt; font-family: 宋体;">方法接收的参数都是其上一个</span><span style="font-size: 9pt; font-family: Consolas;">then</span><span style="font-size: 9pt; font-family: 宋体;">的</span><span style="font-size: 9pt; font-family: Consolas;">done</span><span style="font-size: 9pt; font-family: 宋体;">方法的返回值。通常作为参数传递给某个方法的</span><span style="font-size: 9pt; font-family: Consolas;">Deferred</span><span style="font-size: 9pt; font-family: 宋体;">上面已经绑定了一些默认的</span><span style="font-size: 9pt; font-family: Consolas;">then</span><span style="font-size: 9pt; font-family: 宋体;">对象，来处理一些必要的步骤。比如对接收报文的初步解码。</span></p>  <p align="left" style="margin-left: 42.5pt; text-indent: -42.5pt;"><span style="font-size: 9pt; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-size: 9pt; font-family: 宋体;">注意同在</span><span style="font-size: 9pt; font-family: Consolas;">Reply</span><span style="font-size: 9pt; font-family: 宋体;">接口中</span><span style="font-size: 9pt; font-family: Consolas;">fail</span><span style="font-size: 9pt; font-family: 宋体;">方法是没有返回值的，一旦异步处理链上的某个</span><span style="font-size: 9pt; font-family: Consolas;">Deferred</span><span style="font-size: 9pt; font-family: 宋体;">被</span><span style="font-size: 9pt; font-family: Consolas;">reject</span><span style="font-size: 9pt; font-family: 宋体;">，其本身及后面所有的</span><span style="font-size: 9pt; font-family: Consolas;">Deferred</span><span style="font-size: 9pt; font-family: 宋体;">绑定的</span><span style="font-size: 9pt; font-family: Consolas;">then</span><span style="font-size: 9pt; font-family: 宋体;">都会被触发</span><span style="font-size: 9pt; font-family: Consolas;">fail</span><span style="font-size: 9pt; font-family: 宋体;">方法。这保证了整个业务编排上或是你精心设计的算法编排上任意一个环节，无论如何都会得到响应，这也是</span><span style="font-size: 9pt; font-family: Consolas;">Promise</span><span style="font-size: 9pt; font-family: 宋体;">模型关于异常的最重要的处理方式。</span></p>  <p align="left" style="margin-left: 42.5pt; text-indent: -42.5pt;"><span style="font-size: 9pt; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; &nbsp;&nbsp;Promise</span><span style="font-size: 9pt; font-family: 宋体;">编程模型本身是强健的，但异步服务却不是总能得到响应。在实际应用中，每一个作为计算或业务环节的</span><span style="font-size: 9pt; font-family: Consolas;">Deferred</span><span style="font-size: 9pt; font-family: 宋体;">都应该被定时轮询，以保证在异步服务彻底得不到响应的时候（比如你执行了一个数据库查询，但过了很长很长时间仍没有得到回应），可以给</span><span style="font-size: 9pt; font-family: Consolas;">Deferred</span><span style="font-size: 9pt; font-family: 宋体;">对象</span><span style="font-size:9.0pt">reject</span><span style="font-size:9.0pt;font-family:宋体;">一个超时错误。</span></p>  <p align="left" style="margin-left: 42.5pt; text-indent: -42.5pt;"><span style="font-size:9.0pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;</span><span style="font-size:9.0pt; font-family:宋体;">响应处理对象</span><span style="font-size: 9pt; font-family: Consolas;">then</span><span style="font-size: 9pt; font-family: 宋体;">中方法</span><span style="font-size: 9pt; font-family: Consolas;">done</span><span style="font-size: 9pt; font-family: 宋体;">和</span><span style="font-size: 9pt; font-family: Consolas;">fail</span><span style="font-size: 9pt; font-family: 宋体;">都是不允许抛出任何异常的，特别是</span><span style="font-size: 9pt; font-family: Consolas;">done</span><span style="font-size: 9pt; font-family: 宋体;">方法，如果你的算法依赖异常，请在</span><span style="font-size: 9pt; font-family: Consolas;">done</span><span style="font-size: 9pt; font-family: 宋体;">中加上</span><span style="font-size: 9pt; font-family: Consolas;">try&#8230;catch</span><span style="font-size: 9pt; font-family: 宋体;">，并将异常传换成下一个</span><span style="font-size: 9pt; font-family: Consolas;">then</span><span style="font-size: 9pt; font-family: 宋体;">可以理解的信息，以便这个</span><span style="font-size: 9pt; font-family: Consolas;">Deferred</span><span style="font-size: 9pt; font-family: 宋体;">处理链中可以正常执行下去。</span></p>  <p style="margin-left:42.0pt;text-indent:0cm;">&nbsp;</p>  <p style="margin-left:42.0pt;text-indent:-21.0pt;"><span style="font-size: 9pt; font-family: Consolas;">二． </span><span style="font-size: 9pt; font-family: Consolas;">pipe</span><span style="font-size: 9pt; font-family: 宋体;">到另外一个异步处理流程上去</span></p>  <p style="margin-left:42.0pt;text-indent:18.0pt;"><span style="font-size: 9pt; font-family: 宋体;">假如你有如下的业务场景，你需要顺序调用三个异步的</span><span style="font-size: 9pt; font-family: Consolas;">webservice</span><span style="font-size: 9pt; font-family: 宋体;">服务来得到最终的返回结果，其中没个</span><span style="font-size: 9pt; font-family: Consolas;">webservice</span><span style="font-size: 9pt; font-family: 宋体;">的入参都和上一个的异步返回结果相关。（注意，异步的</span><span style="font-size: 9pt; font-family: Consolas;">webservice</span><span style="font-size: 9pt; font-family: 宋体;">是调用之后，服务端立刻返回，服务端处理完成后再主动访问刚才的请求方返回结果的方式）如果将这种</span><span style="font-size: 9pt; font-family: Consolas;">webservice</span><span style="font-size: 9pt; font-family: 宋体;">调用封装成同步方法无疑在编程上是非常方便的，可以使用我们平常写程序时顺序的书写方式，比如</span></p>  <p style="margin-left:42.0pt;text-indent:18.0pt"><span style="font-size: 9pt; font-family: Consolas;">reval1 = callwebservice1(param0)</span></p>  <p style="margin-left:42.0pt;text-indent:18.0pt"><span style="font-size: 9pt; font-family: Consolas;">reval2 = callwebservice2(reval1)</span></p>  <p style="margin-left:42.0pt;text-indent:18.0pt"><span style="font-size: 9pt; font-family: Consolas;">reval3 = callwebservice3(reval2)</span></p>  <p style="margin-left:42.0pt;text-indent:0cm;"><span style="font-size: 9pt; font-family: Consolas;">&nbsp; &nbsp;&nbsp;</span><span style="font-size: 9pt; font-family: 宋体;">方便的同时却牺牲了性能。调用线程要在</span><span style="font-size: 9pt; font-family: Consolas;">callwebservice</span><span style="font-size: 9pt; font-family: 宋体;">方法内阻塞，以等待异步返回。这样的编程方法无法满足高性能及高并发的需要。那么有没有既能类似于平常写程序时顺序的书写方式又能满足异步无阻塞的需要呢，这就是</span><span style="font-size: 9pt; font-family: Consolas;">Promise</span><span style="font-size: 9pt; font-family: 宋体;">编程模型本身要解决的最大问题。</span></p>  <p style="margin-left:42.0pt;text-indent:18.0pt;"><span style="font-size: 9pt; font-family: 宋体;">通常解决这种问题的方式是使用</span><span style="font-size: 9pt; font-family: Consolas;">pipe</span><span style="font-size: 9pt; font-family: 宋体;">，</span><span style="font-size: 9pt; font-family: Consolas;">pipe</span><span style="font-size: 9pt; font-family: 宋体;">这个方法名称的由来应该是来自于</span><span style="font-size: 9pt; font-family: Consolas;">linux shell</span><span style="font-size: 9pt; font-family: 宋体;">的管道符，即&#8220;</span><span style="font-size: 9pt; font-family: Consolas;">|</span><span style="font-size: 9pt; font-family: 宋体;">&#8221;</span></p>  <p style="margin-left:42.0pt;text-indent:18.0pt;"><span style="font-size: 9pt; font-family: 宋体;">使用</span><span style="font-size: 9pt; font-family: Consolas;">Deferred</span><span style="font-size: 9pt; font-family: 宋体;">对象的解决方案类似于如下：</span></p>  <p style="margin-left:42.0pt;text-indent:18.0pt;"><span style="font-size: 9pt; font-family: Consolas;">Deferred.resolvedDeferred(App.executor,param0).pipe(new AsyncRequest2(){</span></p>  <p style="margin-left:42.0pt;text-indent:18.0pt;"><span style="font-size: 9pt; font-family: Consolas;"> &nbsp;&nbsp;&nbsp; public void apply(Object param0,final Deferred newDefered) throws Exception{</span></p>  <p style="margin-left:105.0pt;text-indent:0cm;"><span style="font-size: 9pt; font-family: Consolas;">asyncCallwebservice1(param0).onResponse(new Response(){</span></p>  <p style="margin-left:105.0pt;text-indent:0cm;"><span style="font-size: 9pt; font-family: Consolas;">&nbsp;&nbsp;&nbsp; public void onMessage(String message){</span></p>  <p style="margin-left:105.0pt;text-indent:0cm;"><span style="font-size: 9pt; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; newDefered.resolve(message);</span></p>  <p style="margin-left:105.0pt;"><span style="font-size: 9pt; font-family: Consolas;">}</span></p>  <p style="margin-left:105.0pt;text-indent:0cm;"><span style="font-size: 9pt; font-family: Consolas;">});</span></p>  <p style="margin-left:42.0pt;text-indent:36.0pt;"><span style="font-size: 9pt; font-family: Consolas;">}</span></p>  <p style="margin-left:42.0pt;text-indent:18.0pt;"><span style="font-size: 9pt; font-family: Consolas;">}).pipe(new AsyncRequest2(){</span></p>  <p style="margin-left:42.0pt;text-indent:18.0pt;"><span style="font-size: 9pt; font-family: Consolas;"> &nbsp;&nbsp;&nbsp; public void apply(Object reval1,final Deferred newDefered) throws Exception{</span></p>  <p style="margin-left:105.0pt;text-indent:0cm;"><span style="font-size: 9pt; font-family: Consolas;">asyncCallwebservice2(reval1).onResponse(new Response(){</span></p>  <p style="margin-left:105.0pt;text-indent:0cm;"><span style="font-size: 9pt; font-family: Consolas;">&nbsp;&nbsp;&nbsp; public void onMessage(String message){</span></p>  <p style="margin-left:105.0pt;text-indent:0cm;"><span style="font-size: 9pt; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; newDefered.resolve(message);</span></p>  <p style="margin-left:105.0pt;"><span style="font-size: 9pt; font-family: Consolas;">}</span></p>  <p style="margin-left:105.0pt;text-indent:0cm;"><span style="font-size: 9pt; font-family: Consolas;">});</span></p>  <p style="margin-left:42.0pt;text-indent:36.0pt;"><span style="font-size: 9pt; font-family: Consolas;">}</span></p>  <p style="margin-left:42.0pt;text-indent:18.0pt;"><span style="font-size: 9pt; font-family: Consolas;">}).pipe(new AsyncRequest2(){</span></p>  <p style="margin-left:42.0pt;text-indent:18.0pt;"><span style="font-size: 9pt; font-family: Consolas;"> &nbsp;&nbsp;&nbsp; public void apply(Object reval2,final Deferred newDefered) throws Exception{</span></p>  <p style="margin-left:105.0pt;text-indent:0cm;"><span style="font-size: 9pt; font-family: Consolas;">asyncCallwebservice3(reval3).onResponse(new Response(){</span></p>  <p style="margin-left:105.0pt;text-indent:0cm;"><span style="font-size: 9pt; font-family: Consolas;">&nbsp;&nbsp;&nbsp; public void onMessage(String message){</span></p>  <p style="margin-left:105.0pt;text-indent:0cm;"><span style="font-size: 9pt; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; newDefered.resolve(message);</span></p>  <p style="margin-left:105.0pt;"><span style="font-size: 9pt; font-family: Consolas;">}</span></p>  <p style="margin-left:105.0pt;text-indent:0cm;"><span style="font-size: 9pt; font-family: Consolas;">});</span></p>  <p style="margin-left:42.0pt;text-indent:36.0pt;"><span style="font-size: 9pt; font-family: Consolas;">}</span></p>  <p align="left" style="margin-left: 42.35pt; text-indent: 13.5pt;"><span style="font-size: 9pt; font-family: Consolas;">}).then(new new Reply(){</span></p>  <p align="left" style="margin-left: 42.5pt; text-indent: -42.5pt;"><span style="font-size: 9pt; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; public Object done(Object d) {</span></p>  <p align="left" style="margin-left: 42.5pt; text-indent: -42.5pt;"><span style="font-size: 9pt; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; //</span><span style="font-size: 9pt; font-family: 宋体;">在这里消费最终结果</span></p>  <p align="left" style="text-indent: 103.5pt;"><span style="font-size: 9pt; font-family: Consolas;">return d;</span></p>  <p align="left" style="margin-left: 42.5pt; text-indent: -42.5pt;"><span style="font-size: 9pt; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</span></p>  <p align="left" style="margin-left: 42.5pt; text-indent: -42.5pt;"><span style="font-size: 9pt; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; public void fail(Object f) {</span></p>  <p align="left" style="margin-left: 42.5pt; text-indent: -42.5pt;"><span style="font-size: 9pt; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; </span></p>  <p align="left" style="margin-left: 5.25pt; text-indent: 76.5pt;"><span style="font-size: 9pt; font-family: Consolas;">}</span></p>  <p style="margin-left:42.0pt;text-indent:18.0pt;"><span style="font-size: 9pt; font-family: Consolas;">});</span></p>  <p style="margin-left:42.0pt;text-indent:18.0pt;"><span style="font-size: 9pt; font-family: 宋体;">使用</span><span style="font-size: 9pt; font-family: Consolas;">Deferred</span><span style="font-size: 9pt; font-family: 宋体;">对象提供的方案好处就是，所有的调用都是异步的，上面这一连串代码立刻就会返回。所有的业务编排会按照书写顺序在线程池中的线程里被调用，你也不必担心返回值结果和参数传递过程中的线程安全问题，框架在关键位置都做了同步，也做了相当多的测试用于验证。</span></p>  <p style="margin-left:42.0pt;text-indent:18.0pt;"><span style="font-size: 9pt; font-family: 宋体;">可以看出，对于异步方法调用而言，比较难以解决的问题是异步算法的编排问题。</span><span style="font-size: 9pt; font-family: Consolas;">Deferred</span><span style="font-size: 9pt; font-family: 宋体;">对象为异步算法提供了很好的解决方案。</span></p>  <p style="margin-left:42.0pt;text-indent:18.0pt;"><span style="font-size: 9pt; font-family: 宋体;">相较于</span><span style="font-size: 9pt; font-family: Consolas;">AsyncRequest2</span><span style="font-size: 9pt; font-family: 宋体;">类还有一个</span><span style="font-size: 9pt; font-family: Consolas;">AsyncRequest1</span><span style="font-size: 9pt; font-family: 宋体;">类，接口如下：</span></p>  <p align="left" style="margin-left: 39pt; text-indent: 21pt;"><strong><span style="font-size:9.0pt;font-family:Consolas;color:#7F0055;">public</span></strong> <strong><span style="font-size:9.0pt;font-family:Consolas;color:#7F0055;">interfac</span></strong><span style="font-size: 9pt; font-family: Consolas;">e AsyncRequest1&lt;R&gt; {</span></p>  <p align="left"><span style="font-size: 9pt; font-family: Consolas;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><strong><span style="font-size:9.0pt;font-family:Consolas;color:#7F0055;">public</span></strong><span style="font-size: 9pt; font-family: Consolas;"> Deferred apply(R result) </span><strong><span style="font-size:9.0pt;font-family:Consolas;color:#7F0055;">throws</span></strong><span style="font-size: 9pt; font-family: Consolas;"> Exception;</span></p>  <p style="margin-left:42.0pt;text-indent:18.0pt;"><span style="font-size: 9pt; font-family: Consolas;">}</span></p>  <p style="margin-left:42.0pt;text-indent:18.0pt;"><span style="font-size: 9pt; font-family: 宋体;">这个类要求在在</span><span style="font-size: 9pt; font-family: Consolas;">apply</span><span style="font-size: 9pt; font-family: 宋体;">方法中要自己创建</span><span style="font-size: 9pt; font-family: Consolas;">Deferred</span><span style="font-size: 9pt; font-family: 宋体;">对象。</span></p>  <p style="margin-left:42.0pt;text-indent:0cm;">&nbsp;</p>  <p style="margin-left:42.0pt;text-indent:0cm;"><span style="font-size: 9pt; font-family: 宋体;">三</span><span style="font-size: 9pt; font-family: Consolas;">. </span><span style="font-size: 9pt; font-family: 宋体;">一些小改进</span></p>  <p style="margin-left:42.0pt;text-indent:0cm;"><span style="font-size: 9pt; font-family: Consolas;">&nbsp;&nbsp;&nbsp; </span><span style="font-size: 9pt; font-family: 宋体;">相较于传统</span><span style="font-size: 9pt; font-family: Consolas;">promise</span><span style="font-size: 9pt; font-family: 宋体;">编程模型，在</span><span style="font-size: 9pt; font-family: Consolas;">java</span><span style="font-size: 9pt; font-family: 宋体;">多线程环境下做了一些小升级。这里主要介绍</span><span style="font-size: 9pt; font-family: Consolas;">synchronize</span><span style="font-size: 9pt; font-family: 宋体;">方法</span></p>  <p style="margin-left:42.0pt;text-indent:18.0pt;"><span style="font-size: 9pt; font-family: Consolas;">Synchronize</span><span style="font-size: 9pt; font-family: 宋体;">方法签名如下</span><span style="font-size: 9pt; font-family: Consolas;">:</span></p>  <p style="margin-left:42.0pt;text-indent:18.0pt;"><span style="font-size: 9pt; font-family: Consolas;">Deferred synchronize(ExecutorService executor,Deferred... deferreds)</span></p>  <p style="margin-left:42.0pt;text-indent:18.0pt;"><span style="font-size: 9pt; font-family: 宋体;">实际上，</span><span style="font-size: 9pt; font-family: Consolas;">synchronize</span><span style="font-size: 9pt; font-family: 宋体;">方法将众多的</span><span style="font-size: 9pt; font-family: Consolas;">Deferred</span><span style="font-size: 9pt; font-family: 宋体;">对象的完成状态同归集到一个唯一的</span><span style="font-size: 9pt; font-family: Consolas;">Deferred</span><span style="font-size: 9pt; font-family: 宋体;">对象上去，即如果所有的</span><span style="font-size: 9pt; font-family: Consolas;">Deferred</span><span style="font-size: 9pt; font-family: 宋体;">对象参数都</span><span style="font-size: 9pt; font-family: Consolas;">resolved</span><span style="font-size: 9pt; font-family: 宋体;">了，作为最终结果的</span><span style="font-size: 9pt; font-family: Consolas;">Deferred</span><span style="font-size: 9pt; font-family: 宋体;">也</span><span style="font-size: 9pt; font-family: Consolas;">resolve</span><span style="font-size: 9pt; font-family: 宋体;">，如果众多的</span><span style="font-size: 9pt; font-family: Consolas;">Deferred</span><span style="font-size: 9pt; font-family: 宋体;">对象参数有一个</span><span style="font-size: 9pt; font-family: Consolas;">reject</span><span style="font-size: 9pt; font-family: 宋体;">了，最终的那个</span><span style="font-size: 9pt; font-family: Consolas;">Deferred</span><span style="font-size: 9pt; font-family: 宋体;">也会立即</span><span style="font-size: 9pt; font-family: Consolas;">reject(</span><span style="font-size: 9pt; font-family: 宋体;">其他参数的状态都舍弃</span><span style="font-size: 9pt; font-family: Consolas;">)</span><span style="font-size: 9pt; font-family: 宋体;">。</span></p>  <p style="margin-left:42.0pt;text-indent:18.0pt;"><span style="font-size: 9pt; font-family: 宋体;">这个方法一般用于多个并行流程最终状态的&#8220;归并&#8221;中。</span></p>  <p style="margin-left:42.0pt;text-indent:18.0pt;"><span style="font-size: 9pt; font-family: 宋体;">除了</span><span style="font-size: 9pt; font-family: Consolas;">synchronize</span><span style="font-size: 9pt; font-family: 宋体;">，框架还提供一些传统</span><span style="font-size: 9pt; font-family: Consolas;">promise</span><span style="font-size: 9pt; font-family: 宋体;">编程模型没有的改进，比如</span><span style="font-size: 9pt; font-family: Consolas;">pipe4fail</span><span style="font-size: 9pt; font-family: 宋体;">和</span><span style="font-size: 9pt; font-family: Consolas;">source</span><span style="font-size: 9pt; font-family: 宋体;">等。</span></p>  <p style="margin-left:42.0pt;text-indent:0cm;">&nbsp;</p>  <p style="margin-left:42.0pt;text-indent:0cm;"><span style="font-size: 9pt; font-family: 宋体;">四．在</span><span style="font-size: 9pt; font-family: Consolas;">android</span><span style="font-size: 9pt; font-family: 宋体;">项目中的应用</span></p>  <p style="margin-left:42.0pt;text-indent:0cm;"><span style="font-size: 9pt; font-family: Consolas;">&nbsp;&nbsp;&nbsp; </span><span style="font-size: 9pt; font-family: 宋体;">（略）</span></p>  <p style="margin-left:42.0pt;text-indent:0cm;"><span style="font-size: 9pt; font-family: Consolas;">https://github.com/jonenine/javaDeferred</span></p><img src ="http://www.blogjava.net/jonenine/aggbug/432679.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jonenine/" target="_blank">溪石</a> 2017-07-23 11:59 <a href="http://www.blogjava.net/jonenine/archive/2017/07/23/432679.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>HDAOOP SIMPLIZE TOOLKIT hadoop mapreduce简化开发包</title><link>http://www.blogjava.net/jonenine/archive/2017/01/29/432281.html</link><dc:creator>溪石</dc:creator><author>溪石</author><pubDate>Sun, 29 Jan 2017 02:10:00 GMT</pubDate><guid>http://www.blogjava.net/jonenine/archive/2017/01/29/432281.html</guid><wfw:comment>http://www.blogjava.net/jonenine/comments/432281.html</wfw:comment><comments>http://www.blogjava.net/jonenine/archive/2017/01/29/432281.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jonenine/comments/commentRss/432281.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jonenine/services/trackbacks/432281.html</trackback:ping><description><![CDATA[<p style="text-indent:21.0pt"><a href="https://github.com/jonenine/HST">https://github.com/jonenine/HST</a></p>  <p style="text-indent:21.0pt">&nbsp;</p>  <p style="text-indent:21.0pt;"><span style="font-family:宋体;">虽然大数据的发展已经将近</span>10<span style="font-family:宋体;">个年头了，</span>hadoop<span style="font-family:宋体;">技术仍然没有过时，特别是一些低成本，入门级的小项目，使用</span>hadoop<span style="font-family:宋体;">还是蛮不错的。而且，也不是每一个公司都有能力招聘和培养自己的</span>spark<span style="font-family:宋体;">人才。</span></p>  <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="font-family:宋体;">我本人对于</span>hadoop mapreduce<span style="font-family:宋体;">是有一些意见的。</span>hadoop mapreduce<span style="font-family:宋体;">技术对于开发人员的友好度不高，程序难写，调试困难，对于复杂的业务逻辑远没有</span>spark<span style="font-family:宋体;">得心应手。</span></p>  <p style="text-indent:21.0pt">2016<span style="font-family:宋体;">年的春节前接到一个任务，要在一个没有</span>spark<span style="font-family:宋体;">的平台实现电力系统的一些统计分析算法，可选的技术只有</span>hadoop mapreduce<span style="font-family:宋体;">。受了这个刺激之后产生了一些奇思妙想，然后做了一些试验，并最终形成</span>HST---hadoop simplize toolkit<span style="font-family:宋体;">，还真是无心载柳柳成荫啊。</span></p>  <p style="text-indent:21.0pt">&nbsp;</p>  <p style="text-indent:21.0pt">HST<span style="font-family:宋体;">基本优点如下：</span></p>  <p align="left"><span style="font-family:宋体;">屏蔽了</span>hadoop<span style="font-family:宋体;">数据类型，取消了</span>driver<span style="font-family:宋体;">，将</span>mapper<span style="font-family:宋体;">和</span>reducer<span style="font-family:宋体;">转化为</span>transformer<span style="font-family:宋体;">和</span>joiner<span style="font-family:宋体;">，业务逻辑更接近</span>sql<span style="font-family:宋体;">。相当程度的减少了代码量，极大的降低了大数据编程的门槛，让基层程序员通过简单的学习即可掌握大数据的开发。</span></p>  <p align="left"><span style="font-family:宋体;">克服了</span>hadoop mapreduce<span style="font-family:宋体;">数据源单一的情况，比如在一个</span>job<span style="font-family:宋体;">内，</span>input<span style="font-family:宋体;">可以同时读文件和来自不同集群的</span>hbase<span style="font-family:宋体;">。</span></p>  <p align="left"><span style="font-family:宋体;">远程日志系统，让</span>mapper<span style="font-family:宋体;">和</span>reducer<span style="font-family:宋体;">的日志集中到</span>driver<span style="font-family:宋体;">的控制台，极大减轻了并行多进程程序的调试难度。</span></p>  <p align="left"><span style="font-family:宋体;">克服了</span>hadoop mapreduce<span style="font-family:宋体;">编写业务逻辑时，不容易区分数据来自哪个数据源的困难。接近了</span>spark<span style="font-family:宋体;">（或者</span>sql<span style="font-family:宋体;">）的水平。</span></p>  <p align="left"><span style="font-family:宋体;">天生的多线程执行，即在</span>mapper<span style="font-family:宋体;">和</span>reducer<span style="font-family:宋体;">端都默认使用多线程来执行业务逻辑。</span></p>  <p align="left"><span style="font-family:宋体;">对于多次迭代的任务，相连的两个任务可以建立关联，下一个任务直接引用上一个任务的结果，使多次迭代任务的代码结构变得清晰优美。</span></p>  <p align="left">&nbsp;</p>  <p style="text-indent:21.0pt"><span style="font-family:宋体;">以下会逐条说明</span></p>  <p>&nbsp;</p>  <p><span style="font-family:宋体;">基本概念的小变化：</span></p>  <p>&nbsp;&nbsp; Source<span style="font-family:宋体;">类代替了</span>hadoop Input<span style="font-family:宋体;">体系</span>(<span style="font-size: 10pt; font-family: 'Courier New';">format</span><span style="font-size: 10pt; font-family: 宋体;">，</span><span style="font-size: 10pt; font-family: 'Courier New';">split</span><span style="font-size: 10pt; font-family: 宋体;">和</span><span style="font-size: 10pt; font-family: 'Courier New';">reader</span>)</p>  <p>&nbsp;&nbsp; <span style="font-size: 10pt; font-family: 'Courier New';">Transformer</span><span style="font-size: 10pt; font-family: 宋体;">代替了</span><span style="font-size: 10pt; font-family: 'Courier New';">mapper</span></p>  <p><span style="font-size: 10pt; font-family: 'Courier New';">&nbsp;&nbsp; Joiner</span><span style="font-size: 10pt; font-family: 宋体;">代替了</span><span style="font-size: 10pt; font-family: 'Courier New';">Reducer</span></p>  <p><span style="font-size: 10pt; font-family: 'Courier New';">&nbsp;&nbsp; </span><span style="font-size: 10pt; font-family: 宋体;">去掉了饱受诟病的</span><span style="font-size: 10pt; font-family: 'Courier New';">Driver</span><span style="font-size: 10pt; font-family: 宋体;">，改为内置的实现，现在完全不用操心了。</span></p>  <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </p>  <p style="margin-left:18.0pt;text-indent:-18.0pt;">1.<span style="font-size: 7pt; line-height: normal; font-family: 'Times New Roman';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-family:宋体;">基本上，屏蔽了</span>hadoop<span style="font-family:宋体;">的数据类型，使用纯</span>java<span style="font-family:宋体;">类型</span></p>  <p style="margin-left:18.0pt"><span style="font-family: 宋体;">在原生的</span>hadoop mapreduce<span style="font-family:宋体;">开发中，使用</span><span style="font-size:9.0pt;font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">org.apache.hadoop.io</span><span style="font-size:9.0pt;font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">包下的各种hadoop数据类型，比如hadoop的Text类型，算法的编写中一些转换非常不方便。而在HST中一律使用java基本类型，完全屏蔽了hadoop类型体系。</span></p>  <p style="margin-left:18.0pt;text-indent:18.0pt"><span style="font-size:9.0pt;font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">比如在hbase作为source（Input）的时候，再也不用直接使用ImmutableBytesWritable和Result了，</span><span style="font-size: 10pt; font-family: 'Courier New';">HST</span><span style="font-size: 10pt; font-family: 宋体;">为你做了自动的转换。</span></p>  <p style="margin-left:18.0pt;text-indent:18.0pt"><span style="font-size:9.0pt;font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">现在的mapper（改名叫Transformer了）风格是这样的</span></p>  <p style="margin-left:18.0pt;text-indent:20.1pt"><strong><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;;color:#7F0055;">public</span></strong> <strong><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;;color:#7F0055;">static</span></strong> <strong><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;;color:#7F0055;">class</span></strong><span style="font-size: 10pt; font-family: 'Courier New';"> TransformerForHBase0 </span><strong><span style="font-size:10.0pt; font-family:&quot;Courier New&quot;;color:#7F0055;">extends</span></strong><span style="font-size: 10pt; font-family: 'Courier New';"> HBaseTransformer&lt;Long&gt;</span></p>  <p style="margin-left:18.0pt;text-indent:18.0pt"><span style="font-size:9.0pt;font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">&#8230;</span></p>  <p style="margin-left:18.0pt;text-indent:18.0pt"><span style="font-size:9.0pt;font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">现在map方法叫flatmap，看到没，已经帮你自动转成了string和map</span></p>  <p align="left" style="margin-left: 15pt; text-indent: 21pt;"><strong><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;;color:#7F0055;">public</span></strong> <strong><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;;color:#7F0055;">void</span></strong><span style="font-size: 10pt; font-family: 'Courier New';"> flatMap(String key, Map&lt;String, String&gt; row,</span></p>  <p style="margin-left:18.0pt;text-indent:20.0pt"><span style="font-size: 10pt; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Collector&lt;Long&gt; collector) </span></p>  <p>&nbsp;</p>  <p style="margin-left:18.0pt;text-indent:18.0pt"><span style="font-size:9.0pt;font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">可阅读xs.hadoop.iterated.IteratedUtil类中关于类型自动转换的部分</span></p>  <p style="margin-left:18.0pt;text-indent:-18.0pt;">2.<span style="font-size: 7pt; line-height: normal; font-family: 'Times New Roman';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-family:宋体;">克服了</span>hadoop mapreduce<span style="font-family:宋体;">数据源单一的情况。比如在一个</span>job<span style="font-family:宋体;">内，数据源同时读文件和</span>hbase<span style="font-family:宋体;">，这在原生的</span>hadoop mapreduce<span style="font-family:宋体;">是不可能做到的</span></p>  <p style="margin-left:18.0pt;text-indent:0cm;">&nbsp;</p>  <p style="margin-left:18.0pt;text-indent:0cm;"><span style="font-family:宋体;">以前访问</span>hbase<span style="font-family:宋体;">，需要使用</span><span style="font-size:9.0pt;font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">org.apache.hadoop.hbase.client.Scan</span><span style="font-size:9.0pt;font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">和TableMapReduceUtil，现在完全改为与spark相似的方式。</span></p>  <p style="margin-left:18.0pt;text-indent:0cm;"><span style="font-size:9.0pt;font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">现在的风格是这样的：</span></p>  <p align="left" style="text-indent: 40pt;"><span style="font-size: 10pt; font-family: 'Courier New';">Configuration conf0 = HBaseConfiguration.<em>create</em>();</span></p>  <p align="left"><span style="font-size: 10pt; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; conf0.set(</span><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;;color:#2A00FF;">"hbase.zookeeper.property.clientPort"</span><span style="font-size: 10pt; font-family: 'Courier New';">, </span><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;; color:#2A00FF;">"2181"</span><span style="font-size: 10pt; font-family: 'Courier New';">);</span></p>  <p align="left"><span style="font-size: 10pt; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; conf0.set(</span><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;;color:#2A00FF;">"hbase.zookeeper.quorum"</span><span style="font-size: 10pt; font-family: 'Courier New';">, </span><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;; color:#2A00FF;">"172.16.144.132,172.16.144.134,172.16.144.136"</span><span style="font-size: 10pt; font-family: 'Courier New';">);</span></p>  <p align="left"><span style="font-size: 10pt; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; conf0.set(TableInputFormat.</span><em><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;;color:#0000C0;">INPUT_TABLE</span></em><span style="font-size: 10pt; font-family: 'Courier New';">,</span><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;;color:#2A00FF;">"APPLICATION_JOBS"</span><span style="font-size: 10pt; font-family: 'Courier New';">);</span></p>  <p align="left"><span style="font-size: 10pt; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; conf0.set(TableInputFormat.</span><em><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;;color:#0000C0;">SCAN_COLUMN_FAMILY</span></em><span style="font-size: 10pt; font-family: 'Courier New';">,</span><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;; color:#2A00FF;">"cf"</span><span style="font-size: 10pt; font-family: 'Courier New';">);</span></p>  <p align="left"><span style="font-size: 10pt; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; conf0.set(TableInputFormat.</span><em><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;;color:#0000C0;">SCAN_CACHEBLOCKS</span></em><span style="font-size: 10pt; font-family: 'Courier New';">,</span><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;; color:#2A00FF;">"false"</span><span style="font-size: 10pt; font-family: 'Courier New';">);</span></p>  <p style="margin-left:18.0pt;"><span style="font-size: 10pt; font-family: 'Courier New';">conf0.set(TableInputFormat.</span><em><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;;color:#0000C0;">SCAN_BATCHSIZE</span></em><span style="font-size: 10pt; font-family: 'Courier New';">,</span><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;;color:#2A00FF;">"20000"</span><span style="font-size: 10pt; font-family: 'Courier New';">);</span></p>  <p style="margin-left:18.0pt;"><span style="font-size: 10pt; font-family: 'Courier New';">...</span><span style="font-size: 10pt; font-family: 宋体;">其他</span><span style="font-size: 10pt; font-family: 'Courier New';">hbase</span><span style="font-size: 10pt; font-family: 宋体;">的</span><span style="font-size: 10pt; font-family: 'Courier New';">Configuration</span><span style="font-size: 10pt; font-family: 宋体;">，可以来自不同集群。</span></p>  <p style="margin-left:18.0pt;">&nbsp;</p>  <p align="left" style="margin-left: 18pt; text-indent: 21pt;"><span style="font-size: 10pt; font-family: 'Courier New';">IteratedJob&lt;Long&gt; iJob = scheduler.createJob(</span><span style="font-size:10.0pt;font-family: &quot;Courier New&quot;;color:#2A00FF;">"testJob"</span><span style="font-size: 10pt; font-family: 'Courier New';">)</span></p>  <p align="left"><span style="font-size: 10pt; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;.from(Source.<em>hBase</em>(conf0), TransformerForHBase0.</span><strong><span style="font-size:10.0pt; font-family:&quot;Courier New&quot;;color:#7F0055;">class</span></strong><span style="font-size: 10pt; font-family: 'Courier New';">)</span></p>  <p align="left"><span style="font-size: 10pt; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .from(Source.<em>hBase</em>(conf1), TransformerForHBase1.</span><strong><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;;color:#7F0055;">class</span></strong><span style="font-size: 10pt; font-family: 'Courier New';">)</span></p>  <p align="left"><span style="font-size: 10pt; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; .from(Source.<em>textFile</em>(</span><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;;color:#2A00FF;">"file:///home/cdh/0.txt"</span><span style="font-size: 10pt; font-family: 'Courier New';">),Transformer0.</span><strong><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;;color:#7F0055;">class</span></strong><span style="font-size: 10pt; font-family: 'Courier New';">)</span></p>  <p style="margin-left:18.0pt;"><span style="font-size: 10pt; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .join(JoinerHBase.</span><strong><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;;color:#7F0055;">class</span></strong><span style="font-size: 10pt; font-family: 'Courier New';">)</span></p>  <p style="margin-left:18.0pt;">&nbsp;</p>  <p style="margin-left:18.0pt;"><span style="font-size: 10pt; font-family: 'Courier New';">Hadoop</span><span style="font-size: 10pt; font-family: 宋体;">中的</span><span style="font-size: 10pt; font-family: 'Courier New';">input,</span><span style="font-size: 10pt; font-family: 宋体;">现在完全由</span><span style="font-size: 10pt; font-family: 'Courier New';">source</span><span style="font-size: 10pt; font-family: 宋体;">类来代替。通过内置的机制转化为</span><span style="font-size: 10pt; font-family: 'Courier New';">inputformat</span><span style="font-size: 10pt; font-family: 宋体;">，</span><span style="font-size: 10pt; font-family: 'Courier New';">inputsplit</span><span style="font-size: 10pt; font-family: 宋体;">和</span><span style="font-size: 10pt; font-family: 'Courier New';">reader</span><span style="font-size: 10pt; font-family: 宋体;">。在</span><span style="font-size: 10pt; font-family: 'Courier New';">HST</span><span style="font-size: 10pt; font-family: 宋体;">的框架下，其实可以很容易的写出诸如</span><span style="font-size: 10pt; font-family: 'Courier New';">Source.dbms(),Source.kafka()</span><span style="font-size: 10pt; font-family: 宋体;">以及</span><span style="font-size: 10pt; font-family: 'Courier New';">Source.redis()</span><span style="font-size: 10pt; font-family: 宋体;">方法。想想吧，在一个</span><span style="font-size: 10pt; font-family: 'Courier New';">hadoop job</span><span style="font-size: 10pt; font-family: 宋体;">中，你终于可以将任意数据源，例如来自不同集群的</span><span style="font-size: 10pt; font-family: 'Courier New';">HBASE</span><span style="font-size: 10pt; font-family: 宋体;">和来自数据库的</span><span style="font-size: 10pt; font-family: 'Courier New';">source</span><span style="font-size: 10pt; font-family: 宋体;">进行</span><span style="font-size: 10pt; font-family: 'Courier New';">join</span><span style="font-size: 10pt; font-family: 宋体;">了，这是多么</span><span style="font-size: 10pt; font-family: 'Courier New';">happy</span><span style="font-size: 10pt; font-family: 宋体;">的事情啊！</span></p>  <p style="margin-left:18.0pt;">&nbsp;</p>  <p style="margin-left:18.0pt;text-indent:-18.0pt;">3.<span style="font-size: 7pt; line-height: normal; font-family: 'Times New Roman';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-family:宋体;">远程日志系统。让</span>mapper<span style="font-family:宋体;">和</span>reducer<span style="font-family:宋体;">的日志集中在</span>driver<span style="font-family:宋体;">进行显示，极大减轻了了并行多进程程序的调试难度</span></p>  <p style="margin-left:18.0pt;text-indent:0cm;">&nbsp;</p>  <p style="margin-left:18.0pt;"><span style="font-family:宋体;">各位都体验过，</span>job fail<span style="font-family:宋体;">后到控制台页面，甚至</span>ssh<span style="font-family:宋体;">到计算节点去查看日志的痛苦了吧。对，</span>hadoop<span style="font-family:宋体;">原生的开发，调试很痛苦的呢！</span></p>  <p style="margin-left:18.0pt;"><span style="font-family:宋体;">现在好了，有远程日志系统，可以在调试时将</span>mapper<span style="font-family:宋体;">和</span>reducer<span style="font-family:宋体;">的日志集中在</span>driver<span style="font-family:宋体;">上，错误和各种</span>counter<span style="font-family:宋体;">也会自动发送到</span>driver<span style="font-family:宋体;">上，并实时显示在你的控制台上。如果在</span>eclipse<span style="font-family:宋体;">中调试程序，就可以实现点击</span>console<span style="font-family:宋体;">中的错误，直接跳到错误代码行的功能喽！</span></p>  <p style="margin-left:18.0pt;">Ps<span style="font-family:宋体;">：有人可能会问，如何在集群外使用</span>eclipse<span style="font-family:宋体;">调试一个</span>job<span style="font-family:宋体;">，却可以以集群方式运行呢？这里不再赘述了，网上有很多答案的哦</span></p>  <p style="margin-left:18.0pt;">&nbsp;</p>  <p style="margin-left:18.0pt;text-indent:-18.0pt;">4.<span style="font-size: 7pt; line-height: normal; font-family: 'Times New Roman';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-family:宋体;">克服了</span>hadoop mapreduce<span style="font-family:宋体;">在</span>join<span style="font-family:宋体;">上，区分数据来自哪个数据源的困难，接近</span>spark<span style="font-family:宋体;">（或者</span>sql<span style="font-family:宋体;">）的水平</span></p>  <p style="margin-left:18.0pt;"><span style="font-family:宋体;">在上面给出示例中，大家都看到了，现在的</span>mapper<span style="font-family:宋体;">可以绑定</span>input<span style="font-family:宋体;">喽！，也就是每个</span>input<span style="font-family:宋体;">都有自己独立的</span>mapper<span style="font-family:宋体;">。正因为此，现在的</span>input<span style="font-family:宋体;">和</span>mapper<span style="font-family:宋体;">改名叫</span>Source<span style="font-family:宋体;">和</span><span style="font-size: 10pt; font-family: 'Courier New';">Transformer</span><span style="font-size: 10pt; font-family: 宋体;">。</span></p>  <p style="margin-left:18.0pt;"><span style="font-size: 10pt; font-family: 宋体;">那么，大家又要问了，在</span><span style="font-size: 10pt; font-family: 'Courier New';">mapper</span><span style="font-size: 10pt; font-family: 宋体;">中，我已经可以轻松根据不同的数据输入写出不同的</span><span style="font-size: 10pt; font-family: 'Courier New';">mapper</span><span style="font-size: 10pt; font-family: 宋体;">了，那</span><span style="font-size: 10pt; font-family: 'Courier New';">reducer</span><span style="font-size: 10pt; font-family: 宋体;">中怎么办，</span><span style="font-size: 10pt; font-family: 'Courier New';">spark</span><span style="font-size: 10pt; font-family: 宋体;">和</span><span style="font-size: 10pt; font-family: 'Courier New';">sql</span><span style="font-size: 10pt; font-family: 宋体;">都是很容易实现的哦？比如看人家</span><span style="font-size: 10pt; font-family: 'Courier New';">sql</span></p>  <p style="margin-left:18.0pt;"><span style="font-size: 10pt; font-family: 'Courier New';">Select a.id,b.name from A&nbsp; a,B &nbsp;b where a.id = b.id</span></p>  <p style="margin-left:18.0pt;"><span style="font-size: 10pt; font-family: 宋体;">多么轻松愉悦啊</span><span style="font-size: 10pt; font-family: 'Courier New';">!</span></p>  <p style="margin-left:18.0pt;"><span style="font-size: 10pt; font-family: 宋体;">在原生</span><span style="font-size: 10pt; font-family: 'Courier New';">hadoop mapreduce</span><span style="font-size: 10pt; font-family: 宋体;">中，在</span><span style="font-size: 10pt; font-family: 'Courier New';">reducer</span><span style="font-size: 10pt; font-family: 宋体;">中找出哪个数据对应来自哪个</span><span style="font-size: 10pt; font-family: 'Courier New';">input</span><span style="font-size: 10pt; font-family: 宋体;">可是一个令人抓狂的问题呢！</span></p>  <p style="margin-left:18.0pt;"><span style="font-size: 10pt; font-family: 宋体;">现在这个问题已经被轻松解决喽！看下面这个</span><span style="font-size: 10pt; font-family: 'Courier New';">joiner</span><span style="font-size: 10pt; font-family: 宋体;">，对应原生的</span><span style="font-size: 10pt; font-family: 'Courier New';">reducer</span></p>  <p style="margin-left:18.0pt;"><strong><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;;color:#7F0055;">public</span></strong> <strong><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;;color:#7F0055;">static</span></strong> <strong><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;;color:#7F0055;">class</span></strong><span style="font-size: 10pt; font-family: 'Courier New';"> Joiner0 </span><strong><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;;color:#7F0055;">extends</span></strong><span style="font-size: 10pt; font-family: 'Courier New';"> Joiner&lt;Long, String, String&gt;</span></p>  <p style="margin-left:18.0pt;">&#8230;</p>  <p style="margin-left:18.0pt;">Reduce<span style="font-family:宋体;">方法改名叫</span>join<span style="font-family:宋体;">方法，是不是更贴近</span>sql<span style="font-family:宋体;">的概念呢？</span></p>  <p align="left"><span style="font-size: 10pt; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; </span><strong><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;;color:#7F0055;">public</span></strong> <strong><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;;color:#7F0055;">void</span></strong><span style="font-size: 10pt; font-family: 'Courier New';"> join(Long key,RowHandler handler,<u>Collector</u> collector) </span><strong><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;;color:#7F0055;">throws</span></strong><span style="font-size: 10pt; font-family: 'Courier New';"> Exception{</span></p>  <p align="left"><span style="font-size: 10pt; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; List&lt;Object&gt; row &nbsp;= handler.getSingleFieldRows(0);//</span><span style="font-size: 10pt; font-family: 宋体;">对应索引为</span><span style="font-size: 10pt; font-family: 'Courier New';">0</span><span style="font-size: 10pt; font-family: 宋体;">的</span><span style="font-size: 10pt; font-family: 'Courier New';">source</span></p>  <p style="margin-left:18.0pt;"><span style="font-size: 10pt; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;List&lt;Object&gt; row2 = handler.getSingleFieldRows(1);//</span><span style="font-size: 10pt; font-family: 宋体;">对应第二个定义的</span><span style="font-size: 10pt; font-family: 'Courier New';">source</span></p>  <p style="margin-left:18.0pt;"><span style="font-size: 10pt; font-family: 宋体;">注意上面两句，可以按照数据源定义的索引来取出来自不同数据源</span><span style="font-size: 10pt; font-family: 'Courier New';">join</span><span style="font-size: 10pt; font-family: 宋体;">后的数据了，以后有时间可能会改成按照别名来取出，大家看源码的时候，会发现别名这个部分的接口都写好了，要不你来帮助实现了吧。</span></p>  <p style="margin-left:18.0pt;">&nbsp;</p>  <p style="margin-left:18.0pt;text-indent:-18.0pt;">5.<span style="font-size: 7pt; line-height: normal; font-family: 'Times New Roman';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-family:宋体;">天生的多线程执行，即在</span>mapper<span style="font-family:宋体;">和</span>reducer<span style="font-family:宋体;">端都默认使用多线程来执行业务逻辑。</span></p>  <p style="margin-left:18.0pt;text-indent:0cm;">&nbsp;&nbsp;&nbsp; <span style="font-family:宋体;">看看源码吧，</span>HST<span style="font-family:宋体;">框架是并发调用</span><span style="font-size: 10pt; font-family: 'Courier New';">flatMap</span><span style="font-size: 10pt; font-family: 宋体;">和</span><span style="font-size: 10pt; font-family: 'Courier New';">join</span><span style="font-size: 10pt; font-family: 宋体;">方法的，同时又不能改变系统调用</span><span style="font-size: 10pt; font-family: 'Courier New';">reduce</span><span style="font-size: 10pt; font-family: 宋体;">方法的顺序</span><span style="font-size: 10pt; font-family: 'Courier New';">(</span><span style="font-size: 10pt; font-family: 宋体;">否则</span><span style="font-size: 10pt; font-family: 'Courier New';">hadoop</span><span style="font-size: 10pt; font-family: 宋体;">的辛苦排序可就白瞎了</span><span style="font-size: 10pt; font-family: 'Courier New';">)</span><span style="font-size: 10pt; font-family: 宋体;">，这可不是一件容易的事呢</span><span style="font-size: 10pt; font-family: 'Courier New';">!</span></p>  <p style="margin-left:18.0pt;"><span style="font-size:9.0pt;font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">看到这里，有的同学说了。你这个HST好是好，但你搞的自动转换类型这个机制可能会把性能拉下来的。这个吗，不得不承认，可能是会有一点影响。但在生产环境做的比对可以证明，影响太小了，基本忽略不计。</span></p>  <p style="margin-left:18.0pt;"><span style="font-size: 10pt; font-family: 宋体;">笔者在生产环境做了做了多次试验，</span><span style="font-size: 10pt; font-family: 'Courier New';">mapper</span><span style="font-size: 10pt; font-family: 宋体;">改成多线程后性能并未有提高，特别是对一些业务简单的</span><span style="font-size: 10pt; font-family: 'Courier New';">job</span><span style="font-size: 10pt; font-family: 宋体;">，增加</span><span style="font-size:9.0pt;font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">Transformer</span><span style="font-size:9.0pt;font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">中的并发级别效率可能还会下降。</span></p>  <p style="margin-left:18.0pt;"><span style="font-size:9.0pt;font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">很多同学喜欢在mapper中做所谓&#8220;mapper端的join&#8221;。这种方式，相信在HST中通过提高mapper的并发级别后会有更好的表现。</span></p>  <p style="margin-left:18.0pt;"><span style="font-size:9.0pt;font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">Reducer</span><span style="font-size:9.0pt;font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">中的性能相对原生提升的空间还是蛮大的。大部分的mapreduce项目，都是mapper简单而reducer复杂，HST采用并发执行join的方式对提升reducer性能是超好的。</span></p>  <p style="margin-left:18.0pt;">&nbsp;</p>  <p style="margin-left:18.0pt;text-indent:-18.0pt;">6.<span style="font-size: 7pt; line-height: normal; font-family: 'Times New Roman';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-family:宋体;">对于多次迭代的任务，相连的两个任务可以建立关联，在流程上的下一个</span>job<span style="font-family:宋体;">直接引用上一个</span>job<span style="font-family:宋体;">的结果，使多次迭代任务的代码结构变得清晰优美</span></p>  <p style="margin-left:18.0pt;"><span style="font-family:宋体;">虽然在最后才提到这一点，但这却是我一开始想要写</span>HST<span style="font-family:宋体;">原因。多次迭代的任务太麻烦了，上一个任务要写在</span>hdfs<span style="font-family:宋体;">做存储，下一个任务再取出使用，麻烦不麻烦。如果都由程序自动完成，岂不美哉！</span></p>  <p style="margin-left:18.0pt;"><span style="font-family:宋体;">在上一个任务里</span>format<span style="font-family:宋体;">一下</span></p>  <p style="margin-left:18.0pt;"><span style="font-size: 10pt; font-family: 'Courier New';">IteratedJob&lt;Long&gt; iJob = scheduler.createJob(</span><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;;color:#2A00FF;">"testJob"</span><span style="font-size: 10pt; font-family: 'Courier New';">)</span></p>  <p style="margin-left:63.0pt;"><span style="font-size: 10pt; font-family: 'Courier New';">...//</span><span style="font-size: 10pt; font-family: 宋体;">各种</span><span style="font-size: 10pt; font-family: 'Courier New';">source</span><span style="font-size: 10pt; font-family: 宋体;">定义</span></p>  <p style="margin-left:63.0pt;"><span style="font-size: 10pt; font-family: 'Courier New';">.format(</span><span style="font-size:10.0pt; font-family:&quot;Courier New&quot;;color:#2A00FF;">"f1"</span><span style="font-size: 10pt; font-family: 'Courier New';">,</span><span style="font-size:10.0pt; font-family:&quot;Courier New&quot;;color:#2A00FF;">"f2"</span><span style="font-size: 10pt; font-family: 'Courier New';">)</span></p>  <p style="margin-left:18.0pt;"><span style="font-size: 10pt; font-family: 宋体;">在第二个任务中，直接引用</span></p>  <p style="margin-left:18.0pt;"><span style="font-size: 10pt; font-family: 'Courier New';">IteratedJob&lt;Long&gt; stage2Job = scheduler.createJob(</span><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;;color:#2A00FF;">"stage2Job"</span><span style="font-size: 10pt; font-family: 'Courier New';">)</span></p>  <p style="margin-left:63.0pt;"><span style="font-size: 10pt; font-family: 'Courier New';">.fromPrevious(iJob, Transformer2_0.</span><strong><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;;color:#7F0055;">class</span></strong><span style="font-size: 10pt; font-family: 'Courier New';">);</span></p>  <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //<span style="font-size: 10pt; font-family: 'Courier New';">Transformer2_0.class</span></p>  <p>&nbsp;</p>  <p><span style="font-size: 10pt; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><strong><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;;color:#7F0055;">public</span></strong> <strong><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;;color:#7F0055;">static</span></strong> <strong><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;;color:#7F0055;">class</span></strong><span style="font-size: 10pt; font-family: 'Courier New';"> Transformer2_0 </span><strong><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;;color:#7F0055;">extends</span></strong><span style="font-size: 10pt; font-family: 'Courier New';"> PreviousResultTransformer&lt;Long&gt;</span></p>  <p><span style="font-size: 10pt; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ...</span></p>  <p align="left"><span style="font-size: 10pt; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; </span><strong><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;;color:#7F0055;">public</span></strong> <strong><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;;color:#7F0055;">void</span></strong><span style="font-size: 10pt; font-family: 'Courier New';"> flatMap(Long inputKey, String[] inputValues,Collector&lt;Long&gt; collector) {</span></p>  <p align="left"><span style="font-size: 10pt; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String f1 = getFiledValue(inputValues, </span><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;;color:#2A00FF;">"f1"</span><span style="font-size: 10pt; font-family: 'Courier New';">);</span></p>  <p><span style="font-size: 10pt; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String f2 = getFiledValue(inputValues, </span><span style="font-size:10.0pt; font-family:&quot;Courier New&quot;;color:#2A00FF;">"f2"</span><span style="font-size: 10pt; font-family: 'Courier New';">);</span></p>  <p><span style="font-size: 10pt; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp; </span><span style="font-size: 10pt; font-family: 宋体;">看到没，就是这么简单。</span></p>  <p style="text-indent:21.0pt"><span style="font-size: 10pt; font-family: 宋体;">在最开始的计划中，我还设计了使用</span><span style="font-size: 10pt; font-family: 'Courier New';">redis</span><span style="font-size: 10pt; font-family: 宋体;">队列来缓冲前面</span><span style="font-size: 10pt; font-family: 'Courier New';">job</span><span style="font-size: 10pt; font-family: 宋体;">的结果，供后面的</span><span style="font-size: 10pt; font-family: 'Courier New';">job</span><span style="font-size: 10pt; font-family: 宋体;">作为输入。这样本来必须严格串行的</span><span style="font-size: 10pt; font-family: 'Courier New';">job</span><span style="font-size: 10pt; font-family: 宋体;">可以在一定程度上并发。另外还设计了子任务的并发调度，这都留给以后去实现吧。</span></p>  <p style="text-indent:21.0pt">&nbsp;</p>  <p style="margin-left:18.0pt;text-indent:-18.0pt;"><span style="font-size: 10pt; font-family: 'Courier New';">7.&nbsp;</span><span style="font-size: 10pt; font-family: 宋体;">便捷的自定义参数传递。</span></p>  <p style="margin-left:18.0pt;text-indent:20.0pt"><span style="font-size: 10pt; font-family: 宋体;">有时候，在业务中需要作一些&#8220;开关变量&#8221;，在运行时动态传入不同的值以实现不同的业务逻辑。这个问题</span><span style="font-size: 10pt; font-family: 'Courier New';">HST</span><span style="font-size: 10pt; font-family: 宋体;">框架其实也为你考虑到了。</span></p>  <p style="margin-left:21.3pt;text-indent:20.0pt"><span style="font-size: 10pt; font-family: 'Courier New';">Driver</span><span style="font-size: 10pt; font-family: 宋体;">中的自定义参数，</span><span style="font-size: 10pt; font-family: 'Courier New';">source</span><span style="font-size: 10pt; font-family: 宋体;">中的自定义参数都会以内置的方式传到</span><span style="font-size: 10pt; font-family: 'Courier New';">transformer</span><span style="font-size: 10pt; font-family: 宋体;">或</span><span style="font-size: 10pt; font-family: 'Courier New';">joiner</span><span style="font-size: 10pt; font-family: 宋体;">中去，方便程序员书写业务。</span></p>  <p style="text-indent:21.0pt"><span style="font-size: 10pt; font-family: 'Courier New';">&nbsp;&nbsp; </span><span style="font-size: 10pt; font-family: 宋体;">查看</span><span style="font-size: 10pt; font-family: 'Courier New';">transformer</span><span style="font-size: 10pt; font-family: 宋体;">或</span><span style="font-size: 10pt; font-family: 'Courier New';">joiner</span><span style="font-size: 10pt; font-family: 宋体;">的源码就会发现：</span></p>  <p style="margin-left:21.2pt; text-indent:15.0pt;"><span style="font-size: 10pt; font-family: 'Courier New';">getSourceParam(name)</span><span style="font-size: 10pt; font-family: 宋体;">和</span><span style="font-size: 10pt; font-family: 'Courier New';">getDriverParam(pIndex)</span><span style="font-size: 10pt; font-family: 宋体;">方法，在计算节点轻松的得到在</span><span style="font-size: 10pt; font-family: 'Courier New';">driver</span><span style="font-size: 10pt; font-family: 宋体;">和</span><span style="font-size: 10pt; font-family: 'Courier New';">source</span><span style="font-size: 10pt; font-family: 宋体;">中设置的各层次级别的自定义参数</span><span style="font-size: 10pt; font-family: 'Courier New';">,</span><span style="font-size: 10pt; font-family: 宋体;">爽吧</span><span style="font-size: 10pt; font-family: 'Courier New';">!</span></p>  <p style="text-indent:21.0pt">&nbsp;</p>  <p style="margin-left:18.0pt;text-indent:-18.0pt;"><span style="font-size: 10pt; font-family: 'Courier New';">8.&nbsp;</span><span style="font-size: 10pt; font-family: 宋体;">其他工具</span></p>  <p style="margin-left:18.0pt;text-indent:20.0pt"><span style="font-size: 10pt; font-family: 'Courier New';">HST</span><span style="font-size: 10pt; font-family: 宋体;">提供的方便还不止以上这些，比如在工具类中还提供了两行数据（</span><span style="font-size: 10pt; font-family: 'Courier New';">map</span><span style="font-size: 10pt; font-family: 宋体;">类型）直接</span><span style="font-size: 10pt; font-family: 'Courier New';">join</span><span style="font-size: 10pt; font-family: 宋体;">的方法。这些都留给你自己去发现并实践吧</span><span style="font-size: 10pt; font-family: 'Courier New';">!<br /></span><a href="https://github.com/jonenine/HST" style="text-indent: 28px;">https://github.com/jonenine/HST</a><br /><span style="font-size: 10pt; font-family: 'Courier New';"><br /></span></p><img src ="http://www.blogjava.net/jonenine/aggbug/432281.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jonenine/" target="_blank">溪石</a> 2017-01-29 10:10 <a href="http://www.blogjava.net/jonenine/archive/2017/01/29/432281.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>使用jboss netty 创建高性能webservice客户端及服务端</title><link>http://www.blogjava.net/jonenine/archive/2014/12/28/421895.html</link><dc:creator>溪石</dc:creator><author>溪石</author><pubDate>Sun, 28 Dec 2014 06:35:00 GMT</pubDate><guid>http://www.blogjava.net/jonenine/archive/2014/12/28/421895.html</guid><wfw:comment>http://www.blogjava.net/jonenine/comments/421895.html</wfw:comment><comments>http://www.blogjava.net/jonenine/archive/2014/12/28/421895.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jonenine/comments/commentRss/421895.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jonenine/services/trackbacks/421895.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;使用jboss netty 创建高性能webservice客户端及服务端  &nbsp;  &nbsp;&nbsp; 通过本文，读者将了解以下内容  （1）利用jboss netty创建一个高性能的web服务客户端  （2）不使用任何第三方框架，手工在web容器内创建webse...&nbsp;&nbsp;<a href='http://www.blogjava.net/jonenine/archive/2014/12/28/421895.html'>阅读全文</a><img src ="http://www.blogjava.net/jonenine/aggbug/421895.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jonenine/" target="_blank">溪石</a> 2014-12-28 14:35 <a href="http://www.blogjava.net/jonenine/archive/2014/12/28/421895.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>在web开发中更加富有效率的使用JSON</title><link>http://www.blogjava.net/jonenine/archive/2014/12/06/json.html</link><dc:creator>溪石</dc:creator><author>溪石</author><pubDate>Sat, 06 Dec 2014 06:08:00 GMT</pubDate><guid>http://www.blogjava.net/jonenine/archive/2014/12/06/json.html</guid><wfw:comment>http://www.blogjava.net/jonenine/comments/421124.html</wfw:comment><comments>http://www.blogjava.net/jonenine/archive/2014/12/06/json.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/jonenine/comments/commentRss/421124.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jonenine/services/trackbacks/421124.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: /Files/jonenine/blog.rar本文一共分3个部分，介绍了在web中如何灵活而高效使用json，并同大家分享了实际的代码，希望大家喜欢。（一）&nbsp;&nbsp;&nbsp;在jvm中使用jsonjson的使用在当下已经普及起来了，作者使用json也已经有很长的时间了，早在它普及之前就尝试着在项目中应用它。今天给大家介绍的代码都是实际项目中真实的代码，虽然不尽完美，但却禁得住实...&nbsp;&nbsp;<a href='http://www.blogjava.net/jonenine/archive/2014/12/06/json.html'>阅读全文</a><img src ="http://www.blogjava.net/jonenine/aggbug/421124.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jonenine/" target="_blank">溪石</a> 2014-12-06 14:08 <a href="http://www.blogjava.net/jonenine/archive/2014/12/06/json.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>利用动态类加载技术调式ECLIPSE插件</title><link>http://www.blogjava.net/jonenine/archive/2009/05/04/268807.html</link><dc:creator>溪石</dc:creator><author>溪石</author><pubDate>Mon, 04 May 2009 06:06:00 GMT</pubDate><guid>http://www.blogjava.net/jonenine/archive/2009/05/04/268807.html</guid><wfw:comment>http://www.blogjava.net/jonenine/comments/268807.html</wfw:comment><comments>http://www.blogjava.net/jonenine/archive/2009/05/04/268807.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.blogjava.net/jonenine/comments/commentRss/268807.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jonenine/services/trackbacks/268807.html</trackback:ping><description><![CDATA[&nbsp;
<p class="MsoNormal" style="text-indent: 105pt; mso-char-indent-count: 10.0"><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 利用动态类加载技术调式</span><span lang="EN-US">ECLIPSE</span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">插件</span></p>
<p class="MsoNormal"><span lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal" style="text-indent: 15.75pt; mso-char-indent-count: 1.5"><span lang="EN-US">&nbsp;&nbsp; eclipse</span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">平台提供</span><span lang="EN-US">runtime</span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">方式调试插件和</span><span lang="EN-US">RCP</span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">项目，但随着插件项目越写约复杂，启动时间也越来越长，特别是集成了诸如</span><span lang="EN-US"> Hibernate</span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">和</span><span lang="EN-US">Spring</span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">之类的容器级框架的时候。仅仅为了调试代码中一些琐碎的片段而频繁的重启项目实在是一件异常烦人的工作。</span></p>
<p class="MsoNormal"><span lang="EN-US"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">即使重启了项目也许还没完。为了使项目处于某个特定的状态下以方便测试，每次都要重新操作一遍前面业务流程，这同样是十分令人厌倦的。</span></p>
<p class="MsoNormal"><span lang="EN-US"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>eclispe</span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">使用了</span><span lang="EN-US">OGSI</span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">作为微内核，引入了一些动态特性。但是</span><span lang="EN-US">OSGI</span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">的动态特性是在保持平台运行的情况下动态更新</span><span lang="EN-US">Bundle</span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">，也就是说需要重启插件才能完成动态加载的过程。有没有一些更加细粒度的动态载入方案呢？</span></p>
<p class="MsoNormal"><span lang="EN-US"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">在</span><span lang="EN-US">Tomcat</span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">下开发过</span><span lang="EN-US">web</span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">项目的人都知道，使用调试模式来部署项目即</span><span lang="EN-US">&#8221;</span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">热部署</span><span lang="EN-US">&#8221;</span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">可以实现动态载入</span><span lang="EN-US">class</span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">文件</span><span lang="EN-US">,</span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">让程序员得以动态调试项目。今天向大家提供的这个</span><span lang="EN-US">jar</span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">包使得这种效果可以在</span><span lang="EN-US">eclipse runtime</span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">上实现。</span></p>
<p class="MsoNormal" style="text-indent: 20.4pt"><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">这是我在自己的插件平台项目——</span><span lang="EN-US">SCOOP</span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">框架中使用的几个包。</span></p>
<p class="MsoNormal" style="text-indent: 20.4pt"><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">它可以非常好的解决动态类载入的问题</span><span lang="EN-US">,</span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">包括内部类的动态载入都可以很好解决。</span></p>
<p class="MsoNormal" style="text-indent: 20.4pt"><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">其他的几个包还进行了以下尝试</span></p>
<p class="MsoListParagraph" style="margin-left: 38.4pt; text-indent: -18pt; mso-char-indent-count: 0; mso-list: l1 level1 lfo1"><span lang="EN-US" style="mso-fareast-font-family: Calibri; mso-fareast-theme-font: minor-latin; mso-bidi-font-family: Calibri; mso-bidi-theme-font: minor-latin"><span style="mso-list: Ignore">1.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">使用元数据标注的办法解决</span><span lang="EN-US">SWT UI </span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">线程的种种问题</span></p>
<p class="MsoListParagraph" style="margin-left: 38.4pt; text-indent: -18pt; mso-char-indent-count: 0; mso-list: l1 level1 lfo1"><span lang="EN-US" style="mso-fareast-font-family: Calibri; mso-fareast-theme-font: minor-latin; mso-bidi-font-family: Calibri; mso-bidi-theme-font: minor-latin"><span style="mso-list: Ignore">2.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">还提供了</span><span lang="EN-US">eclipse</span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">流程框架的简单实现，以规范插件开发。特别是提出了一个面向业务而不是面向技术的工作流概念，使得编码粒度变大，并得以提高效率。另外这个简单的流程框架还将前面的两种机制很好的结合起来，并且可以和</span><span lang="EN-US">eclipse</span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">平台的一些复杂机制解耦，为复杂流程的开发测试提供了方便。为将来实现自定义脚本语言</span><span lang="EN-US">(</span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">比如某个类似于</span><span lang="EN-US">BPEL</span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">的工作流语言</span><span lang="EN-US">)</span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">开发</span><span lang="EN-US">eclise</span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">插件项目甚至使用图形化的开发奠定了一定的基础。</span></p>
<p class="MsoNormal"><span lang="EN-US"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">我给出了一个完整的示例——</span><span lang="EN-US">JAXB</span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">插件。很多框架同</span><span lang="EN-US">jaxb</span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">一样提供了</span><span lang="EN-US">code generation</span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">工具，可以在这个例子的基础上经过简单修改为这些框架提供插件，比如</span><span lang="EN-US">CXF</span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">插件、</span><span lang="EN-US">AXIS2</span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">插件等等。</span></p>
<p class="MsoNormal"><span lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal"><span style="font-size: 12pt; font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">动态类载入编码原则</span><span lang="EN-US" style="font-size: 12pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US"><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">使用动态类载入机制来进行调试在编码上有一定限制。</span></p>
<p class="MsoNormal"><span lang="EN-US"><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">首先是要进行动态载入的实例不要在非动态域进行引用。只有这样，当一个流程结束时此实例才会在</span><span lang="EN-US">jvm</span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">中得以释放。当然，非要在其他地方进行引用从而长久的在运行时保持这个实例也是有解决方案的</span><span lang="EN-US">(</span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">可以使用代理类技术来实现，具体解决办法不在本文之内</span><span lang="EN-US">)</span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">。</span></p>
<p class="MsoNormal"><span lang="EN-US"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">其次是进行接口同实现类的分离或父类同子类的分离，以隔离不同的</span><span lang="EN-US">class load scope</span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">。接口由父类载入器载入，不同的实现</span><span lang="EN-US">(</span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">比如修改后的实现</span><span lang="EN-US">)</span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">由不同的子类载入器载入。使得最终同一个类型由同一个类载入器载入，这样才能符合</span><span lang="EN-US">jvm</span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">的类载入规范。在父类载入域的父类型的方法的参数类型及返回值类型也不能在动态域中。</span></p>
<p class="MsoNormal" style="text-indent: 21pt"><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">最后</span><span lang="EN-US">,</span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">那些注册在扩展点上的类如</span><span lang="EN-US">ActionDelegate</span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">和</span><span lang="EN-US">WorkbenchPart</span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">等是不能够动态载入的，他们必须由</span><span lang="EN-US">eclipse</span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">提供的类载入器载入（平台会自动载入并管理其生命周期）。如果需要让这些类也动态载入，就需要在平台提供的动态注册机制基础上使用代理或像</span><span lang="EN-US">EJB2.0</span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">一样使用侵入式编译来实现代理机制，这个话题同样不在本文之内。</span></p>
<p class="MsoNormal"><span lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal" style="text-indent: 21pt"><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">下面就举例说明使用方法</span></p>
<p class="MsoNormal" style="text-indent: 21pt"><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">因为时间有限我无法详尽的完成此文，请感兴趣的朋友自己阅读示例源码。</span></p>
<p class="MsoListParagraph" style="margin-left: 18pt; text-indent: -18pt; mso-char-indent-count: 0; mso-list: l0 level1 lfo2"><span lang="EN-US" style="mso-fareast-font-family: Calibri; mso-fareast-theme-font: minor-latin; mso-bidi-font-family: Calibri; mso-bidi-theme-font: minor-latin"><span style="mso-list: Ignore">1.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">几种动态类载入的办法</span></p>
<p class="MsoListParagraph" style="margin-left: 36pt; text-indent: -18pt; mso-char-indent-count: 0; mso-list: l2 level1 lfo3"><span lang="EN-US" style="mso-fareast-font-family: Calibri; mso-fareast-theme-font: minor-latin; mso-bidi-font-family: Calibri; mso-bidi-theme-font: minor-latin"><span style="mso-list: Ignore">(1)<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp; </span></span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">使用手动编码进行类载入</span></p>
<p class="MsoListParagraph" style="margin-left: 36pt; text-indent: 0cm; mso-char-indent-count: 0"><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">因为会使二次开发人员产生迷惑，故未举例</span></p>
<p class="MsoListParagraph" style="margin-left: 36pt; text-indent: -18pt; mso-char-indent-count: 0; mso-list: l2 level1 lfo3"><span lang="EN-US" style="mso-fareast-font-family: Calibri; mso-fareast-theme-font: minor-latin; mso-bidi-font-family: Calibri; mso-bidi-theme-font: minor-latin"><span style="mso-list: Ignore">(2)<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp; </span></span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">在调试时使用</span><span lang="EN-US">spring</span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">文件配置动态类载入域</span></p>
<p class="MsoListParagraph" style="margin-left: 36pt; text-indent: 0cm; mso-char-indent-count: 0"><span lang="EN-US">Spring</span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">配置文件同样也是动态的，而且会使调试开发工作变得更加清晰，推荐使用</span></p>
<p class="MsoListParagraph" style="margin-left: 36pt; text-indent: -18pt; mso-char-indent-count: 0; mso-list: l2 level1 lfo3"><span lang="EN-US" style="mso-fareast-font-family: Calibri; mso-fareast-theme-font: minor-latin; mso-bidi-font-family: Calibri; mso-bidi-theme-font: minor-latin"><span style="mso-list: Ignore">(3)<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp; </span></span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">使用</span><span lang="EN-US">Flow</span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">框架来进行动态类载入</span></p>
<p class="MsoListParagraph" style="margin-left: 36pt; text-indent: 0cm; mso-char-indent-count: 0"><span lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoListParagraph" style="margin-left: 18pt; text-indent: -18pt; mso-char-indent-count: 0; mso-list: l0 level1 lfo2"><span lang="EN-US" style="mso-fareast-font-family: Calibri; mso-fareast-theme-font: minor-latin; mso-bidi-font-family: Calibri; mso-bidi-theme-font: minor-latin"><span style="mso-list: Ignore">2.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">使用元数据标注解决</span><span lang="EN-US">UI</span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">线程访问的问题</span></p>
<p class="MsoNormal" style="margin-left: 18pt"><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">使用三个元数据及动态代理类解决</span><span lang="EN-US">SWT</span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">及</span><span lang="EN-US">Eclipse</span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">的线程问题。</span></p>
<p class="MsoNormal" style="margin-left: 18pt"><span lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoListParagraph" style="margin-left: 18pt; text-indent: -18pt; mso-char-indent-count: 0; mso-list: l0 level1 lfo2"><span lang="EN-US" style="mso-fareast-font-family: Calibri; mso-fareast-theme-font: minor-latin; mso-bidi-font-family: Calibri; mso-bidi-theme-font: minor-latin"><span style="mso-list: Ignore">3.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">同</span><span lang="EN-US">eclipse</span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">内部机制解耦以方便开发和测试</span></p>
<p class="MsoListParagraph"><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">&nbsp;&nbsp;&nbsp; 开发插件项目很多时候需要实现</span><span lang="EN-US">Eclipse</span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">内部的一些回调接口来实现功能，这对程序员的水平是一种考验，也使得插件开发工作更加复杂化。比如在实现</span><span lang="EN-US">progressMonitor</span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">的时候，就需要实现它的回调接口，将业务逻辑放置在其指定的回调接口——</span><span lang="EN-US">runable</span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">接口来实现，这是非常不方便的。我们需要是一种可以提供功能的工具类，像调用一个普通</span><span lang="EN-US">javaBean</span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">一样来调用它，而不是将我们的业务代码变形撕碎去融入到</span><span lang="EN-US">Eclipse</span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">的种种机制中去。</span></p>
<p class="MsoListParagraph"><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">&nbsp;&nbsp;&nbsp; 这样做的另外一个坏处就是很难进行单元测试，比如脱离</span><span lang="EN-US">eclipse</span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">平台，使用一些</span><span lang="EN-US">mock</span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">类来进行简单有效的单元测试。</span></p>
<p class="MsoListParagraph"><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">&nbsp;&nbsp;&nbsp; 我在这方面也进行了一些尝试——</span><span lang="EN-US">&#8221;</span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">反客为主</span><span lang="EN-US">&#8221;</span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">，将必须遵守</span><span lang="EN-US">eclipse</span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">的回调要求变为必须遵守业务开发简单快捷的要求。同样是在</span><span lang="EN-US">progressMonitor</span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">上面，使用工厂类来创建</span><span lang="EN-US">delegate</span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">，然后可以在回调机制的外部向调用</span><span lang="EN-US">javaBean</span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">一样来使用平台给我们提供的这个功能。</span></p>
<p class="MsoListParagraph"><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">这种尝试是有一定难度的，要使用到不同的设计模式，处理各种线程问题。更重要的一点是</span><span lang="EN-US">eclipse</span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">平台本身有这样的潜力，它也在等待着我们这样做。</span></p>
<p class="MsoNormal"><span lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoListParagraph" style="margin-left: 18pt; text-indent: -18pt; mso-char-indent-count: 0; mso-list: l0 level1 lfo2"><span lang="EN-US" style="mso-fareast-font-family: Calibri; mso-fareast-theme-font: minor-latin; mso-bidi-font-family: Calibri; mso-bidi-theme-font: minor-latin"><span style="mso-list: Ignore">4.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">使用</span><span lang="EN-US">Flow</span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">规范插件项目开发</span></p>
<p class="MsoListParagraph"><span lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal"><span lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal" style="text-indent: 15.75pt; mso-char-indent-count: 1.5"><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">我的</span><span lang="EN-US">scoop</span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">项目最终搁浅，到最后我发现实现它已经超出了我当时的能力。我原本是想开发一个统一的插件开发及部署平台。这样很多中小软件企业，特别是像我原来工作的那家公司就可以拥有自己的</span><span lang="EN-US">eclipse</span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">插件集，以适应自己特殊的要求。我还想提供一套面向插件开发业务的接口，而不再面向技术也屏蔽各种技术细节，使得可以非常方便的扩展、修改甚至移植插件。我只是心里有想念就去实现而已，当最终认识到它有多么困难的时候不得不放弃了。</span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">最后虽然失败了，但并不觉得气馁。因为知道了要努力的方向，同时也积累了丰富的经验。最后就将这个</span><span lang="EN-US">jar</span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">包命名为</span><span lang="EN-US">SCOOP</span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">已示纪念。<br />
</span></p>
<p class="MsoNormal"><span lang="EN-US"><o:p><a href="/Files/jonenine/webTreeViewer.rar"></a>&nbsp;演示文档及框架JAR包如下</o:p></span></p>
<a href="/Files/jonenine/Eclipse_Dynamic_Classload.rar">/Files/jonenine/Eclipse_Dynamic_Classload.rar</a>
<img src ="http://www.blogjava.net/jonenine/aggbug/268807.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jonenine/" target="_blank">溪石</a> 2009-05-04 14:06 <a href="http://www.blogjava.net/jonenine/archive/2009/05/04/268807.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>在web开发中的树状视图技术</title><link>http://www.blogjava.net/jonenine/archive/2009/05/04/268791.html</link><dc:creator>溪石</dc:creator><author>溪石</author><pubDate>Mon, 04 May 2009 05:14:00 GMT</pubDate><guid>http://www.blogjava.net/jonenine/archive/2009/05/04/268791.html</guid><wfw:comment>http://www.blogjava.net/jonenine/comments/268791.html</wfw:comment><comments>http://www.blogjava.net/jonenine/archive/2009/05/04/268791.html#Feedback</comments><slash:comments>7</slash:comments><wfw:commentRss>http://www.blogjava.net/jonenine/comments/commentRss/268791.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jonenine/services/trackbacks/268791.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 在web开发中的树状视图技术树型数据模型在现实生活中应用相当广泛，从超市的商品分类到政府的组织结构无不都是&#8221;树形&#8221;的。在实际的项目开发中也经常需要显示这种结构。比如，在树状视图上给一个单位的职工赋予系统操作权限。&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在web开发中实现树状显示在技术上主要有以下两种方案1...&nbsp;&nbsp;<a href='http://www.blogjava.net/jonenine/archive/2009/05/04/268791.html'>阅读全文</a><img src ="http://www.blogjava.net/jonenine/aggbug/268791.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jonenine/" target="_blank">溪石</a> 2009-05-04 13:14 <a href="http://www.blogjava.net/jonenine/archive/2009/05/04/268791.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>