﻿<?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-于吉吉的技术博客-随笔分类-java</title><link>http://www.blogjava.net/dongbule/category/46466.html</link><description>建造高性能门户网</description><language>zh-cn</language><lastBuildDate>Tue, 04 Mar 2014 08:54:29 GMT</lastBuildDate><pubDate>Tue, 04 Mar 2014 08:54:29 GMT</pubDate><ttl>60</ttl><item><title>朋友要招几个java，让帮忙出点面试题目</title><link>http://www.blogjava.net/dongbule/archive/2013/07/05/401249.html</link><dc:creator>陈于喆</dc:creator><author>陈于喆</author><pubDate>Fri, 05 Jul 2013 09:18:00 GMT</pubDate><guid>http://www.blogjava.net/dongbule/archive/2013/07/05/401249.html</guid><wfw:comment>http://www.blogjava.net/dongbule/comments/401249.html</wfw:comment><comments>http://www.blogjava.net/dongbule/archive/2013/07/05/401249.html#Feedback</comments><slash:comments>6</slash:comments><wfw:commentRss>http://www.blogjava.net/dongbule/comments/commentRss/401249.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/dongbule/services/trackbacks/401249.html</trackback:ping><description><![CDATA[<div>上周朋友说要招几个高级点的java，网上那些java面试宝典已经被人背得熟透了，让帮忙出出几个面试的问题，主要看看对所使用得语言有较深入得了解，不停留在使用什么开源框架，和对自己一些项目得见解。当然还要装装B，最后问一些别人不懂得问题，好压压价钱。。。罪过，公司是他自己的</div><div></div><div>随便整理了一下，以后面试也可以用到，主要针对平时日常得应用，只要有稍微阅读过jdk源码，对数据结构有一点点了解回答应该没什么问题。</div><div></div><div>随便写了几个</div><div><br /><div></div><div><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; </span><span style="font-family:宋体;">当需要往一个</span>hashMap<span style="font-family:宋体;">里面</span>put<span style="font-family:宋体;">很多对象，你会怎么去</span>new <span style="font-family:宋体;">这个</span>hashmap?</p>  <p style="margin-left:18.0pt;text-indent:0cm;"><span style="font-family:宋体;color:gray;">注：主要审查是否懂得</span><span style="color:gray;">hash</span><span style="font-family:宋体;color:gray;">的数据结构，是否会用</span></p>  <p style="margin-left:18.0pt;text-indent:0cm;"><span style="color:gray;">HashMap(int initialCapacity, float loadFactor) </span></p>  <p style="margin-left:18.0pt;text-indent:0cm;"><span style="font-family:宋体;color:gray;">这个构造函数去创建一个大容积的</span><span style="color:gray;">Hash</span><span style="font-family:宋体;color:gray;">结构，懂得原理即可。如果回答正确，可深入问</span><span style="color:gray;">hashmap</span><span style="font-family:宋体;color:gray;">的扩容。</span></p>  <p style="margin-left:18.0pt;text-indent:0cm;">&nbsp;</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; </span><span style="font-family:宋体;">实现一个先进先出的队列，分别有</span>arraylist<span style="font-family:宋体;">和</span>linkedlist<span style="font-family:宋体;">，选择哪个，为什么？</span></p>  <p style="margin-left:18.0pt;text-indent:0cm;"><span style="font-family:宋体;color:gray;">注：主要审查是否懂得线性表和链表。</span></p>  <p style="margin-left:18.0pt;text-indent:0cm;">&nbsp;</p>  <p>3. <span style="font-family:宋体;">当我们</span>new arrayList(20)<span style="font-family:宋体;">一个这样的对象后，不断往里面添加</span>add(object),<span style="font-family:宋体;">加到第</span>21<span style="font-family:宋体;">个后，内存会有什么调整。</span></p>  <p style="margin-left:21.0pt;text-indent:0cm;"><span style="font-family:宋体;color:gray;">注：主要审查是否懂得可变</span><span style="color:gray;">array</span><span style="font-family:宋体;color:gray;">的本质，当内存进行扩容的本质是</span></p>  <p style="margin-left:21.0pt;text-indent:0cm;"><span style="color:gray;">Arrays.copyOf(elementData, newCapacity)</span></p>  <p><span style="color:gray;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></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; </span><span style="font-family:宋体;">一个类有几百个实现方法，突然有个需求：要纪录每个方法被调用的参数，时间为日志，这个怎么去实现？</span></p>  <p style="margin-left:18.0pt;text-indent:0cm;"><span style="font-family:宋体; color:gray;">注：主要审查是否使用</span><span style="color:gray;">aop</span><span style="font-family:宋体;color:gray;">等面向切面编程。</span><span style="font-family:宋体;">如果回答正确，继续追问，只对方法名开头为</span>&#8217;insert&#8217;<span style="font-family:宋体;">，</span>&#8217;update&#8217;<span style="font-family:宋体;">等方法进行日志纪录，该怎么配对<span style="color:gray;">。注：主要审查对正则表达式的掌握。</span></span></p>  <p style="margin-left:18.0pt;text-indent:0cm;">&nbsp;</p>  <p style="margin-left:-.5pt; text-indent:-18.0pt;">&nbsp; &nbsp; &nbsp;5<span style="font-family:宋体;">．在</span>vi<span style="font-family:宋体;">的编辑下，对光标所在行进行整行删除命令是什么，将光标移到当前行</span>&nbsp;&nbsp; <span style="font-family:宋体;">第一列的命令是什么</span></p>  <p style="margin-left:-.5pt; text-indent:-18.0pt;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; <span style="font-family:宋体;color:gray;">注：主要审查在</span><span style="color:gray;">linux</span><span style="font-family:宋体;color:gray;">下最基础的</span><span style="color:gray;">vi</span><span style="font-family:宋体;color:gray;">编辑命令，不懂</span><span style="color:gray;">vi</span><span style="font-family: 宋体;color:gray;">是否可认为无在</span><span style="color:gray;">linux</span><span style="font-family:宋体;color:gray;">真实工作？</span></p>  <p style="margin-left:-.5pt; text-indent:-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; </span><span style="font-family:宋体;">机器出现</span>OutOfMemoryError<span style="font-family:宋体;">：</span> PermGen space <span style="font-family:宋体;">的内存溢出错误，解决思路是什么</span></p>  <p style="margin-left:18.0pt;text-indent:0cm;"><span style="font-family:宋体; color:gray;">注：主要审查是否明白方法区或叫永久区的定义，该区是否内存回收，什么实例会存放在该区，不求具体实现方案，主要有大概思路即可。</span></p>  <p>&nbsp;</p>  <p style="margin-left:18.0pt;text-indent:-18.0pt;">7.<span style="font-size: 7pt; line-height: normal; font-family: 'Times New Roman';">&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-family:宋体;">你的系统将在明天出现读的高并发，该怎么准备</span></p>  <p style="margin-left:18.0pt;text-indent:0cm;"><span style="font-family:宋体; color:gray;">注：方法多种，主要检查思路，漫谈来观察。</span></p>  <p>&nbsp;</p>  <p style="margin-left:18.0pt;text-indent:-18.0pt;">8.<span style="font-size: 7pt; line-height: normal; font-family: 'Times New Roman';">&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-family:宋体;">一台</span>linux<span style="font-family:宋体;">服务器每天定时生成一批文件，需要将这批文件同步到其他多台服务器，该怎么实现。</span></p>  <p style="margin-left:18.0pt;text-indent:0cm;"><span style="font-family:宋体;">注：方法多种，如</span>rsync<span style="font-family:宋体;">，</span>nfs<span style="font-family:宋体;">，</span>scp<span style="font-family:宋体;">等等，主要检查</span>linux<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:-18.0pt;">9.<span style="font-size: 7pt; line-height: normal; font-family: 'Times New Roman';">&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-family:宋体;">为什么说尽量减小</span>synchronized <span style="font-family:宋体;">方法</span></p>  <p style="margin-left:18.0pt;text-indent:0cm;"><span style="font-family:宋体; color:gray;">注：主要审核对同步实现方法的认识，如果能回答出&#8220;锁&#8221;的概念，</span><span style="font-family:宋体;">继续追问，如果对实例方法加</span>synchronized<span style="font-family:宋体;">，</span> <span style="font-family: 宋体;">锁的对象是什么，对静态方法加</span>synchronized <span style="font-family:宋体;">，锁的对象是什么</span></p>  <p style="margin-left:18.0pt;text-indent:0cm;">&nbsp;&nbsp;</p>  <p style="text-indent:0cm;">10<span style="font-family:宋体;">．说说单例的使用场景是什么，如</span>spring<span style="font-family:宋体;">场景中就有许多单例模式</span></p>  <p style="text-indent:0cm;"><span style="color:gray;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-family:宋体;color:gray;">注：答案很多，可以漫谈来观察，能回答出，让多个线程相互通信达到资源共享即可</span></p>  <p style="text-indent:0cm;">&nbsp;</p>  <p style="margin-left:18.0pt;text-indent:-18.0pt;">11. <span style="font-family:宋体;">随便在</span>jdk<span style="font-family:宋体;">或</span>spring<span style="font-family:宋体;">的英文</span>api<span style="font-family:宋体;">中找一段让其翻译</span></p>  <p style="margin-left: 18pt; text-indent: 0cm;"><span style="font-family: 宋体; color: gray;">注：能大概说出接口的用处即可<br /><br /><br /><br /></span>----------------------------------------<br />  <br />  by 陈于喆 <br />  QQ:34174409<br />  Mail: dongbule@163.com<br />  <br /></p></div></div><img src ="http://www.blogjava.net/dongbule/aggbug/401249.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/dongbule/" target="_blank">陈于喆</a> 2013-07-05 17:18 <a href="http://www.blogjava.net/dongbule/archive/2013/07/05/401249.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>简单分析cglib引起的PermSize Space内存溢出</title><link>http://www.blogjava.net/dongbule/archive/2011/08/21/356987.html</link><dc:creator>陈于喆</dc:creator><author>陈于喆</author><pubDate>Sun, 21 Aug 2011 07:55:00 GMT</pubDate><guid>http://www.blogjava.net/dongbule/archive/2011/08/21/356987.html</guid><wfw:comment>http://www.blogjava.net/dongbule/comments/356987.html</wfw:comment><comments>http://www.blogjava.net/dongbule/archive/2011/08/21/356987.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/dongbule/comments/commentRss/356987.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/dongbule/services/trackbacks/356987.html</trackback:ping><description><![CDATA[<div><font class="Apple-style-span" face="Arial" size="2"><span class="Apple-style-span" style="line-height: 18px;"><br /></span></font>上段时间有台机器发生了 java.lang.OutOfMemoryError: PermGen space 内存溢出的异常，当时大概判断了原因后就把 MaxPermSize 配置调高后，就把问题解决了，不过空下时间后还是需要继续把review代码。<br /><br /><span>一般来说PermSize Space OOM的话，第一种可能就是方法区溢出，第二种就是运行时常量池溢出，第二种查看后基本排除掉，问题就应该出现在方法区的溢出，方法区用于存放class的相关信息，如类名，访问修饰符，常量池，字段描述，方法描述等等，对于这个区域的溢出，基本上都是运行时产生大量的类填满了整个方法区，直到溢出。<br /></span><br /><span>spring aop中都是使用到了cglib这类字节码的技术，动态代理的类越多，就需要越多的方法区来保证动态生成的class可以加载入到内存中去，</span><div style="display: inline-block; "></div><span class="Apple-style-span" style="font-family: Arial; line-height: 18px; ">不过spring框架导致的不会因为这种原因。<strong>撑爆perm的应该是各种methodaccessorX和constructoracccessorX等等</strong>。本来这些accessor也有缓存，但它们使用内存大小敏感的reference引用着的，且使用的是堆内存。当你堆内存吃紧的时候，这些缓存就摧毁了，就必然会不断产生新的methodAccessor字节码，是这个撑爆了perm。<strong>所以除增大permsize还应该看看平时运行时堆内存是不是经常用光</strong>。</span><br /><br />下面的例使用cglib直接进行动态代理产生大量的动态类，然后使用jconsole进行观察。<br /><br />首先将本机的jvm配置为 -XX:PermSize=64M -XX:MaxPermSize=64M ，给到PermSize最大为64M的内存</div><br /><div style="background-color: #eeeeee; font-size: 13px; border: 1px solid #cccccc; padding: 4px 5px 4px 4px; width: 98%;"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;PermgenOOM&nbsp;{<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">static</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;main(String[]&nbsp;args)&nbsp;</span><span style="color: #0000ff;">throws</span><span style="color: #000000;">&nbsp;InterruptedException&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;i</span><span style="color: #000000;">=</span><span style="color: #000000;">0</span><span style="color: #000000;">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">while</span><span style="color: #000000;">(</span><span style="color: #0000ff;">true</span><span style="color: #000000;">){<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Enhancer&nbsp;enhancer&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;Enhancer();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;enhancer.setSuperclass(Product.</span><span style="color: #0000ff;">class</span><span style="color: #000000;">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;enhancer.setUseCache(</span><span style="color: #0000ff;">false</span><span style="color: #000000;">);</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;关闭CGLib缓存，否则总是生成同一个类</span><span style="color: #008000;"><br /></span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;enhancer.setCallback(</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;MethodInterceptor()&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@Override<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;Object&nbsp;intercept(Object&nbsp;obj,&nbsp;Method&nbsp;method,&nbsp;Object[]&nbsp;args,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MethodProxy&nbsp;methodproxy)&nbsp;</span><span style="color: #0000ff;">throws</span><span style="color: #000000;">&nbsp;Throwable&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;TODO&nbsp;Auto-generated&nbsp;method&nbsp;stub</span><span style="color: #008000;"><br /></span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;methodproxy.invokeSuper(obj,args);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;});<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;enhancer.create();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Thread.sleep(</span><span style="color: #000000;">100</span><span style="color: #000000;">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />}</span></div><br /><div>很快，系统就抛出了 java.lang.OutOfMemoryError: PermGen space<br />内存池peimgen的情况</div><br /><img alt="" src="http://www.blogjava.net/images/blogjava_net/dongbule/permsize/1.jpg" width="837" height="441" /><br /><div>加载类的情况</div><br /><img alt="" src="http://www.blogjava.net/images/blogjava_net/dongbule/permsize/2.jpg" width="396" height="303" /><br /><br /><div>并且在方法区中，一个类如果要被垃圾收集器回收掉，判断的条件是非常苛刻的，很多人都把方法区称为&#8220;永久区&#8221;(Permanent Generation),但据说2者在本质上是不一致的，另外还有称呼为&#8220;非堆区&#8221;，不纠结这个了。<br /><br />再看看enhancer.setUseCache(false)，如果选择为true的话，那么就使用和更新一类具有相同属性生成的类的静态缓存，而不会在同一个类文件还继续被动态加载并视为不同的类，这个其实跟类的equals()和hashCode()有关，它们是与cglib内部的class cache的key相关的。<br /><br />将上面的程序 enhancer.setUseCache(false) 改为 enhancer.setUseCache(ture)</div><br /><div style="background-color: #eeeeee; font-size: 13px; border: 1px solid #cccccc; padding: 4px 5px 4px 4px; width: 98%;"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;PermgenOOM&nbsp;{<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">static</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;main(String[]&nbsp;args)&nbsp;</span><span style="color: #0000ff;">throws</span><span style="color: #000000;">&nbsp;InterruptedException&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;i</span><span style="color: #000000;">=</span><span style="color: #000000;">0</span><span style="color: #000000;">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">while</span><span style="color: #000000;">(</span><span style="color: #0000ff;">true</span><span style="color: #000000;">){<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Enhancer&nbsp;enhancer&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;Enhancer();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;enhancer.setSuperclass(Product.</span><span style="color: #0000ff;">class</span><span style="color: #000000;">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;enhancer.setUseCache(</span><span style="color: #0000ff;">true</span><span style="color: #000000;">);</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;或者不写，默认值就是true</span><span style="color: #008000;"><br /></span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;enhancer.setCallback(</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;MethodInterceptor()&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@Override<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;Object&nbsp;intercept(Object&nbsp;obj,&nbsp;Method&nbsp;method,&nbsp;Object[]&nbsp;args,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MethodProxy&nbsp;methodproxy)&nbsp;</span><span style="color: #0000ff;">throws</span><span style="color: #000000;">&nbsp;Throwable&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;TODO&nbsp;Auto-generated&nbsp;method&nbsp;stub</span><span style="color: #008000;"><br /></span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;methodproxy.invokeSuper(obj,args);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;});<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;enhancer.create();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Thread.sleep(</span><span style="color: #000000;">100</span><span style="color: #000000;">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />}</span></div><br /><div>内存池peimgen的情况</div><br /><img alt="" src="http://www.blogjava.net/images/blogjava_net/dongbule/permsize/3.jpg" width="851" height="440" /><br /><div>加载类的情况</div><br /><img alt="" src="http://www.blogjava.net/images/blogjava_net/dongbule/permsize/4.jpg" width="392" height="302" /><br /><br /><div>可以发现内存池peimgen和加载类的情况并没有呈现直线上涨，已经他们一直都使用者动态类生成类的静态缓存，但是这种动态创建类使用静态缓存在一些情况下并不适合需求。<br /><br /><font class="Apple-style-span" face="Arial" size="2"><span class="Apple-style-span" style="line-height: 18px;"><br /></span></font></div><img src ="http://www.blogjava.net/dongbule/aggbug/356987.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/dongbule/" target="_blank">陈于喆</a> 2011-08-21 15:55 <a href="http://www.blogjava.net/dongbule/archive/2011/08/21/356987.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java编程中'为了性能'一些尽量做到的地方</title><link>http://www.blogjava.net/dongbule/archive/2011/08/15/356577.html</link><dc:creator>陈于喆</dc:creator><author>陈于喆</author><pubDate>Mon, 15 Aug 2011 08:51:00 GMT</pubDate><guid>http://www.blogjava.net/dongbule/archive/2011/08/15/356577.html</guid><wfw:comment>http://www.blogjava.net/dongbule/comments/356577.html</wfw:comment><comments>http://www.blogjava.net/dongbule/archive/2011/08/15/356577.html#Feedback</comments><slash:comments>12</slash:comments><wfw:commentRss>http://www.blogjava.net/dongbule/comments/commentRss/356577.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/dongbule/services/trackbacks/356577.html</trackback:ping><description><![CDATA[<div><div><br /><br />最近的机器内存又爆满了，出了新增机器内存外，还应该好好review一下我们的代码，有很多代码编写过于随意化，这些不好的习惯或对程序语言的不了解是应该好好打压打压了。</div><div>下面是参考网络资源和总结一些在java编程中尽可能做到的一些地方<br />-</div><div></div><div><strong>1.尽量在合适的场合使用单例</strong></div><div>使用单例可以减轻加载的负担，缩短加载的时间，提高加载的效率，但并不是所有地方都适用于单例，简单来说，单例主要适用于以下三个方面</div><div>第一，控制资源的使用，通过线程同步来控制资源的并发访问</div><div>第二，控制实例的产生，以达到节约资源的目的</div><div>第三，控制数据共享，在不建立直接关联的条件下，让多个不相关的进程或线程之间实现通信<br />-<br /><strong>2.尽量避免随意使用静态变量</strong></div><div>要知道，当某个对象被定义为stataic变量所引用，那么gc通常是不会回收这个对象所占有的内存，如</div><div>public class A{</div><div><span style="white-space: pre;">	</span>static B b = new B();</div><div>}</div><div>此时静态变量b的生命周期与A类同步，如果A类不会卸载，那么b对象会常驻内存，直到程序终止。<br />-</div><div></div><div><strong>3.尽量避免过多过常的创建java对象</strong></div><div>尽量避免在经常调用的方法，循环中new对象，由于系统不仅要花费时间来创建对象，而且还要花时间对这些对象进行垃圾回收和处理，在我们可以控制的范围内，最</div><div></div><div>大限度的重用对象，最好能用基本的数据类型或数组来替代对象。<br /><div>-</div></div><div></div><div><strong>4.尽量使用final修饰符</strong></div><div>带有final修饰符的类是不可派生的。在Java核心API中，有许多应用final的例子，例如java.lang.String。为String类指定final防止了使用者覆盖length()方法。另外，如果一个类是final的，则该类所有方法都是final的。java编译器会寻找机会内联(inline)所有的final方法(这和具体的编译器实现有关)。此举能够使性能平均提高50%。<br /><div>-</div></div><div></div><div><strong>5.尽量使用局部变量</strong></div><div>调用方法时传递的参数以及在调用中创建的临时变量都保存在栈(Stack)中，速度较快。其他变量，如静态变量，实例变量等，都在堆(Heap)中创建，速度较慢。<br />-</div><div></div><div><strong>6.尽量处理好包装类型和基本类型两者的使用场所</strong></div><div>虽然包装类型和基本类型在使用过程中是可以相互转换，但它们两者所产生的内存区域是完全不同的，基本类型数据产生和处理都在栈中处理，包装类型是对象，是在堆中产生实例。</div><div>在集合类对象，有对象方面需要的处理适用包装类型，其他的处理提倡使用基本类型。<br />-</div><div></div><div><strong>7.慎用synchronized，尽量减小synchronize的方法</strong></div><div>都知道，实现同步是要很大的系统开销作为代价的，甚至可能造成死锁，所以尽量避免无谓的同步控制。synchronize方法被调用时，直接会把当前对象锁了，在方法执行完之前其他线程无法调用当前对象的其他方法。所以synchronize的方法尽量小，并且应尽量使用方法同步代替代码块同步。<br />-</div><div></div><div><strong>8.尽量使用StringBuilder和StringBuffer进行字符串连接</strong></div><div>这个就不多讲了<br />-</div><div></div><div><strong>9.尽量不要使用finalize方法</strong></div><div>实际上，将资源清理放在finalize方法中完成是非常不好的选择，由于GC的工作量很大，尤其是回收Young代内存时，大都会引起应用程序暂停，所以再选择使用finalize方法进行资源清理，会导致GC负担更大，程序运行效率更差。<br /><div>-</div></div><div></div><div><strong>10.尽量使用基本数据类型代替对象</strong></div><div>String str = "hello";</div><div>上面这种方式会创建一个&#8220;hello&#8221;字符串，而且JVM的字符缓存池还会缓存这个字符串；</div><div>String str = new String("hello");</div><div>此时程序除创建字符串外，str所引用的String对象底层还包含一个char[]数组，这个char[]数组依次存放了h,e,l,l,o<br /><div>-</div></div><div></div><div><strong>11.单线程应尽量使用HashMap, ArrayList</strong></div><div>HashTable,Vector等使用了同步机制，降低了性能。<br /><div>-</div></div><div></div><div><strong>12.尽量合理的创建HashMap</strong></div><div>当你要创建一个比较大的hashMap时，充分利用另一个构造函数</div><div>public HashMap(int initialCapacity, float loadFactor)</div><div>避免HashMap多次进行了hash重构,扩容是一件很耗费性能的事，在默认中initialCapacity只有16，而loadFactor是0.75，需要多大的容量，你最好能准确的估计你所需要的最佳大小，同样的Hashtable，Vectors也是一样的道理。<br /><div>-</div></div><div></div><div><strong>13.尽量减少对变量的重复计算</strong></div><div>如</div><div>for(int i=0;i&lt;list.size();i++)</div><div>应该改为</div><div>for(int i=0,len=list.size();i&lt;len;i++)</div><div>并且在循环中应该避免使用复杂的表达式，在循环中，循环条件会被反复计算，如果不使用复杂表达式，而使循环条件值不变的话，程序将会运行的更快。&nbsp;<br /><div>-</div></div><div></div><div><strong>14.尽量避免不必要的创建</strong></div><div>如</div><div>A a = new A();</div><div>if(i==1){list.add(a);}</div><div>应该改为</div><div>if(i==1){</div><div>A a = new A();</div><div>list.add(a);}<br /><div>-</div></div><div></div><div><strong>15.尽量在finally块中释放资源</strong></div><div>程序中使用到的资源应当被释放，以避免资源泄漏。这最好在finally块中去做。不管程序执行的结果如何，finally块总是会执行的，以确保资源的正确关闭。&nbsp;<br /><div>-</div></div><div></div><div><strong>16.尽量使用移位来代替'a/b'的操作</strong></div><div>"/"是一个代价很高的操作，使用移位的操作将会更快和更有效</div><div>如</div><div>int num = a / 4;</div><div>int num = a / 8;</div><div>应该改为</div><div>int num = a &gt;&gt; 2;</div><div>int num = a &gt;&gt; 3;</div><div>但注意的是使用移位应添加注释，因为移位操作不直观，比较难理解<br /><div>-</div></div><div></div><div><strong>17.尽量使用移位来代替'a*b'的操作</strong></div><div>同样的，对于'*'操作，使用移位的操作将会更快和更有效</div><div>如</div><div>int num = a * 4;</div><div>int num = a * 8;</div><div>应该改为</div><div>int num = a &lt;&lt; 2;</div><div>int num = a &lt;&lt; 3;<br /><div>-</div></div><div></div><div><strong>18.尽量确定StringBuffer的容量</strong></div><div>StringBuffer的构造器会创建一个默认大小(通常是16)的字符数组。在使用中，如果超出这个大小，就会重新分配内存，创建一个更大的数组，并将原先的数组复制过来，再丢弃旧的数组。在大多数情况下，你可以在创建 StringBuffer的时候指定大小，这样就避免了在容量不够的时候自动增长，以提高性能。&nbsp;</div><div>如：StringBuffer buffer = new StringBuffer(1000); &nbsp;<br /><div>-</div></div><div></div><div><strong>19.尽量早释放无用对象的引用</strong></div><div>大部分时，方法局部引用变量所引用的对象 会随着方法结束而变成垃圾，因此，大部分时候程序无需将局部，引用变量显式设为null。</div><div>例如：</div><div>Public void test(){</div><div>Object obj = new Object();</div><div>&#8230;&#8230;</div><div>Obj=null;</div><div>}</div><div>上面这个就没必要了，随着方法test()的执行完成，程序中obj引用变量的作用域就结束了。但是如果是改成下面：</div><div>Public void test(){</div><div>Object obj = new Object();</div><div>&#8230;&#8230;</div><div>Obj=null;</div><div>//执行耗时，耗内存操作；或调用耗时，耗内存的方法</div><div>&#8230;&#8230;</div><div>}</div><div>这时候就有必要将obj赋值为null，可以尽早的释放对Object对象的引用。<br /><div>-</div></div><div></div><div><strong>20.尽量避免使用二维数组</strong></div><div>二维数据占用的内存空间比一维数组多得多，大概10倍以上。<br /><div>-</div></div><div></div><div><strong>21.尽量避免使用split</strong></div><div>除非是必须的，否则应该避免使用split，split由于支持正则表达式，所以效率比较低，如果是频繁的几十，几百万的调用将会耗费大量资源，如果确实需要频繁的调用split，可以考虑使用apache的StringUtils.split(string,char)，频繁split的可以缓存结果。<br /><div>-</div></div><div></div><div><strong>22.ArrayList &amp; LinkedList</strong></div><div>一个是线性表，一个是链表，一句话，随机查询尽量使用ArrayList，ArrayList优于LinkedList，LinkedList还要移动指针，添加删除的操作LinkedList优于ArrayList，ArrayList还要移动数据，不过这是理论性分析，事实未必如此，重要的是理解好2者得数据结构，对症下药。<br /><div>-</div></div><div></div><div><strong>23.尽量使用System.arraycopy ()代替通过来循环复制数组</strong></div><div>System.arraycopy() 要比通过循环来复制数组快的多&nbsp;<br /><div>-</div></div><div></div><div><strong>24.尽量缓存经常使用的对象</strong></div><div>尽可能将经常使用的对象进行缓存，可以使用数组，或HashMap的容器来进行缓存，但这种方式可能导致系统占用过多的缓存，性能下降，推荐可以使用一些第三方的开源工具，如EhCache，Oscache进行缓存，他们基本都实现了FIFO/FLU等缓存算法。<br /><div>-</div></div><div></div><div><strong>25.尽量避免非常大的内存分配</strong></div><div>有时候问题不是由当时的堆状态造成的，而是因为分配失败造成的。分配的内存块都必须是连续的，而随着堆越来越满，找到较大的连续块越来越困难。<br /><div>-</div></div><div></div><div><strong>26.慎用异常</strong></div><div>当创建一个异常时，需要收集一个栈跟踪(stack track)，这个栈跟踪用于描述异常是在何处创建的。构建这些栈跟踪时需要为运行时栈做一份快照，正是这一部分开销很大。当需要创建一个 Exception 时，JVM 不得不说：先别动，我想就您现在的样子存一份快照，所以暂时停止入栈和出栈操作。栈跟踪不只包含运行时栈中的一两个元素，而是包含这个栈中的每一个元素。</div><div>如果您创建一个 Exception ，就得付出代价。好在捕获异常开销不大，因此可以使用 try-catch 将核心内容包起来。从技术上讲，您甚至可以随意地抛出异常，而不用花费很大的代价。招致性能损失的并不是 throw 操作&#8212;&#8212;尽管在没有预先创建异常的情况下就抛出异常是有点不寻常。真正要花代价的是创建异常。幸运的是，好的编程习惯已教会我们，不应该不管三七二十一就抛出异常。异常是为异常的情况而设计的，使用时也应该牢记这一原则。<br /><br />文章主要是为了抛砖引玉，希望有更多牛人的指点<br /><br />谢谢的&nbsp;<div style="display: inline-block;"></div><span class="Apple-style-span" style="font-family: Verdana,Geneva,Arial,Helvetica,sans-serif; font-size: 13px; line-height: normal; background-color: #f5f5f5;"><a id="AjaxHolder_Comments_CommentList_ctl02_NameLink" target="_blank"><strong>xuanyuan </strong>的建议：</a></span><br />===================================================<br /><span class="Apple-style-span" style="font-family: Verdana,Geneva,Arial,Helvetica,sans-serif; font-size: 13px; line-height: 16px; background-color: #ffffff;">7.慎用synchronized，尽量减小synchronize的方法<br />re：同意，不过文中有个地方说错了，使用synchronized关键字并不一定都是锁定当前对象的，要看具体的锁是什么。如果是在方法上加的synchronized，则是以对象本身为锁的，如果是静态方法则锁的粒度是类。<br />---------------<br />9.尽量不要使用finalize方法<br />re：同意，其实不推荐用finalize方法的根本原因在于，JVM的规范并不保证何时执行该方法，所以用这个方法来释放资源很不合适，有可能造成长时间资源得不到释放。<br />---------------<br />16.尽量使用移位来代替'a/b'的操作；17.尽量使用移位来代替'a*b'的操作<br />re：个人不太同意这两条。这样做确实有更好的性能，但是却牺牲了可读性。这两个操作符对很多程序员来说并不直观。我认为在如今硬件价格不那么昂贵的情况下，略微牺牲一些性能，换来更好的可读性和可维护性是好的选择。<br /></span>===================================================<br /><div><a id="AjaxHolder_Comments_CommentList_ctl09_NameLink" target="_blank"><strong>wuzhengju</strong> 的建议：<br /><div>===================================================</div></a></div><div><span style="font-size: 10pt;">19.尽量早释放无用对象的引用</span><br /><span style="font-size: 10pt;">大部分时，方法局部引用变量所引用的对象 会随着方法结束而变成垃圾，因此，大部分时候程序无需将局部，引用变量显式设为null。</span><br /><span style="font-size: 10pt;">例如：</span><br /><span style="font-size: 10pt;">Public void test(){</span><br /><span style="font-size: 10pt;">Object obj = new Object();</span><br /><span style="font-size: 10pt;">&#8230;&#8230;</span><br /><span style="font-size: 10pt;">Obj=null;</span><br /><span style="font-size: 10pt;">}</span><br /><span style="font-size: 10pt;">上面这个就没必要了，随着方法test()的执行完成，程序中obj引用变量的作用域就结束了。但是如果是改成下面：</span><br /><span style="font-size: 10pt;">Public void test(){</span><br /><span style="font-size: 10pt;">Object obj = new Object();</span><br /><span style="font-size: 10pt;">&#8230;&#8230;</span><br /><span style="font-size: 10pt;">Obj=null;</span><br /><span style="font-size: 10pt;">//执行耗时，耗内存操作；或调用耗时，耗内存的方法</span><br /><span style="font-size: 10pt;">&#8230;&#8230;</span><br /><span style="font-size: 10pt;">}   </span><br /><span style="font-size: 10pt;">如果Object obj = new Object();  如果这对象并不是大对象，这有必要吗？Obj=null;只是告诉jvm这个对象已经成为垃圾，至于什么时候回收，还不能确定！   这可读性也不好！</span></div><div>===================================================</div></div><div></div></div><img src ="http://www.blogjava.net/dongbule/aggbug/356577.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/dongbule/" target="_blank">陈于喆</a> 2011-08-15 16:51 <a href="http://www.blogjava.net/dongbule/archive/2011/08/15/356577.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>说说MongoDB的ObjectId</title><link>http://www.blogjava.net/dongbule/archive/2011/06/12/352138.html</link><dc:creator>陈于喆</dc:creator><author>陈于喆</author><pubDate>Sun, 12 Jun 2011 10:30:00 GMT</pubDate><guid>http://www.blogjava.net/dongbule/archive/2011/06/12/352138.html</guid><wfw:comment>http://www.blogjava.net/dongbule/comments/352138.html</wfw:comment><comments>http://www.blogjava.net/dongbule/archive/2011/06/12/352138.html#Feedback</comments><slash:comments>8</slash:comments><wfw:commentRss>http://www.blogjava.net/dongbule/comments/commentRss/352138.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/dongbule/services/trackbacks/352138.html</trackback:ping><description><![CDATA[<div>前段时间有个朋友问我，分布式主键生成策略在我们这边是怎么实现的，当时我给的答案是sequence，当然这在不高并发的情况下是没有任何问题，实际上，我们的主键生成是可控的，但如果是在分布式高并发的情况下，那肯定是有问题的。<br /><br />突然想起mongodb的objectid，记得以前看过文档，objectid是一种轻量型的，不同的机器都能用全局唯一的同种方法轻量的生成它，而不是采用传统的自增的主键策略，因为在多台服务器上同步自动增加主键既费力又费时，不得不佩服，mongodb从开始设计就被定义为分布式数据库。<br />下面深入一点来翻翻这个Objectid的底细，在mongodb集合中的每个document中都必须有一个"_id"建，这个键的值可以是任何类型的，在默认的情况下是个Objectid对象。<br />当我们让一个collection中插入一条不带_id的记录，系统会自动地生成一个_id的key</div><br /><div style="background-color: #eeeeee; font-size: 13px; border: 1px solid #cccccc; padding: 4px 5px 4px 4px; width: 98%;"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000;">&gt;&nbsp;db.t_test.insert({"name":"cyz"})<br />&gt;&nbsp;db.t_test.findOne({"name":"cyz"})<br />{&nbsp;"_id"&nbsp;:&nbsp;ObjectId("4df2dcec2cdcd20936a8b817"),&nbsp;"name"&nbsp;:&nbsp;"cyz"&nbsp;}</span></div><br /><div>可以发现这里多出一个Objectid类型的_id，当然了，这个_id是系统默认生成的，你也可以为其指定一个值，不过在同一collections中该值必须是唯一的<br /><br />把 ObjectId("4df2dcec2cdcd20936a8b817")这串值拿出来并对照官网的解析来深入分析。<br /><br />"4df2dcec2cdcd20936a8b817" 以这段字符串为例来进行解析，这是一个24位的字符串，看起来很长，很难理解，实际上它是由ObjectId(string)所创建的一组十六进制的字符，每个字节两位的十六进制数字，总共使用了12字节的存储空间，可能有些朋友会感到很奇怪，居然是用了12个字节，而mysql的INT类型也只有4个字节，不过按照现在的存储设备，多出来的这点字节也应该不会成为什么瓶颈，实际上，mongodb在设计上无处不在的体现着用空间换时间的思想，接下看吧<br /><br />下面是官网指定Bson中ObjectId的详细规范<br /><br /><img alt="" src="http://www.blogjava.net/images/blogjava_net/dongbule/46046/o_111.PNG" /><br /><br /><div><strong>TimeStamp</strong><br />前4位是一个unix的时间戳，是一个int类别，我们将上面的例子中的objectid的前4位进行提取&#8220;4df2dcec&#8221;，然后再将他们安装十六进制专为十进制：&#8220;1307761900&#8221;，这个数字就是一个时间戳，为了让效果更佳明显，我们将这个时间戳转换成我们习惯的时间格式</div><br /><div style="background-color: #eeeeee; font-size: 13px; border: 1px solid #cccccc; padding: 4px 5px 4px 4px; width: 98%;"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000;">$&nbsp;date&nbsp;-d&nbsp;'1970-01-01&nbsp;UTC&nbsp;1307761900&nbsp;&nbsp;sec'&nbsp;&nbsp;-u<br />2011年&nbsp;06月&nbsp;11日&nbsp;星期六&nbsp;03:11:40&nbsp;UTC</span></div><br /><div>前4个字节其实隐藏了文档创建的时间，并且时间戳处在于字符的最前面，这就意味着ObjectId大致会按照插入进行排序，这对于某些方面起到很大作用，如作为索引提高搜索效率等等。使用时间戳还有一个好处是，某些客户端驱动可以通过ObjectId解析出该记录是何时插入的，这也解答了我们平时快速连续创建多个Objectid时，会发现前几位数字很少发现变化的现实，因为使用的是当前时间，很多用户担心要对服务器进行时间同步，其实这个时间戳的真实值并不重要，只要其总不停增加就好。</div><br /><div><strong>Machine </strong><br />接下来的三个字节，就是 2cdcd2 ,这三个字节是所在主机的唯一标识符，一般是机器主机名的散列值，这样就确保了不同主机生成不同的机器hash值，确保在分布式中不造成冲突，这也就是在同一台机器生成的objectid中间的字符串都是一模一样的原因。<br /><br /><strong>pid</strong><br />上面的Machine是为了确保在不同机器产生的objectid不冲突，而pid就是为了在同一台机器不同的mongodb进程产生了objectid不冲突，接下来的0936两位就是产生objectid的进程标识符。<br /><br /><strong>increment</strong><br />前面的九个字节是保证了一秒内不同机器不同进程生成objectid不冲突，这后面的三个字节a8b817，是一个自动增加的计数器，用来确保在同一秒内产生的objectid也不会发现冲突，允许256的3次方等于16777216条记录的唯一性。</div><br /><div><strong>客户端生成</strong><br />mongodb产生objectid还有一个更大的优势，就是mongodb可以通过自身的服务来产生objectid，也可以通过客户端的驱动程序来产生，如果你仔细看文档你会感叹，mongodb的设计无处不在的使<br /><br />用空间换时间的思想，比较objectid是轻量级，但服务端产生也必须开销时间，所以能从服务器转移到客户端驱动程序完成的就尽量的转移，必须将事务扔给客户端来完成，减低服务端的开销，另还有一点原因就是扩展应用层比扩展数据库层要变量得多。<br /><br />好吧，既然我们了解到我们的程序产生objectid是在客户端完成，那再继续，进一步了解，打开<strong>mongodb java driver源码</strong>，无源码可以到mongodb官网进行下载，下面摘录部分代码<br /><br /><div style="background-color: #eeeeee; font-size: 13px; border: 1px solid #cccccc; padding: 4px 5px 4px 4px; width: 98%;"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;ObjectId&nbsp;</span><span style="color: #0000ff;">implements</span><span style="color: #000000;">&nbsp;Comparable</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">ObjectId</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">&nbsp;,&nbsp;java.io.Serializable&nbsp;{<br /><img src="http://www.blogjava.net/Images/dot.gif"  alt="" /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">final</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;_time;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">final</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;_machine;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">final</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;_inc;<br /><img src="http://www.blogjava.net/Images/dot.gif"  alt="" /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;ObjectId(&nbsp;</span><span style="color: #0000ff;">byte</span><span style="color: #000000;">[]&nbsp;b&nbsp;){<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(&nbsp;b.length&nbsp;</span><span style="color: #000000;">!=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">12</span><span style="color: #000000;">&nbsp;)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">throw</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;IllegalArgumentException(&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">need&nbsp;12&nbsp;bytes</span><span style="color: #000000;">"</span><span style="color: #000000;">&nbsp;);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ByteBuffer&nbsp;bb&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;ByteBuffer.wrap(&nbsp;b&nbsp;);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_time&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;bb.getInt();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_machine&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;bb.getInt();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_inc&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;bb.getInt();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_new&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">false</span><span style="color: #000000;">;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;ObjectId(&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;time&nbsp;,&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;machine&nbsp;,&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;inc&nbsp;){<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_time&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;time;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_machine&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;machine;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_inc&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;inc;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_new&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">false</span><span style="color: #000000;">;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;ObjectId(){<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_time&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;(</span><span style="color: #0000ff;">int</span><span style="color: #000000;">)&nbsp;(System.currentTimeMillis()&nbsp;</span><span style="color: #000000;">/</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">1000</span><span style="color: #000000;">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_machine&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;_genmachine;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_inc&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;_nextInc.getAndIncrement();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_new&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">true</span><span style="color: #000000;">;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br /><img src="http://www.blogjava.net/Images/dot.gif"  alt="" /><br />（完整代码请查看源码）</span></div><br /><div>这里可以发现ObjectId的构建可以有多种方式，可以由自己制定字节，也可以指定时间，机器码和自增值，这里重点看看驱动程序默认的构建，也就是public ObjectId()<br />可以看到objectid主要由_time _machine _inc 所组成，其中 _time直接由(System.currentTimeMillis() / 1000)计算出所谓的时间戳，这里很简单，接下来是重点，主要看看<strong>机器码和进程码</strong>的构建</div></div><br /><div style="background-color: #eeeeee; font-size: 13px; border: 1px solid #cccccc; padding: 4px 5px 4px 4px; width: 98%;"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">private</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">static</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">final</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;_genmachine;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">static</span><span style="color: #000000;">&nbsp;{<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">try</span><span style="color: #000000;">&nbsp;{</span><span style="color: #008000;"><br /></span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">final</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;machinePiece;</span><span style="color: #008000;">//</span><span style="color: #008000;">机器码块</span><span style="color: #008000;"><br /></span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;StringBuilder&nbsp;sb&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;StringBuilder();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Enumeration</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">NetworkInterface</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">&nbsp;e&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;NetworkInterface.getNetworkInterfaces();</span><span style="color: #008000;">//</span><span style="color: #008000;">NetworkInterface此类表示一个由名称和分配给此接口的&nbsp;IP&nbsp;地址列表组成的网络接口，它用于标识将多播组加入的本地接口，这里通过NetworkInterface此机器上所有的接口</span><span style="color: #008000;"><br /></span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">while</span><span style="color: #000000;">&nbsp;(&nbsp;e.hasMoreElements()&nbsp;){<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NetworkInterface&nbsp;ni&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;e.nextElement();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sb.append(&nbsp;ni.toString()&nbsp;);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;machinePiece&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;sb.toString().hashCode()&nbsp;</span><span style="color: #000000;">&lt;&lt;</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">16</span><span style="color: #000000;">;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">将得到所有接口的字符串进行取散列值</span><span style="color: #008000;"><br /></span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;LOGGER.fine(&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">machine&nbsp;piece&nbsp;post:&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;Integer.toHexString(&nbsp;machinePiece&nbsp;)&nbsp;);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span><span style="color: #008000;"><br /></span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">final</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;processPiece;</span><span style="color: #008000;">//</span><span style="color: #008000;">进程块</span><span style="color: #008000;"><br /></span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;processId&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;java.util.Random().nextInt();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">try</span><span style="color: #000000;">&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;processId&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;java.lang.management.ManagementFactory.getRuntimeMXBean().getName().hashCode();</span><span style="color: #008000;">//</span><span style="color: #008000;">RuntimeMXBean是Java虚拟机的运行时系统的管理接口，这里是返回表示正在运行的&nbsp;Java&nbsp;虚拟机的名称，并进行取散列值。</span><span style="color: #008000;"><br /></span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">catch</span><span style="color: #000000;">&nbsp;(&nbsp;Throwable&nbsp;t&nbsp;){<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ClassLoader&nbsp;loader&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;ObjectId.</span><span style="color: #0000ff;">class</span><span style="color: #000000;">.getClassLoader();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;loaderId&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;loader&nbsp;</span><span style="color: #000000;">!=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">null</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">?</span><span style="color: #000000;">&nbsp;System.identityHashCode(loader)&nbsp;:&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;StringBuilder&nbsp;sb&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;StringBuilder();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sb.append(Integer.toHexString(processId));<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sb.append(Integer.toHexString(loaderId));<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;processPiece&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;sb.toString().hashCode()&nbsp;</span><span style="color: #000000;">&amp;</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">0xFFFF</span><span style="color: #000000;">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;LOGGER.fine(&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">process&nbsp;piece:&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;Integer.toHexString(&nbsp;processPiece&nbsp;)&nbsp;);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_genmachine&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;machinePiece&nbsp;</span><span style="color: #000000;">|</span><span style="color: #000000;">&nbsp;processPiece;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">最后将机器码块的散列值与进程块的散列值进行位或运算，得到&nbsp;_genmachine&nbsp;</span><span style="color: #008000;"><br /></span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;LOGGER.fine(&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">machine&nbsp;:&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;Integer.toHexString(&nbsp;_genmachine&nbsp;)&nbsp;);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">catch</span><span style="color: #000000;">&nbsp;(&nbsp;java.io.IOException&nbsp;ioe&nbsp;){<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">throw</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;RuntimeException(&nbsp;ioe&nbsp;);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;}</span></div></div><br /><div><strong>&nbsp;Enumeration&lt;NetworkInterface&gt; e = NetworkInterface.getNetworkInterfaces();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while ( e.hasMoreElements() ){<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; NetworkInterface ni = e.nextElement();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sb.append( ni.toString() );<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;machinePiece = sb.toString().hashCode() &lt;&lt; 16;</strong><br />这里的NetworkInterface.getNetworkInterfaces();取得的接口通常是按名称（如 "le0"）区分的，大约是下面的类型</div><br /><div style="background-color: #eeeeee; font-size: 13px; border: 1px solid #cccccc; padding: 4px 5px 4px 4px; width: 98%;"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000;">name:lo&nbsp;(Software&nbsp;Loopback&nbsp;Interface&nbsp;</span><span style="color: #000000;">1</span><span style="color: #000000;">)&nbsp;index:&nbsp;</span><span style="color: #000000;">1</span><span style="color: #000000;">&nbsp;addresses:<br /></span><span style="color: #000000;">/</span><span style="color: #000000;">0</span><span style="color: #000000;">:</span><span style="color: #000000;">0</span><span style="color: #000000;">:</span><span style="color: #000000;">0</span><span style="color: #000000;">:</span><span style="color: #000000;">0</span><span style="color: #000000;">:</span><span style="color: #000000;">0</span><span style="color: #000000;">:</span><span style="color: #000000;">0</span><span style="color: #000000;">:</span><span style="color: #000000;">0</span><span style="color: #000000;">:</span><span style="color: #000000;">1</span><span style="color: #000000;">;<br /></span><span style="color: #000000;">/</span><span style="color: #000000;">127.0</span><span style="color: #000000;">.</span><span style="color: #000000;">0.1</span><span style="color: #000000;">;<br />name:net0&nbsp;(WAN&nbsp;Miniport&nbsp;(SSTP))&nbsp;index:&nbsp;</span><span style="color: #000000;">2</span><span style="color: #000000;">&nbsp;addresses:<br />name:net1&nbsp;(WAN&nbsp;Miniport&nbsp;(IKEv2))&nbsp;index:&nbsp;</span><span style="color: #000000;">3</span><span style="color: #000000;">&nbsp;addresses:<br />name:net2&nbsp;(WAN&nbsp;Miniport&nbsp;(L2TP))&nbsp;index:&nbsp;</span><span style="color: #000000;">4</span><span style="color: #000000;">&nbsp;addresses:<br />name:net3&nbsp;(WAN&nbsp;Miniport&nbsp;(PPTP))&nbsp;index:&nbsp;</span><span style="color: #000000;">5</span><span style="color: #000000;">&nbsp;addresses:<br />name:ppp0&nbsp;(WAN&nbsp;Miniport&nbsp;(PPPOE))&nbsp;index:&nbsp;</span><span style="color: #000000;">6</span><span style="color: #000000;">&nbsp;addresses:</span></div><br /><div>这里为什么要采取这样方面进行取散列值，感觉有些不太理解，应该网络接口本身相对而言是并不稳定的<br /><br /><div><strong>int processId = new java.util.Random().nextInt();<br />&nbsp;try {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; processId = java.lang.management.ManagementFactory.getRuntimeMXBean().getName().hashCode();<br />&nbsp;}<br />&nbsp;catch ( Throwable t ){<br />}</strong><br />RuntimeMXBean是Java虚拟机的运行时系统的管理接口，这里是返回表示正在运行的 Java 虚拟机的名称，并进行取散列值，如果在这过程中出现异常，processId 将以随机数的方式继续计算<br /><br /><strong>_genmachine = machinePiece | processPiece;</strong><br /><div>最后将机器码块的散列值与进程块的散列值进行位或运算，当然这里是十进制，你把这里的十进制专为十六进制，就会发现这块的值就是生产objectid中间部分的值，这里的构建跟服务端的构建是有些不一样的，不过最基本的构建元素还是一致的，就是<strong>TimeStamp，Machine ，pid，increment</strong>。<br /><br />mongodb的ObejctId生产思想在很多方面挺值得我们借鉴的，特别是在大型分布式的开发，如何构建轻量级的生产，如何将生产的负载进行转移，如何以空间换取时间提高生产的最大优化等等。</div></div>----------------------------------------<br />  <br />  by 陈于喆 <br />  QQ:34174409<br />  Mail: dongbule@163.com<br /></div><img src ="http://www.blogjava.net/dongbule/aggbug/352138.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/dongbule/" target="_blank">陈于喆</a> 2011-06-12 18:30 <a href="http://www.blogjava.net/dongbule/archive/2011/06/12/352138.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>解答一下几道笔试题</title><link>http://www.blogjava.net/dongbule/archive/2011/04/21/348723.html</link><dc:creator>陈于喆</dc:creator><author>陈于喆</author><pubDate>Thu, 21 Apr 2011 09:23:00 GMT</pubDate><guid>http://www.blogjava.net/dongbule/archive/2011/04/21/348723.html</guid><wfw:comment>http://www.blogjava.net/dongbule/comments/348723.html</wfw:comment><comments>http://www.blogjava.net/dongbule/archive/2011/04/21/348723.html#Feedback</comments><slash:comments>9</slash:comments><wfw:commentRss>http://www.blogjava.net/dongbule/comments/commentRss/348723.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/dongbule/services/trackbacks/348723.html</trackback:ping><description><![CDATA[有朋友去一家大型的互联网公司参加了java程序员的笔试，抄下了一些笔试题，可能有的抄的并不全，试了解答一下，有些还真的答不出来<br />
<br />
&nbsp;&nbsp;&nbsp; 1.cookie和session的作用以及他们的应用场合<br />
&nbsp;&nbsp;&nbsp; 2.怎样让jvm加载一个Class的同时执行一段代码<br />
&nbsp;&nbsp;&nbsp; 3.post和get区别<br />
&nbsp;&nbsp;&nbsp; 4.事务的属性有哪些？写出spring或jdbc管理事务的例子<br />
&nbsp;&nbsp;&nbsp; 5.实现一个高并发、高性能的hashmap。写出伪代码<br />
&nbsp;&nbsp;&nbsp; 6.解析一段xml，拼接成一个url。<br />
&nbsp;&nbsp;&nbsp; 7.怎么解决并发？怎么解决集群环境下的并发?<br />
&nbsp;&nbsp;&nbsp; 8.java GC的原理.<br />
&nbsp;&nbsp;&nbsp; 9.mysql支持事务吗？mysql存储引擎有哪些？<br />
&nbsp;&nbsp;&nbsp; 10.数据库数据查找比较慢的时候，如何解决？<br />
&nbsp;&nbsp;&nbsp; 11.学生 课程 选课的一个sql语句书写<br />
&nbsp;&nbsp;&nbsp; 12.查找日志文件中某一个信息出现的次数<br />
&nbsp;&nbsp;&nbsp; 13.32位linux操作系统中，最多支持多少个线程？<br />
&nbsp;&nbsp;&nbsp; 14.关于TreeMap操作的<br />
&nbsp;&nbsp;&nbsp; 15.重写类A的equals和hascode方法。类A有个属性private B b；<br />
&nbsp;&nbsp;&nbsp; 16.实现一个mysql的sequence。<br />
<br />
下面是我的一点解答，也不知道对不对，现在的笔试要你白纸黑字写出这些东西真是难啊！<br />
<br />
<strong>1)cookie和session的作用以及他们的应用场合</strong><br />
两者都是记录用户访问网站信息，但他们的保持状态不同，cookie是采用客户端保持，而session是采用服务端保持，一般来说cookie不是很安全，因为别人可以分析本地的cookie进行cookie欺骗，考虑到安全的问题应该使用session，session是保持在服务端，但当访问增多时，会增加服务器的压力。<br />
在应用场合中，建议建用户登录，交易重要信息存放session，其他信息可以存放在cookie中，根据实际需求两者可以交替搭配使用。<br />
<br />
<strong>2)怎样让jvm加载一个Class的同时执行一段代码</strong><br />
使用Class.forName()动态加载类（题目中有"同时"，是否启用另一线程？）<br />
<br />
<strong>3)post和get区别</strong><br />
从http动词协议来看，get是从服务器获取数据，post是向服务器上传数据<br />
get方式会把数据出现在url中，post则不会<br />
get提交的数据有大小限制，post则无<br />
<br />
<strong>4)事务的属性有哪些？写出spring或jdbc管理事务的例子</strong><br />
有原子性，一致性，隔离性，持久性<br />
spring提供了丰富的事务模型，主要是针对jdbc事务，jta事务，还有一些自定义事务（如果有人能从一张白纸写出spring transaction的例子，那真是佩服之极）<br />
还是写一个简单jdbc事务<br />
try{<br />
class.forName("***");<br />
...<br />
conn=DriverManager.getConnection(url,user,password);<br />
conn.createStartement().executeUpdate("****");//更新操作<br />
conn.commit();//事务提交<br />
}catch(Exception e){<br />
..<br />
conn.rollback();//事务回滚<br />
..<br />
}<br />
<br />
<strong>5)实现一个高并发、高性能的hashmap。写出伪代码</strong><br />
什么叫做高性能，高并发的hashmap? 是要考hashmap的数据结构??<br />
<br />
<strong>6)解析一段xml，拼接成一个url</strong><br />
xml,url???这两者有什么联系吗?<br />
<br />
<strong>7)怎么解决并发？怎么解决集群环境下的并发?</strong><br />
（有很多点可以并发，web请求可以并发，数据库请求可以并发，怎么那么空泛）<br />
高并发最重要的还是考虑到锁的问题，如数据库该用表锁用表锁，该用排他锁用排它锁，程序中要注意非线程安全的问题<br />
高并发还有带来性能问题，缓存，负载均衡，这些看情况而定<br />
<br />
<strong>8)java GC的原理.</strong><br />
又来，不回答你<br />
<br />
<strong>9)mysql支持事务吗？mysql存储引擎有哪些？</strong><br />
支持，常用的是inndb和myisam<br />
<br />
<strong>10)数据库数据查找比较慢的时候，如何解决？</strong><br />
假如是mysql<br />
1.漏了索引,用explain看看查询语句是不是没使用索引或者索引使用有问题<br />
2.使用show processlist看看是不是有sql卡住了<br />
3.还有一种情况就是sql写得过于复杂，如goroupby，多表关联等等，使用desc来进行分析<br />
4.还有就是配置的问题，如key_buffer等参数，这个看文档吧<br />
5.最后一种就是机器负荷过高，调整结构来解决吧，比如使用mysql-proxy代理等等<br />
<br />
<strong>11)学生 课程 选课的一个sql语句书写</strong><br />
??<br />
<br />
<strong>12)查找日志文件中某一个信息出现的次数</strong><br />
cat 日志 | grep 信息 | wc -l<br />
<br />
<strong>13) 32位linux操作系统中，最多支持多少个线程？</strong><br />
上网查了，写得很复杂，附上文章<br />
http://www.517sou.net/Article/Linux-maximum-number-of-threads-and-the-maximum-number-of-processes.aspx<br />
<br />
<strong>14)关于TreeMap操作的</strong><br />
TreeMap就是一颗平衡排序二叉树，操作的。。后面是什么??<br />
<br />
<strong>15)重写类A的equals和hascode方法。类A有个属性private B b；</strong><br />
??<br />
<br />
<strong>16)实现一个mysql的sequence</strong><br />
mysql的last_insert_id()大致可以满足，如果不行就写触发器吧<br />
<br />
<img src ="http://www.blogjava.net/dongbule/aggbug/348723.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/dongbule/" target="_blank">陈于喆</a> 2011-04-21 17:23 <a href="http://www.blogjava.net/dongbule/archive/2011/04/21/348723.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>制定hessian服务端的访问列表</title><link>http://www.blogjava.net/dongbule/archive/2010/12/21/341246.html</link><dc:creator>陈于喆</dc:creator><author>陈于喆</author><pubDate>Tue, 21 Dec 2010 08:05:00 GMT</pubDate><guid>http://www.blogjava.net/dongbule/archive/2010/12/21/341246.html</guid><wfw:comment>http://www.blogjava.net/dongbule/comments/341246.html</wfw:comment><comments>http://www.blogjava.net/dongbule/archive/2010/12/21/341246.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/dongbule/comments/commentRss/341246.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/dongbule/services/trackbacks/341246.html</trackback:ping><description><![CDATA[由于历史原因,几个项目都选用hessian作为web service的实现方式,hessian的确是非常轻量级,基于http协议进行传输,通过自定义的串行化机制将请求信息进行序列化,以二进制传输节省了不少的开销,速度跟socket差不多.客户端和服务器发起和接收请求都是通过spring提供的hessian api进行请求和接收,但是在服务端中并没有记录和控制远端ip地址和主机的信息,所以需要对源码进行一些重写<br />
<br />
对org.springframework.remoting.caucho.HessianServiceExporter进行重写<br />
<br />
<div style="background-color: rgb(238, 238, 238); font-size: 13px; border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: rgb(0, 128, 0);">/**</span><span style="color: rgb(0, 128, 0);"><br />
&nbsp;*&nbsp;重写HessianServiceExporter.handleRequest(),拦截获取远端调用信息<br />
&nbsp;*&nbsp;</span><span style="color: rgb(128, 128, 128);">@author</span><span style="color: rgb(0, 128, 0);">&nbsp;chenyz<br />
&nbsp;*<br />
&nbsp;</span><span style="color: rgb(0, 128, 0);">*/</span><span style="color: rgb(0, 0, 0);"><br />
</span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">class</span><span style="color: rgb(0, 0, 0);">&nbsp;HouseHessianServiceExporter&nbsp;</span><span style="color: rgb(0, 0, 255);">extends</span><span style="color: rgb(0, 0, 0);">&nbsp;HessianServiceExporter&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">private</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">static</span><span style="color: rgb(0, 0, 0);">&nbsp;String[]&nbsp;entryIP&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;{</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">192.168.0.1</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">,</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">192.168.0.3</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">,</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">192.168.0.3</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">};<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">private</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">static</span><span style="color: rgb(0, 0, 0);">&nbsp;Log&nbsp;log&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;LogFactory.getLog(</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">Myremote</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">);&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;@Override<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);">&nbsp;handleRequest(HttpServletRequest&nbsp;request,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;HttpServletResponse&nbsp;response)&nbsp;</span><span style="color: rgb(0, 0, 255);">throws</span><span style="color: rgb(0, 0, 0);">&nbsp;ServletException,&nbsp;IOException&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;log.info(</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">try&nbsp;==&gt;remote&nbsp;'s&nbsp;IP:</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">+</span><span style="color: rgb(0, 0, 0);">IpUtil.getIpAddr(request)</span><span style="color: rgb(0, 0, 0);">+</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">remote&nbsp;'s&nbsp;host:&nbsp;</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">+</span><span style="color: rgb(0, 0, 0);">request.getRemoteHost());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);">&nbsp;call&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">0</span><span style="color: rgb(0, 0, 0);">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">for</span><span style="color: rgb(0, 0, 0);">(String&nbsp;ip:entryIP){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);">(ip.equals(IpUtil.getIpAddr(request)))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;call</span><span style="color: rgb(0, 0, 0);">++</span><span style="color: rgb(0, 0, 0);">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);">(call</span><span style="color: rgb(0, 0, 0);">&gt;</span><span style="color: rgb(0, 0, 0);">0</span><span style="color: rgb(0, 0, 0);">){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;log.info(</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">call&nbsp;==&gt;remote&nbsp;'s&nbsp;IP:</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">+</span><span style="color: rgb(0, 0, 0);">IpUtil.getIpAddr(request)</span><span style="color: rgb(0, 0, 0);">+</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">remote&nbsp;'s&nbsp;host:&nbsp;</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">+</span><span style="color: rgb(0, 0, 0);">request.getRemoteHost());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">super</span><span style="color: rgb(0, 0, 0);">.handleRequest(request,&nbsp;response);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
}</span></div>
<br />
<div style="background-color: rgb(238, 238, 238); font-size: 13px; border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">&lt;</span><span style="color: rgb(128, 0, 0);">bean&nbsp;</span><span style="color: rgb(255, 0, 0);">id</span><span style="color: rgb(0, 0, 255);">="shineLibWSImpl"</span><span style="color: rgb(255, 0, 0);">&nbsp;class</span><span style="color: rgb(0, 0, 255);">="com.***.shine.remote.ShineLibWSImpl"</span><span style="color: rgb(0, 0, 255);">/&gt;</span><span style="color: rgb(0, 0, 0);"><br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">&lt;</span><span style="color: rgb(128, 0, 0);">bean&nbsp;</span><span style="color: rgb(255, 0, 0);">name</span><span style="color: rgb(0, 0, 255);">="/remote/shineinfo"</span><span style="color: rgb(255, 0, 0);">&nbsp;class</span><span style="color: rgb(0, 0, 255);">="com.***.shine.hessian.service.HouseHessianServiceExporter"</span><span style="color: rgb(0, 0, 255);">&gt;</span><span style="color: rgb(0, 0, 0);"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">&lt;</span><span style="color: rgb(128, 0, 0);">property&nbsp;</span><span style="color: rgb(255, 0, 0);">name</span><span style="color: rgb(0, 0, 255);">="service"</span><span style="color: rgb(0, 0, 255);">&gt;</span><span style="color: rgb(0, 0, 0);"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">&lt;</span><span style="color: rgb(128, 0, 0);">ref&nbsp;</span><span style="color: rgb(255, 0, 0);">bean</span><span style="color: rgb(0, 0, 255);">="shineLibWSImpl"</span><span style="color: rgb(0, 0, 255);">/&gt;</span><span style="color: rgb(0, 0, 0);"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">&lt;/</span><span style="color: rgb(128, 0, 0);">property</span><span style="color: rgb(0, 0, 255);">&gt;</span><span style="color: rgb(0, 0, 0);"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">&lt;</span><span style="color: rgb(128, 0, 0);">property&nbsp;</span><span style="color: rgb(255, 0, 0);">name</span><span style="color: rgb(0, 0, 255);">="serviceInterface"</span><span style="color: rgb(0, 0, 255);">&gt;</span><span style="color: rgb(0, 0, 0);"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">&lt;</span><span style="color: rgb(128, 0, 0);">value</span><span style="color: rgb(0, 0, 255);">&gt;</span><span style="color: rgb(0, 0, 0);">com.***.shine.remote.ShineLibWebService</span><span style="color: rgb(0, 0, 255);">&lt;/</span><span style="color: rgb(128, 0, 0);">value</span><span style="color: rgb(0, 0, 255);">&gt;</span><span style="color: rgb(0, 0, 0);"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">&lt;/</span><span style="color: rgb(128, 0, 0);">property</span><span style="color: rgb(0, 0, 255);">&gt;</span><span style="color: rgb(0, 0, 0);"><br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">&lt;/</span><span style="color: rgb(128, 0, 0);">bean</span><span style="color: rgb(0, 0, 255);">&gt;</span></div>
<br />
重写HessianServiceExporter.handleRequest(),拦截获取远端调用信息,提取出调用端的ip信息与服务端制定的ip列表进行对比,并将所有调用信息记录日志<br />
<br />
如果直接使用hessian的api的HessianServlet,直接对HessianServlet的service()重写,拦截并提取远端调用信息<br />
<br />
<div style="background-color: rgb(238, 238, 238); font-size: 13px; border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: rgb(0, 128, 0);">/**</span><span style="color: rgb(0, 128, 0);"><br />
&nbsp;*&nbsp;重写HouseHessianServlet.service(),拦截获取远端调用信息<br />
&nbsp;*&nbsp;</span><span style="color: rgb(128, 128, 128);">@author</span><span style="color: rgb(0, 128, 0);">&nbsp;chenyz<br />
&nbsp;*<br />
&nbsp;</span><span style="color: rgb(0, 128, 0);">*/</span><span style="color: rgb(0, 0, 0);"><br />
</span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">class</span><span style="color: rgb(0, 0, 0);">&nbsp;HouseHessianServlet&nbsp;</span><span style="color: rgb(0, 0, 255);">extends</span><span style="color: rgb(0, 0, 0);">&nbsp;HessianServlet{<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">private</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">static</span><span style="color: rgb(0, 0, 0);">&nbsp;String[]&nbsp;entryIP&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;{</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">192.168.0.1</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">,</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">192.168.0.3</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">,</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">192.168.0.3</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">};<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">private</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">static</span><span style="color: rgb(0, 0, 0);">&nbsp;Log&nbsp;log&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;LogFactory.getLog(</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">Myremote</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">);&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;@Override<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);">&nbsp;service(ServletRequest&nbsp;request,&nbsp;ServletResponse&nbsp;response)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">throws</span><span style="color: rgb(0, 0, 0);">&nbsp;IOException,&nbsp;ServletException&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;HttpServletRequest&nbsp;req&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;(HttpServletRequest)&nbsp;request;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;log.info(</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">try&nbsp;==&gt;remote&nbsp;'s&nbsp;IP:</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">+</span><span style="color: rgb(0, 0, 0);">IpUtil.getIpAddr(req)</span><span style="color: rgb(0, 0, 0);">+</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">remote&nbsp;'s&nbsp;host:&nbsp;</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">+</span><span style="color: rgb(0, 0, 0);">request.getRemoteHost());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);">&nbsp;call&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">0</span><span style="color: rgb(0, 0, 0);">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">for</span><span style="color: rgb(0, 0, 0);">(String&nbsp;ip:entryIP){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);">(ip.equals(IpUtil.getIpAddr(request)))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;call</span><span style="color: rgb(0, 0, 0);">++</span><span style="color: rgb(0, 0, 0);">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);">(call</span><span style="color: rgb(0, 0, 0);">&gt;</span><span style="color: rgb(0, 0, 0);">0</span><span style="color: rgb(0, 0, 0);">){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;log.info(</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">call&nbsp;==&gt;remote&nbsp;'s&nbsp;IP:</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">+</span><span style="color: rgb(0, 0, 0);">IpUtil.getIpAddr(req)</span><span style="color: rgb(0, 0, 0);">+</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">remote&nbsp;'s&nbsp;host:&nbsp;</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">+</span><span style="color: rgb(0, 0, 0);">request.getRemoteHost());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">super</span><span style="color: rgb(0, 0, 0);">.service(request,&nbsp;response);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
}</span></div>
<br />
web.xml<br />
<br />
<div style="background-color: rgb(238, 238, 238); font-size: 13px; border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">&lt;</span><span style="color: rgb(128, 0, 0);">servlet</span><span style="color: rgb(0, 0, 255);">&gt;</span><span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">&lt;</span><span style="color: rgb(128, 0, 0);">servlet-name</span><span style="color: rgb(0, 0, 255);">&gt;</span><span style="color: rgb(0, 0, 0);">HessianServlet</span><span style="color: rgb(0, 0, 255);">&lt;/</span><span style="color: rgb(128, 0, 0);">servlet-name</span><span style="color: rgb(0, 0, 255);">&gt;</span><span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">&lt;</span><span style="color: rgb(128, 0, 0);">servlet-class</span><span style="color: rgb(0, 0, 255);">&gt;</span><span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;com.***.product.remote.Htest<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">&lt;/</span><span style="color: rgb(128, 0, 0);">servlet-class</span><span style="color: rgb(0, 0, 255);">&gt;</span><span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">&lt;/</span><span style="color: rgb(128, 0, 0);">servlet</span><span style="color: rgb(0, 0, 255);">&gt;</span><span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;<br />
<br />
&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">&lt;</span><span style="color: rgb(128, 0, 0);">servlet-mapping</span><span style="color: rgb(0, 0, 255);">&gt;</span><span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">&lt;</span><span style="color: rgb(128, 0, 0);">servlet-name</span><span style="color: rgb(0, 0, 255);">&gt;</span><span style="color: rgb(0, 0, 0);">HessianServlet</span><span style="color: rgb(0, 0, 255);">&lt;/</span><span style="color: rgb(128, 0, 0);">servlet-name</span><span style="color: rgb(0, 0, 255);">&gt;</span><span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">&lt;</span><span style="color: rgb(128, 0, 0);">url-pattern</span><span style="color: rgb(0, 0, 255);">&gt;</span><span style="color: rgb(0, 0, 0);">/service/hession</span><span style="color: rgb(0, 0, 255);">&lt;/</span><span style="color: rgb(128, 0, 0);">url-pattern</span><span style="color: rgb(0, 0, 255);">&gt;</span><span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">&lt;/</span><span style="color: rgb(128, 0, 0);">servlet-mapping</span><span style="color: rgb(0, 0, 255);">&gt;</span><span style="color: rgb(0, 0, 0);">&nbsp;&nbsp; <br />
</span></div>
<br />
com.***.product.remote.Htest<br />
<br />
<div style="background-color: rgb(238, 238, 238); font-size: 13px; border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">class</span><span style="color: rgb(0, 0, 0);">&nbsp;Htest&nbsp;</span><span style="color: rgb(0, 0, 255);">extends</span><span style="color: rgb(0, 0, 0);">&nbsp;HouseHessianServlet&nbsp;</span><span style="color: rgb(0, 0, 255);">implements</span><span style="color: rgb(0, 0, 0);">&nbsp;IHtest{<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);">&nbsp;hello(){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">hello</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
}</span></div>
<br />
<br />
<img src ="http://www.blogjava.net/dongbule/aggbug/341246.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/dongbule/" target="_blank">陈于喆</a> 2010-12-21 16:05 <a href="http://www.blogjava.net/dongbule/archive/2010/12/21/341246.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>解决hessian远程调用连接超时的问题</title><link>http://www.blogjava.net/dongbule/archive/2010/12/16/340894.html</link><dc:creator>陈于喆</dc:creator><author>陈于喆</author><pubDate>Thu, 16 Dec 2010 06:46:00 GMT</pubDate><guid>http://www.blogjava.net/dongbule/archive/2010/12/16/340894.html</guid><wfw:comment>http://www.blogjava.net/dongbule/comments/340894.html</wfw:comment><comments>http://www.blogjava.net/dongbule/archive/2010/12/16/340894.html#Feedback</comments><slash:comments>10</slash:comments><wfw:commentRss>http://www.blogjava.net/dongbule/comments/commentRss/340894.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/dongbule/services/trackbacks/340894.html</trackback:ping><description><![CDATA[目前几套系统中主要使用的hessian进行远程调用webservice服务的有hessian的HessianProxyFactory(com.caucho.hessian.client.HessianProxyFactory)和spring的HessianProxyFactoryBean(org.springframework.remoting.caucho.HessianProxyFactoryBean).<br />
<br />
<strong>1.HessianProxyFactory</strong><br />
查看HessianProxyFactory源码后发现,hessian在创建http请求连接webservice服务并没有对连接超时进行相关的参数设置,所以当网络出现问题就会造成整个hessian处理的阻塞,进而阻塞整个线程后续的处理<br />
以下是HessianProxyFactory对连接处理的源码<br />
<br />
<div style="background-color: rgb(238, 238, 238); font-size: 13px; border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: rgb(0, 0, 255);">protected</span><span style="color: rgb(0, 0, 0);">&nbsp;URLConnection&nbsp;openConnection(URL&nbsp;url)<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">throws</span><span style="color: rgb(0, 0, 0);">&nbsp;IOException<br />
&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;URLConnection&nbsp;conn&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;url.openConnection();<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;conn.setDoOutput(</span><span style="color: rgb(0, 0, 255);">true</span><span style="color: rgb(0, 0, 0);">);<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);">&nbsp;(_readTimeout&nbsp;</span><span style="color: rgb(0, 0, 0);">&gt;</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">0</span><span style="color: rgb(0, 0, 0);">)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">try</span><span style="color: rgb(0, 0, 0);">&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;conn.setReadTimeout((</span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);">)&nbsp;_readTimeout);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span><span style="color: rgb(0, 0, 255);">catch</span><span style="color: rgb(0, 0, 0);">&nbsp;(Throwable&nbsp;e)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;conn.setRequestProperty(</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">Content-Type</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">,&nbsp;</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">x-application/hessian</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">);<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);">&nbsp;(_basicAuth&nbsp;</span><span style="color: rgb(0, 0, 0);">!=</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">null</span><span style="color: rgb(0, 0, 0);">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;conn.setRequestProperty(</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">Authorization</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">,&nbsp;_basicAuth);<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">else</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);">&nbsp;(_user&nbsp;</span><span style="color: rgb(0, 0, 0);">!=</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">null</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">&amp;&amp;</span><span style="color: rgb(0, 0, 0);">&nbsp;_password&nbsp;</span><span style="color: rgb(0, 0, 0);">!=</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">null</span><span style="color: rgb(0, 0, 0);">)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_basicAuth&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">Basic&nbsp;</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">+</span><span style="color: rgb(0, 0, 0);">&nbsp;base64(_user&nbsp;</span><span style="color: rgb(0, 0, 0);">+</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">:</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">+</span><span style="color: rgb(0, 0, 0);">&nbsp;_password);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;conn.setRequestProperty(</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">Authorization</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">,&nbsp;_basicAuth);<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);">&nbsp;conn;<br />
&nbsp;&nbsp;}</span></div>
<br />
所以我们针对此逻辑继承并重写该openConnection方法,在创建http连接的时候通过设置连接超时时间来解决因网络问题阻塞程序继续的问题<br />
<br />
<div style="background-color: rgb(238, 238, 238); font-size: 13px; border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">class</span><span style="color: rgb(0, 0, 0);">&nbsp;MyHessianProxyFactory&nbsp;</span><span style="color: rgb(0, 0, 255);">extends</span><span style="color: rgb(0, 0, 0);">&nbsp;HessianProxyFactory&nbsp;{<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">private</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);">&nbsp;connectTimeOut&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">10000</span><span style="color: rgb(0, 0, 0);">;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">private</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);">&nbsp;readTimeOut&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">10000</span><span style="color: rgb(0, 0, 0);">;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);">&nbsp;getConnectTimeOut()&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);">&nbsp;connectTimeOut;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);">&nbsp;setConnectTimeOut(</span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);">&nbsp;connectTimeOut)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">this</span><span style="color: rgb(0, 0, 0);">.connectTimeOut&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;connectTimeOut;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);">&nbsp;getReadTimeOut()&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);">&nbsp;readTimeOut;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);">&nbsp;setReadTimeOut(</span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);">&nbsp;readTimeOut)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">this</span><span style="color: rgb(0, 0, 0);">.readTimeOut&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;readTimeOut;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">protected</span><span style="color: rgb(0, 0, 0);">&nbsp;URLConnection&nbsp;openConnection(URL&nbsp;url)&nbsp;</span><span style="color: rgb(0, 0, 255);">throws</span><span style="color: rgb(0, 0, 0);">&nbsp;IOException&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;URLConnection&nbsp;conn&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;url.openConnection();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;conn.setDoOutput(</span><span style="color: rgb(0, 0, 255);">true</span><span style="color: rgb(0, 0, 0);">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);">&nbsp;(</span><span style="color: rgb(0, 0, 255);">this</span><span style="color: rgb(0, 0, 0);">.connectTimeOut&nbsp;</span><span style="color: rgb(0, 0, 0);">&gt;</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">0</span><span style="color: rgb(0, 0, 0);">)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;conn.setConnectTimeout(</span><span style="color: rgb(0, 0, 255);">this</span><span style="color: rgb(0, 0, 0);">.connectTimeOut);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);">&nbsp;(</span><span style="color: rgb(0, 0, 255);">this</span><span style="color: rgb(0, 0, 0);">.readTimeOut&nbsp;</span><span style="color: rgb(0, 0, 0);">&gt;</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">0</span><span style="color: rgb(0, 0, 0);">)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;conn.setReadTimeout(</span><span style="color: rgb(0, 0, 255);">this</span><span style="color: rgb(0, 0, 0);">.readTimeOut);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;conn.setRequestProperty(</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">Content-Type</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">,&nbsp;</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">x-application/hessian</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);">&nbsp;(_basicAuth&nbsp;</span><span style="color: rgb(0, 0, 0);">!=</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">null</span><span style="color: rgb(0, 0, 0);">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;conn.setRequestProperty(</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">Authorization</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">,&nbsp;_basicAuth);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">else</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);">&nbsp;(_user&nbsp;</span><span style="color: rgb(0, 0, 0);">!=</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">null</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">&amp;&amp;</span><span style="color: rgb(0, 0, 0);">&nbsp;_password&nbsp;</span><span style="color: rgb(0, 0, 0);">!=</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">null</span><span style="color: rgb(0, 0, 0);">)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_basicAuth&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">Basic&nbsp;</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">+</span><span style="color: rgb(0, 0, 0);">&nbsp;base64(_user&nbsp;</span><span style="color: rgb(0, 0, 0);">+</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">:</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">+</span><span style="color: rgb(0, 0, 0);">&nbsp;_password);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;conn.setRequestProperty(</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">Authorization</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">,&nbsp;_basicAuth);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);">&nbsp;conn;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
}</span></div>
<br />
<strong>2.HessianProxyFactoryBean</strong><br />
查看spring的HessianProxyFactoryBean源码发现,它在封装hessian是直接创建一个HessianProxyFactory实例,然后利用该实例完成创建远程服务<br />
<br />
<div style="background-color: rgb(238, 238, 238); font-size: 13px; border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">class</span><span style="color: rgb(0, 0, 0);">&nbsp;HessianProxyFactoryBean&nbsp;</span><span style="color: rgb(0, 0, 255);">extends</span><span style="color: rgb(0, 0, 0);">&nbsp;HessianClientInterceptor&nbsp;</span><span style="color: rgb(0, 0, 255);">implements</span><span style="color: rgb(0, 0, 0);">&nbsp;FactoryBean&nbsp;{<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">private</span><span style="color: rgb(0, 0, 0);">&nbsp;Object&nbsp;serviceProxy;<br />
<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);">&nbsp;afterPropertiesSet()&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">super</span><span style="color: rgb(0, 0, 0);">.afterPropertiesSet();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">this</span><span style="color: rgb(0, 0, 0);">.serviceProxy&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;ProxyFactory.getProxy(getServiceInterface(),&nbsp;</span><span style="color: rgb(0, 0, 255);">this</span><span style="color: rgb(0, 0, 0);">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);">&nbsp;Object&nbsp;getObject()&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">this</span><span style="color: rgb(0, 0, 0);">.serviceProxy;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);">&nbsp;Class&nbsp;getObjectType()&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);">&nbsp;getServiceInterface();<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">boolean</span><span style="color: rgb(0, 0, 0);">&nbsp;isSingleton()&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">true</span><span style="color: rgb(0, 0, 0);">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
}</span></div>
<br />
所以对此的解决方法与上面差不多,继承HessianProxyFactoryBean然后加入相应的连接超时和读取超时的变量,重写afterPropertiesSet方法,并且同时完成上面第一步对HessianProxyFactory的改造,这样就能保证连接远程webserver服务器时不会因为网络原因阻塞程序的执行<br />
<br />
<div style="background-color: rgb(238, 238, 238); font-size: 13px; border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">class</span><span style="color: rgb(0, 0, 0);">&nbsp;MyHessianProxyFactoryBean&nbsp;</span><span style="color: rgb(0, 0, 255);">extends</span><span style="color: rgb(0, 0, 0);">&nbsp;HessianProxyFactoryBean&nbsp;{<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">private</span><span style="color: rgb(0, 0, 0);">&nbsp;MyHessianProxyFactory&nbsp;proxyFactory&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);">&nbsp;MyHessianProxyFactory();<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">private</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);">&nbsp;readTimeOut&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">10000</span><span style="color: rgb(0, 0, 0);">;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">private</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);">&nbsp;connectTimeOut&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">10000</span><span style="color: rgb(0, 0, 0);">;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);">&nbsp;getReadTimeOut()&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);">&nbsp;readTimeOut;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);">&nbsp;setReadTimeOut(</span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);">&nbsp;readTimeOut)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">this</span><span style="color: rgb(0, 0, 0);">.readTimeOut&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;readTimeOut;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);">&nbsp;getConnectTimeOut()&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);">&nbsp;connectTimeOut;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);">&nbsp;setConnectTimeOut(</span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);">&nbsp;connectTimeOut)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">this</span><span style="color: rgb(0, 0, 0);">.connectTimeOut&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;connectTimeOut;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);">&nbsp;afterPropertiesSet()&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;proxyFactory.setReadTimeout(readTimeOut);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;proxyFactory.setConnectTimeOut(connectTimeOut);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;setProxyFactory(proxyFactory);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">super</span><span style="color: rgb(0, 0, 0);">.afterPropertiesSet();<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
}</span></div>
<br />
<br />
<img src ="http://www.blogjava.net/dongbule/aggbug/340894.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/dongbule/" target="_blank">陈于喆</a> 2010-12-16 14:46 <a href="http://www.blogjava.net/dongbule/archive/2010/12/16/340894.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>一个伴随已久的时间操作工具类</title><link>http://www.blogjava.net/dongbule/archive/2010/12/09/340174.html</link><dc:creator>陈于喆</dc:creator><author>陈于喆</author><pubDate>Thu, 09 Dec 2010 10:37:00 GMT</pubDate><guid>http://www.blogjava.net/dongbule/archive/2010/12/09/340174.html</guid><wfw:comment>http://www.blogjava.net/dongbule/comments/340174.html</wfw:comment><comments>http://www.blogjava.net/dongbule/archive/2010/12/09/340174.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/dongbule/comments/commentRss/340174.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/dongbule/services/trackbacks/340174.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 下面一个伴随了好几个工程的时间操作的工具类,提供了一些常用的时间操作和计算的方法,每段时间都会进行一次整理,希望能去冗余和得到好的扩展Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->package&nbsp;com.***....&nbsp;&nbsp;<a href='http://www.blogjava.net/dongbule/archive/2010/12/09/340174.html'>阅读全文</a><img src ="http://www.blogjava.net/dongbule/aggbug/340174.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/dongbule/" target="_blank">陈于喆</a> 2010-12-09 18:37 <a href="http://www.blogjava.net/dongbule/archive/2010/12/09/340174.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>memcached一些应用点滴</title><link>http://www.blogjava.net/dongbule/archive/2010/12/08/340066.html</link><dc:creator>陈于喆</dc:creator><author>陈于喆</author><pubDate>Wed, 08 Dec 2010 07:00:00 GMT</pubDate><guid>http://www.blogjava.net/dongbule/archive/2010/12/08/340066.html</guid><wfw:comment>http://www.blogjava.net/dongbule/comments/340066.html</wfw:comment><comments>http://www.blogjava.net/dongbule/archive/2010/12/08/340066.html#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://www.blogjava.net/dongbule/comments/commentRss/340066.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/dongbule/services/trackbacks/340066.html</trackback:ping><description><![CDATA[大名鼎鼎的分布式缓存系统memcached，在开源社区中可谓是无人不知无人不晓，memcached支持分布式的横向扩展，但memcached的服务端却是单实例，并无"分布式"的功能，所谓的分布式只是客户端在存储的主键做分布的存储；还有memcached组件缓存对象，如果组件无进行序列化必定无法正确取得数据；如何使用memcached的java组件来监控memcached的运行状态；以上等等的问题是我在日常的工作中碰到并解决的,拿出来跟大家做个分享^_^<br />
<br />
<hr width="100%" size="2" />
<br />
<strong>对象的序列化</strong><br />
首先memcached是独立的服务器组件,独立于应用系统,从客户端保存和读取对象到memcached是必须通过网络传输,因为网络传输都是二进制的数据,所以所有的对象都必须经过序列化,否则无法存储到memcahced的服务器端.<br />
正如我们以往在集群中应用的序列化一样,memcached的序列化的性能也是往往让大家头疼,如果我们对我们的domain类进行对象的序列化,第一次序列化时间会比较长,但后续会优化,也就是说序列化最大的消耗不是对象的序列化,而是类的序列化,如果存储的只是一个String对象,这种情况是最理想的,省去了序列化的操作.实际上String对象本身已经实现了序列化接口,无法我们再次去进行序列化操作.<br />
<br />
<hr width="100%" size="2" />
<br />
<strong>memcached的原子加法</strong><br />
记录一下上次犯得一个错误<br />
<div style="background-color: #eeeeee; font-size: 13px; border: 1px solid #cccccc; padding: 4px 5px 4px 4px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">&lt;%</span><span style="color: #000000;"><br />
</span><span style="color: #0000ff;">static</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;count&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">;<br />
count</span><span style="color: #000000;">++</span><span style="color: #000000;">;<br />
MemCachedClient&nbsp;mcc&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;MemCachedClient();<br />
mcc.add(</span><span style="color: #000000;">"</span><span style="color: #000000;">test.html</span><span style="color: #000000;">"</span><span style="color: #000000;">,&nbsp;count);<br />
</span><span style="color: #000000;">%&gt;</span></div>
<br />
这段代码的作用是将test.html的用户访问次数保存到memcached中,粗劣一看好像并无错误,但在高并发时的出来的访问数据一定是小于实际的访问数量,当然这里并不是memcached对象锁的问题,主要还是程序中线程的同步问题,但是如果使用java的synchronized或lock那么在性能上肯定是无法忍受的,memcached客户端组件带有原子性的加法和减法<br />
<br />
<div style="background-color: #eeeeee; font-size: 13px; border: 1px solid #cccccc; padding: 4px 5px 4px 4px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">&lt;%</span><span style="color: #000000;"><br />
MemCachedClient&nbsp;mcc&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;MemCachedClient();<br />
System.out.println(mcc.addOrIncr(</span><span style="color: #000000;">"</span><span style="color: #000000;">test.html</span><span style="color: #000000;">"</span><span style="color: #000000;">,</span><span style="color: #000000;">1</span><span style="color: #000000;">));<br />
</span><span style="color: #000000;">%&gt;</span></div>
<br />
long addORIncr(String key,long inc)为计数器值增加inc,如果计数器不存在,则保存inc为计数器的值,必须注意的是服务器端不会对超过2的32次方的行为进行检查<br />
<br />
<hr width="100%" size="2" />
<br />
<br />
<strong>分布式的mencached</strong><br />
memcached虽然是属于分布式的缓存服务器,但实际上memcached服务端之间并无分布式的功能,不会互相通信共享数据,如何进行分布式,这完全是取决于客户端的实现<br />
<br />
<img alt="" src="http://www.blogjava.net/images/blogjava_net/dongbule/memcached/2.png" width="456" height="390" /><br />
<br />
假设我们现在有三台memcached服务器分别为node1，node2，node3，应用程序要保存键名分别为"test1","test2","test3",客户端实现的算法就是根据键名来决定保存数据的memcached服务器,我们将"test1"保存到node1，"test2"保存到node2，"test3"保存到node3，并且在读取缓存数据也是通过一样的算法从各台服务器上读取相应的key,这样通过一个最简单的算法将不同的键保存到不同的服务器上,实现了memcached的分布式.<br />
但是这种算法很难确保每台服务器得到较为平均的数据量,我们需要改变一下客户端的算法,简单来说,就是根据服务器的台数的余数进行分散<br />
<br />
<div style="background-color: #eeeeee; font-size: 13px; border: 1px solid #cccccc; padding: 4px 5px 4px 4px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">&lt;%<br />
"</span><span style="color: #000000;">test1</span><span style="color: #000000;">"</span><span style="color: #000000;">.hashCode()</span><span style="color: #000000;">%</span><span style="color: #000000;">3<br />
%&gt;<br />
</span></div>
<br />
根据key的java.lang.String.hashCode()取得散列值,再将值模服务器的台数得到余数值,我们再根据这个余数值来判定这个key要存入哪一台服务器,当key的数量越来越大,对key的散列取模也会趋向平均,基本可以保证几台memcached服务器所存储的缓存量趋向平均<br />
似乎很完美,余数计算的方法很简单,数据的分散性也很优秀,但也有其缺点,就是当需要添加或移除服务器时,缓存的重组代价是相当巨大的,添加或移除服务器时,余数就会发生变化,这样就无法取到与原来缓存时相同的服务器.<br />
网上介绍的Consistent Hashing算法基本上可以解决这个问题,这里做个简单的说明,首先是求出memcached服务器节点的哈希值,并将其配置到0-2的32次方的圆上,然后用同样的方法求出存储数据的键的哈希值,并映射到圆上.然后从数据映射到的位置开始顺时针查找,将数据保存到找到的第一个服务器上.如果超过2的32次方仍然找不到服务器,就会保存到第一台memcached服务器上<br />
<img alt="" src="http://www.blogjava.net/images/blogjava_net/dongbule/memcached/3.png" width="512" height="421" /><br />
<br />
从上图的状态中添加一台memcached服务器。余数分布式算法由于保存键的服务器会发生巨大变化而影响缓存的命中率，但Consistent Hashing中，只有在continuum上增加服务器的地点逆时针方向的第一台服务器上的键会受到影响<br />
<br />
<hr width="100%" size="2" />
<br />
<strong>几种连接客户端的对比</strong><br />
目前java的memcached主要有Java-Memcached-Client,Xmemached,Spymemcached三种,这三个客户端的性能测试可以看<br />
http://xmemcached.googlecode.com/svn/trunk/benchmark/benchmark.html<br />
<br />
<img alt="" src="http://www.blogjava.net/images/blogjava_net/dongbule/memcached/4.png" width="942" height="612" /><br />
请求的资源为64Bytes,在低并发Java-Memcached-Client是占有一定的优势,但在并发数超过100以后,Java-Memcached-Client是呈现直线下跌,并发数达到300已经无法承受,Spymemcached和Xmemached表现相对稳定,特别是Xmemached无论在低并发或高并发都保持优秀的性能表现<br />
<br />
<img alt="" src="http://www.blogjava.net/images/blogjava_net/dongbule/memcached/5.png" width="950" height="610" /><br />
<br />
并发数固定为100时,在小文件的请求Java-Memcached-Client还是占有优势,当随着请求的size越来越大,三者趋向于同一点<br />
如果你对memcached访问的负载不高,那么Java-Memcached-Client是一个不错的选择,如果你对memcached访问的负载要求较高,推荐使用Xmemached,如果需要异步的批量处理,可以选择Spymemcached,如果你什么都不知道,那么建议使用Xmemached,因为无论在何种情况,它都可以表现出较好的性能,虽然不是最好<br />
<br />
<hr width="100%" size="2" />
<br />
<strong>监控memcached </strong><br />
推荐使用nagios或cactis进行监控,nagios没有配置过,cactis是需要下载一个脚本插件<br />
这里推荐一个从网上淘来的php,只要把它放到你的机器中,当然你的机器要支持php环境,将此php放入你的网页访问网络就可以访问<br />
下载<br />
<a href="/Files/dongbule/cacti/memcache.rar">http://www.blogjava.net/Files/dongbule/cacti/memcache.rar</a><br />
修改php以下几个选项<br />
<br />
<div style="background-color: #eeeeee; font-size: 13px; border: 1px solid #cccccc; padding: 4px 5px 4px 4px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #008080;">define</span><span style="color: #000000;">(</span><span style="color: #000000;">'</span><span style="color: #000000;">ADMIN_USERNAME</span><span style="color: #000000;">'</span><span style="color: #000000;">,</span><span style="color: #000000;">'</span><span style="color: #000000;">memcache</span><span style="color: #000000;">'</span><span style="color: #000000;">);&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;Admin&nbsp;Username</span><span style="color: #008000;"><br />
</span><span style="color: #008080;">define</span><span style="color: #000000;">(</span><span style="color: #000000;">'</span><span style="color: #000000;">ADMIN_PASSWORD</span><span style="color: #000000;">'</span><span style="color: #000000;">,</span><span style="color: #000000;">'</span><span style="color: #000000;">password</span><span style="color: #000000;">'</span><span style="color: #000000;">);&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;Admin&nbsp;Password</span><span style="color: #008000;"><br />
</span><span style="color: #000000;"><br />
</span><span style="color: #800080;">$MEMCACHE_SERVERS</span><span style="color: #000000;">[]&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">192.168.1.100:11211</span><span style="color: #000000;">'</span><span style="color: #000000;">;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;add&nbsp;more&nbsp;as&nbsp;an&nbsp;array</span><span style="color: #008000;"><br />
#</span><span style="color: #008000;">$MEMCACHE_SERVERS[]&nbsp;=&nbsp;'mymemcache-server2:11211';&nbsp;//&nbsp;add&nbsp;more&nbsp;as&nbsp;an&nbsp;array</span></div>
<br />
监控的平台<br />
<br />
<img alt="" src="http://www.blogjava.net/images/blogjava_net/dongbule/memcached/6.png" width="992" height="422" /><br />
<br />
<hr width="100%" size="2" />
<br />
<strong>理解memcached的删除机制</strong><br />
memcached内部不会监视记录是否过期,而是在get时查看记录的时间戳,检查记录是否过期, 这种技术被称为lazy(惰性)expiration.因此,memcached不会在过期监视上耗费CPU时间<br />
memcached会优先使用已超时的记录的空间,并使用LRU算法来分配空间,因此当memcached的内存空间不足,就从最近违背使用的记录中搜索,并将空间分配给新的记录<br />
不过在某些情况下LRU机制会造成某些麻烦,如你并不想要淘汰已被缓存过的记录,可以在memcached启动时添加 -M 参数来禁止LRU,但这样在memcached的内存用尽时,memcached会返回错误,是否使用LRU,在于你的需求<br />
<br />
<br />
----------------------------------------<br />
<br />
by 陈于喆 <br />
QQ:34174409<br />
Mail: dongbule@163.com<br />
<br />
<br />
<br />
<img src ="http://www.blogjava.net/dongbule/aggbug/340066.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/dongbule/" target="_blank">陈于喆</a> 2010-12-08 15:00 <a href="http://www.blogjava.net/dongbule/archive/2010/12/08/340066.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>开发人员与软件测试</title><link>http://www.blogjava.net/dongbule/archive/2010/12/03/339721.html</link><dc:creator>陈于喆</dc:creator><author>陈于喆</author><pubDate>Fri, 03 Dec 2010 08:00:00 GMT</pubDate><guid>http://www.blogjava.net/dongbule/archive/2010/12/03/339721.html</guid><wfw:comment>http://www.blogjava.net/dongbule/comments/339721.html</wfw:comment><comments>http://www.blogjava.net/dongbule/archive/2010/12/03/339721.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.blogjava.net/dongbule/comments/commentRss/339721.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/dongbule/services/trackbacks/339721.html</trackback:ping><description><![CDATA[上个月参加的网易游戏部QA组的黑盒测试培训,觉得挺有意思的,不过最让我感兴趣的是,能和真正专业的测试人员做了一点讨论,发现站在开发人员的角度看待测试和站在测试人员看待测试时完全不同的一种东西.<br />
<br />
<strong>程序员和测试人员的心理差别</strong><br />
程序员和测试人员的心理差别可以简单的归纳为以下几种<br />
<br />
<strong>成功 / 不成功</strong><br />
什么才是一次成功的测试,大多数的开发人员对自己的程序测试完没发现错误,就会说"这是一个成功的测试",如果发现某些新的错误则称"这是不成功的测试";而测试人员刚好相反,当然这也是因为双方的职责不同而引起的<br />
<br />
<strong>维护 / 破坏,施虐</strong><br />
开发人员对测试往往是一种维护性的测试,目标在于证明自己开发的程序没有错误,可能跟我们开发人员经常做建设性工作,更倾向创造事物,而不是将事物破坏有关;而测试人员在测试更多是一种破坏的过程,甚至是一种施虐,摆出一种把鸡蛋打碎搅黄来挑骨头的姿态<br />
<br />
<strong>做了应该做的 / 做了不该做的</strong><br />
开发人员在做测试更多倾向于对实现的功能进行检查,当测试证明了该完成的功能全部通过时就认为测试完毕了,但程序即使能够完成预定的功能,也可能隐藏了错误,如做了应该做的东西,同时也做了不应该做的东西<br />
<br />
<strong>建立一种信心 / 必须做</strong><br />
测试这个东西对于开发人员来说,更多的是建立一种信心的保证,例如我们尽可能多的单元测试,很多时候就是让我们确信程序的正确性,并让我们建立信心,而对于测试人员来说,测试是他们的职责所在,只有尽可能多的把系统挖出错误来才证明他们的存在价值<br />
<br />
<strong>测试的态度</strong><br />
测试是一项技术性的工作,但同时也涉及到了心里学的一些重要的因素.<br />
作为程序员的我们也经常会对我们的程序进行相关的测试,但你想想我们为什么要对我们的系统做测试,原因大概有以下的几种<br />
<br />
1.测试就是为了证明我们的系统是不存在错误的.<br />
2.测试的目的是想证明系统能够正确完成预定的功能.<br />
3.测试是保证一个系统强壮性的信心过程.<br />
4.测试是上级规定要做的.<br />
<br />
站在测试人员的角度来看,除了最后一点,其他的都是本末倒置(难怪他们会抱怨我们做的测试很差)<br />
<br />
"测试就是为了证明我们的系统是不存在错误的",试想一下,如果我们的目标是证明程序中不存在错误,那么我们的潜意识就会倾向于这个目标,我们会倾向选择可能较少导致出现程序失效的测试数据,如果我们的测试目标证明程序中存在错误,我们设计的测试数据就可能更多的发现问题.于前一种方法相比,后一种方法会更多地增加程序的价值.<br />
每当测试一个程序,都是想为程序增加多一些的价值,通过测试发现系统的更多错误来增加程序的可靠性质量,提高了程序的可靠性,是指出并最终修改程序的错误.与"测试就是为了证明我们的系统是不存在错误的"比较,更适合的定义是<br />
<strong>测试时为了发现错误而执行的过程</strong><br />
<br />
"测试的目的是想证明系统能够正确完成预定的功能",这个定义又会带来另一个问题,程序即使能够完成预定的功能,也依然可能隐藏错误,也就是说,当程序没有实现预期的功能,错误时能够清晰显示出来,但程序做了不应该做的呢,这同样也是一个错误,如我们程序实现了一个除法计算器,即使我们通过各种数据正确的完成了计算任务,但在完成了不应执行的任务(除数为0),程序依然是错误的,如果我们将软件测试作为发现错误的过程,而不是只是证明"系统能够正确完成预定的功能",我们发现这类的错误可能性会打很多,所以更好的定义是<br />
<strong>测试就是建立程序即使能完成预定功能,也发现存在完成非预定功能<br />
</strong><br />
ps:当然了,测试更多是跟软件成本方面相关,这里就不细想了,附上讲座的ppt&lt;<a href="http://download.csdn.net/source/2879755">实用的黑盒测试方法</a>&gt;<br />
<br />
----------------------------------------<br />
<br />
<br />
<img src ="http://www.blogjava.net/dongbule/aggbug/339721.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/dongbule/" target="_blank">陈于喆</a> 2010-12-03 16:00 <a href="http://www.blogjava.net/dongbule/archive/2010/12/03/339721.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[整理]工程中jar功能对照表</title><link>http://www.blogjava.net/dongbule/archive/2010/11/03/336905.html</link><dc:creator>陈于喆</dc:creator><author>陈于喆</author><pubDate>Wed, 03 Nov 2010 06:59:00 GMT</pubDate><guid>http://www.blogjava.net/dongbule/archive/2010/11/03/336905.html</guid><wfw:comment>http://www.blogjava.net/dongbule/comments/336905.html</wfw:comment><comments>http://www.blogjava.net/dongbule/archive/2010/11/03/336905.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/dongbule/comments/commentRss/336905.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/dongbule/services/trackbacks/336905.html</trackback:ping><description><![CDATA[<br />
把我上次的工程所用到的jar包做了一个整理,也加了一些简单的描述,下面图是上次工程用到的所有jar吧<br />
<br />
<img alt="" src="http://www.blogjava.net/images/blogjava_net/dongbule/jar/1.png" width="549" height="600" /><br />
<br />
<table width="964" border="0" cellpadding="2" cellspacing="2" height="734">
    <tbody>
        <tr>
            <td><strong>JAR包与描述对照表</strong></td>
            <td><strong>注：jar包尾后的版本号不代表当前最高版本</strong></td>
        </tr>
        <tr>
            <td>activation-1.1.jar</td>
            <td>Sun的JavaBeans Activation Framework（JAF）,JavaMail要运行必须依赖于它的支持</td>
        </tr>
        <tr>
            <td>asm-3.0.jar<br />
            asm-commons-2.2.3.jar<br />
            asm-util-2.2.3.jar<br />
            </td>
            <td>asm是一个轻量级字节码处理和分析框架</td>
        </tr>
        <tr>
            <td>alveole-struts2.jar<br />
            alveole-tools.jar<br />
            </td>
            <td>&nbsp;</td>
        </tr>
        <tr>
            <td valign="top">aspectjtools-1.5.3.jar<br />
            </td>
            <td valign="top">Aspect提供的注释类库和相应的解析类库<br />
            </td>
        </tr>
        <tr>
            <td valign="top">atomikos-util.jar<br />
            </td>
            <td valign="top">数据库提供分布式事务支持<br />
            </td>
        </tr>
        <tr>
            <td valign="top">c3p0-0.8.5.2.jar<br />
            </td>
            <td valign="top">C3PO是一个数据库连接池<br />
            </td>
        </tr>
        <tr>
            <td valign="top">cglib-nodep-2.2.jar<br />
            </td>
            <td valign="top">CGLIB是一个强大的高质量高性能的代码生成库,在运行时可以用它来扩展Java类<br />
            </td>
        </tr>
        <tr>
            <td valign="top">commons-attributes-api.jar<br />
            </td>
            <td valign="top">Apache Commons包中的一个,包含了一些属性的api<br />
            </td>
        </tr>
        <tr>
            <td valign="top">commons-beanutils-1.6.jar<br />
            </td>
            <td valign="top">Apache Commons包中的一个，包含了一些Bean工具类类<br />
            </td>
        </tr>
        <tr>
            <td valign="top">commons-chain-1.1.jar<br />
            </td>
            <td valign="top"><br />
            </td>
        </tr>
        <tr>
            <td valign="top">commons-codec-1.3.jar<br />
            </td>
            <td valign="top"><br />
            </td>
        </tr>
        <tr>
            <td valign="top">commons-collections-3.2.jar<br />
            </td>
            <td valign="top">Apache Commons包中的一个,包含了一些Apache开发的集合类，功能比java.util.*强大<br />
            </td>
        </tr>
        <tr>
            <td valign="top">commons-configuration.jar<br />
            </td>
            <td valign="top">Apache Commons包中的一个,用于协助读取配置和首选项文件<br />
            </td>
        </tr>
        <tr>
            <td valign="top">commons-digester-1.8.jar<br />
            </td>
            <td valign="top">Apache Commons包中的一个,通过它可以很方便的解析xml文件生成java对象<br />
            </td>
        </tr>
        <tr>
            <td valign="top">commons-fileupload.jar<br />
            </td>
            <td valign="top">Apache Commons包中的一个,是一个通过Http接收上传的文件并处理结果文件的库<br />
            </td>
        </tr>
        <tr>
            <td valign="top">commons-lang-2.1.jar<br />
            </td>
            <td valign="top">Apache Commons包中的一个,包含了一些数据类型工具类，是java.lang.*的扩展<br />
            </td>
        </tr>
        <tr>
            <td valign="top">commons-httpclient-3.0.jar<br />
            </td>
            <td valign="top">Apache Commons包中的一个,提供一个框架啊处理http客户端的扩展<br />
            </td>
        </tr>
        <tr>
            <td valign="top">commons-io.jar&nbsp;&nbsp;&nbsp; <br />
            </td>
            <td valign="top">Apache Commons包中的一个,java.io.*的扩展,输入输出,支持文件上传<br />
            </td>
        </tr>
        <tr>
            <td valign="top">commons-logging-1.1.1.jar<br />
            </td>
            <td valign="top">Apache Commons包中的一个,包含日志功能<br />
            </td>
        </tr>
        <tr>
            <td valign="top">commons-logging-api-1.1.jar<br />
            </td>
            <td valign="top">Apache Commons包中的一个,Commons Logging应用接口,一种超薄适配器允许其他可配置桥连接<br />
            </td>
        </tr>
        <tr>
            <td valign="top">commons-validator-1.3.0.jar<br />
            </td>
            <td valign="top">Apache Commons包中的一个,struts使用它进行表单验证<br />
            </td>
        </tr>
        <tr>
            <td valign="top">dom4j-1.6.1.jar&nbsp;&nbsp;&nbsp; <br />
            </td>
            <td valign="top">dom4j XML 解析器<br />
            </td>
        </tr>
        <tr>
            <td valign="top">ezmorph-1.0.4.jar<br />
            </td>
            <td valign="top">json和java转化的辅助工具<br />
            </td>
        </tr>
        <tr>
            <td valign="top">freemarker-2.3.8.jar<br />
            </td>
            <td valign="top">freemarker表现层模板工具<br />
            </td>
        </tr>
        <tr>
            <td valign="top">hessian-3.1.3.jar<br />
            </td>
            <td valign="top">一个轻量级的remoting onhttp工具，使用简单的方法提供了RMI的功能<br />
            </td>
        </tr>
        <tr>
            <td valign="top">htmlparser.jar<br />
            </td>
            <td valign="top">强大的html解析器<br />
            </td>
        </tr>
        <tr>
            <td valign="top">httpsqs4j.jar<br />
            </td>
            <td valign="top">一款基于 HTTP GET/POST 协议的轻量级开源简单消息队列服务<br />
            </td>
        </tr>
        <tr>
            <td valign="top">ibatis-2.3.3.720.jar<br />
            </td>
            <td valign="top">iBATIS提供的持久层框架包括SQL Maps和Data Access Objects（DAO）<br />
            </td>
        </tr>
        <tr>
            <td valign="top">jamon-2.7.jar<br />
            </td>
            <td valign="top">一个小巧的，免费的，高性能的，线程安全的性能监测工具<br />
            </td>
        </tr>
        <tr>
            <td valign="top">java_memcached-release.jar<br />
            </td>
            <td valign="top">memcached连接的java客户端<br />
            </td>
        </tr>
        <tr>
            <td valign="top">jfreechart-1.0.1.jar<br />
            </td>
            <td valign="top">使用java生成图表的工具<br />
            </td>
        </tr>
        <tr>
            <td valign="top">jcommon-1.0.8.jar<br />
            </td>
            <td valign="top">使用java生成图表的工具<br />
            </td>
        </tr>
        <tr>
            <td valign="top">json-lib-2.2-jdk15.jar<br />
            </td>
            <td valign="top">json和java转化的辅助工具<br />
            </td>
        </tr>
        <tr>
            <td valign="top">jta.jar<br />
            </td>
            <td valign="top">Java事务API,为J2EE平台提供了分布式事务服务<br />
            </td>
        </tr>
        <tr>
            <td valign="top">junit-3.8.1.jar<br />
            </td>
            <td valign="top">是一个开放源代码的Java测试框架，用于编写和运行可重复的测试。他是用于单元测试框架体系xUnit的一个实例<br />
            </td>
        </tr>
        <tr>
            <td valign="top">jxl.jar<br />
            </td>
            <td valign="top">通过java操作excel表格的工具类库<br />
            </td>
        </tr>
        <tr>
            <td valign="top">log4j-1.2.9.jar<br />
            </td>
            <td valign="top">通过使用Log4j，我们可以控制日志信息输送的目的地是控制台、文件、GUI组件、甚至是套接口服务器<br />
            </td>
        </tr>
        <tr>
            <td valign="top">lucene-core-2.3.2.jar<br />
            </td>
            <td valign="top">是一个全文检索引擎的架构，提供了完整的查询引擎和索引引擎<br />
            </td>
        </tr>
        <tr>
            <td valign="top">mongo-2.2.jar<br />
            </td>
            <td valign="top">java连接mongodb客户端接口<br />
            </td>
        </tr>
        <tr>
            <td valign="top">morphia.jar</td>
            <td valign="top">是一个轻量级的类型安全的Java类库，用来将在MongoDB和Java对象之间进行映射</td>
        </tr>
        <tr>
            <td valign="top">mysql-connector-java.jar<br />
            </td>
            <td valign="top">mysql连接驱动<br />
            </td>
        </tr>
        <tr>
            <td valign="top">ognl-2.6.11.jar<br />
            </td>
            <td valign="top">OGNL表达式,支持EL<br />
            </td>
        </tr>
        <tr>
            <td valign="top">oscache-2.3.2.jar<br />
            </td>
            <td valign="top">Java对象的缓存工具,比ehcache的优势在于页面缓存<br />
            </td>
        </tr>
        <tr>
            <td valign="top">poi-3.0.1.jar<br />
            </td>
            <td valign="top">apache工具,用于操作pdf和excel的工具类<br />
            </td>
        </tr>
        <tr>
            <td valign="top">quartz-1.6.0.jar<br />
            </td>
            <td valign="top">自动任务处理功能类包<br />
            </td>
        </tr>
        <tr>
            <td valign="top">proxool-0.9.1.jar<br />
            </td>
            <td valign="top">Proxool JDBC 连接池 工具<br />
            </td>
        </tr>
        <tr>
            <td valign="top">servlet.jar<br />
            </td>
            <td valign="top"><br />
            </td>
        </tr>
        <tr>
            <td valign="top">spring-2.0.2.jar</td>
            <td valign="top"><br />
            </td>
        </tr>
        <tr>
            <td valign="top">spring-2.0.2.jar<br />
            </td>
            <td valign="top"><br />
            </td>
        </tr>
        <tr>
            <td valign="top">velocity-1.6.3-dep.jar<br />
            velocity-tools-1.4.jar&nbsp;&nbsp;&nbsp; <br />
            </td>
            <td valign="top">velocity基于java的模板引擎,允许用简单的模板语言来引用java定义的对象<br />
            </td>
        </tr>
        <tr>
            <td valign="top">xwork-core-2.1.6.jar<br />
            </td>
            <td valign="top">web work的核心库<br />
            </td>
        </tr>
    </tbody>
</table>
<br />
<hr width="100%" size="2" />
<br />
下载&lt;<a href="http://download.csdn.net/source/2806071">http://download.csdn.net/source/2806071</a>&gt;<br />
<br />
注:blogjava上传不了,我传到csdn<br />
<br />
----------------------------------------<br />
<br />
by 陈于喆 <br />
QQ:34174409<br />
Mail: dongbule@163.com<br />
<br />
<br />
<img src ="http://www.blogjava.net/dongbule/aggbug/336905.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/dongbule/" target="_blank">陈于喆</a> 2010-11-03 14:59 <a href="http://www.blogjava.net/dongbule/archive/2010/11/03/336905.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>解析xml时遇到的一些问题</title><link>http://www.blogjava.net/dongbule/archive/2010/09/28/333262.html</link><dc:creator>陈于喆</dc:creator><author>陈于喆</author><pubDate>Tue, 28 Sep 2010 09:10:00 GMT</pubDate><guid>http://www.blogjava.net/dongbule/archive/2010/09/28/333262.html</guid><wfw:comment>http://www.blogjava.net/dongbule/comments/333262.html</wfw:comment><comments>http://www.blogjava.net/dongbule/archive/2010/09/28/333262.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/dongbule/comments/commentRss/333262.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/dongbule/services/trackbacks/333262.html</trackback:ping><description><![CDATA[先感谢同事renial的&lt;解析xml时遇到的一些问题&gt;技术分享,下面是一些记录和实际操作<br />
<br />
<strong>1.使用Dom4j解析大文件时内存溢出的问题</strong><br />
<br />
问题是这样的,当我用dom4j去解析一个几十M的xml时,就出现out of memory.当然了,这也是根据你的机器性能而定的,我们都知道dom4j在各种DOM解析器中应该算是性能最好的,连大名鼎鼎的Hibernate都是用dom4j来解析XML配置文件的<br />
问题出在于使用dom4j的SAXReader是会把整个XML文件一次性读入,如果XML文件过大就会抛出out of memory,但即使是使用SAXParser批量读入解析,但它也是一次解析完,假设XML文件有几万条数据,那么解析后就必须在内存放入这几万条对象.<br />
<br />
常用的Dom4j文件解析方式：<br />
<br />
<div style="background-color: rgb(238, 238, 238); font-size: 13px; border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; width: 98%;"><span style="color: rgb(0, 0, 0);">InputStream&nbsp;is&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);">&nbsp;FileInputStream(filePath);<br />
SAXReader&nbsp;reader&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);">&nbsp;SAXReader();&nbsp;&nbsp;</span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">将整个XML构建为一个Document</span><span style="color: rgb(0, 128, 0);"><br />
</span><span style="color: rgb(0, 0, 0);">Document&nbsp;doc&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;reader.read(is);<br />
Element&nbsp;root&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;doc.getRootElement();&nbsp;</span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">&nbsp;获得根节点</span><span style="color: rgb(0, 128, 0);"><br />
</span><span style="color: rgb(0, 0, 255);">for</span><span style="color: rgb(0, 0, 0);">&nbsp;(Object&nbsp;obj&nbsp;:&nbsp;root.elements())&nbsp;{&nbsp;</span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">&nbsp;遍历每个节点</span><span style="color: rgb(0, 128, 0);"><br />
</span><span style="color: rgb(0, 0, 0);">Element&nbsp;e&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;(Element)obj;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">&nbsp;对当前节点进行操作</span><span style="color: rgb(0, 128, 0);"><br />
</span><span style="color: rgb(0, 0, 0);">}<br />
</span></div>
<br />
解决方法:使用ElementHandler解析文件<br />
<br />
通过查API可以发现ElementHandler接口,下面是接口的介绍<br />
<br />
<div style="background-color: rgb(238, 238, 238); font-size: 13px; border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; width: 98%;"><span style="color: rgb(0, 0, 0);">ElementHandler&nbsp;</span><span style="color: rgb(0, 0, 255);">interface</span><span style="color: rgb(0, 0, 0);">&nbsp;defines&nbsp;a&nbsp;handler&nbsp;of&nbsp;Element&nbsp;objects.&nbsp;It&nbsp;is&nbsp;used&nbsp;primarily&nbsp;in&nbsp;event&nbsp;based&nbsp;processing&nbsp;models&nbsp;such&nbsp;as&nbsp;</span><span style="color: rgb(0, 0, 255);">for</span><span style="color: rgb(0, 0, 0);"> <br />
processing&nbsp;large&nbsp;XML&nbsp;documents&nbsp;as&nbsp;they&nbsp;are&nbsp;being&nbsp;parsed&nbsp;rather&nbsp;than&nbsp;waiting&nbsp;until&nbsp;the&nbsp;whole&nbsp;document&nbsp;is&nbsp;parsed. <br />
</span></div>
<br />
好了,它就是我们想要的,通过实现以下两个method,就可以达成我们的需求<br />
<br />
onEnd(ElementPath elementPath)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Called by an event based processor when an elements closing tag is encountered.<br />
onStart(ElementPath elementPath)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Called by an event based processor when an elements openning tag is encountered.<br />
<br />
下面是代码<br />
<br />
<div style="background-color: rgb(238, 238, 238); font-size: 13px; border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; width: 98%;"><span style="color: rgb(0, 0, 0);">FileInputStream&nbsp;fis&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);">&nbsp;FileInputStream(addPath);<br />
SAXReader&nbsp;reader&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);">&nbsp;SAXReader();<br />
ElementHandler&nbsp;addHandler&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);">&nbsp;MyElementHandler();&nbsp;&nbsp;</span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">建立&nbsp;MyElementHandler&nbsp;的实例</span><span style="color: rgb(0, 128, 0);"><br />
</span><span style="color: rgb(0, 0, 0);">reader.addHandler(</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">/root/test1</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">,&nbsp;addHandler);&nbsp;</span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">&nbsp;节点</span><span style="color: rgb(0, 128, 0);"><br />
</span><span style="color: rgb(0, 0, 0);">reader.addHandler(</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">/root/test2</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">,&nbsp;addHandler);&nbsp;</span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">&nbsp;节点</span><span style="color: rgb(0, 128, 0);"><br />
</span><span style="color: rgb(0, 0, 0);">reader.read(fis);</span></div>
<br />
...<br />
<br />
<div style="background-color: rgb(238, 238, 238); font-size: 13px; border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; width: 98%;"><span style="color: rgb(0, 0, 255);">class</span><span style="color: rgb(0, 0, 0);">&nbsp;MyElementHandler&nbsp;</span><span style="color: rgb(0, 0, 255);">implements</span><span style="color: rgb(0, 0, 0);">&nbsp;ElementHandler&nbsp;{<br />
&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);">&nbsp;onStart(ElementPath&nbsp;ep)&nbsp;{}<br />
&nbsp;&nbsp;<br />
&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);">&nbsp;onEnd(ElementPath&nbsp;ep)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;Element&nbsp;e&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;ep.getCurrent();&nbsp;</span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">&nbsp;获得当前节点<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">&nbsp;对节点进行操作。。。</span><span style="color: rgb(0, 128, 0);"><br />
</span><span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;e.detach();&nbsp;</span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">&nbsp;处理完当前节点后，将其从dom树中剪除</span><span style="color: rgb(0, 128, 0);"><br />
</span><span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;}<br />
}</span></div>
<br />
因为每次处理完一个节点后并没有保存在dom树中，所以不会出现内存溢出的情况<br />
上面的省略了一些业务代码,不知道你是否明白或有更好的方法,可以和我联系QQ:34174409<br />
<br />
<strong>2.BOM头问题</strong><br />
<br />
使用java.io.Reader读取XML文件进行解析时出现异常<br />
org.dom4j.DocumentException: Error on line 1 of document : Content is not allowed in prolog.<br />
Nested exception: <br />
org.xml.sax.SAXParseException: Content is not allowed in prolog.<br />
原因在于:UTF-8编码文件存在BOM头，Reader类无法正确识别<br />
<br />
解决方法：<br />
(1).使用16进制编辑器手动删除BOM头<br />
<br />
这个...自行解决<br />
<br />
(2).InputStream读取流中前面的字符，看是否有BOM,如果有BOM,干掉BOM头<br />
<br />
<div style="background-color: rgb(238, 238, 238); font-size: 13px; border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; width: 98%;"><span style="color: rgb(0, 0, 0);">PushbackInputStream&nbsp;pis&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);">&nbsp;PushbackInputStream(in);<br />
</span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);">&nbsp;ch&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;pis.read();<br />
</span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);">&nbsp;(ch&nbsp;</span><span style="color: rgb(0, 0, 0);">!=</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">0xEF</span><span style="color: rgb(0, 0, 0);">){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;testin.unread(ch);<br />
}&nbsp;</span><span style="color: rgb(0, 0, 255);">else</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);">&nbsp;((ch&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;pis.read())&nbsp;</span><span style="color: rgb(0, 0, 0);">!=</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">0xBB</span><span style="color: rgb(0, 0, 0);">){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pis.unread(ch);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pis.unread(</span><span style="color: rgb(0, 0, 0);">0xef</span><span style="color: rgb(0, 0, 0);">);<br />
}&nbsp;</span><span style="color: rgb(0, 0, 255);">else</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);">&nbsp;((ch&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;pis.read())&nbsp;</span><span style="color: rgb(0, 0, 0);">!=</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">0xBF</span><span style="color: rgb(0, 0, 0);">){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">throw</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);">&nbsp;IOException(</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">wrong&nbsp;format</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">);<br />
}&nbsp;</span><span style="color: rgb(0, 0, 255);">else</span><span style="color: rgb(0, 0, 0);"><br />
{<br />
}</span></div>
<br />
(3).InputStream读取完文件，干掉BOM头<br />
<br />
<div style="background-color: rgb(238, 238, 238); font-size: 13px; border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; width: 98%;"><span style="color: rgb(0, 0, 0);">FileInputStream&nbsp;fin&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);">&nbsp;FileInputStream(fileName);<br />
</span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">写入临时文件</span><span style="color: rgb(0, 128, 0);"><br />
</span><span style="color: rgb(0, 0, 0);">InputStream&nbsp;in&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;getInputStream(fin);<br />
String&nbsp;tmpFileName&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;fileName&nbsp;</span><span style="color: rgb(0, 0, 0);">+</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">.tmp</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">;<br />
FileOutputStream&nbsp;out&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);">&nbsp;FileOutputStream(tmpFileName);<br />
</span><span style="color: rgb(0, 0, 255);">byte</span><span style="color: rgb(0, 0, 0);">&nbsp;b[]&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">byte</span><span style="color: rgb(0, 0, 0);">[</span><span style="color: rgb(0, 0, 0);">4096</span><span style="color: rgb(0, 0, 0);">];<br />
<br />
</span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);">&nbsp;len&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">0</span><span style="color: rgb(0, 0, 0);">;<br />
</span><span style="color: rgb(0, 0, 255);">while</span><span style="color: rgb(0, 0, 0);">&nbsp;(in.available()&nbsp;</span><span style="color: rgb(0, 0, 0);">&gt;</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">0</span><span style="color: rgb(0, 0, 0);">){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;len&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;in.read(b,&nbsp;</span><span style="color: rgb(0, 0, 0);">0</span><span style="color: rgb(0, 0, 0);">,&nbsp;</span><span style="color: rgb(0, 0, 0);">4096</span><span style="color: rgb(0, 0, 0);">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;out.write(b,&nbsp;</span><span style="color: rgb(0, 0, 0);">0</span><span style="color: rgb(0, 0, 0);">,&nbsp;len);<br />
}<br />
in.close();<br />
fin.close();<br />
out.close();<br />
<br />
</span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">临时文件写完，开始将临时文件写回本文件。</span><span style="color: rgb(0, 128, 0);"><br />
</span><span style="color: rgb(0, 0, 0);">in&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);">&nbsp;FileInputStream(tmpFileName);<br />
System.out.println(</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">[</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">+</span><span style="color: rgb(0, 0, 0);">&nbsp;fileName&nbsp;</span><span style="color: rgb(0, 0, 0);">+</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">]</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">);<br />
out&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);">&nbsp;FileOutputStream(fileName);<br />
<br />
</span><span style="color: rgb(0, 0, 255);">while</span><span style="color: rgb(0, 0, 0);">&nbsp;(in.available()&nbsp;</span><span style="color: rgb(0, 0, 0);">&gt;</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">0</span><span style="color: rgb(0, 0, 0);">){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;len&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;in.read(b,&nbsp;</span><span style="color: rgb(0, 0, 0);">0</span><span style="color: rgb(0, 0, 0);">,&nbsp;</span><span style="color: rgb(0, 0, 0);">4096</span><span style="color: rgb(0, 0, 0);">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;out.write(b,&nbsp;</span><span style="color: rgb(0, 0, 0);">0</span><span style="color: rgb(0, 0, 0);">,&nbsp;len);<br />
}<br />
in.close();<br />
out.close();</span></div>
<br />
<strong>(3).非法XML字符串</strong><br />
<br />
解析XML文件时出现非法字符的Exception（即使该字符位于CDATA段内）：&nbsp;&nbsp;&nbsp; org.xml.sax.SAXParseException: An invalid XML character (Unicode: 0xb) was found in the CDATA section.<br />
原因在于:根据W3C标准，有一些字符不能出现在XML文件中：<br />
&nbsp;&nbsp;&nbsp; 0x00 - 0x08<br />
&nbsp;&nbsp;&nbsp; 0x0b - 0x0c<br />
&nbsp;&nbsp;&nbsp; 0x0e - 0x1f<br />
解析XML时遇到这些字符就会出错<br />
<br />
解决方法：<br />
对有可能出问题的XML文件，进行字符过滤后再进行解析。<br />
<br />
<div style="background-color: rgb(238, 238, 238); font-size: 13px; border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; width: 98%;"><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">static</span><span style="color: rgb(0, 0, 0);">&nbsp;String&nbsp;stripNonValidXMLChars(String&nbsp;str)&nbsp;{<br />
&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);">&nbsp;(str&nbsp;</span><span style="color: rgb(0, 0, 0);">==</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">null</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">||</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">""</span><span style="color: rgb(0, 0, 0);">.equals(str))&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);">&nbsp;str;<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);">&nbsp;str.replaceAll(</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">[\\x00-\\x08\\x0b-\\x0c\\x0e-\\x1f]</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">,&nbsp;</span><span style="color: rgb(0, 0, 0);">""</span><span style="color: rgb(0, 0, 0);">);<br />
}</span></div>
<br />
<br />
----------------------------------------<br />
<br />
by 陈于喆 <br />
QQ:34174409<br />
Mail: chenyz@corp.netease.com
<br />
<br />
<br />
<img src ="http://www.blogjava.net/dongbule/aggbug/333262.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/dongbule/" target="_blank">陈于喆</a> 2010-09-28 17:10 <a href="http://www.blogjava.net/dongbule/archive/2010/09/28/333262.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>