﻿<?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-stone2083-随笔分类-java</title><link>http://www.blogjava.net/stone2083/category/28155.html</link><description /><language>zh-cn</language><lastBuildDate>Tue, 17 May 2022 02:50:01 GMT</lastBuildDate><pubDate>Tue, 17 May 2022 02:50:01 GMT</pubDate><ttl>60</ttl><item><title>Camunda学习点滴</title><link>http://www.blogjava.net/stone2083/archive/2022/05/16/450746.html</link><dc:creator>stone2083</dc:creator><author>stone2083</author><pubDate>Mon, 16 May 2022 02:10:00 GMT</pubDate><guid>http://www.blogjava.net/stone2083/archive/2022/05/16/450746.html</guid><wfw:comment>http://www.blogjava.net/stone2083/comments/450746.html</wfw:comment><comments>http://www.blogjava.net/stone2083/archive/2022/05/16/450746.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/stone2083/comments/commentRss/450746.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/stone2083/services/trackbacks/450746.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 1. 主要包括：<br>    架构总览、核心概念关系、场景例子、源码分析<br>2. 建议阅读顺序<br>    2.1 从架构总览，了解整体camunda概念，包括DB表结构，内心有概念和底层存储的关系映射<br>    2.2 再解核心概念关系，建立业务概念、代码模型、表结构的映射关系<br>    2.3 通过场景例子，了解不同概念的使用场景，配置<br>    2.4 通过源码分析，了解底层实现，方便必要时对其做扩展&nbsp;&nbsp;<a href='http://www.blogjava.net/stone2083/archive/2022/05/16/450746.html'>阅读全文</a><img src ="http://www.blogjava.net/stone2083/aggbug/450746.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/stone2083/" target="_blank">stone2083</a> 2022-05-16 10:10 <a href="http://www.blogjava.net/stone2083/archive/2022/05/16/450746.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>获得Java对象内存占用大小</title><link>http://www.blogjava.net/stone2083/archive/2013/06/08/400410.html</link><dc:creator>stone2083</dc:creator><author>stone2083</author><pubDate>Sat, 08 Jun 2013 09:32:00 GMT</pubDate><guid>http://www.blogjava.net/stone2083/archive/2013/06/08/400410.html</guid><wfw:comment>http://www.blogjava.net/stone2083/comments/400410.html</wfw:comment><comments>http://www.blogjava.net/stone2083/archive/2013/06/08/400410.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/stone2083/comments/commentRss/400410.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/stone2083/services/trackbacks/400410.html</trackback:ping><description><![CDATA[懒惰，直接上代码，用法见JAVA DOC.<br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008080; ">&nbsp; 1</span>&nbsp;<span style="color: #0000FF; ">package</span>&nbsp;com.alibaba.stonelab.javalab.jvm.sizeof;<br /><span style="color: #008080; ">&nbsp;&nbsp;2</span>&nbsp;<br /><span style="color: #008080; ">&nbsp;&nbsp;3</span>&nbsp;<span style="color: #0000FF; ">import</span>&nbsp;java.lang.instrument.Instrumentation;<br /><span style="color: #008080; ">&nbsp;&nbsp;4</span>&nbsp;<span style="color: #0000FF; ">import</span>&nbsp;java.lang.reflect.Array;<br /><span style="color: #008080; ">&nbsp;&nbsp;5</span>&nbsp;<span style="color: #0000FF; ">import</span>&nbsp;java.lang.reflect.Field;<br /><span style="color: #008080; ">&nbsp;&nbsp;6</span>&nbsp;<span style="color: #0000FF; ">import</span>&nbsp;java.lang.reflect.Modifier;<br /><span style="color: #008080; ">&nbsp;&nbsp;7</span>&nbsp;<span style="color: #0000FF; ">import</span>&nbsp;java.util.IdentityHashMap;<br /><span style="color: #008080; ">&nbsp;&nbsp;8</span>&nbsp;<span style="color: #0000FF; ">import</span>&nbsp;java.util.Map;<br /><span style="color: #008080; ">&nbsp;&nbsp;9</span>&nbsp;<span style="color: #0000FF; ">import</span>&nbsp;java.util.Stack;<br /><span style="color: #008080; ">&nbsp;10</span>&nbsp;<br /><span style="color: #008080; ">&nbsp;11</span>&nbsp;<span style="color: #008000; ">/**</span><span style="color: #008000; "><br /></span><span style="color: #008080; ">&nbsp;12</span>&nbsp;<span style="color: #008000; ">&nbsp;*&nbsp;&lt;pre&gt;<br /></span><span style="color: #008080; ">&nbsp;13</span>&nbsp;<span style="color: #008000; ">&nbsp;*&nbsp;1.&nbsp;MANIFEST.MF<br /></span><span style="color: #008080; ">&nbsp;14</span>&nbsp;<span style="color: #008000; ">&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Premain-Class:&nbsp;xxx.yyy.zzz.JavaSizeOf<br /></span><span style="color: #008080; ">&nbsp;15</span>&nbsp;<span style="color: #008000; ">&nbsp;*&nbsp;<br /></span><span style="color: #008080; ">&nbsp;16</span>&nbsp;<span style="color: #008000; ">&nbsp;*&nbsp;2.&nbsp;MAIN.JAVA<br /></span><span style="color: #008080; ">&nbsp;17</span>&nbsp;<span style="color: #008000; ">&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(JavaSizeOf.sizeof(new&nbsp;ConcurrentHashMap&lt;Object,&nbsp;Object&gt;()));<br /></span><span style="color: #008080; ">&nbsp;18</span>&nbsp;<span style="color: #008000; ">&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(JavaSizeOf.sizeof(new&nbsp;String("1234567")));<br /></span><span style="color: #008080; ">&nbsp;19</span>&nbsp;<span style="color: #008000; ">&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(JavaSizeOf.sizeof(new&nbsp;String("1234")));<br /></span><span style="color: #008080; ">&nbsp;20</span>&nbsp;<span style="color: #008000; ">&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(JavaSizeOf.sizeof(new&nbsp;Object()));<br /></span><span style="color: #008080; ">&nbsp;21</span>&nbsp;<span style="color: #008000; ">&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(JavaSizeOf.sizeof(new&nbsp;int[]&nbsp;{&nbsp;1,&nbsp;2,&nbsp;3&nbsp;}));<br /></span><span style="color: #008080; ">&nbsp;22</span>&nbsp;<span style="color: #008000; ">&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(JavaSizeOf.sizeof(new&nbsp;CopyOnWriteArrayList&lt;Object&gt;()));<br /></span><span style="color: #008080; ">&nbsp;23</span>&nbsp;<span style="color: #008000; ">&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(JavaSizeOf.sizeof(null));<br /></span><span style="color: #008080; ">&nbsp;24</span>&nbsp;<span style="color: #008000; ">&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br /></span><span style="color: #008080; ">&nbsp;25</span>&nbsp;<span style="color: #008000; ">&nbsp;*&nbsp;3.&nbsp;USAGE:<br /></span><span style="color: #008080; ">&nbsp;26</span>&nbsp;<span style="color: #008000; ">&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;java&nbsp;-javaagent:sizeof.jar&nbsp;xxx.yyy.zzz.Main<br /></span><span style="color: #008080; ">&nbsp;27</span>&nbsp;<span style="color: #008000; ">&nbsp;*&nbsp;&lt;/pre&gt;<br /></span><span style="color: #008080; ">&nbsp;28</span>&nbsp;<span style="color: #008000; ">&nbsp;*&nbsp;<br /></span><span style="color: #008080; ">&nbsp;29</span>&nbsp;<span style="color: #008000; ">&nbsp;*&nbsp;</span><span style="color: #808080; ">@author</span><span style="color: #008000; ">&nbsp;&lt;a&nbsp;href="mailto:li.jinl@alibaba-inc.com"&gt;Stone.J&lt;/a&gt;&nbsp;2013-6-8<br /></span><span style="color: #008080; ">&nbsp;30</span>&nbsp;<span style="color: #008000; ">&nbsp;</span><span style="color: #008000; ">*/</span><br /><span style="color: #008080; ">&nbsp;31</span>&nbsp;<span style="color: #0000FF; ">public</span>&nbsp;<span style="color: #0000FF; ">class</span>&nbsp;JavaSizeOf&nbsp;{<br /><span style="color: #008080; ">&nbsp;32</span>&nbsp;<br /><span style="color: #008080; ">&nbsp;33</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">private</span>&nbsp;<span style="color: #0000FF; ">static</span>&nbsp;Instrumentation&nbsp;inst;<br /><span style="color: #008080; ">&nbsp;34</span>&nbsp;<br /><span style="color: #008080; ">&nbsp;35</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">public</span>&nbsp;<span style="color: #0000FF; ">static</span>&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;premain(String&nbsp;agentArgs,&nbsp;Instrumentation&nbsp;inst)&nbsp;{<br /><span style="color: #008080; ">&nbsp;36</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;JavaSizeOf.inst&nbsp;=&nbsp;inst;<br /><span style="color: #008080; ">&nbsp;37</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><span style="color: #008080; ">&nbsp;38</span>&nbsp;<br /><span style="color: #008080; ">&nbsp;39</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">/**</span><span style="color: #008000; "><br /></span><span style="color: #008080; ">&nbsp;40</span>&nbsp;<span style="color: #008000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;get&nbsp;size&nbsp;of&nbsp;java&nbsp;object.<br /></span><span style="color: #008080; ">&nbsp;41</span>&nbsp;<span style="color: #008000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;<br /></span><span style="color: #008080; ">&nbsp;42</span>&nbsp;<span style="color: #008000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: #808080; ">@param</span><span style="color: #008000; ">&nbsp;o<br /></span><span style="color: #008080; ">&nbsp;43</span>&nbsp;<span style="color: #008000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: #808080; ">@return</span><span style="color: #008000; "><br /></span><span style="color: #008080; ">&nbsp;44</span>&nbsp;<span style="color: #008000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">*/</span><br /><span style="color: #008080; ">&nbsp;45</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">public</span>&nbsp;<span style="color: #0000FF; ">static</span>&nbsp;<span style="color: #0000FF; ">long</span>&nbsp;sizeof(Object&nbsp;o)&nbsp;{<br /><span style="color: #008080; ">&nbsp;46</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">assert</span>&nbsp;inst&nbsp;!=&nbsp;<span style="color: #0000FF; ">null</span>;<br /><span style="color: #008080; ">&nbsp;47</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Map&lt;Object,&nbsp;Object&gt;&nbsp;visited&nbsp;=&nbsp;<span style="color: #0000FF; ">new</span>&nbsp;IdentityHashMap&lt;Object,&nbsp;Object&gt;();<br /><span style="color: #008080; ">&nbsp;48</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Stack&lt;Object&gt;&nbsp;visiting&nbsp;=&nbsp;<span style="color: #0000FF; ">new</span>&nbsp;Stack&lt;Object&gt;();<br /><span style="color: #008080; ">&nbsp;49</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;visiting.add(o);<br /><span style="color: #008080; ">&nbsp;50</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">long</span>&nbsp;size&nbsp;=&nbsp;0;<br /><span style="color: #008080; ">&nbsp;51</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">while</span>&nbsp;(!visiting.isEmpty())&nbsp;{<br /><span style="color: #008080; ">&nbsp;52</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;size&nbsp;+=&nbsp;analysis(visiting,&nbsp;visited);<br /><span style="color: #008080; ">&nbsp;53</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><span style="color: #008080; ">&nbsp;54</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;size;<br /><span style="color: #008080; ">&nbsp;55</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><span style="color: #008080; ">&nbsp;56</span>&nbsp;<br /><span style="color: #008080; ">&nbsp;57</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">/**</span><span style="color: #008000; "><br /></span><span style="color: #008080; ">&nbsp;58</span>&nbsp;<span style="color: #008000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;analysis&nbsp;java&nbsp;object&nbsp;size&nbsp;recursively.<br /></span><span style="color: #008080; ">&nbsp;59</span>&nbsp;<span style="color: #008000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;<br /></span><span style="color: #008080; ">&nbsp;60</span>&nbsp;<span style="color: #008000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: #808080; ">@param</span><span style="color: #008000; ">&nbsp;visiting<br /></span><span style="color: #008080; ">&nbsp;61</span>&nbsp;<span style="color: #008000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: #808080; ">@param</span><span style="color: #008000; ">&nbsp;visited<br /></span><span style="color: #008080; ">&nbsp;62</span>&nbsp;<span style="color: #008000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: #808080; ">@return</span><span style="color: #008000; "><br /></span><span style="color: #008080; ">&nbsp;63</span>&nbsp;<span style="color: #008000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">*/</span><br /><span style="color: #008080; ">&nbsp;64</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">protected</span>&nbsp;<span style="color: #0000FF; ">static</span>&nbsp;<span style="color: #0000FF; ">long</span>&nbsp;analysis(Stack&lt;Object&gt;&nbsp;visiting,&nbsp;Map&lt;Object,&nbsp;Object&gt;&nbsp;visited)&nbsp;{<br /><span style="color: #008080; ">&nbsp;65</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Object&nbsp;o&nbsp;=&nbsp;visiting.pop();<br /><span style="color: #008080; ">&nbsp;66</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(skip(o,&nbsp;visited))&nbsp;{<br /><span style="color: #008080; ">&nbsp;67</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;0;<br /><span style="color: #008080; ">&nbsp;68</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><span style="color: #008080; ">&nbsp;69</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;visited.put(o,&nbsp;<span style="color: #0000FF; ">null</span>);<br /><span style="color: #008080; ">&nbsp;70</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;array.</span><span style="color: #008000; "><br /></span><span style="color: #008080; ">&nbsp;71</span>&nbsp;<span style="color: #008000; "></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(o.getClass().isArray()&nbsp;&amp;&amp;&nbsp;!o.getClass().getComponentType().isPrimitive())&nbsp;{<br /><span style="color: #008080; ">&nbsp;72</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(o.getClass().getName().length()&nbsp;!=&nbsp;2)&nbsp;{<br /><span style="color: #008080; ">&nbsp;73</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">for</span>&nbsp;(<span style="color: #0000FF; ">int</span>&nbsp;i&nbsp;=&nbsp;0;&nbsp;i&nbsp;&lt;&nbsp;Array.getLength(o);&nbsp;i++)&nbsp;{<br /><span style="color: #008080; ">&nbsp;74</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;visiting.add(Array.get(o,&nbsp;i));<br /><span style="color: #008080; ">&nbsp;75</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><span style="color: #008080; ">&nbsp;76</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><span style="color: #008080; ">&nbsp;77</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><span style="color: #008080; ">&nbsp;78</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;object.</span><span style="color: #008000; "><br /></span><span style="color: #008080; ">&nbsp;79</span>&nbsp;<span style="color: #008000; "></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">else</span>&nbsp;{<br /><span style="color: #008080; ">&nbsp;80</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Class&lt;?&gt;&nbsp;clazz&nbsp;=&nbsp;o.getClass();<br /><span style="color: #008080; ">&nbsp;81</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">while</span>&nbsp;(clazz&nbsp;!=&nbsp;<span style="color: #0000FF; ">null</span>)&nbsp;{<br /><span style="color: #008080; ">&nbsp;82</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Field[]&nbsp;fields&nbsp;=&nbsp;clazz.getDeclaredFields();<br /><span style="color: #008080; ">&nbsp;83</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">for</span>&nbsp;(Field&nbsp;field&nbsp;:&nbsp;fields)&nbsp;{<br /><span style="color: #008080; ">&nbsp;84</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(Modifier.isStatic(field.getModifiers()))&nbsp;{<br /><span style="color: #008080; ">&nbsp;85</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">continue</span>;<br /><span style="color: #008080; ">&nbsp;86</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><span style="color: #008080; ">&nbsp;87</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(field.getType().isPrimitive())&nbsp;{<br /><span style="color: #008080; ">&nbsp;88</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">continue</span>;<br /><span style="color: #008080; ">&nbsp;89</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><span style="color: #008080; ">&nbsp;90</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;field.setAccessible(<span style="color: #0000FF; ">true</span>);<br /><span style="color: #008080; ">&nbsp;91</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">try</span>&nbsp;{<br /><span style="color: #008080; ">&nbsp;92</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;visiting.add(field.get(o));<br /><span style="color: #008080; ">&nbsp;93</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<span style="color: #0000FF; ">catch</span>&nbsp;(Exception&nbsp;e)&nbsp;{<br /><span style="color: #008080; ">&nbsp;94</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">assert</span>&nbsp;<span style="color: #0000FF; ">false</span>;<br /><span style="color: #008080; ">&nbsp;95</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><span style="color: #008080; ">&nbsp;96</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><span style="color: #008080; ">&nbsp;97</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;clazz&nbsp;=&nbsp;clazz.getSuperclass();<br /><span style="color: #008080; ">&nbsp;98</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><span style="color: #008080; ">&nbsp;99</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><span style="color: #008080; ">100</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;inst.getObjectSize(o);<br /><span style="color: #008080; ">101</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><span style="color: #008080; ">102</span>&nbsp;<br /><span style="color: #008080; ">103</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">/**</span><span style="color: #008000; "><br /></span><span style="color: #008080; ">104</span>&nbsp;<span style="color: #008000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&lt;pre&gt;<br /></span><span style="color: #008080; ">105</span>&nbsp;<span style="color: #008000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;skip&nbsp;statistics.<br /></span><span style="color: #008080; ">106</span>&nbsp;<span style="color: #008000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&lt;/pre&gt;<br /></span><span style="color: #008080; ">107</span>&nbsp;<span style="color: #008000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;<br /></span><span style="color: #008080; ">108</span>&nbsp;<span style="color: #008000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: #808080; ">@param</span><span style="color: #008000; ">&nbsp;o<br /></span><span style="color: #008080; ">109</span>&nbsp;<span style="color: #008000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: #808080; ">@param</span><span style="color: #008000; ">&nbsp;visited<br /></span><span style="color: #008080; ">110</span>&nbsp;<span style="color: #008000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: #808080; ">@return</span><span style="color: #008000; "><br /></span><span style="color: #008080; ">111</span>&nbsp;<span style="color: #008000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">*/</span><br /><span style="color: #008080; ">112</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">protected</span>&nbsp;<span style="color: #0000FF; ">static</span>&nbsp;<span style="color: #0000FF; ">boolean</span>&nbsp;skip(Object&nbsp;o,&nbsp;Map&lt;Object,&nbsp;Object&gt;&nbsp;visited)&nbsp;{<br /><span style="color: #008080; ">113</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(o&nbsp;<span style="color: #0000FF; ">instanceof</span>&nbsp;String)&nbsp;{<br /><span style="color: #008080; ">114</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(o&nbsp;==&nbsp;((String)&nbsp;o).intern())&nbsp;{<br /><span style="color: #008080; ">115</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;<span style="color: #0000FF; ">true</span>;<br /><span style="color: #008080; ">116</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><span style="color: #008080; ">117</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><span style="color: #008080; ">118</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;o&nbsp;==&nbsp;<span style="color: #0000FF; ">null</span>&nbsp;||&nbsp;visited.containsKey(o);<br /><span style="color: #008080; ">119</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><span style="color: #008080; ">120</span>&nbsp;<br /><span style="color: #008080; ">121</span>&nbsp;}<br /><span style="color: #008080; ">122</span>&nbsp;</div><img src ="http://www.blogjava.net/stone2083/aggbug/400410.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/stone2083/" target="_blank">stone2083</a> 2013-06-08 17:32 <a href="http://www.blogjava.net/stone2083/archive/2013/06/08/400410.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Spring Data JPA 代码分析</title><link>http://www.blogjava.net/stone2083/archive/2011/08/25/357281.html</link><dc:creator>stone2083</dc:creator><author>stone2083</author><pubDate>Thu, 25 Aug 2011 08:28:00 GMT</pubDate><guid>http://www.blogjava.net/stone2083/archive/2011/08/25/357281.html</guid><wfw:comment>http://www.blogjava.net/stone2083/comments/357281.html</wfw:comment><comments>http://www.blogjava.net/stone2083/archive/2011/08/25/357281.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/stone2083/comments/commentRss/357281.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/stone2083/services/trackbacks/357281.html</trackback:ping><description><![CDATA[<strong>背景</strong><br />
接上文：<a title="Spring Data JPA 简单介绍" href="http://www.blogjava.net/stone2083/archive/2011/08/25/357262.html">Spring Data JPA 简单介绍</a>
<br />
本文将从配置解析，Bean的创建，Repository执行三个方面来简单介绍下Spring Data JPA的代码实现<br />
<br />友情提醒：<br />图片均可放大<br /><br />
<strong>
配置解析</strong><br />
1. parser类
<table border="0" cellspacing="2" cellpadding="2" width="100%">
     <tbody>
         <tr>
             <td colspan="1" width="50%" height=""><img src="http://www.blogjava.net/images/blogjava_net/stone2083/java/parser.png" width="600" height="385" alt="" /> </td>
             <td width="50%" height="">Spring通过Schema的方式进行配置，通过AbstractRepositoryConfigDefinitionParser进行解析。其中包含对NamedQuery的解析。<br />
             解析的主要目的，是将配置文件中的repositories和repository元素信息分别解析成GlobalRepositoryConfigInformation和SingleRepositoryConfigInformation。<br />
             详见下图</td>
         </tr>
     </tbody>
     <tbody>
     </tbody>
</table>
2. Information<br />
<table border="0" cellspacing="2" cellpadding="2" width="100%">
     <tbody>
         <tr>
             <td><img src="http://www.blogjava.net/images/blogjava_net/stone2083/config_information.png" width="800" height="378" alt="" /><br />
             </td>
             <td>CommonRepositoryConfigInformation:<br />
             xml中repositories的通用配置，一般对应其中的attributes<br />
             SingleRepositoryConfigInformation:<br />
             xml中repository的配置信息，对应其中的attributes<br />
             GlobalRepositoryCOnfigInformation:<br />
             一组SingleRepositoryConfigInfomation信息，包含所有的Single信息<br />
             在JPA实现中，针对Single，有两份实现，一份是自动配置信息，一份是手动配置信息，分别对应图中的Automatic和Manual。<br />
             SimpleJpaRepositoryConfiguration是JPA中的所有配置信息，包含所有的Jpa中的SingleRepositoryConfigInformation。</td>
         </tr>
     </tbody>
</table>
3. Query Lookup Strategy<br /><table border="0" cellspacing="2" cellpadding="2" width="100%" bordercolor=""><tbody><tr><td><img src="http://www.blogjava.net/images/blogjava_net/stone2083/java/query_lookup_strategy.png" width="600" height="437" alt="" /> </td><td>CreateQueryLookupStrategy:对应repositories元素<div style="display: inline-block; "><div>query-lookup-strategy的create值，主要针对method query方式<br />DeclaredQueryLookupStrategy:对应use-declared-query值，主要针对带有@Query注解的查询方式<br />CreateIfNotFoundQueryLookupStrategy:对应create-if-not-found值（default值），结合了上述两种方式</div></div></td></tr></tbody></table><br />
<br />
<strong>Bean的创建<br />
</strong>
<table border="0" cellspacing="2" cellpadding="2" width="500">
     <tbody>
         <tr>
             <td><img src="http://www.blogjava.net/images/blogjava_net/stone2083/java/jpa_factory_bean.png" width="1000" height="484" alt="" /><br />
             </td>
         </tr>
         <tr>
             <td>主要包含两个类<br />
             RepositoryFactoryBeanSupport, Spring Factory Bean，用于创建Reposiory代理类。其本身并不真正做代理的事情，只是接受Spring的配置，具体交由RepositoryFactorySupport进行代理工作<br />
             RepositoryFactorySupport, 真正做Repository代理工作，根据JpaRepositoryFactoryBean的定义找到TargetClass：SimpleJpaRepository实现类，中间加入3个拦截器，一个是异常翻译，一个是事务管理，最后一个是QueryExecutorMethodInterceptor。<br />
             QueryExecutorMethodInterceptor是个重点，主要做特定的Query（查询语句）的操作。</td>
         </tr>
     </tbody>
</table>
<br />
<strong>Repository执行<br />
</strong>1. 主要执行类<br />
<table border="0" cellspacing="2" cellpadding="2" width="100%" bordercolor="">
     <tbody>
         <tr>
             <td><img src="http://www.blogjava.net/images/blogjava_net/stone2083/java/jpa_repository.png" width="800" height="499" alt="" /> </td>
             <td>在看上面Bean定义的时候，其实已经明白了执行过程：<br />1. 将JPA CRUD规范相关的方法交给SimpleJpaRepository这个类执行<br />2. 将特殊查询相关的交给QueryExecutorMethodInterceptor执行。主要做自定义实现的部分，method query部分和named query部分。<br />具体查询类详见下图。</td>
         </tr>
     </tbody>
</table>
<br />
2. 查询相关<br /><table border="0" cellspacing="2" cellpadding="2" width="100%" bordercolor=""><tbody><tr><td><img src="http://www.blogjava.net/images/blogjava_net/stone2083/jpa_query.png" width="600" height="472" alt="" /></td><td>主要支持NamedQuery和JPA Query。</td></tr></tbody></table><br />
<br /><strong>主要执行代码<br /></strong><div>QueryExecutorMethodInterceptor#invoke(MethodInvocation invocation)</div><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008080; ">&nbsp;1</span>&nbsp;<span style="color: #0000FF; ">public</span><span style="color: #000000; ">&nbsp;Object&nbsp;invoke(MethodInvocation&nbsp;invocation)&nbsp;</span><span style="color: #0000FF; ">throws</span><span style="color: #000000; ">&nbsp;Throwable&nbsp;{<br /></span><span style="color: #008080; ">&nbsp;2</span>&nbsp;<span style="color: #000000; "><br /></span><span style="color: #008080; ">&nbsp;3</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Method&nbsp;method&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;invocation.getMethod();<br /></span><span style="color: #008080; ">&nbsp;4</span>&nbsp;<span style="color: #000000; "><br /></span><span style="color: #008080; ">&nbsp;5</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">&nbsp;(isCustomMethodInvocation(invocation))&nbsp;{<br /></span><span style="color: #008080; ">&nbsp;6</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Method&nbsp;actualMethod&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;repositoryInformation.getTargetClassMethod(method);<br /></span><span style="color: #008080; ">&nbsp;7</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;makeAccessible(actualMethod);<br /></span><span style="color: #008080; ">&nbsp;8</span>&nbsp;<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; ">return</span><span style="color: #000000; ">&nbsp;executeMethodOn(customImplementation,&nbsp;actualMethod,<br /></span><span style="color: #008080; ">&nbsp;9</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;invocation.getArguments());<br /></span><span style="color: #008080; ">10</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /></span><span style="color: #008080; ">11</span>&nbsp;<span style="color: #000000; "><br /></span><span style="color: #008080; ">12</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">&nbsp;(hasQueryFor(method))&nbsp;{<br /></span><span style="color: #008080; ">13</span>&nbsp;<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; ">return</span><span style="color: #000000; ">&nbsp;queries.get(method).execute(invocation.getArguments());<br /></span><span style="color: #008080; ">14</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /></span><span style="color: #008080; ">15</span>&nbsp;<span style="color: #000000; "><br /></span><span style="color: #008080; ">16</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;Lookup&nbsp;actual&nbsp;method&nbsp;as&nbsp;it&nbsp;might&nbsp;be&nbsp;redeclared&nbsp;in&nbsp;the&nbsp;interface<br /></span><span style="color: #008080; ">17</span>&nbsp;<span style="color: #008000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;and&nbsp;we&nbsp;have&nbsp;to&nbsp;use&nbsp;the&nbsp;repository&nbsp;instance&nbsp;nevertheless</span><span style="color: #008000; "><br /></span><span style="color: #008080; ">18</span>&nbsp;<span style="color: #008000; "></span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Method&nbsp;actualMethod&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;repositoryInformation.getTargetClassMethod(method);<br /></span><span style="color: #008080; ">19</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">&nbsp;executeMethodOn(target,&nbsp;actualMethod,<br /></span><span style="color: #008080; ">20</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;invocation.getArguments());<br /></span><span style="color: #008080; ">21</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></div>
<br />主要分3个步骤：<br />1. 如果配置文件中执行了接口类的实现类，则直接交给实现类处理<br />2. 判断是查询方法的，交给RepositoryQuery实现，具体又分:NamedQuery,SimpleJpaQuery,PartTreeJpaQuery<br />3. 不属于上述两个，则直接将其交给真正的targetClass执行，在JPA中，就交给SimpleJpaRepository执行。<br /><br />本文并没有做详细的分析，只是将核心的组件类一一点到，方便大家自行深入了解代码。<img src ="http://www.blogjava.net/stone2083/aggbug/357281.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/stone2083/" target="_blank">stone2083</a> 2011-08-25 16:28 <a href="http://www.blogjava.net/stone2083/archive/2011/08/25/357281.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Spring Data JPA 简单介绍 </title><link>http://www.blogjava.net/stone2083/archive/2011/08/25/357262.html</link><dc:creator>stone2083</dc:creator><author>stone2083</author><pubDate>Thu, 25 Aug 2011 07:18:00 GMT</pubDate><guid>http://www.blogjava.net/stone2083/archive/2011/08/25/357262.html</guid><wfw:comment>http://www.blogjava.net/stone2083/comments/357262.html</wfw:comment><comments>http://www.blogjava.net/stone2083/archive/2011/08/25/357262.html#Feedback</comments><slash:comments>12</slash:comments><wfw:commentRss>http://www.blogjava.net/stone2083/comments/commentRss/357262.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/stone2083/services/trackbacks/357262.html</trackback:ping><description><![CDATA[<strong>背景</strong><br />考虑到公司应用中数据库访问的多样性和复杂性，目前正在开发UDSL（统一数据访问层），开发到一半的时候，偶遇<a href="http://www.springsource.org/spring-data">SpringData</a>工程。发现两者的思路惊人的一致。<br />于是就花了点时间了解SpringData，可能UDSL II期会基于SpringData做扩展<br /><br /><strong>SpringData相关资料</strong><br />介绍：针对关系型数据库，KV数据库，Document数据库，Graph数据库，Map-Reduce等一些主流数据库，采用统一技术进行访问，并且尽可能简化访问手段。<br />目前已支持的数据库有（主要）：<font class="Apple-style-span" face="Arial, Helvetica, sans-serif"><span class="Apple-style-span" style="font-size: 12px; line-height: normal">MongoDB，Neo4j，Redis，Hadoop，JPA等<br /></span></font><br />SpringData官方资料（强烈推荐，文档非常详细）<br />SpringData主页：<a href="http://www.springsource.org/spring-data">http://www.springsource.org/spring-data</a><br />SpringDataJPA 指南文档：<a href="http://static.springsource.org/spring-data/data-jpa/docs/current/reference/html/">http://static.springsource.org/spring-data/data-jpa/docs/current/reference/html/</a>&nbsp;（非常详细）<br />SpringDataJPA Examples：&nbsp;https://github.com/SpringSource/spring-data-jpa-examples （非常详细的例子）<br /><br /><strong>Spring-Data-Jpa简介</strong><br />Spring Data Jpa 极大简化了数据库访问层代码，只要3步，就能搞定一切<br />1. 编写Entity类，依照JPA规范，定义实体<br />2. 编写Repository接口，依靠SpringData规范，定义数据访问接口（注意，只要接口，不需要任何实现）<br />3. 写一小陀配置文件 （Spring Scheme配置方式极大地简化了配置方式）<br /><br />下面，我依赖Example中的例子，简单地介绍下以上几个步骤<br />User.java<br />
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><img id="Code_Closed_Image_143814" onclick="this.style.display='none'; Code_Closed_Text_143814.style.display='none'; Code_Open_Image_143814.style.display='inline'; Code_Open_Text_143814.style.display='inline';" height="16" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" width="11" align="top"><img id="Code_Open_Image_143814" style="display: none" onclick="this.style.display='none'; Code_Open_Text_143814.style.display='none'; Code_Closed_Image_143814.style.display='inline'; Code_Closed_Text_143814.style.display='inline';" height="16" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" width="11" align="top"><span id="Code_Closed_Text_143814" style="border-right: #808080 1px solid; border-top: #808080 1px solid; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff">User.java</span><span id="Code_Open_Text_143814" style="display: none"><br />
<!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #008080">&nbsp;1</span>&nbsp;<span style="color: #008000">/**</span><span style="color: #008000"><br /></span><span style="color: #008080">&nbsp;2</span>&nbsp;<span style="color: #008000">&nbsp;*&nbsp;User&nbsp;Entity&nbsp;Sample<br /></span><span style="color: #008080">&nbsp;3</span>&nbsp;<span style="color: #008000">&nbsp;*&nbsp;<br /></span><span style="color: #008080">&nbsp;4</span>&nbsp;<span style="color: #008000">&nbsp;*&nbsp;</span><span style="color: #808080">@author</span><span style="color: #008000">&nbsp;&lt;a&nbsp;href="mailto:li.jinl@alibaba-inc.com"&gt;Stone.J&lt;/a&gt;&nbsp;Aug&nbsp;25,&nbsp;2011<br /></span><span style="color: #008080">&nbsp;5</span>&nbsp;<span style="color: #008000">&nbsp;</span><span style="color: #008000">*/</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;6</span>&nbsp;<span style="color: #000000">@Entity<br /></span><span style="color: #008080">&nbsp;7</span>&nbsp;<span style="color: #000000"></span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;User&nbsp;</span><span style="color: #0000ff">extends</span><span style="color: #000000">&nbsp;AbstractPersistable</span><span style="color: #000000">&lt;</span><span style="color: #000000">Long</span><span style="color: #000000">&gt;</span><span style="color: #000000">&nbsp;{<br /></span><span style="color: #008080">&nbsp;8</span>&nbsp;<span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;9</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&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">long</span><span style="color: #000000">&nbsp;serialVersionUID&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">-</span><span style="color: #000000">2952735933715107252L</span><span style="color: #000000">;<br /></span><span style="color: #008080">10</span>&nbsp;<span style="color: #000000"><br /></span><span style="color: #008080">11</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;@Column(unique&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">true</span><span style="color: #000000">)<br /></span><span style="color: #008080">12</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">private</span><span style="color: #000000">&nbsp;String&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;username;<br /></span><span style="color: #008080">13</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">private</span><span style="color: #000000">&nbsp;String&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;firstname;<br /></span><span style="color: #008080">14</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">private</span><span style="color: #000000">&nbsp;String&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lastname;<br /></span><span style="color: #008080">15</span>&nbsp;<span style="color: #000000"><br /></span><span style="color: #008080">16</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;String&nbsp;getUsername()&nbsp;{<br /></span><span style="color: #008080">17</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;username;<br /></span><span style="color: #008080">18</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;}<br /></span><span style="color: #008080">19</span>&nbsp;<span style="color: #000000"><br /></span><span style="color: #008080">20</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;setUsername(String&nbsp;username)&nbsp;{<br /></span><span style="color: #008080">21</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">this</span><span style="color: #000000">.username&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;username;<br /></span><span style="color: #008080">22</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;}<br /></span><span style="color: #008080">23</span>&nbsp;<span style="color: #000000"><br /></span><span style="color: #008080">24</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;String&nbsp;getFirstname()&nbsp;{<br /></span><span style="color: #008080">25</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;firstname;<br /></span><span style="color: #008080">26</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;}<br /></span><span style="color: #008080">27</span>&nbsp;<span style="color: #000000"><br /></span><span style="color: #008080">28</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;setFirstname(String&nbsp;firstname)&nbsp;{<br /></span><span style="color: #008080">29</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">this</span><span style="color: #000000">.firstname&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;firstname;<br /></span><span style="color: #008080">30</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;}<br /></span><span style="color: #008080">31</span>&nbsp;<span style="color: #000000"><br /></span><span style="color: #008080">32</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;String&nbsp;getLastname()&nbsp;{<br /></span><span style="color: #008080">33</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;lastname;<br /></span><span style="color: #008080">34</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;}<br /></span><span style="color: #008080">35</span>&nbsp;<span style="color: #000000"><br /></span><span style="color: #008080">36</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;setLastname(String&nbsp;lastname)&nbsp;{<br /></span><span style="color: #008080">37</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">this</span><span style="color: #000000">.lastname&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;lastname;<br /></span><span style="color: #008080">38</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;}<br /></span><span style="color: #008080">39</span>&nbsp;<span style="color: #000000"></span></span></div>没什么技术，JPA规范要求怎么写，它就怎么写<br /><br />Repository.java<br />
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><img id="Code_Closed_Image_143903" onclick="this.style.display='none'; Code_Closed_Text_143903.style.display='none'; Code_Open_Image_143903.style.display='inline'; Code_Open_Text_143903.style.display='inline';" height="16" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" width="11" align="top"><img id="Code_Open_Image_143903" style="display: none" onclick="this.style.display='none'; Code_Open_Text_143903.style.display='none'; Code_Closed_Image_143903.style.display='inline'; Code_Closed_Text_143903.style.display='inline';" height="16" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" width="11" align="top"><span id="Code_Closed_Text_143903" style="border-right: #808080 1px solid; border-top: #808080 1px solid; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff">SimpleUserRepository.java</span><span id="Code_Open_Text_143903" style="display: none"><br />
<!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #008080">&nbsp;1</span>&nbsp;<span style="color: #008000">/**</span><span style="color: #008000"><br /></span><span style="color: #008080">&nbsp;2</span>&nbsp;<span style="color: #008000">&nbsp;*&nbsp;User&nbsp;Repository&nbsp;Interface.<br /></span><span style="color: #008080">&nbsp;3</span>&nbsp;<span style="color: #008000">&nbsp;*&nbsp;<br /></span><span style="color: #008080">&nbsp;4</span>&nbsp;<span style="color: #008000">&nbsp;*&nbsp;</span><span style="color: #808080">@author</span><span style="color: #008000">&nbsp;&lt;a&nbsp;href="mailto:li.jinl@alibaba-inc.com"&gt;Stone.J&lt;/a&gt;&nbsp;Aug&nbsp;25,&nbsp;2011<br /></span><span style="color: #008080">&nbsp;5</span>&nbsp;<span style="color: #008000">&nbsp;</span><span style="color: #008000">*/</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;6</span>&nbsp;<span style="color: #000000"></span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">interface</span><span style="color: #000000">&nbsp;SimpleUserRepository&nbsp;</span><span style="color: #0000ff">extends</span><span style="color: #000000">&nbsp;CrudRepository</span><span style="color: #000000">&lt;</span><span style="color: #000000">User,&nbsp;Long</span><span style="color: #000000">&gt;</span><span style="color: #000000">,&nbsp;JpaSpecificationExecutor</span><span style="color: #000000">&lt;</span><span style="color: #000000">User</span><span style="color: #000000">&gt;</span><span style="color: #000000">&nbsp;{<br /></span><span style="color: #008080">&nbsp;7</span>&nbsp;<span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;8</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;User&nbsp;findByTheUsersName(String&nbsp;username);<br /></span><span style="color: #008080">&nbsp;9</span>&nbsp;<span style="color: #000000"><br /></span><span style="color: #008080">10</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;List</span><span style="color: #000000">&lt;</span><span style="color: #000000">User</span><span style="color: #000000">&gt;</span><span style="color: #000000">&nbsp;findByLastname(String&nbsp;lastname);<br /></span><span style="color: #008080">11</span>&nbsp;<span style="color: #000000"><br /></span><span style="color: #008080">12</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;@Query(</span><span style="color: #000000">"</span><span style="color: #000000">select&nbsp;u&nbsp;from&nbsp;User&nbsp;u&nbsp;where&nbsp;u.firstname&nbsp;=&nbsp;?</span><span style="color: #000000">"</span><span style="color: #000000">)<br /></span><span style="color: #008080">13</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;List</span><span style="color: #000000">&lt;</span><span style="color: #000000">User</span><span style="color: #000000">&gt;</span><span style="color: #000000">&nbsp;findByFirstname(String&nbsp;firstname);<br /></span><span style="color: #008080">14</span>&nbsp;<span style="color: #000000"><br /></span><span style="color: #008080">15</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;@Query(</span><span style="color: #000000">"</span><span style="color: #000000">select&nbsp;u&nbsp;from&nbsp;User&nbsp;u&nbsp;where&nbsp;u.firstname&nbsp;=&nbsp;:name&nbsp;or&nbsp;u.lastname&nbsp;=&nbsp;:name</span><span style="color: #000000">"</span><span style="color: #000000">)<br /></span><span style="color: #008080">16</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;List</span><span style="color: #000000">&lt;</span><span style="color: #000000">User</span><span style="color: #000000">&gt;</span><span style="color: #000000">&nbsp;findByFirstnameOrLastname(@Param(</span><span style="color: #000000">"</span><span style="color: #000000">name</span><span style="color: #000000">"</span><span style="color: #000000">)&nbsp;String&nbsp;name);<br /></span><span style="color: #008080">17</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;<br /></span><span style="color: #008080">18</span>&nbsp;<span style="color: #000000"></span></span></div>需要关注它继承的接口，我简单介绍几个核心接口<br />
<div>Repository： 仅仅是一个标识，表明任何继承它的均为仓库接口类，方便Spring自动扫描识别</div>
<div>CrudRepository： 继承Repository，实现了一组CRUD相关的方法<br />
<div>PagingAndSortingRepository： 继承CrudRepository，实现了一组分页排序相关的方法<br />
<div>JpaRepository： 继承PagingAndSortingRepository，实现一组JPA规范相关的方法<br />
<div>JpaSpecificationExecutor： 比较特殊，不属于Repository体系，实现一组JPA Criteria查询相关的方法<br /><br />不需要写任何实现类，Spring Data Jpa框架帮你搞定这一切。<br /><br />Spring Configuration<br />
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><img id="Code_Closed_Image_144827" onclick="this.style.display='none'; Code_Closed_Text_144827.style.display='none'; Code_Open_Image_144827.style.display='inline'; Code_Open_Text_144827.style.display='inline';" height="16" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" width="11" align="top"><img id="Code_Open_Image_144827" style="display: none" onclick="this.style.display='none'; Code_Open_Text_144827.style.display='none'; Code_Closed_Image_144827.style.display='inline'; Code_Closed_Text_144827.style.display='inline';" height="16" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" width="11" align="top"><span id="Code_Closed_Text_144827" style="border-right: #808080 1px solid; border-top: #808080 1px solid; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff">Configuration.xml</span><span id="Code_Open_Text_144827" style="display: none"><br />
<!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #008080">&nbsp;1</span>&nbsp;<span style="color: #000000">&lt;</span><span style="color: #000000">beans</span><span style="color: #000000">&gt;</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;2</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000">&lt;</span><span style="color: #000000">bean&nbsp;id</span><span style="color: #000000">=</span><span style="color: #000000">"</span><span style="color: #000000">entityManagerFactory</span><span style="color: #000000">"</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">class</span><span style="color: #000000">=</span><span style="color: #000000">"</span><span style="color: #000000">org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean</span><span style="color: #000000">"</span><span style="color: #000000">&gt;</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;3</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000">&lt;</span><span style="color: #000000">property&nbsp;name</span><span style="color: #000000">=</span><span style="color: #000000">"</span><span style="color: #000000">dataSource</span><span style="color: #000000">"</span><span style="color: #000000">&nbsp;ref</span><span style="color: #000000">=</span><span style="color: #000000">"</span><span style="color: #000000">dataSource</span><span style="color: #000000">"</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">/&gt;</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;4</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000">&lt;</span><span style="color: #000000">property&nbsp;name</span><span style="color: #000000">=</span><span style="color: #000000">"</span><span style="color: #000000">jpaVendorAdapter</span><span style="color: #000000">"</span><span style="color: #000000">&gt;</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;5</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000">&lt;</span><span style="color: #000000">bean&nbsp;</span><span style="color: #0000ff">class</span><span style="color: #000000">=</span><span style="color: #000000">"</span><span style="color: #000000">org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter</span><span style="color: #000000">"</span><span style="color: #000000">&gt;</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;6</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000">&lt;</span><span style="color: #000000">property&nbsp;name</span><span style="color: #000000">=</span><span style="color: #000000">"</span><span style="color: #000000">generateDdl</span><span style="color: #000000">"</span><span style="color: #000000">&nbsp;value</span><span style="color: #000000">=</span><span style="color: #000000">"</span><span style="color: #000000">true</span><span style="color: #000000">"</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">/&gt;</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;7</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000">&lt;</span><span style="color: #000000">property&nbsp;name</span><span style="color: #000000">=</span><span style="color: #000000">"</span><span style="color: #000000">database</span><span style="color: #000000">"</span><span style="color: #000000">&nbsp;value</span><span style="color: #000000">=</span><span style="color: #000000">"</span><span style="color: #000000">HSQL</span><span style="color: #000000">"</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">/&gt;</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;8</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000">&lt;/</span><span style="color: #000000">bean</span><span style="color: #000000">&gt;</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;9</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000">&lt;/</span><span style="color: #000000">property</span><span style="color: #000000">&gt;</span><span style="color: #000000"><br /></span><span style="color: #008080">10</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000">&lt;</span><span style="color: #000000">property&nbsp;name</span><span style="color: #000000">=</span><span style="color: #000000">"</span><span style="color: #000000">persistenceUnitName</span><span style="color: #000000">"</span><span style="color: #000000">&nbsp;value</span><span style="color: #000000">=</span><span style="color: #000000">"</span><span style="color: #000000">jpa.sample</span><span style="color: #000000">"</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">/&gt;</span><span style="color: #000000"><br /></span><span style="color: #008080">11</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000">&lt;/</span><span style="color: #000000">bean</span><span style="color: #000000">&gt;</span><span style="color: #000000"><br /></span><span style="color: #008080">12</span>&nbsp;<span style="color: #000000"><br /></span><span style="color: #008080">13</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000">&lt;</span><span style="color: #000000">bean&nbsp;id</span><span style="color: #000000">=</span><span style="color: #000000">"</span><span style="color: #000000">transactionManager</span><span style="color: #000000">"</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">class</span><span style="color: #000000">=</span><span style="color: #000000">"</span><span style="color: #000000">org.springframework.orm.jpa.JpaTransactionManager</span><span style="color: #000000">"</span><span style="color: #000000">&gt;</span><span style="color: #000000"><br /></span><span style="color: #008080">14</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000">&lt;</span><span style="color: #000000">property&nbsp;name</span><span style="color: #000000">=</span><span style="color: #000000">"</span><span style="color: #000000">entityManagerFactory</span><span style="color: #000000">"</span><span style="color: #000000">&nbsp;ref</span><span style="color: #000000">=</span><span style="color: #000000">"</span><span style="color: #000000">entityManagerFactory</span><span style="color: #000000">"</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">/&gt;</span><span style="color: #000000"><br /></span><span style="color: #008080">15</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000">&lt;/</span><span style="color: #000000">bean</span><span style="color: #000000">&gt;</span><span style="color: #000000"><br /></span><span style="color: #008080">16</span>&nbsp;<span style="color: #000000"><br /></span><span style="color: #008080">17</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000">&lt;</span><span style="color: #000000">jdbc:embedded</span><span style="color: #000000">-</span><span style="color: #000000">database&nbsp;id</span><span style="color: #000000">=</span><span style="color: #000000">"</span><span style="color: #000000">dataSource</span><span style="color: #000000">"</span><span style="color: #000000">&nbsp;type</span><span style="color: #000000">=</span><span style="color: #000000">"</span><span style="color: #000000">HSQL</span><span style="color: #000000">"</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">/&gt;</span><span style="color: #000000"><br /></span><span style="color: #008080">18</span>&nbsp;<span style="color: #000000"><br /></span><span style="color: #008080">19</span>&nbsp;<span style="color: #000000"><br /></span><span style="color: #008080">20</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000">&lt;</span><span style="color: #000000">jpa:repositories&nbsp;base</span><span style="color: #000000">-</span><span style="color: #0000ff">package</span><span style="color: #000000">=</span><span style="color: #000000">"</span><span style="color: #000000">org.springframework.data.jpa.example.repository.simple</span><span style="color: #000000">"</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">/&gt;</span><span style="color: #000000"><br /></span><span style="color: #008080">21</span>&nbsp;<span style="color: #000000"></span><span style="color: #000000">&lt;/</span><span style="color: #000000">beans&gt;</span><span style="color: #000000"></span></span></div><br />核心代码只要配置一行：&lt;jpa:repositories base-package="org.springframework.data.jpa.example.repository.simple" /&gt;即可。上面的仅仅是数据源，事务的配置而已。<br /><br />至此，大功告成，即可运行<br />
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><img id="Code_Closed_Image_150018" onclick="this.style.display='none'; Code_Closed_Text_150018.style.display='none'; Code_Open_Image_150018.style.display='inline'; Code_Open_Text_150018.style.display='inline';" height="16" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" width="11" align="top"><img id="Code_Open_Image_150018" style="display: none" onclick="this.style.display='none'; Code_Open_Text_150018.style.display='none'; Code_Closed_Image_150018.style.display='inline'; Code_Closed_Text_150018.style.display='inline';" height="16" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" width="11" align="top"><span id="Code_Closed_Text_150018" style="border-right: #808080 1px solid; border-top: #808080 1px solid; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff">Sample.java</span><span id="Code_Open_Text_150018" style="display: none"><br />
<!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #008080">&nbsp;1</span>&nbsp;<span style="color: #008000">/**</span><span style="color: #008000"><br /></span><span style="color: #008080">&nbsp;2</span>&nbsp;<span style="color: #008000">&nbsp;*&nbsp;Intergration&nbsp;test&nbsp;showing&nbsp;the&nbsp;basic&nbsp;usage&nbsp;of&nbsp;{</span><span style="color: #808080">@link</span><span style="color: #008000">&nbsp;SimpleUserRepository}.<br /></span><span style="color: #008080">&nbsp;3</span>&nbsp;<span style="color: #008000">&nbsp;*&nbsp;<br /></span><span style="color: #008080">&nbsp;4</span>&nbsp;<span style="color: #008000">&nbsp;*&nbsp;</span><span style="color: #808080">@author</span><span style="color: #008000">&nbsp;&lt;a&nbsp;href="mailto:li.jinl@alibaba-inc.com"&gt;Stone.J&lt;/a&gt;&nbsp;Aug&nbsp;25,&nbsp;2011<br /></span><span style="color: #008080">&nbsp;5</span>&nbsp;<span style="color: #008000">&nbsp;</span><span style="color: #008000">*/</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;6</span>&nbsp;<span style="color: #000000">@RunWith(SpringJUnit4ClassRunner.</span><span style="color: #0000ff">class</span><span style="color: #000000">)<br /></span><span style="color: #008080">&nbsp;7</span>&nbsp;<span style="color: #000000">@ContextConfiguration(locations&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">classpath:simple-repository-context.xml</span><span style="color: #000000">"</span><span style="color: #000000">)<br /></span><span style="color: #008080">&nbsp;8</span>&nbsp;<span style="color: #000000">@Transactional<br /></span><span style="color: #008080">&nbsp;9</span>&nbsp;<span style="color: #000000"></span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;SimpleUserRepositorySample&nbsp;{<br /></span><span style="color: #008080">10</span>&nbsp;<span style="color: #000000"><br /></span><span style="color: #008080">11</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;@Autowired<br /></span><span style="color: #008080">12</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;SimpleUserRepository&nbsp;repository;<br /></span><span style="color: #008080">13</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;User&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;user;<br /></span><span style="color: #008080">14</span>&nbsp;<span style="color: #000000"><br /></span><span style="color: #008080">15</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;@Before<br /></span><span style="color: #008080">16</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;setUp()&nbsp;{<br /></span><span style="color: #008080">17</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;user&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;User();<br /></span><span style="color: #008080">18</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;user.setUsername(</span><span style="color: #000000">"</span><span style="color: #000000">foobar</span><span style="color: #000000">"</span><span style="color: #000000">);<br /></span><span style="color: #008080">19</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;user.setFirstname(</span><span style="color: #000000">"</span><span style="color: #000000">firstname</span><span style="color: #000000">"</span><span style="color: #000000">);<br /></span><span style="color: #008080">20</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;user.setLastname(</span><span style="color: #000000">"</span><span style="color: #000000">lastname</span><span style="color: #000000">"</span><span style="color: #000000">);<br /></span><span style="color: #008080">21</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;}<br /></span><span style="color: #008080">22</span>&nbsp;<span style="color: #000000"><br /></span><span style="color: #008080">23</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;crud方法测试</span><span style="color: #008000"><br /></span><span style="color: #008080">24</span>&nbsp;<span style="color: #008000"></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;@Test<br /></span><span style="color: #008080">25</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;testCrud()&nbsp;{<br /></span><span style="color: #008080">26</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;user&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;repository.save(user);<br /></span><span style="color: #008080">27</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;assertEquals(user,&nbsp;repository.findOne(user.getId()));<br /></span><span style="color: #008080">28</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;}<br /></span><span style="color: #008080">29</span>&nbsp;<span style="color: #000000"><br /></span><span style="color: #008080">30</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;method&nbsp;query测试</span><span style="color: #008000"><br /></span><span style="color: #008080">31</span>&nbsp;<span style="color: #008000"></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;@Test<br /></span><span style="color: #008080">32</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;testMethodQuery()&nbsp;</span><span style="color: #0000ff">throws</span><span style="color: #000000">&nbsp;Exception&nbsp;{<br /></span><span style="color: #008080">33</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;user&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;repository.save(user);<br /></span><span style="color: #008080">34</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;List</span><span style="color: #000000">&lt;</span><span style="color: #000000">User</span><span style="color: #000000">&gt;</span><span style="color: #000000">&nbsp;users&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;repository.findByLastname(</span><span style="color: #000000">"</span><span style="color: #000000">lastname</span><span style="color: #000000">"</span><span style="color: #000000">);<br /></span><span style="color: #008080">35</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;assertNotNull(users);<br /></span><span style="color: #008080">36</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;assertTrue(users.contains(user));<br /></span><span style="color: #008080">37</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;}<br /></span><span style="color: #008080">38</span>&nbsp;<span style="color: #000000"><br /></span><span style="color: #008080">39</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;named&nbsp;query测试</span><span style="color: #008000"><br /></span><span style="color: #008080">40</span>&nbsp;<span style="color: #008000"></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;@Test<br /></span><span style="color: #008080">41</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;testNamedQuery()&nbsp;</span><span style="color: #0000ff">throws</span><span style="color: #000000">&nbsp;Exception&nbsp;{<br /></span><span style="color: #008080">42</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;user&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;repository.save(user);<br /></span><span style="color: #008080">43</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;List</span><span style="color: #000000">&lt;</span><span style="color: #000000">User</span><span style="color: #000000">&gt;</span><span style="color: #000000">&nbsp;users&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;repository.findByFirstnameOrLastname(</span><span style="color: #000000">"</span><span style="color: #000000">lastname</span><span style="color: #000000">"</span><span style="color: #000000">);<br /></span><span style="color: #008080">44</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;assertTrue(users.contains(user));<br /></span><span style="color: #008080">45</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;}<br /></span><span style="color: #008080">46</span>&nbsp;<span style="color: #000000"><br /></span><span style="color: #008080">47</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;criteria&nbsp;query测试</span><span style="color: #008000"><br /></span><span style="color: #008080">48</span>&nbsp;<span style="color: #008000"></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;@Test<br /></span><span style="color: #008080">49</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;testCriteriaQuery()&nbsp;</span><span style="color: #0000ff">throws</span><span style="color: #000000">&nbsp;Exception&nbsp;{<br /></span><span style="color: #008080">50</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;user&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;repository.save(user);<br /></span><span style="color: #008080">51</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;List</span><span style="color: #000000">&lt;</span><span style="color: #000000">User</span><span style="color: #000000">&gt;</span><span style="color: #000000">&nbsp;users&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;repository.findAll(</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;Specification</span><span style="color: #000000">&lt;</span><span style="color: #000000">User</span><span style="color: #000000">&gt;</span><span style="color: #000000">()&nbsp;{<br /></span><span style="color: #008080">52</span>&nbsp;<span style="color: #000000"><br /></span><span style="color: #008080">53</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@Override<br /></span><span style="color: #008080">54</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;Predicate&nbsp;toPredicate(Root</span><span style="color: #000000">&lt;</span><span style="color: #000000">User</span><span style="color: #000000">&gt;</span><span style="color: #000000">&nbsp;root,&nbsp;CriteriaQuery</span><span style="color: #000000">&lt;?&gt;</span><span style="color: #000000">&nbsp;query,&nbsp;CriteriaBuilder&nbsp;cb)&nbsp;{<br /></span><span style="color: #008080">55</span>&nbsp;<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">return</span><span style="color: #000000">&nbsp;cb.equal(root.get(</span><span style="color: #000000">"</span><span style="color: #000000">lastname</span><span style="color: #000000">"</span><span style="color: #000000">),&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">lastname</span><span style="color: #000000">"</span><span style="color: #000000">);<br /></span><span style="color: #008080">56</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /></span><span style="color: #008080">57</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;});<br /></span><span style="color: #008080">58</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;assertTrue(users.contains(user));<br /></span><span style="color: #008080">59</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;}<br /></span><span style="color: #008080">60</span>&nbsp;<span style="color: #000000"></span></span></div><br />其中，写操作相对比较简单，我不做详细介绍，针对读操作，我稍微描述下：<br />Method Query: 方法级别的查询，针对 
<div style="display: inline-block"></div><span class="Apple-style-span" style="font-size: 15px; line-height: normal; font-family: Verdana, Arial, sans-serif; background-color: #ffffff"><code class="code">findBy</code>,&nbsp;<code class="code">find</code>,&nbsp;<code class="code">readBy</code>,&nbsp;<code class="code">read</code>,&nbsp;<code class="code">getBy等前缀的方法，解析方法字符串，生成查询语句，其中支持的关键词有：<br /></code></span><img height="408" alt="" src="http://www.blogjava.net/images/blogjava_net/stone2083/java/mq.png" width="1046" /><br /><br />Named Query： 针对一些复杂的SQL，支持原生SQL方式，进行查询，保证性能<br />Criteria Query： 支持JPA标准中的Criteria Query<br /><br />备注：<br />本文只是简单介绍SpringDataJpa功能，要深入了解的同学，建议直接传送到<a href="http://www.springsource.org/spring-data/jpa">官方网站</a><br /></div></div></div></div><img src ="http://www.blogjava.net/stone2083/aggbug/357262.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/stone2083/" target="_blank">stone2083</a> 2011-08-25 15:18 <a href="http://www.blogjava.net/stone2083/archive/2011/08/25/357262.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>推荐：Eclipse全屏插件</title><link>http://www.blogjava.net/stone2083/archive/2011/04/09/347970.html</link><dc:creator>stone2083</dc:creator><author>stone2083</author><pubDate>Sat, 09 Apr 2011 13:12:00 GMT</pubDate><guid>http://www.blogjava.net/stone2083/archive/2011/04/09/347970.html</guid><wfw:comment>http://www.blogjava.net/stone2083/comments/347970.html</wfw:comment><comments>http://www.blogjava.net/stone2083/archive/2011/04/09/347970.html#Feedback</comments><slash:comments>5</slash:comments><wfw:commentRss>http://www.blogjava.net/stone2083/comments/commentRss/347970.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/stone2083/services/trackbacks/347970.html</trackback:ping><description><![CDATA[推荐一个eclipse插件--全屏插件（显示器整个屏幕）。<br />
发觉这个东东还是挺不错的，尤其对于本本的同学，特别实用。<br />
在我自己的本本上，发现一旦使用全屏，能多显示8行代码，多了21%左右，挺可观的。<br />
<br />
插件地址：http://code.google.com/p/eclipse-fullscreen/<br />
<br />
给个图：<br />
<img alt="" src="http://www.blogjava.net/images/blogjava_net/stone2083/java/fs.png" height="600" width="800" /><br />
<br />
<img src ="http://www.blogjava.net/stone2083/aggbug/347970.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/stone2083/" target="_blank">stone2083</a> 2011-04-09 21:12 <a href="http://www.blogjava.net/stone2083/archive/2011/04/09/347970.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>HttpClient使用过程中的安全隐患</title><link>http://www.blogjava.net/stone2083/archive/2011/04/09/347969.html</link><dc:creator>stone2083</dc:creator><author>stone2083</author><pubDate>Sat, 09 Apr 2011 12:46:00 GMT</pubDate><guid>http://www.blogjava.net/stone2083/archive/2011/04/09/347969.html</guid><wfw:comment>http://www.blogjava.net/stone2083/comments/347969.html</wfw:comment><comments>http://www.blogjava.net/stone2083/archive/2011/04/09/347969.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/stone2083/comments/commentRss/347969.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/stone2083/services/trackbacks/347969.html</trackback:ping><description><![CDATA[HttpClient使用过程中的安全隐患，这个有些标题党。因为这本身不是HttpClient的问题，而是使用者的问题。<br />
<br />
安全隐患场景说明：<br />
一旦请求大数据资源，则HttpClient线程会被长时间占有。即便调用了org.apache.commons.httpclient.HttpMethod#releaseConnection()方法，也无济于事。<br />
如果请求的资源是应用可控的，那么不存在任何问题。可是恰恰我们应用的使用场景是，请求资源由用户自行输入，于是乎，我们不得不重视这个问题。<br />
<br />
我们跟踪releaseConnection代码发现：<br />
org.apache.commons.httpclient.HttpMethodBase#releaseConnection()<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;">&nbsp;1</span>&nbsp;<span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;releaseConnection()&nbsp;{<br />
</span><span style="color: #008080;">&nbsp;2</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">try</span><span style="color: #000000;">&nbsp;{<br />
</span><span style="color: #008080;">&nbsp;3</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(</span><span style="color: #0000ff;">this</span><span style="color: #000000;">.responseStream&nbsp;</span><span style="color: #000000;">!=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">null</span><span style="color: #000000;">)&nbsp;{<br />
</span><span style="color: #008080;">&nbsp;4</span>&nbsp;<span style="color: #000000;">&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 />
</span><span style="color: #008080;">&nbsp;5</span>&nbsp;<span style="color: #000000;">&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;FYI&nbsp;-&nbsp;this&nbsp;may&nbsp;indirectly&nbsp;invoke&nbsp;responseBodyConsumed.</span><span style="color: #008000;"><br />
</span><span style="color: #008080;">&nbsp;6</span>&nbsp;<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;">this</span><span style="color: #000000;">.responseStream.close();<br />
</span><span style="color: #008080;">&nbsp;7</span>&nbsp;<span style="color: #000000;">&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;(IOException&nbsp;ignore)&nbsp;{<br />
</span><span style="color: #008080;">&nbsp;8</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
</span><span style="color: #008080;">&nbsp;9</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
</span><span style="color: #008080;">10</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span><span style="color: #0000ff;">finally</span><span style="color: #000000;">&nbsp;{<br />
</span><span style="color: #008080;">11</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ensureConnectionRelease();<br />
</span><span style="color: #008080;">12</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;}<br />
</span><span style="color: #008080;">13</span>&nbsp;<span style="color: #000000;">}</span></div>
org.apache.commons.httpclient.ChunkedInputStream#close()<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;">&nbsp;1</span>&nbsp;<span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;close()&nbsp;</span><span style="color: #0000ff;">throws</span><span style="color: #000000;">&nbsp;IOException&nbsp;{<br />
</span><span style="color: #008080;">&nbsp;2</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(</span><span style="color: #000000;">!</span><span style="color: #000000;">closed)&nbsp;{<br />
</span><span style="color: #008080;">&nbsp;3</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">try</span><span style="color: #000000;">&nbsp;{<br />
</span><span style="color: #008080;">&nbsp;4</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(</span><span style="color: #000000;">!</span><span style="color: #000000;">eof)&nbsp;{<br />
</span><span style="color: #008080;">&nbsp;5</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exhaustInputStream(</span><span style="color: #0000ff;">this</span><span style="color: #000000;">);<br />
</span><span style="color: #008080;">&nbsp;6</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
</span><span style="color: #008080;">&nbsp;7</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span><span style="color: #0000ff;">finally</span><span style="color: #000000;">&nbsp;{<br />
</span><span style="color: #008080;">&nbsp;8</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;eof&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">true</span><span style="color: #000000;">;<br />
</span><span style="color: #008080;">&nbsp;9</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;closed&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">true</span><span style="color: #000000;">;<br />
</span><span style="color: #008080;">10</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
</span><span style="color: #008080;">11</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;}<br />
</span><span style="color: #008080;">12</span>&nbsp;<span style="color: #000000;">}</span></div>
org.apache.commons.httpclient.ChunkedInputStream#exhaustInputStream(InputStream inStream)<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;">1</span>&nbsp;<span style="color: #0000ff;">static</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;exhaustInputStream(InputStream&nbsp;inStream)&nbsp;</span><span style="color: #0000ff;">throws</span><span style="color: #000000;">&nbsp;IOException&nbsp;{<br />
</span><span style="color: #008080;">2</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;read&nbsp;and&nbsp;discard&nbsp;the&nbsp;remainder&nbsp;of&nbsp;the&nbsp;message</span><span style="color: #008000;"><br />
</span><span style="color: #008080;">3</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">byte</span><span style="color: #000000;">&nbsp;buffer[]&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">byte</span><span style="color: #000000;">[</span><span style="color: #000000;">1024</span><span style="color: #000000;">];<br />
</span><span style="color: #008080;">4</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">while</span><span style="color: #000000;">&nbsp;(inStream.read(buffer)&nbsp;</span><span style="color: #000000;">&gt;=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">)&nbsp;{<br />
</span><span style="color: #008080;">5</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;;<br />
</span><span style="color: #008080;">6</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;}<br />
</span><span style="color: #008080;">7</span>&nbsp;<span style="color: #000000;">}</span></div>
看到了吧，所谓的丢弃response，其实是读完了一次请求的response，只是不做任何处理罢了。<br />
<br />
想想也是，HttpClient的设计理念是重复使用HttpConnection，岂能轻易被强制close呢。<br />
<br />
怎么办？有朋友说，不是有time out设置嘛，设置下就可以下。<br />
我先来解释下Httpclient中两个time out的概念：<br />
1.public static final String CONNECTION_TIMEOUT = "http.connection.timeout";<br />
即创建socket连接的超时时间:java.net.Socket#connect(SocketAddress endpoint, int timeout)中的timeout<br />
<br />
2.public static final String SO_TIMEOUT = "http.socket.timeout";<br />
即read data过程中，等待数据的timeout：java.net.Socket#setSoTimeout(int timeout)中的timeout<br />
<br />
而在我上面场景中，这两个timeout都不满足，确实是由于资源过大，而占用了大量的请求时间。<br />
<br />
问题总是要解决的，解决思路如下：<br />
1.利用DelayQueue，管理所有请求<br />
2.利用一个异步线程监控，关闭超长时间的请求<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: #008080;">&nbsp;&nbsp;1</span>&nbsp;<span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;Misc2&nbsp;{<br />
</span><span style="color: #008080;">&nbsp;&nbsp;2</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">&nbsp;&nbsp;3</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&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;DelayQueue</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">Timeout</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">&nbsp;TIMEOUT_QUEUE&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;DelayQueue</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">Timeout</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">();<br />
</span><span style="color: #008080;">&nbsp;&nbsp;4</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">&nbsp;&nbsp;5</span>&nbsp;<span style="color: #000000;">&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;Exception&nbsp;{<br />
</span><span style="color: #008080;">&nbsp;&nbsp;6</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;Monitor().start();&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;超时监控线程</span><span style="color: #008000;"><br />
</span><span style="color: #008080;">&nbsp;&nbsp;7</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">&nbsp;&nbsp;8</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;Request(</span><span style="color: #000000;">4</span><span style="color: #000000;">).start();</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;模拟第一个下载</span><span style="color: #008000;"><br />
</span><span style="color: #008080;">&nbsp;&nbsp;9</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;Request(</span><span style="color: #000000;">3</span><span style="color: #000000;">).start();</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;模拟第二个下载</span><span style="color: #008000;"><br />
</span><span style="color: #008080;">&nbsp;10</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;Request(</span><span style="color: #000000;">2</span><span style="color: #000000;">).start();</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;模拟第三个下载</span><span style="color: #008000;"><br />
</span><span style="color: #008080;">&nbsp;11</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;}<br />
</span><span style="color: #008080;">&nbsp;12</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">&nbsp;13</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">/**</span><span style="color: #008000;"><br />
</span><span style="color: #008080;">&nbsp;14</span>&nbsp;<span style="color: #008000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;模拟一次HttpClient请求<br />
</span><span style="color: #008080;">&nbsp;15</span>&nbsp;<span style="color: #008000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;<br />
</span><span style="color: #008080;">&nbsp;16</span>&nbsp;<span style="color: #008000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: #808080;">@author</span><span style="color: #008000;">&nbsp;&lt;a&nbsp;href="mailto:li.jinl@alibaba-inc.com"&gt;Stone.J&lt;/a&gt;&nbsp;2011-4-9<br />
</span><span style="color: #008080;">&nbsp;17</span>&nbsp;<span style="color: #008000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">*/</span><span style="color: #000000;"><br />
</span><span style="color: #008080;">&nbsp;18</span>&nbsp;<span style="color: #000000;">&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;">class</span><span style="color: #000000;">&nbsp;Request&nbsp;</span><span style="color: #0000ff;">extends</span><span style="color: #000000;">&nbsp;Thread&nbsp;{<br />
</span><span style="color: #008080;">&nbsp;19</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">&nbsp;20</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">private</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">long</span><span style="color: #000000;">&nbsp;delay;<br />
</span><span style="color: #008080;">&nbsp;21</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">&nbsp;22</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;Request(</span><span style="color: #0000ff;">long</span><span style="color: #000000;">&nbsp;delay){<br />
</span><span style="color: #008080;">&nbsp;23</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">this</span><span style="color: #000000;">.delay&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;delay;<br />
</span><span style="color: #008080;">&nbsp;24</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
</span><span style="color: #008080;">&nbsp;25</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">&nbsp;26</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;run()&nbsp;{<br />
</span><span style="color: #008080;">&nbsp;27</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;HttpClient&nbsp;hc&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;HttpClient();<br />
</span><span style="color: #008080;">&nbsp;28</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;GetMethod&nbsp;req&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;GetMethod(</span><span style="color: #000000;">"</span><span style="color: #000000;">http://www.python.org/ftp/python/2.7.1/Python-2.7.1.tgz</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br />
</span><span style="color: #008080;">&nbsp;29</span>&nbsp;<span style="color: #000000;">&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 />
</span><span style="color: #008080;">&nbsp;30</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TIMEOUT_QUEUE.offer(</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;Timeout(delay&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">1000</span><span style="color: #000000;">,&nbsp;hc.getHttpConnectionManager()));<br />
</span><span style="color: #008080;">&nbsp;31</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;hc.executeMethod(req);<br />
</span><span style="color: #008080;">&nbsp;32</span>&nbsp;<span style="color: #000000;">&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;(Exception&nbsp;e)&nbsp;{<br />
</span><span style="color: #008080;">&nbsp;33</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(e);<br />
</span><span style="color: #008080;">&nbsp;34</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
</span><span style="color: #008080;">&nbsp;35</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;req.releaseConnection();<br />
</span><span style="color: #008080;">&nbsp;36</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
</span><span style="color: #008080;">&nbsp;37</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">&nbsp;38</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;}<br />
</span><span style="color: #008080;">&nbsp;39</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">&nbsp;40</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">/**</span><span style="color: #008000;"><br />
</span><span style="color: #008080;">&nbsp;41</span>&nbsp;<span style="color: #008000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;监工：监控线程，通过DelayQueue，阻塞得到最近超时的对象，强制关闭<br />
</span><span style="color: #008080;">&nbsp;42</span>&nbsp;<span style="color: #008000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;<br />
</span><span style="color: #008080;">&nbsp;43</span>&nbsp;<span style="color: #008000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: #808080;">@author</span><span style="color: #008000;">&nbsp;&lt;a&nbsp;href="mailto:li.jinl@alibaba-inc.com"&gt;Stone.J&lt;/a&gt;&nbsp;2011-4-9<br />
</span><span style="color: #008080;">&nbsp;44</span>&nbsp;<span style="color: #008000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">*/</span><span style="color: #000000;"><br />
</span><span style="color: #008080;">&nbsp;45</span>&nbsp;<span style="color: #000000;">&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;">class</span><span style="color: #000000;">&nbsp;Monitor&nbsp;</span><span style="color: #0000ff;">extends</span><span style="color: #000000;">&nbsp;Thread&nbsp;{<br />
</span><span style="color: #008080;">&nbsp;46</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">&nbsp;47</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@Override<br />
</span><span style="color: #008080;">&nbsp;48</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;run()&nbsp;{<br />
</span><span style="color: #008080;">&nbsp;49</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">while</span><span style="color: #000000;">&nbsp;(</span><span style="color: #0000ff;">true</span><span style="color: #000000;">)&nbsp;{<br />
</span><span style="color: #008080;">&nbsp;50</span>&nbsp;<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;">try</span><span style="color: #000000;">&nbsp;{<br />
</span><span style="color: #008080;">&nbsp;51</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Timeout&nbsp;timeout&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;TIMEOUT_QUEUE.take();<br />
</span><span style="color: #008080;">&nbsp;52</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;timeout.forceClose();<br />
</span><span style="color: #008080;">&nbsp;53</span>&nbsp;<span style="color: #000000;">&nbsp;&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;(InterruptedException&nbsp;e)&nbsp;{<br />
</span><span style="color: #008080;">&nbsp;54</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(e);<br />
</span><span style="color: #008080;">&nbsp;55</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
</span><span style="color: #008080;">&nbsp;56</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
</span><span style="color: #008080;">&nbsp;57</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
</span><span style="color: #008080;">&nbsp;58</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">&nbsp;59</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;}<br />
</span><span style="color: #008080;">&nbsp;60</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">&nbsp;61</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">/**</span><span style="color: #008000;"><br />
</span><span style="color: #008080;">&nbsp;62</span>&nbsp;<span style="color: #008000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;使用delay&nbsp;queue，对Delayed接口的实现&nbsp;根据请求当前时间+该请求允许timeout时间，和当前时间比较，判断是否已经超时<br />
</span><span style="color: #008080;">&nbsp;63</span>&nbsp;<span style="color: #008000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;<br />
</span><span style="color: #008080;">&nbsp;64</span>&nbsp;<span style="color: #008000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: #808080;">@author</span><span style="color: #008000;">&nbsp;&lt;a&nbsp;href="mailto:li.jinl@alibaba-inc.com"&gt;Stone.J&lt;/a&gt;&nbsp;2011-4-9<br />
</span><span style="color: #008080;">&nbsp;65</span>&nbsp;<span style="color: #008000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">*/</span><span style="color: #000000;"><br />
</span><span style="color: #008080;">&nbsp;66</span>&nbsp;<span style="color: #000000;">&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;">class</span><span style="color: #000000;">&nbsp;Timeout&nbsp;</span><span style="color: #0000ff;">implements</span><span style="color: #000000;">&nbsp;Delayed&nbsp;{<br />
</span><span style="color: #008080;">&nbsp;67</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">&nbsp;68</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">private</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">long</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;debut;<br />
</span><span style="color: #008080;">&nbsp;69</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">private</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">long</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;delay;<br />
</span><span style="color: #008080;">&nbsp;70</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">private</span><span style="color: #000000;">&nbsp;HttpConnectionManager&nbsp;manager;<br />
</span><span style="color: #008080;">&nbsp;71</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">&nbsp;72</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;Timeout(</span><span style="color: #0000ff;">long</span><span style="color: #000000;">&nbsp;delay,&nbsp;HttpConnectionManager&nbsp;manager){<br />
</span><span style="color: #008080;">&nbsp;73</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">this</span><span style="color: #000000;">.debut&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;System.currentTimeMillis();<br />
</span><span style="color: #008080;">&nbsp;74</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">this</span><span style="color: #000000;">.delay&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;delay;<br />
</span><span style="color: #008080;">&nbsp;75</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">this</span><span style="color: #000000;">.manager&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;manager;<br />
</span><span style="color: #008080;">&nbsp;76</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
</span><span style="color: #008080;">&nbsp;77</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">&nbsp;78</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;forceClose()&nbsp;{<br />
</span><span style="color: #008080;">&nbsp;79</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="color: #0000ff;">this</span><span style="color: #000000;">.debut&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">:</span><span style="color: #000000;">"</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">this</span><span style="color: #000000;">.delay);<br />
</span><span style="color: #008080;">&nbsp;80</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(manager&nbsp;</span><span style="color: #0000ff;">instanceof</span><span style="color: #000000;">&nbsp;SimpleHttpConnectionManager)&nbsp;{<br />
</span><span style="color: #008080;">&nbsp;81</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;((SimpleHttpConnectionManager)&nbsp;manager).shutdown();<br />
</span><span style="color: #008080;">&nbsp;82</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
</span><span style="color: #008080;">&nbsp;83</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(manager&nbsp;</span><span style="color: #0000ff;">instanceof</span><span style="color: #000000;">&nbsp;MultiThreadedHttpConnectionManager)&nbsp;{<br />
</span><span style="color: #008080;">&nbsp;84</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;((MultiThreadedHttpConnectionManager)&nbsp;manager).shutdown();<br />
</span><span style="color: #008080;">&nbsp;85</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
</span><span style="color: #008080;">&nbsp;86</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
</span><span style="color: #008080;">&nbsp;87</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">&nbsp;88</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@Override<br />
</span><span style="color: #008080;">&nbsp;89</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;compareTo(Delayed&nbsp;o)&nbsp;{<br />
</span><span style="color: #008080;">&nbsp;90</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(o&nbsp;</span><span style="color: #0000ff;">instanceof</span><span style="color: #000000;">&nbsp;Timeout)&nbsp;{<br />
</span><span style="color: #008080;">&nbsp;91</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Timeout&nbsp;timeout&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;(Timeout)&nbsp;o;<br />
</span><span style="color: #008080;">&nbsp;92</span>&nbsp;<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;">if</span><span style="color: #000000;">&nbsp;(</span><span style="color: #0000ff;">this</span><span style="color: #000000;">.debut&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">this</span><span style="color: #000000;">.delay&nbsp;</span><span style="color: #000000;">==</span><span style="color: #000000;">&nbsp;timeout.debut&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;timeout.delay)&nbsp;{<br />
</span><span style="color: #008080;">&nbsp;93</span>&nbsp;<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;</span><span style="color: #000000;">0</span><span style="color: #000000;">;<br />
</span><span style="color: #008080;">&nbsp;94</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span><span style="color: #0000ff;">else</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(</span><span style="color: #0000ff;">this</span><span style="color: #000000;">.debut&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">this</span><span style="color: #000000;">.delay&nbsp;</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">&nbsp;timeout.debut&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;timeout.delay)&nbsp;{<br />
</span><span style="color: #008080;">&nbsp;95</span>&nbsp;<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;</span><span style="color: #000000;">1</span><span style="color: #000000;">;<br />
</span><span style="color: #008080;">&nbsp;96</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span><span style="color: #0000ff;">else</span><span style="color: #000000;">&nbsp;{<br />
</span><span style="color: #008080;">&nbsp;97</span>&nbsp;<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;</span><span style="color: #000000;">-</span><span style="color: #000000;">1</span><span style="color: #000000;">;<br />
</span><span style="color: #008080;">&nbsp;98</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
</span><span style="color: #008080;">&nbsp;99</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
</span><span style="color: #008080;">100</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">;<br />
</span><span style="color: #008080;">101</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
</span><span style="color: #008080;">102</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">103</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@Override<br />
</span><span style="color: #008080;">104</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">long</span><span style="color: #000000;">&nbsp;getDelay(TimeUnit&nbsp;unit)&nbsp;{<br />
</span><span style="color: #008080;">105</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;debut&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;delay&nbsp;</span><span style="color: #000000;">-</span><span style="color: #000000;">&nbsp;System.currentTimeMillis();<br />
</span><span style="color: #008080;">106</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
</span><span style="color: #008080;">107</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">108</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;}<br />
</span><span style="color: #008080;">109</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">110</span>&nbsp;<span style="color: #000000;">}</span></div>
<br />
<br />
本来还想详细讲下DelayQueue，但是发现同事已经有比较纤细的描述，就加个链接吧 （人懒，没办法）<br />
http://agapple.iteye.com/blog/916837<br />
http://agapple.iteye.com/blog/947133<br />
<br />
备注：<br />
HttpClient3.1中，SimpleHttpConnectionManager才有shutdown方法，3.0.1中还存在 ：）<br />
<img src ="http://www.blogjava.net/stone2083/aggbug/347969.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/stone2083/" target="_blank">stone2083</a> 2011-04-09 20:46 <a href="http://www.blogjava.net/stone2083/archive/2011/04/09/347969.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>HtmlParser疑似Bug</title><link>http://www.blogjava.net/stone2083/archive/2011/04/08/347910.html</link><dc:creator>stone2083</dc:creator><author>stone2083</author><pubDate>Fri, 08 Apr 2011 12:50:00 GMT</pubDate><guid>http://www.blogjava.net/stone2083/archive/2011/04/08/347910.html</guid><wfw:comment>http://www.blogjava.net/stone2083/comments/347910.html</wfw:comment><comments>http://www.blogjava.net/stone2083/archive/2011/04/08/347910.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/stone2083/comments/commentRss/347910.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/stone2083/services/trackbacks/347910.html</trackback:ping><description><![CDATA[最近的项目中，使用到了HtmlParser（1.5版本）.在使用过程中（如访问url为：<a href="http://athena2002.vip.china.alibaba.com/">http://athena2002.vip.china.alibaba.com/</a>
），遇到了异常：<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;">Exception&nbsp;in&nbsp;thread&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">main</span><span style="color: #000000;">"</span><span style="color: #000000;">&nbsp;java.lang.IllegalArgumentException:&nbsp;invalid&nbsp;cookie&nbsp;name:&nbsp;Discard<br />
&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;org.htmlparser.http.Cookie.</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">init</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">(Cookie.java:</span><span style="color: #000000;">136</span><span style="color: #000000;">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;org.htmlparser.http.ConnectionManager.parseCookies(ConnectionManager.java:</span><span style="color: #000000;">1126</span><span style="color: #000000;">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;org.htmlparser.http.ConnectionManager.openConnection(ConnectionManager.java:</span><span style="color: #000000;">621</span><span style="color: #000000;">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;org.htmlparser.http.ConnectionManager.openConnection(ConnectionManager.java:</span><span style="color: #000000;">792</span><span style="color: #000000;">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;org.htmlparser.Parser.</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">init</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">(Parser.java:</span><span style="color: #000000;">251</span><span style="color: #000000;">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;org.htmlparser.Parser.</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">init</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">(Parser.java:</span><span style="color: #000000;">261</span><span style="color: #000000;">)</span></div>
检查代码，发现：<br />
org.htmlparser.http.Cookie<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;">&nbsp;1</span>&nbsp;<span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;Cookie&nbsp;(String&nbsp;name,&nbsp;String&nbsp;value)<br />
</span><span style="color: #008080;">&nbsp;2</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;{<br />
</span><span style="color: #008080;">&nbsp;3</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(</span><span style="color: #000000;">!</span><span style="color: #000000;">isToken&nbsp;(name)&nbsp;</span><span style="color: #000000;">||</span><span style="color: #000000;">&nbsp;name.equalsIgnoreCase&nbsp;(</span><span style="color: #000000;">"</span><span style="color: #000000;">Comment</span><span style="color: #000000;">"</span><span style="color: #000000;">)&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;rfc2019</span><span style="color: #008000;"><br />
</span><span style="color: #008080;">&nbsp;4</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">||</span><span style="color: #000000;">&nbsp;name.equalsIgnoreCase&nbsp;(</span><span style="color: #000000;">"</span><span style="color: #000000;">Discard</span><span style="color: #000000;">"</span><span style="color: #000000;">)&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;2019++</span><span style="color: #008000;"><br />
</span><span style="color: #008080;">&nbsp;5</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">||</span><span style="color: #000000;">&nbsp;name.equalsIgnoreCase&nbsp;(</span><span style="color: #000000;">"</span><span style="color: #000000;">Domain</span><span style="color: #000000;">"</span><span style="color: #000000;">)<br />
</span><span style="color: #008080;">&nbsp;6</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">||</span><span style="color: #000000;">&nbsp;name.equalsIgnoreCase&nbsp;(</span><span style="color: #000000;">"</span><span style="color: #000000;">Expires</span><span style="color: #000000;">"</span><span style="color: #000000;">)&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;(old&nbsp;cookies)</span><span style="color: #008000;"><br />
</span><span style="color: #008080;">&nbsp;7</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">||</span><span style="color: #000000;">&nbsp;name.equalsIgnoreCase&nbsp;(</span><span style="color: #000000;">"</span><span style="color: #000000;">Max-Age</span><span style="color: #000000;">"</span><span style="color: #000000;">)&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;rfc2019</span><span style="color: #008000;"><br />
</span><span style="color: #008080;">&nbsp;8</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">||</span><span style="color: #000000;">&nbsp;name.equalsIgnoreCase&nbsp;(</span><span style="color: #000000;">"</span><span style="color: #000000;">Path</span><span style="color: #000000;">"</span><span style="color: #000000;">)<br />
</span><span style="color: #008080;">&nbsp;9</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">||</span><span style="color: #000000;">&nbsp;name.equalsIgnoreCase&nbsp;(</span><span style="color: #000000;">"</span><span style="color: #000000;">Secure</span><span style="color: #000000;">"</span><span style="color: #000000;">)<br />
</span><span style="color: #008080;">10</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">||</span><span style="color: #000000;">&nbsp;name.equalsIgnoreCase&nbsp;(</span><span style="color: #000000;">"</span><span style="color: #000000;">Version</span><span style="color: #000000;">"</span><span style="color: #000000;">))<br />
</span><span style="color: #008080;">11</span>&nbsp;<span style="color: #000000;">&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;">invalid&nbsp;cookie&nbsp;name:&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;name);<br />
</span><span style="color: #008080;">12</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mName&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;name;<br />
</span><span style="color: #008080;">13</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mValue&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;value;<br />
</span><span style="color: #008080;">14</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mComment&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">null</span><span style="color: #000000;">;<br />
</span><span style="color: #008080;">15</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mDomain&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">null</span><span style="color: #000000;">;<br />
</span><span style="color: #008080;">16</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mExpiry&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: #008000;">//</span><span style="color: #008000;">&nbsp;not&nbsp;persisted</span><span style="color: #008000;"><br />
</span><span style="color: #008080;">17</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mPath&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">/</span><span style="color: #000000;">"</span><span style="color: #000000;">;<br />
</span><span style="color: #008080;">18</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mSecure&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">false</span><span style="color: #000000;">;<br />
</span><span style="color: #008080;">19</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mVersion&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">;<br />
</span><span style="color: #008080;">20</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;}</span></div>
一旦发现name值为&#8220;Discard&#8221;，则抛异常。<br />
<br />
而在org.htmlparser.http.ConnectionManager.parseCookies (URLConnection connection) 解析cookie的代码中，见代码片段<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;">if</span><span style="color: #000000;">&nbsp;(key.equals&nbsp;(</span><span style="color: #000000;">"</span><span style="color: #000000;">domain</span><span style="color: #000000;">"</span><span style="color: #000000;">))<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;&nbsp;&nbsp;&nbsp;&nbsp;cookie.setDomain&nbsp;(value);<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;</span><span style="color: #0000ff;">else</span><span style="color: #000000;"><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;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(key.equals&nbsp;(</span><span style="color: #000000;">"</span><span style="color: #000000;">path</span><span style="color: #000000;">"</span><span style="color: #000000;">))<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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cookie.setPath&nbsp;(value);<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;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">else</span><span style="color: #000000;"><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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(key.equals&nbsp;(</span><span style="color: #000000;">"</span><span style="color: #000000;">secure</span><span style="color: #000000;">"</span><span style="color: #000000;">))<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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cookie.setSecure&nbsp;(</span><span style="color: #0000ff;">true</span><span style="color: #000000;">);<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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">else</span><span style="color: #000000;"><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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(key.equals&nbsp;(</span><span style="color: #000000;">"</span><span style="color: #000000;">comment</span><span style="color: #000000;">"</span><span style="color: #000000;">))<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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cookie.setComment&nbsp;(value);<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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">else</span><span style="color: #000000;"><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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(key.equals&nbsp;(</span><span style="color: #000000;">"</span><span style="color: #000000;">version</span><span style="color: #000000;">"</span><span style="color: #000000;">))<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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cookie.setVersion&nbsp;(Integer.parseInt&nbsp;(value));<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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">else</span><span style="color: #000000;"><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;&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;">if</span><span style="color: #000000;">&nbsp;(key.equals&nbsp;(</span><span style="color: #000000;">"</span><span style="color: #000000;">max-age</span><span style="color: #000000;">"</span><span style="color: #000000;">))<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;&nbsp;&nbsp;&nbsp;&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Date&nbsp;date&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;Date&nbsp;();<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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">long</span><span style="color: #000000;">&nbsp;then&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;date.getTime&nbsp;()&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;Integer.parseInt&nbsp;(value)&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;date.setTime&nbsp;(then);<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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cookie.setExpiryDate&nbsp;(date);<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;&nbsp;&nbsp;&nbsp;&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">else</span><span style="color: #000000;"><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;&nbsp;&nbsp;&nbsp;&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;error,?&nbsp;unknown&nbsp;attribute,<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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;maybe&nbsp;just&nbsp;another&nbsp;cookie&nbsp;not&nbsp;separated&nbsp;by&nbsp;a&nbsp;comma</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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cookie&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;Cookie&nbsp;(name,&nbsp;value); <span style="color: red;">//出问题的地方</span><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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cookies.addElement&nbsp;(cookie);<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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></div>
没有对Discard做特殊处理。<br />
无奈之下，覆写了此方法，加上对Discard的处理--直接continue ：）<br />
<br />
今天在写blog的时候，拿了1.6的代码测试，发现没有问题，分析代码后发现<br />
1. ConnectionManager parserCookie之前，加了条件判断<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;">if</span><span style="color: #000000;">&nbsp;(getCookieProcessingEnabled&nbsp;())<br />
&nbsp;&nbsp;parseCookies&nbsp;(ret);</span></div>
默认情况下，条件为false<br />
2. parserCookie的时候，catch了异常<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;">&nbsp;1</span>&nbsp;<span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;error,?&nbsp;unknown&nbsp;attribute,<br />
</span><span style="color: #008080;">&nbsp;2</span>&nbsp;<span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;maybe&nbsp;just&nbsp;another&nbsp;cookie<br />
</span><span style="color: #008080;">&nbsp;3</span>&nbsp;<span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;not&nbsp;separated&nbsp;by&nbsp;a&nbsp;comma</span><span style="color: #008000;"><br />
</span><span style="color: #008080;">&nbsp;4</span>&nbsp;<span style="color: #0000ff;">try</span><span style="color: #000000;"><br />
</span><span style="color: #008080;">&nbsp;5</span>&nbsp;<span style="color: #000000;">{<br />
</span><span style="color: #008080;">&nbsp;6</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;cookie&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;Cookie&nbsp;(name,<br />
</span><span style="color: #008080;">&nbsp;7</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;value);<br />
</span><span style="color: #008080;">&nbsp;8</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;cookies.addElement&nbsp;(cookie);<br />
</span><span style="color: #008080;">&nbsp;9</span>&nbsp;<span style="color: #000000;">}<br />
</span><span style="color: #008080;">10</span>&nbsp;<span style="color: #0000ff;">catch</span><span style="color: #000000;">&nbsp;(IllegalArgumentException&nbsp;iae)<br />
</span><span style="color: #008080;">11</span>&nbsp;<span style="color: #000000;">{<br />
</span><span style="color: #008080;">12</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;should&nbsp;print&nbsp;a&nbsp;warning<br />
</span><span style="color: #008080;">13</span>&nbsp;<span style="color: #008000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;for&nbsp;now&nbsp;just&nbsp;bail</span><span style="color: #008000;"><br />
</span><span style="color: #008080;">14</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">break</span><span style="color: #000000;">;<br />
</span><span style="color: #008080;">15</span>&nbsp;<span style="color: #000000;">}</span></div>
虽然解决了问题，但是明显还没有意识到Discard的问题。<br />
<br />
从我的理解看，最合理的解决方案是:<br />
1. org.htmlparser.http.Cookie中添加 boolean discard方法<br />
2. org.htmlparser.http.ConnectionManager parserCookies()方法，对Discard做处理，如有值，则设置cookie.discard=true<br />
<br />
关于discard的解释，见<a href="http://www.faqs.org/rfcs/rfc2965.html">http://www.faqs.org/rfcs/rfc2965.html</a>：<br />
<span style="border-collapse: separate; color: #000000; font-family: 文泉驿等宽微米黑; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; font-size: medium;"><span style="color: #2e2c2c; font-family: Georgia,'Times New Roman',Times,serif; font-size: 15px; line-height: 22px;">
<pre style="text-align: left;">Discard<br />
OPTIONAL.  The Discard attribute instructs the user agent to<br />
discard the cookie unconditionally when the user agent terminates</pre>
</span></span><br />
<img src ="http://www.blogjava.net/stone2083/aggbug/347910.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/stone2083/" target="_blank">stone2083</a> 2011-04-08 20:50 <a href="http://www.blogjava.net/stone2083/archive/2011/04/08/347910.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>语言杂谈（shell/python/java）</title><link>http://www.blogjava.net/stone2083/archive/2010/11/08/337548.html</link><dc:creator>stone2083</dc:creator><author>stone2083</author><pubDate>Mon, 08 Nov 2010 09:24:00 GMT</pubDate><guid>http://www.blogjava.net/stone2083/archive/2010/11/08/337548.html</guid><wfw:comment>http://www.blogjava.net/stone2083/comments/337548.html</wfw:comment><comments>http://www.blogjava.net/stone2083/archive/2010/11/08/337548.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/stone2083/comments/commentRss/337548.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/stone2083/services/trackbacks/337548.html</trackback:ping><description><![CDATA[<strong>背景：</strong><br />
公司产品一直使用Java作为开发语言，平时常用Shell脚本进行文本的处理，最近自学了Python.<br />
感觉这3门语言挺具代表性，故对其分析了自己对它们的理解。<br />
由于是部门分享，考虑避免重复劳动力，就把PPT转成图片放上来。<br />
<br />
<strong>内容：</strong><br />
<img alt="" src="http://www.blogjava.net/images/blogjava_net/stone2083/java/lang-0.jpg" height="405" width="540" /><br />
<img alt="" src="http://www.blogjava.net/images/blogjava_net/stone2083/java/lang-1.jpg" height="405" width="540" /><br />
<img alt="" src="http://www.blogjava.net/images/blogjava_net/stone2083/lang-2.jpg" height="405" width="540" /><br />
<img alt="" src="http://www.blogjava.net/images/blogjava_net/stone2083/lang-3.jpg" height="405" width="540" /><br />
<img alt="" src="http://www.blogjava.net/images/blogjava_net/stone2083/lang-4.jpg" height="405" width="540" /><br />
<img alt="" src="http://www.blogjava.net/images/blogjava_net/stone2083/lang-5.jpg" height="405" width="540" /><br />
<img alt="" src="http://www.blogjava.net/images/blogjava_net/stone2083/lang-6.jpg" height="405" width="540" /><br />
<img alt="" src="http://www.blogjava.net/images/blogjava_net/stone2083/lang-7.jpg" height="405" width="540" /><br />
<img alt="" src="http://www.blogjava.net/images/blogjava_net/stone2083/lang-8.jpg" height="405" width="540" /><br />
<img alt="" src="http://www.blogjava.net/images/blogjava_net/stone2083/lang-9.jpg" height="405" width="540" /><br />
<img alt="" src="http://www.blogjava.net/images/blogjava_net/stone2083/lang-10.jpg" height="405" width="540" /><br />
<img alt="" src="http://www.blogjava.net/images/blogjava_net/stone2083/lang-11.jpg" height="405" width="540" /><br />
<img alt="" src="http://www.blogjava.net/images/blogjava_net/stone2083/lang-12.jpg" height="405" width="540" /><br />
<img alt="" src="http://www.blogjava.net/images/blogjava_net/stone2083/lang-13.jpg" height="405" width="540" /><br />
<br />
结束语：<br />
一家之言，属于个人观点<br />
<br />
备注：<br />
ubuntu下convert命令挺强悍的，支持PDF和图片的互转<br />
<br />
附上PDF文档：<br />
<a href="/Files/stone2083/java/lang.pdf" title="分享文档">分享文档</a><br />
<br />
<br />
<br />
<img src ="http://www.blogjava.net/stone2083/aggbug/337548.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/stone2083/" target="_blank">stone2083</a> 2010-11-08 17:24 <a href="http://www.blogjava.net/stone2083/archive/2010/11/08/337548.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>关于cookie特殊字符的一点理解</title><link>http://www.blogjava.net/stone2083/archive/2010/11/03/336923.html</link><dc:creator>stone2083</dc:creator><author>stone2083</author><pubDate>Wed, 03 Nov 2010 05:27:00 GMT</pubDate><guid>http://www.blogjava.net/stone2083/archive/2010/11/03/336923.html</guid><wfw:comment>http://www.blogjava.net/stone2083/comments/336923.html</wfw:comment><comments>http://www.blogjava.net/stone2083/archive/2010/11/03/336923.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/stone2083/comments/commentRss/336923.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/stone2083/services/trackbacks/336923.html</trackback:ping><description><![CDATA[背景：<br />
加密的cookie信息中带有特殊字符（&#8220;=&#8221;），导致读cookie的时候，特殊符号丢失，解密失败<br />
<br />
看了同事&#8220;关于cookie特殊字符&#8221;的说明邮件，和网上对cookie特殊字符问题的解释：<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="border-collapse: separate; color: #000000; font-family: 文泉驿等宽微米黑; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; font-size: medium;"><span style="font-family: Arial,Helvetica,sans-serif; font-size: 12px; line-height: 24px; text-align: left;">
<p style="font-family: Arial,Helvetica,sans-serif; font-size: 9pt; color: #666666; text-align: left;"><font face="宋体" size="2">我们在实际使用Cookie过程中要注意一些问题：</font></p>
<p style="font-family: Arial,Helvetica,sans-serif; font-size: 9pt; color: #666666; text-align: left;"><font face="宋体" size="2">　　<u>1. Cookie的兼容性问题</u></font></p>
<p style="font-family: Arial,Helvetica,sans-serif; font-size: 9pt; color: #666666; text-align: left;"><font face="宋体" size="2">　　Cookie的格式有2个不同的版本，第一个版本，我们称为Cookie Version 0，是最初由Netscape公司制定的，也被几乎所有的浏览器支持。而较新的版本，Cookie Version 1，则是根据RFC 2109文档制定的。为了确保兼容性，JAVA规定，前面所提到的涉及Cookie的操作都是针对旧版本的Cookie进行的。而新版本的Cookie目前还不被Javax.servlet.http.Cookie包所支持。</font></p>
<p style="font-family: Arial,Helvetica,sans-serif; font-size: 9pt; color: #666666; text-align: left;"><font face="宋体" size="2">　　<u>2. Cookie的内容</u></font></p>
<p style="font-family: Arial,Helvetica,sans-serif; font-size: 9pt; color: #666666; text-align: left;"><font face="宋体" size="2">　　同样的Cookie的内容的字符限制针对不同的Cookie版本也有不同。<u>在Cookie Version 0中，某些特殊的字符，例如：空格，方括号，圆括号，等于号（=），逗号，双引号，斜杠，问号，@符号，冒号，分号都不能作为Cookie的内容。</u>这也就是为什么我们在例子中设定Cookie的内容为&#8220;Test_Content&#8221;的原因。</font></p>
<p style="font-family: Arial,Helvetica,sans-serif; font-size: 9pt; color: #666666; text-align: left;"><font face="宋体" size="2">　　虽然在Cookie Version 1规定中放宽了限制，可以使用这些字符，但是考虑到新版本的Cookie规范目前仍然没有为所有的浏览器所支持，因而为保险起见，我们应该在Cookie的内容中尽量避免使用这些字符。</font></p>
</span></span></div>
摘自：<a href="http://swingchen.bokee.com/6200015.html">http://swingchen.bokee.com/6200015.html</a><br />
类似这样的解释，搜索出来的结果，挺多。<br />
<br />
但是，我去看了RFC2109（<a href="http://www.faqs.org/rfcs/rfc2109.html">http://www.faqs.org/rfcs/rfc2109.html</a>）,其说明如下：<br />
<img alt="" src="http://www.blogjava.net/images/blogjava_net/stone2083/java/cookie.png" height="329" width="598" /><br />
value中的token，是有一组非特殊字符，非空白字符。而它是在RFC 2068（<a href="http://www.faqs.org/rfcs/rfc2068.html">http://www.faqs.org/rfcs/rfc2068.html</a>）中制定的 （是对Header的规范），请看：<br />
<img alt="" src="http://www.blogjava.net/images/blogjava_net/stone2083/java/header.png" height="247" width="556" /><br />
<br />
也就是说，所谓的Cookie1,同样有特殊字符的限制。<br />
同样，在Cookie2（RFC2965）中，也如此。<br />
<br />
想想也是啊，如果没有特殊字符的限制，解析Header的时候，还不乱套了？<br />
<br />
看了RFC之后，我们再来看看Tomcat中的实现（6.0.29版本），请看：<br />
org.apache.tomcat.util.http.Cookies<br />
<br />
1.类注释：<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;">A&nbsp;collection&nbsp;of&nbsp;cookies&nbsp;-&nbsp;reusable&nbsp;and&nbsp;tuned&nbsp;for&nbsp;server&nbsp;side&nbsp;performance.<br />
Based&nbsp;on&nbsp;RFC2965&nbsp;(&nbsp;and&nbsp;2109&nbsp;)</span></div>
是基于RFC2965/RFC2109规范来实现的<br />
<br />
2.特殊字符的定义<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: #008000;">/*</span><span style="color: #008000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;List&nbsp;of&nbsp;Separator&nbsp;Characters&nbsp;(see&nbsp;isSeparator())<br />
&nbsp;&nbsp;&nbsp;&nbsp;Excluding&nbsp;the&nbsp;'/'&nbsp;char&nbsp;violates&nbsp;the&nbsp;RFC,&nbsp;but&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;it&nbsp;looks&nbsp;like&nbsp;a&nbsp;lot&nbsp;of&nbsp;people&nbsp;put&nbsp;'/'<br />
&nbsp;&nbsp;&nbsp;&nbsp;in&nbsp;unquoted&nbsp;values:&nbsp;'/':&nbsp;;&nbsp;//47&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;'\t':9&nbsp;'&nbsp;':32&nbsp;'\"':34&nbsp;'(':40&nbsp;')':41&nbsp;',':44&nbsp;':':58&nbsp;';':59&nbsp;'&lt;':60&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;'=':61&nbsp;'&gt;':62&nbsp;'?':63&nbsp;'@':64&nbsp;'[':91&nbsp;'\\':92&nbsp;']':93&nbsp;'{':123&nbsp;'}':125<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">*/</span><span style="color: #000000;"><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;">final</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">char</span><span style="color: #000000;">&nbsp;SEPARATORS[]&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;{&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">\t</span><span style="color: #000000;">'</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;">,&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">\"</span><span style="color: #000000;">'</span><span style="color: #000000;">,&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">(</span><span style="color: #000000;">'</span><span style="color: #000000;">,&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">)</span><span style="color: #000000;">'</span><span style="color: #000000;">,&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">,</span><span style="color: #000000;">'</span><span style="color: #000000;">,&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">:</span><span style="color: #000000;">'</span><span style="color: #000000;">,&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">;</span><span style="color: #000000;">'</span><span style="color: #000000;">,&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">'</span><span style="color: #000000;">,&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">=</span><span style="color: #000000;">'</span><span style="color: #000000;">,&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">'</span><span style="color: #000000;">,&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">?</span><span style="color: #000000;">'</span><span style="color: #000000;">,&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">@</span><span style="color: #000000;">'</span><span style="color: #000000;">,&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">[</span><span style="color: #000000;">'</span><span style="color: #000000;">,&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">\\</span><span style="color: #000000;">'</span><span style="color: #000000;">,&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">]</span><span style="color: #000000;">'</span><span style="color: #000000;">,&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">{</span><span style="color: #000000;">'</span><span style="color: #000000;">,&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">}</span><span style="color: #000000;">'</span><span style="color: #000000;">&nbsp;};</span></div>
根据规范，定义了特殊字符。除了&#8220;/&#8221;这个符号。因为大多数人会直接使用&#8220;/&#8221;。<br />
<br />
3.针对&#8220;=&#8221;特殊处理<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: #008000;">/**</span><span style="color: #008000;"><br />
&nbsp;*&nbsp;If&nbsp;true,&nbsp;cookie&nbsp;values&nbsp;are&nbsp;allowed&nbsp;to&nbsp;contain&nbsp;an&nbsp;equals&nbsp;character&nbsp;without<br />
&nbsp;*&nbsp;being&nbsp;quoted.<br />
&nbsp;</span><span style="color: #008000;">*/</span><span style="color: #000000;"><br />
</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;">final</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">boolean</span><span style="color: #000000;">&nbsp;ALLOW_EQUALS_IN_VALUE;</span></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;">static</span><span style="color: #000000;">&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;ALLOW_EQUALS_IN_VALUE&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;Boolean.valueOf(System.getProperty(<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">org.apache.tomcat.util.http.ServerCookie.ALLOW_EQUALS_IN_VALUE</span><span style="color: #000000;">"</span><span style="color: #000000;">,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">false</span><span style="color: #000000;">"</span><span style="color: #000000;">)).booleanValue();<br />
}</span></div>
可以在catalina.properties中，添加这个配置项 （或者启动过程中加上-D参数），使得cookie value中允许存在&#8220;=&#8221;符号。<br />
所以本文开头提到的问题，可以使用这个方法得到解决<br />
<br />
4.解析过程<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: #008000;">/**</span><span style="color: #008000;"><br />
&nbsp;*&nbsp;Parses&nbsp;a&nbsp;cookie&nbsp;header&nbsp;after&nbsp;the&nbsp;initial&nbsp;"Cookie:"<br />
&nbsp;*&nbsp;[WS][$]token[WS]=[WS](token|QV)[;|,]<br />
&nbsp;*&nbsp;RFC&nbsp;2965<br />
&nbsp;*&nbsp;JVK<br />
&nbsp;</span><span style="color: #008000;">*/</span><span style="color: #000000;"><br />
</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">final</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;processCookieHeader(</span><span style="color: #0000ff;">byte</span><span style="color: #000000;">&nbsp;bytes[],&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;off,&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;len){<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">详细代码，省略</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">}</span></div>
<br />
<br />
备注：<br />
RFC没有仔细看（时间有限，并且看E文挺累的），如理解有误，请告知。<br />
<br />
<br />
<img src ="http://www.blogjava.net/stone2083/aggbug/336923.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/stone2083/" target="_blank">stone2083</a> 2010-11-03 13:27 <a href="http://www.blogjava.net/stone2083/archive/2010/11/03/336923.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>爬取交通违章信息的脚本</title><link>http://www.blogjava.net/stone2083/archive/2010/10/29/334643.html</link><dc:creator>stone2083</dc:creator><author>stone2083</author><pubDate>Fri, 29 Oct 2010 10:30:00 GMT</pubDate><guid>http://www.blogjava.net/stone2083/archive/2010/10/29/334643.html</guid><wfw:comment>http://www.blogjava.net/stone2083/comments/334643.html</wfw:comment><comments>http://www.blogjava.net/stone2083/archive/2010/10/29/334643.html#Feedback</comments><slash:comments>8</slash:comments><wfw:commentRss>http://www.blogjava.net/stone2083/comments/commentRss/334643.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/stone2083/services/trackbacks/334643.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 会开车了，也慢慢不规矩起来了，于是乎，违章信息也慢慢多起来了，但是无法第一时间通知到自己。虽说，有个网站：http://www.hzti.com/service/qry/violation_veh.aspx?pgid=&amp;type=1&amp;node=249可以查询非现场违章情况，不过：1.我是懒人，主动去查询的时候不太乐意做2.车辆识别码，永远记不住3.每次输验证...&nbsp;&nbsp;<a href='http://www.blogjava.net/stone2083/archive/2010/10/29/334643.html'>阅读全文</a><img src ="http://www.blogjava.net/stone2083/aggbug/334643.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/stone2083/" target="_blank">stone2083</a> 2010-10-29 18:30 <a href="http://www.blogjava.net/stone2083/archive/2010/10/29/334643.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java反射效率</title><link>http://www.blogjava.net/stone2083/archive/2010/09/15/332065.html</link><dc:creator>stone2083</dc:creator><author>stone2083</author><pubDate>Wed, 15 Sep 2010 06:04:00 GMT</pubDate><guid>http://www.blogjava.net/stone2083/archive/2010/09/15/332065.html</guid><wfw:comment>http://www.blogjava.net/stone2083/comments/332065.html</wfw:comment><comments>http://www.blogjava.net/stone2083/archive/2010/09/15/332065.html#Feedback</comments><slash:comments>9</slash:comments><wfw:commentRss>http://www.blogjava.net/stone2083/comments/commentRss/332065.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/stone2083/services/trackbacks/332065.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: java反射效率到底如何,花了点时间,做了一个简单的测试.供大家参考.测试背景:1. 测试简单Bean(int,Integer,String)的set方法2. loop 1亿次3. 测试代码尽可能避免对象的创建,复发方法的调用,仅仅测试set方法的耗时测试结果:                        &nbsp;场景            &...&nbsp;&nbsp;<a href='http://www.blogjava.net/stone2083/archive/2010/09/15/332065.html'>阅读全文</a><img src ="http://www.blogjava.net/stone2083/aggbug/332065.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/stone2083/" target="_blank">stone2083</a> 2010-09-15 14:04 <a href="http://www.blogjava.net/stone2083/archive/2010/09/15/332065.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>IBatis下DAO单元测试另类思路</title><link>http://www.blogjava.net/stone2083/archive/2010/08/12/328602.html</link><dc:creator>stone2083</dc:creator><author>stone2083</author><pubDate>Thu, 12 Aug 2010 01:03:00 GMT</pubDate><guid>http://www.blogjava.net/stone2083/archive/2010/08/12/328602.html</guid><wfw:comment>http://www.blogjava.net/stone2083/comments/328602.html</wfw:comment><comments>http://www.blogjava.net/stone2083/archive/2010/08/12/328602.html#Feedback</comments><slash:comments>9</slash:comments><wfw:commentRss>http://www.blogjava.net/stone2083/comments/commentRss/328602.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/stone2083/services/trackbacks/328602.html</trackback:ping><description><![CDATA[在说另类思路之前,先说下传统的测试方法:<br />
0.准备一个干净的测试数据库环境<br />
&nbsp; 这个是前提<br />
1.测试数据准备<br />
&nbsp; 使用文本,excel,或者wiki等,准备测试sql以及测试数据<br />
&nbsp; 利用dbfit,dbutil等工具将准备的测试数据导入到数据库中<br />
2.执行dao方法<br />
&nbsp; 执行被测试的dao方法<br />
3.测试结果断言<br />
&nbsp; 利用dbfit,dbutil等工具,断言测试结果数据和预计是否一致<br />
4.所有数据回滚<br />
<br />
其实,对于这个流程来说,目前的dao测试框架,支持的已经比较完美了<br />
但是此类测试方法,也有明显的缺点(或者不能叫缺点,叫使用比较麻烦的地方)<br />
如下:<br />
1.背上了一个数据库环境.<br />
&nbsp; 不轻量<br />
&nbsp; 这是一个共享环境,谁也无法确保环境数据是否真正的干净<br />
2.测试数据准备是一件麻烦的事情<br />
&nbsp; 新表,10几个字段毫不为奇;老表,50几个字段甚至百来个字段,也偶有可见;无论是使用文本,excel,wiki,准备工作量,都是巨大的.<br />
&nbsp; 准备的数据,部分字段内容可以是无意义的,部分字段内容又是需要符合测试意图(testcase设计目的),部分字段还是其他表的关联字段.从而导致后续维护人员无法了解准备数据意图.<br />
&nbsp; (实践中,也出现过,一同事在维护他人单元测试时,由于无法了解测试数据准备意图,宁可重新删除,自己准备一份)<br />
3.预计结果数据准备也是一件麻烦的事情<br />
&nbsp; 理由如上<br />
<br />
所以,理论上是完美的测试方案,在实践过程中,却是一件麻烦的事情.导致DAO单元测试维护困难.<br />
<br />
<br />
分析了现状,我们再来分析下,IBatis下DAO,程序员主要做了哪些编码:<br />
1. 写了一份sqlmap.xml配置文件<br />
2. 通过<em>getSqlMapClientTemplate</em>.doSomething($sqlID,$param), 执行语句<br />
(当然,没有使用spring的同学,也是使用了类似sqlMapClient.doSomething($sqlID,$param)方法)<br />
<br />
而步骤2其实是框架替我们做了的事情,按照MOCK的思想,其实这部分代码可以被MOCK的,那么我们是否可以做如下假设:<br />
<strong>只要sqlmap.xml中配置信息(主要包括resultmap和statement)是正确的,那么执行结果也应该是正确的</strong>.<br />
<br />
而我所谓的另类思路,就是基于这个假设,得出的:<br />
IBatis下,DAO单元测试,我们抛弃背负的数据库环境,只要根据不同的条件,断言不同的sql即可.<br />
<br />
于是乎,封装了一个IbatisSqlTester,可以根据sqlmap中的statement和传入的条件参数,生成sql语句.<br />
那么,DAO单元测试就简单了,脱离下数据库环境:<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;ScoreDAOTest&nbsp;</span><span style="color: #0000ff;">extends</span><span style="color: #000000;">&nbsp;TestCase&nbsp;{<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;@SpringBeanByName<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">private</span><span style="color: #000000;">&nbsp;IbatisSqlTester&nbsp;ibatisSqlTester;&nbsp; //通过spring配置,需要注入sqlmapclient对象<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;@Test<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;testListTpScores()&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Map</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">String,&nbsp;Object</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">&nbsp;param&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;HashMap</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">String,&nbsp;Object</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">(</span><span style="color: #000000;">1</span><span style="color: #000000;">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;param.put(</span><span style="color: #000000;">"</span><span style="color: #000000;">memberIds</span><span style="color: #000000;">"</span><span style="color: #000000;">,&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;String[]&nbsp;{&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">stone</span><span style="color: #000000;">"</span><span style="color: #000000;">,&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">stone2083</span><span style="color: #000000;">"</span><span style="color: #000000;">&nbsp;});<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SqlStatement&nbsp;sql&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;ibatisSqlTester.test(</span><span style="color: #000000;">"</span><span style="color: #000000;">MS-LIST-SCORES</span><span style="color: #000000;">"</span><span style="color: #000000;">,&nbsp;param);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;sql全部匹配</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SqlAssert.isEqual(</span><span style="color: #000000;">"</span><span style="color: #000000;">select&nbsp;*&nbsp;from&nbsp;score&nbsp;where&nbsp;member_id&nbsp;in&nbsp;('stone','stone2083')</span><span style="color: #000000;">"</span><span style="color: #000000;">,&nbsp;sql.toString());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;sql包含member_id,athena2002,stone关键词</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SqlAssert.keyWith(sql.toString(),&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">member_id</span><span style="color: #000000;">"</span><span style="color: #000000;">,&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">stone</span><span style="color: #000000;">"</span><span style="color: #000000;">,&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">stone2083</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;sql符合某个&nbsp;正则</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SqlAssert.regexWith(</span><span style="color: #000000;">"</span><span style="color: #000000;">.*&nbsp;where&nbsp;member_id&nbsp;in&nbsp;.*</span><span style="color: #000000;">"</span><span style="color: #000000;">,&nbsp;sql.toString());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">其中,SqlAssert也可以换&nbsp;成want.string()中的方法.</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;}<br />
}</span></div>
<br />
<strong>优势:</strong><br />
&nbsp; 脱离了数据库环境<br />
&nbsp; 脱离了表结构数据准备<br />
&nbsp; 脱离了预计结果数据准备<br />
&nbsp; 让单元测试变成sql的断言,编写相对更简单<br />
<strong>缺点:<br />
&nbsp; </strong>row mapper过程无法被测试<br />
<br />
<br />
最后,附上两个核心的代码类(还未完成),供大家参考:<br />
<strong>SqlStatement.java</strong><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: #008000;">/**</span><span style="color: #008000;"><br />
&nbsp;*&nbsp;&lt;pre&gt;<br />
&nbsp;*&nbsp;SqlStatement:Sql语句对象.<br />
&nbsp;*&nbsp;包含:<br />
&nbsp;*&nbsp;&nbsp;1.sql语句,类似&nbsp;&nbsp;select&nbsp;*&nbsp;from&nbsp;offer&nbsp;where&nbsp;id&nbsp;=&nbsp;?&nbsp;and&nbsp;member_id&nbsp;=&nbsp;?<br />
&nbsp;*&nbsp;&nbsp;2.参数值,类似&nbsp;[1,stone2083]<br />
&nbsp;*&nbsp;&nbsp;<br />
&nbsp;*&nbsp;&nbsp;toString方法,返回执行的sql语句,如:<br />
&nbsp;*&nbsp;&nbsp;select&nbsp;*&nbsp;from&nbsp;offer&nbsp;where&nbsp;id&nbsp;=&nbsp;'1'&nbsp;and&nbsp;member_id&nbsp;=&nbsp;'stone2083'<br />
&nbsp;*&nbsp;&lt;/pre&gt;<br />
&nbsp;*&nbsp;<br />
&nbsp;*&nbsp;</span><span style="color: #808080;">@author</span><span style="color: #008000;">&nbsp;Stone.J&nbsp;2010-8-9&nbsp;下午02:55:36<br />
&nbsp;</span><span style="color: #008000;">*/</span><span style="color: #000000;"><br />
</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;SqlStatement&nbsp;{<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">sql</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">private</span><span style="color: #000000;">&nbsp;String&nbsp;&nbsp;&nbsp;sql;<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">sql参数</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">private</span><span style="color: #000000;">&nbsp;Object[]&nbsp;param;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">/**</span><span style="color: #008000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&lt;pre&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;输出最终执行的sql内容.<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;将sql和param进行merge,产生最终执行的sql语句<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&lt;/pre&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">*/</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;@Override<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;String&nbsp;toString()&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;merge();<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">/**</span><span style="color: #008000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&lt;pre&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;将sql进行格式化.<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;目前只是简单进行格式化.去除前后空格,已经重复空格<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;TODO:请使用统一格式化标准规,建议使用SqlFormater类,进行处理<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&lt;/pre&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: #808080;">@param</span><span style="color: #008000;">&nbsp;sql<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: #808080;">@return</span><span style="color: #008000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">*/</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">protected</span><span style="color: #000000;">&nbsp;String&nbsp;format(String&nbsp;sql)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(sql&nbsp;</span><span style="color: #000000;">==</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">null</span><span style="color: #000000;">)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">null</span><span style="color: #000000;">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;sql.toLowerCase().trim().replaceAll(</span><span style="color: #000000;">"</span><span style="color: #000000;">\\s{1,}</span><span style="color: #000000;">"</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;">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">/**</span><span style="color: #008000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&lt;pre&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;将sql和param进行merge.<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;TODO:请严格按照SQL标准,进行merge&nbsp;sql内容<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&lt;/pre&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">*/</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">protected</span><span style="color: #000000;">&nbsp;String&nbsp;merge()&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(param&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;param.length&nbsp;</span><span style="color: #000000;">==</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">this</span><span style="color: #000000;">.sql;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;ret&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;sql;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">for</span><span style="color: #000000;">&nbsp;(Object&nbsp;p&nbsp;:&nbsp;param)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ret&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;ret.replaceFirst(</span><span style="color: #000000;">"</span><span style="color: #000000;">\\?</span><span style="color: #000000;">"</span><span style="color: #000000;">,&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">'</span><span style="color: #000000;">"</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;p.toString()&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">'</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;ret;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;String&nbsp;getSql()&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;sql;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;setSql(String&nbsp;sql)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">this</span><span style="color: #000000;">.sql&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;format(sql);<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;Object[]&nbsp;getParam()&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;param;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;setParam(Object[]&nbsp;param)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">this</span><span style="color: #000000;">.param&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;param;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
}</span></div>
<br />
<strong>IbatisSqlTester.java</strong><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: #008000;">/**</span><span style="color: #008000;"><br />
&nbsp;*&nbsp;&lt;pre&gt;<br />
&nbsp;*&nbsp;IBtatis&nbsp;SQL&nbsp;测试<br />
&nbsp;*&nbsp;一般IBatis&nbsp;DAO单元测试,主要就是在测试ibatis的配置文件.<br />
&nbsp;*&nbsp;IbatisSqlTester将根据提供的Sql&nbsp;Map&nbsp;Id&nbsp;和&nbsp;对应的参数,返回&nbsp;{</span><span style="color: #808080;">@link</span><span style="color: #008000;">&nbsp;SqlStatement}对象,提供最终执行的sql语句<br />
&nbsp;*&nbsp;通过外部SqlAssert对象,将预计Sql和实际产生的Sql进行对比,判断是否正确<br />
&nbsp;*&nbsp;&lt;/pre&gt;<br />
&nbsp;*&nbsp;<br />
&nbsp;*&nbsp;</span><span style="color: #808080;">@author</span><span style="color: #008000;">&nbsp;Stone.J&nbsp;2010-8-9&nbsp;下午02:58:46<br />
&nbsp;</span><span style="color: #008000;">*/</span><span style="color: #000000;"><br />
</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;IbatisSqlTester&nbsp;{<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;sqlMapClient</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">private</span><span style="color: #000000;">&nbsp;ExtendedSqlMapClient&nbsp;sqlMapClient;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">/**</span><span style="color: #008000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;根据提供的SqlMap&nbsp;ID,得到&nbsp;{</span><span style="color: #808080;">@link</span><span style="color: #008000;">&nbsp;SqlStatement}对象<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: #808080;">@param</span><span style="color: #008000;">&nbsp;sqlId:&nbsp;sql&nbsp;map&nbsp;id<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: #808080;">@return</span><span style="color: #008000;">&nbsp;</span><span style="color: #808080;">@see</span><span style="color: #008000;">&nbsp;{</span><span style="color: #808080;">@link</span><span style="color: #008000;">&nbsp;SqlStatement}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">*/</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;SqlStatement&nbsp;test(String&nbsp;sqlId)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">得到MappedStatement对象</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MappedStatement&nbsp;ms&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;sqlMapClient.getMappedStatement(sqlId);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(ms&nbsp;</span><span style="color: #000000;">==</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">null</span><span style="color: #000000;">)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">TODO:建议封转自己的异常对象</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;">throw</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;RuntimeException(</span><span style="color: #000000;">"</span><span style="color: #000000;">can't&nbsp;find&nbsp;MappedStatement.</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">按照Ibatis代码,得到Sql和Param信息</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;RequestScope&nbsp;request&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;RequestScope();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ms.initRequest(request);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Sql&nbsp;sql&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;ms.getSql();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;sqlValue&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;sql.getSql(request,&nbsp;</span><span style="color: #0000ff;">null</span><span style="color: #000000;">);<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&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;SqlStatement&nbsp;ret&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;SqlStatement();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ret.setSql(sqlValue);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;ret;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">/**</span><span style="color: #008000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;根据提供的SqlMap&nbsp;ID和对应的param信息,得到&nbsp;{</span><span style="color: #808080;">@link</span><span style="color: #008000;">&nbsp;SqlStatement}对象<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: #808080;">@param</span><span style="color: #008000;">&nbsp;sqlId:&nbsp;sql&nbsp;map&nbsp;id<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: #808080;">@param</span><span style="color: #008000;">&nbsp;param:&nbsp;参数内容<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: #808080;">@return</span><span style="color: #008000;">&nbsp;</span><span style="color: #808080;">@see</span><span style="color: #008000;">&nbsp;{</span><span style="color: #808080;">@link</span><span style="color: #008000;">&nbsp;SqlStatement}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">*/</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;SqlStatement&nbsp;test(String&nbsp;sqlId,&nbsp;Object&nbsp;param)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">得到MappedStatement对象</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MappedStatement&nbsp;ms&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;sqlMapClient.getMappedStatement(sqlId);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(ms&nbsp;</span><span style="color: #000000;">==</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">null</span><span style="color: #000000;">)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">TODO:建议封转自己的异常对象</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;">throw</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;RuntimeException(</span><span style="color: #000000;">"</span><span style="color: #000000;">can't&nbsp;find&nbsp;MappedStatement.</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">按照Ibatis代码,得到Sql和Param信息</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;RequestScope&nbsp;request&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;RequestScope();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ms.initRequest(request);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Sql&nbsp;sql&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;ms.getSql();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;sqlValue&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;sql.getSql(request,&nbsp;param);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Object[]&nbsp;sqlParam&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;sql.getParameterMap(request,&nbsp;param).getParameterObjectValues(request,&nbsp;param);<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&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;SqlStatement&nbsp;ret&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;SqlStatement();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ret.setSql(sqlValue);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ret.setParam(sqlParam);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;ret;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">/**</span><span style="color: #008000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;设置SqlMapClient对象<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">*/</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;setSqlMapClient(ExtendedSqlMapClient&nbsp;sqlMapClient)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">this</span><span style="color: #000000;">.sqlMapClient&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;sqlMapClient;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">/**</span><span style="color: #008000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&lt;pre&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;不推荐使用<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;推荐使用:&nbsp;{</span><span style="color: #808080;">@link</span><span style="color: #008000;">&nbsp;IbatisSqlTester#setSqlMapClient(ExtendedSqlMapClient)}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;TODO:请去除这个方法,或者增加初始化的方式<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&lt;/pre&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: #808080;">@param</span><span style="color: #008000;">&nbsp;sqlMapConfig&nbsp;sqlMapConfig&nbsp;xml文件<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">*/</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;setSqlMapConfig(String&nbsp;sqlMapConfig)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;InputStream&nbsp;in&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">null</span><span style="color: #000000;">;<br />
&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;File&nbsp;file&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;ResourceUtils.getFile(sqlMapConfig);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;in&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;FileInputStream(file);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">this</span><span style="color: #000000;">.sqlMapClient&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;(ExtendedSqlMapClient)&nbsp;SqlMapClientBuilder.buildSqlMapClient(in);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span><span style="color: #0000ff;">catch</span><span style="color: #000000;">&nbsp;(Exception&nbsp;e)&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(</span><span style="color: #000000;">"</span><span style="color: #000000;">sqlMapConfig&nbsp;init&nbsp;error.</span><span style="color: #000000;">"</span><span style="color: #000000;">,&nbsp;e);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span><span style="color: #0000ff;">finally</span><span style="color: #000000;">&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(in&nbsp;</span><span style="color: #000000;">!=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">null</span><span style="color: #000000;">)&nbsp;{<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;in.close();<br />
&nbsp;&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;(IOException&nbsp;e)&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;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
}</span></div>
<br />
<br />
最后的最后附上所有代码(通过单元测试代码,可以看如何使用).欢迎大家的讨论.<br />
<a href="/Files/stone2083/java/sqltester.zip" title="sqltester">sqltester</a><br />
<a href="/Files/stone2083/java/builder.zip" title="builder">builder</a><br />
<img src ="http://www.blogjava.net/stone2083/aggbug/328602.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/stone2083/" target="_blank">stone2083</a> 2010-08-12 09:03 <a href="http://www.blogjava.net/stone2083/archive/2010/08/12/328602.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>扫描classpath下类资源</title><link>http://www.blogjava.net/stone2083/archive/2010/07/23/326941.html</link><dc:creator>stone2083</dc:creator><author>stone2083</author><pubDate>Fri, 23 Jul 2010 06:55:00 GMT</pubDate><guid>http://www.blogjava.net/stone2083/archive/2010/07/23/326941.html</guid><wfw:comment>http://www.blogjava.net/stone2083/comments/326941.html</wfw:comment><comments>http://www.blogjava.net/stone2083/archive/2010/07/23/326941.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/stone2083/comments/commentRss/326941.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/stone2083/services/trackbacks/326941.html</trackback:ping><description><![CDATA[很早之前,为了简化配置信息,自己写了一坨代码,基于classpath扫描类信息,加载.<br />
其实,在spring中,已经提供了类似组件(后知后觉了...):<br />
<br />
org.springframework.core.io.support.PathMatchingResourcePatternResolver&nbsp; 资源解析器(基于路径的正则表达式)<br />
org.springframework.core.type.classreading.MetadataReader ClassMeta信息解读器<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: #008080;">&nbsp;1</span>&nbsp;<span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;Test&nbsp;{<br />
</span><span style="color: #008080;">&nbsp;2</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">&nbsp;3</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">/*</span><span style="color: #008000;">&nbsp;资源路径&nbsp;</span><span style="color: #008000;">*/</span><span style="color: #000000;"><br />
</span><span style="color: #008080;">&nbsp;4</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&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;String&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PATH&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">classpath*:com/alibaba/javalab/t*/**/*.class</span><span style="color: #000000;">"</span><span style="color: #000000;">;<br />
</span><span style="color: #008080;">&nbsp;5</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">/*</span><span style="color: #008000;">&nbsp;资源解析器&nbsp;</span><span style="color: #008000;">*/</span><span style="color: #000000;"><br />
</span><span style="color: #008080;">&nbsp;6</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&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;ResourcePatternResolver&nbsp;RESOLVER&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;PathMatchingResourcePatternResolver();<br />
</span><span style="color: #008080;">&nbsp;7</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">/*</span><span style="color: #008000;">&nbsp;Meta信息Reader&nbsp;Factory.用于创建MetaReader&nbsp;</span><span style="color: #008000;">*/</span><span style="color: #000000;"><br />
</span><span style="color: #008080;">&nbsp;8</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&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;MetadataReaderFactory&nbsp;&nbsp;&nbsp;READER_FACTORY&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;SimpleMetadataReaderFactory();<br />
</span><span style="color: #008080;">&nbsp;9</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">10</span>&nbsp;<span style="color: #000000;">&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;Exception&nbsp;{<br />
</span><span style="color: #008080;">11</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">根据正则表达式,得到资源列表</span><span style="color: #008000;"><br />
</span><span style="color: #008080;">12</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Resource[]&nbsp;resources&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;RESOLVER.getResources(PATH);<br />
</span><span style="color: #008080;">13</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">for</span><span style="color: #000000;">&nbsp;(Resource&nbsp;res&nbsp;:&nbsp;resources)&nbsp;{<br />
</span><span style="color: #008080;">14</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">通过&nbsp;MetadataReader得到ClassMeta信息,打印类名</span><span style="color: #008000;"><br />
</span><span style="color: #008080;">15</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MetadataReader&nbsp;meta&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;READER_FACTORY.getMetadataReader(res);<br />
</span><span style="color: #008080;">16</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(meta.getClassMetadata().getClassName());<br />
</span><span style="color: #008080;">17</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
</span><span style="color: #008080;">18</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;}<br />
</span><span style="color: #008080;">19</span>&nbsp;<span style="color: #000000;">}</span></div>
<br />
输出结果:<br />
com.alibaba.javalab.tool.fetion.protocol.Config<br />
com.alibaba.javalab.tool.fetion.protocol.Fetion<br />
com.alibaba.javalab.tool.fetion.protocol.FetionHelper<br />
com.alibaba.javalab.tool.fetion.protocol.LoginSession<br />
com.alibaba.javalab.tool.trace.TimeTrace<br />
...<br />
<br />
挺好使的一个工具 :)<br />
<br />
<br />
<img src ="http://www.blogjava.net/stone2083/aggbug/326941.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/stone2083/" target="_blank">stone2083</a> 2010-07-23 14:55 <a href="http://www.blogjava.net/stone2083/archive/2010/07/23/326941.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>初识InheritableThreadLocal</title><link>http://www.blogjava.net/stone2083/archive/2010/07/23/326894.html</link><dc:creator>stone2083</dc:creator><author>stone2083</author><pubDate>Fri, 23 Jul 2010 01:17:00 GMT</pubDate><guid>http://www.blogjava.net/stone2083/archive/2010/07/23/326894.html</guid><wfw:comment>http://www.blogjava.net/stone2083/comments/326894.html</wfw:comment><comments>http://www.blogjava.net/stone2083/archive/2010/07/23/326894.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/stone2083/comments/commentRss/326894.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/stone2083/services/trackbacks/326894.html</trackback:ping><description><![CDATA[一直来只知道ThreadLocal,直到最近看slf4j MDC实现代码的时候,才认识了InheritableThreadLocal.<br />
InheritableThreadLocal顾名思义,可继承的ThreadLocal.<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;">This&nbsp;class&nbsp;extends&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">tt</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;">ThreadLocal</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">tt</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;">&nbsp;to&nbsp;provide&nbsp;inheritance&nbsp;of&nbsp;values<br />
&nbsp;*&nbsp;from&nbsp;parent&nbsp;thread&nbsp;to&nbsp;child&nbsp;thread:&nbsp;when&nbsp;a&nbsp;child&nbsp;thread&nbsp;is&nbsp;created,&nbsp;the<br />
&nbsp;*&nbsp;child&nbsp;receives&nbsp;initial&nbsp;values&nbsp;for&nbsp;all&nbsp;inheritable&nbsp;thread-local&nbsp;variables<br />
&nbsp;*&nbsp;for&nbsp;which&nbsp;the&nbsp;parent&nbsp;has&nbsp;values.</span></div>
<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;">&nbsp;1</span>&nbsp;<span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;Test&nbsp;{<br />
</span><span style="color: #008080;">&nbsp;2</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">&nbsp;3</span>&nbsp;<span style="color: #000000;">&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;{<br />
</span><span style="color: #008080;">&nbsp;4</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">使用ThreadLocal,父子线程之间,不共享Value</span><span style="color: #008000;"><br />
</span><span style="color: #008080;">&nbsp;5</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">final</span><span style="color: #000000;">&nbsp;ThreadLocal</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">String</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">&nbsp;tl&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;ThreadLocal</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">String</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">();<br />
</span><span style="color: #008080;">&nbsp;6</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tl.set(</span><span style="color: #000000;">"</span><span style="color: #000000;">ThreadLocal-VAL</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br />
</span><span style="color: #008080;">&nbsp;7</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="color: #000000;">"</span><span style="color: #000000;">Main-1:</span><span style="color: #000000;">"</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;tl.get());<br />
</span><span style="color: #008080;">&nbsp;8</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;Thread()&nbsp;{<br />
</span><span style="color: #008080;">&nbsp;9</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;run()&nbsp;{<br />
</span><span style="color: #008080;">10</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="color: #000000;">"</span><span style="color: #000000;">Child-1:</span><span style="color: #000000;">"</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;tl.get());<br />
</span><span style="color: #008080;">11</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;};<br />
</span><span style="color: #008080;">12</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}.start();<br />
</span><span style="color: #008080;">13</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">14</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">使用InheritableThreadLocal,父线程Value可让子线程共享</span><span style="color: #008000;"><br />
</span><span style="color: #008080;">15</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">final</span><span style="color: #000000;">&nbsp;ThreadLocal</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">String</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">&nbsp;itl&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;InheritableThreadLocal</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">String</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">();<br />
</span><span style="color: #008080;">16</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;itl.set(</span><span style="color: #000000;">"</span><span style="color: #000000;">InheritableThreadLocal-VAL</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br />
</span><span style="color: #008080;">17</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="color: #000000;">"</span><span style="color: #000000;">Main-2:</span><span style="color: #000000;">"</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;itl.get());<br />
</span><span style="color: #008080;">18</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;Thread()&nbsp;{<br />
</span><span style="color: #008080;">19</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;run()&nbsp;{<br />
</span><span style="color: #008080;">20</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="color: #000000;">"</span><span style="color: #000000;">Child-2:</span><span style="color: #000000;">"</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;itl.get());<br />
</span><span style="color: #008080;">21</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;};<br />
</span><span style="color: #008080;">22</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}.start();<br />
</span><span style="color: #008080;">23</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">24</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;}<br />
</span><span style="color: #008080;">25</span>&nbsp;<span style="color: #000000;">}</span></div>
<br />
输出内容:<br />
Main-1:ThreadLocal-VAL<br />
Main-2:InheritableThreadLocal-VAL<br />
Child-1:null<br />
Child-2:InheritableThreadLocal-VAL<br />
<br />
<br />
......分隔符号......<br />
<br />
顺带着简单说下MDC.(Mapped Diagnostic Context). 中文直译太恶心了,我理解的意思是,和环境相关的上下文信息.<br />
比如在web应用中,我们可以把用户的ip,访问url等放入到这个上下文中,log打印的时候,就能得到这个信息.<br />
<br />
在slf4j BasicMDCAdapter实现中,就是用了InheritableThreadLocal<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;">1</span>&nbsp;<span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;BasicMDCAdapter&nbsp;</span><span style="color: #0000ff;">implements</span><span style="color: #000000;">&nbsp;MDCAdapter&nbsp;{<br />
</span><span style="color: #008080;">2</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">3</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;</span><span style="color: #0000ff;">private</span><span style="color: #000000;">&nbsp;InheritableThreadLocal&nbsp;inheritableThreadLocal&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;InheritableThreadLocal();<br />
</span><span style="color: #008080;">4</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;<br />
</span><span style="color: #008080;">5</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;"><img src="http://www.blogjava.net/Images/dot.gif"  alt="" />.</span><span style="color: #008000;"><br />
</span><span style="color: #008080;">6</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">7</span>&nbsp;<span style="color: #000000;">}</span></div>
<br />
<img src ="http://www.blogjava.net/stone2083/aggbug/326894.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/stone2083/" target="_blank">stone2083</a> 2010-07-23 09:17 <a href="http://www.blogjava.net/stone2083/archive/2010/07/23/326894.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>小谈PropertyPlaceholderConfigurer</title><link>http://www.blogjava.net/stone2083/archive/2010/07/23/326891.html</link><dc:creator>stone2083</dc:creator><author>stone2083</author><pubDate>Fri, 23 Jul 2010 00:51:00 GMT</pubDate><guid>http://www.blogjava.net/stone2083/archive/2010/07/23/326891.html</guid><wfw:comment>http://www.blogjava.net/stone2083/comments/326891.html</wfw:comment><comments>http://www.blogjava.net/stone2083/archive/2010/07/23/326891.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/stone2083/comments/commentRss/326891.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/stone2083/services/trackbacks/326891.html</trackback:ping><description><![CDATA[背景:让应用在一个环境下,以多实例的方法运行.<br />
Log问题,可以通过Log4j占位符实现(见前文:<a href="http://www.blogjava.net/stone2083/archive/2010/07/01/324935.html">http://www.blogjava.net/stone2083/archive/2010/07/01/324935.html</a>)<br />
其他Java组件代码依赖了本地环境资源,怎么解决呢?<br />
<br />
对于使用Spring的组件来说,PropertyPlaceholderConfigurer能帮我们解决这一问题.<br />
<br />
PropertyPlaceholderConfigurer除了支持配置的properties文件外,还支持系统属性(System.getProperties()).当然,它有三种模式:<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;">&nbsp;1</span><span style="color: #008000;">/**</span><span style="color: #008000;">&nbsp;Never&nbsp;check&nbsp;system&nbsp;properties.&nbsp;</span><span style="color: #008000;">*/</span><span style="color: #000000;"><br />
</span><span style="color: #008080;">&nbsp;2</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;">final</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;SYSTEM_PROPERTIES_MODE_NEVER&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">;<br />
</span><span style="color: #008080;">&nbsp;3</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">&nbsp;4</span><span style="color: #008000;">/**</span><span style="color: #008000;"><br />
</span><span style="color: #008080;">&nbsp;5</span><span style="color: #008000;"> *&nbsp;Check&nbsp;system&nbsp;properties&nbsp;if&nbsp;not&nbsp;resolvable&nbsp;in&nbsp;the&nbsp;specified&nbsp;properties.<br />
</span><span style="color: #008080;">&nbsp;6</span><span style="color: #008000;"> *&nbsp;This&nbsp;is&nbsp;the&nbsp;default.<br />
</span><span style="color: #008080;">&nbsp;7</span><span style="color: #008000;"> </span><span style="color: #008000;">*/</span><span style="color: #000000;"><br />
</span><span style="color: #008080;">&nbsp;8</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;">final</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;SYSTEM_PROPERTIES_MODE_FALLBACK&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">1</span><span style="color: #000000;">;<br />
</span><span style="color: #008080;">&nbsp;9</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">10</span><span style="color: #008000;">/**</span><span style="color: #008000;"><br />
</span><span style="color: #008080;">11</span><span style="color: #008000;"> *&nbsp;Check&nbsp;system&nbsp;properties&nbsp;first,&nbsp;before&nbsp;trying&nbsp;the&nbsp;specified&nbsp;properties.<br />
</span><span style="color: #008080;">12</span><span style="color: #008000;"> *&nbsp;This&nbsp;allows&nbsp;system&nbsp;properties&nbsp;to&nbsp;override&nbsp;any&nbsp;other&nbsp;property&nbsp;source.<br />
</span><span style="color: #008080;">13</span><span style="color: #008000;"> </span><span style="color: #008000;">*/</span><span style="color: #000000;"><br />
</span><span style="color: #008080;">14</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;">final</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;SYSTEM_PROPERTIES_MODE_OVERRIDE&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">2</span><span style="color: #000000;">;</span></div>
<br />
对于使用本地环境资源的bean来说,只要配置:<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;">&nbsp;1</span>&nbsp;<span style="color: #0000ff;">&lt;</span><span style="color: #800000;">bean&nbsp;</span><span style="color: #ff0000;">class</span><span style="color: #0000ff;">="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
</span><span style="color: #008080;">&nbsp;2</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">property&nbsp;</span><span style="color: #ff0000;">name</span><span style="color: #0000ff;">="systemPropertiesModeName"</span><span style="color: #ff0000;">&nbsp;value</span><span style="color: #0000ff;">="SYSTEM_PROPERTIES_MODE_OVERRIDE"</span><span style="color: #ff0000;">&nbsp;</span><span style="color: #0000ff;">/&gt;</span><span style="color: #000000;"><br />
</span><span style="color: #008080;">&nbsp;3</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">property&nbsp;</span><span style="color: #ff0000;">name</span><span style="color: #0000ff;">="locations"</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
</span><span style="color: #008080;">&nbsp;4</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">list</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
</span><span style="color: #008080;">&nbsp;5</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">value</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;">classpath*:spring/env.properties</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">value</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"> &lt;!--无需配置node--&gt;<br />
</span><span style="color: #008080;">&nbsp;6</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">list</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
</span><span style="color: #008080;">&nbsp;7</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">property</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
</span><span style="color: #008080;">&nbsp;8</span> <span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">bean</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
</span><span style="color: #008080;">&nbsp;9</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">10</span>&nbsp;<span style="color: #0000ff;">&lt;</span><span style="color: #800000;">bean&nbsp;</span><span style="color: #ff0000;">id</span><span style="color: #0000ff;">="javaBean"</span><span style="color: #ff0000;">&nbsp;class</span><span style="color: #0000ff;">="com.alibaba.javalab.spring.JavaBean"</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
</span><span style="color: #008080;">11</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">property&nbsp;</span><span style="color: #ff0000;">name</span><span style="color: #0000ff;">="lockFile"</span><span style="color: #ff0000;">&nbsp;value</span><span style="color: #0000ff;">="/home/stone/base/${node}/lock"</span><span style="color: #ff0000;">&nbsp;</span><span style="color: #0000ff;">/&gt;</span><span style="color: #000000;"><br />
</span><span style="color: #008080;">12</span>&nbsp;<span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">bean</span><span style="color: #0000ff;">&gt;</span></div>
<br />
<br />
在启动脚本中,只要加入-Dnode=instanceX即可.<br />
<br />
总结:<br />
PropertyPlaceholderConfigurer支持properties文件和系统属性.并且存在三种覆盖策略.<br />
<img src ="http://www.blogjava.net/stone2083/aggbug/326891.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/stone2083/" target="_blank">stone2083</a> 2010-07-23 08:51 <a href="http://www.blogjava.net/stone2083/archive/2010/07/23/326891.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java Exception性能问题</title><link>http://www.blogjava.net/stone2083/archive/2010/07/09/325649.html</link><dc:creator>stone2083</dc:creator><author>stone2083</author><pubDate>Fri, 09 Jul 2010 06:30:00 GMT</pubDate><guid>http://www.blogjava.net/stone2083/archive/2010/07/09/325649.html</guid><wfw:comment>http://www.blogjava.net/stone2083/comments/325649.html</wfw:comment><comments>http://www.blogjava.net/stone2083/archive/2010/07/09/325649.html#Feedback</comments><slash:comments>16</slash:comments><wfw:commentRss>http://www.blogjava.net/stone2083/comments/commentRss/325649.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/stone2083/services/trackbacks/325649.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 背景:大学里学java,老师口口声声,言之凿凿,告诫我们,Java千万别用异常控制业务流程,只有系统级别的问题,才能使用异常;(当时,我们都不懂为什么不能用异常,只知道老师这么说,我们就这么做,考试才不会错 :) )公司里,有两派.异常拥护者说,使用业务异常,代码逻辑更清晰,更OOP;反之者说,使用异常,性能非常糟糕;(当然,我是拥护者)论坛上,争论得更多,仁者见仁智者见智,口...&nbsp;&nbsp;<a href='http://www.blogjava.net/stone2083/archive/2010/07/09/325649.html'>阅读全文</a><img src ="http://www.blogjava.net/stone2083/aggbug/325649.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/stone2083/" target="_blank">stone2083</a> 2010-07-09 14:30 <a href="http://www.blogjava.net/stone2083/archive/2010/07/09/325649.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>让log4j支持占位符</title><link>http://www.blogjava.net/stone2083/archive/2010/07/01/324935.html</link><dc:creator>stone2083</dc:creator><author>stone2083</author><pubDate>Thu, 01 Jul 2010 00:52:00 GMT</pubDate><guid>http://www.blogjava.net/stone2083/archive/2010/07/01/324935.html</guid><wfw:comment>http://www.blogjava.net/stone2083/comments/324935.html</wfw:comment><comments>http://www.blogjava.net/stone2083/archive/2010/07/01/324935.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/stone2083/comments/commentRss/324935.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/stone2083/services/trackbacks/324935.html</trackback:ping><description><![CDATA[目标:让log4j.xml配置文件中允许使用占位符(${key}).<br />
<br />
使用场景:<br />
在运行期决定一些动态的配置内容.<br />
比如在我们项目中,希望一台物理机同一个应用跑多个实例.<br />
因为多进程操作同一份log文件存在并发问题(打印,DailyRolling等),所以我希望配置如下:${loggingRoot}/${instance}/project.log<br />
在运行脚本中,通过加入-Dinstance=instance1参数,来动态指定实例名.让同一份应用在不同的运行实例下,日志打印到不同的路径<br />
<br />
Log4j分析:<br />
我以为,Log4j天生就支持占位符的.请见:org.apache.log4j.helpers.OptionConverter.substVars(String val, Properties props)就有对占位符的处理.<br />
org.apache.log4j.PropertyConfigurator (log4j.properties文件解析).默认就支持对占位符的处理.<br />
org.apache.log4j.xml.DOMConfigurator挺怪异的.明明也有对占位符的处理.但是我们就是无法对其属性props进行赋值.<br />
(当然,有可能是我误解了其props的用法--还没有完整读过他的源码)<br />
<br />
处理方案:<br />
继承org.apache.log4j.xml.DOMConfigurator,实现自己的DOMConfigurator.<br />
<div style="background-color: #eeeeee; font-size: 13px; border-left-color: #cccccc; padding-top: 4px; padding-right: 5px; padding-bottom: 4px; padding-left: 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;PlaceHolderDOMConfigurator&nbsp;</span><span style="color: #0000ff;">extends</span><span style="color: #000000;">&nbsp;org.apache.log4j.xml.DOMConfigurator&nbsp;{<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">private</span><span style="color: #000000;">&nbsp;Properties&nbsp;props;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;PlaceHolderDOMConfigurator(Properties&nbsp;props){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">this</span><span style="color: #000000;">.props&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;props;<br />
&nbsp;&nbsp;&nbsp;&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;configure(String&nbsp;filename,&nbsp;Properties&nbsp;props)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;PlaceHolderDOMConfigurator(props).doConfigure(filename,&nbsp;LogManager.getLoggerRepository());<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp; //主要是覆写这个方案.传入properties对象<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">protected</span><span style="color: #000000;">&nbsp;String&nbsp;subst(String&nbsp;value)&nbsp;{<br />
&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;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;OptionConverter.substVars(value,&nbsp;props);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span><span style="color: #0000ff;">catch</span><span style="color: #000000;">&nbsp;(IllegalArgumentException&nbsp;e)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;LogLog.warn(</span><span style="color: #000000;">"</span><span style="color: #000000;">Could&nbsp;not&nbsp;perform&nbsp;variable&nbsp;substitution.</span><span style="color: #000000;">"</span><span style="color: #000000;">,&nbsp;e);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;value;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
}</span></div>
<br />
测试代码:<br />
log4j.xml片段:<br />
<div style="background-color: #eeeeee; font-size: 13px; border-left-color: #cccccc; padding-top: 4px; padding-right: 5px; padding-bottom: 4px; padding-left: 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;">appender&nbsp;name</span><span style="color: #000000;">=</span><span style="color: #000000;">"</span><span style="color: #000000;">PROJECT</span><span style="color: #000000;">"</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">class</span><span style="color: #000000;">=</span><span style="color: #000000;">"</span><span style="color: #000000;">org.apache.log4j.DailyRollingFileAppender</span><span style="color: #000000;">"</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">param&nbsp;name</span><span style="color: #000000;">=</span><span style="color: #000000;">"</span><span style="color: #000000;">file</span><span style="color: #000000;">"</span><span style="color: #000000;">&nbsp;value</span><span style="color: #000000;">=</span><span style="color: #000000;">"</span><span style="color: #000000;">${loggingRoot}/${instance}/project.log</span><span style="color: #000000;">"</span><span style="color: #000000;">/&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">param&nbsp;name</span><span style="color: #000000;">=</span><span style="color: #000000;">"</span><span style="color: #000000;">append</span><span style="color: #000000;">"</span><span style="color: #000000;">&nbsp;value</span><span style="color: #000000;">=</span><span style="color: #000000;">"</span><span style="color: #000000;">false</span><span style="color: #000000;">"</span><span style="color: #000000;">/&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">param&nbsp;name</span><span style="color: #000000;">=</span><span style="color: #000000;">"</span><span style="color: #000000;">encoding</span><span style="color: #000000;">"</span><span style="color: #000000;">&nbsp;value</span><span style="color: #000000;">=</span><span style="color: #000000;">"</span><span style="color: #000000;">GB2312</span><span style="color: #000000;">"</span><span style="color: #000000;">/&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">param&nbsp;name</span><span style="color: #000000;">=</span><span style="color: #000000;">"</span><span style="color: #000000;">threshold</span><span style="color: #000000;">"</span><span style="color: #000000;">&nbsp;value</span><span style="color: #000000;">=</span><span style="color: #000000;">"</span><span style="color: #000000;">info</span><span style="color: #000000;">"</span><span style="color: #000000;">/&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">layout&nbsp;</span><span style="color: #0000ff;">class</span><span style="color: #000000;">=</span><span style="color: #000000;">"</span><span style="color: #000000;">org.apache.log4j.PatternLayout</span><span style="color: #000000;">"</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">param&nbsp;name</span><span style="color: #000000;">=</span><span style="color: #000000;">"</span><span style="color: #000000;">ConversionPattern</span><span style="color: #000000;">"</span><span style="color: #000000;">&nbsp;value</span><span style="color: #000000;">=</span><span style="color: #000000;">"</span><span style="color: #000000;">%d&nbsp;[%X{requestURIWithQueryString}]&nbsp;%-5p&nbsp;%c{2}&nbsp;-&nbsp;%m%n</span><span style="color: #000000;">"</span><span style="color: #000000;">/&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">&lt;/</span><span style="color: #000000;">layout</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">&lt;/</span><span style="color: #000000;">appender</span><span style="color: #000000;">&gt;</span></div>
Run.java:<br />
<div style="background-color: #eeeeee; font-size: 13px; border-left-color: #cccccc; padding-top: 4px; padding-right: 5px; padding-bottom: 4px; padding-left: 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;">static</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;main(String[]&nbsp;args)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Properties&nbsp;props&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;Properties();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;props.setProperty(</span><span style="color: #000000;">"</span><span style="color: #000000;">loggingRoot</span><span style="color: #000000;">"</span><span style="color: #000000;">,&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">d:/tmp</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;props.setProperty(</span><span style="color: #000000;">"</span><span style="color: #000000;">instance</span><span style="color: #000000;">"</span><span style="color: #000000;">,&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">instance1</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PlaceHolderDOMConfigurator.configure(LOG4J_PATH,&nbsp;props);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Logger&nbsp;rootLogger&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;LogManager.getRootLogger();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;FileAppender&nbsp;fileAppender&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;(FileAppender)&nbsp;rootLogger.getAppender(</span><span style="color: #000000;">"</span><span style="color: #000000;">PROJECT</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(fileAppender.getFile());<br />
&nbsp;&nbsp;&nbsp;&nbsp;}</span></div>
<br />
输出结果:<br />
d:/tmp/instance1/project.log<br />
<br />
当然,你也可以通过在启动参数中加 -DloggingRoot=xxxx&nbsp; -Dinstance=yyyy动态指定内容.<br />
<br />
<br />
特别说明:<br />
本文:log4j版本为1.2.14<br />
log4j 1.2.15测试不通过,原因见:<a href="https://issues.apache.org/bugzilla/show_bug.cgi?id=43325">https://issues.apache.org/bugzilla/show_bug.cgi?id=43325</a>
<img src ="http://www.blogjava.net/stone2083/aggbug/324935.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/stone2083/" target="_blank">stone2083</a> 2010-07-01 08:52 <a href="http://www.blogjava.net/stone2083/archive/2010/07/01/324935.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>单元测试下简易性能测试工具</title><link>http://www.blogjava.net/stone2083/archive/2010/06/10/323205.html</link><dc:creator>stone2083</dc:creator><author>stone2083</author><pubDate>Thu, 10 Jun 2010 01:13:00 GMT</pubDate><guid>http://www.blogjava.net/stone2083/archive/2010/06/10/323205.html</guid><wfw:comment>http://www.blogjava.net/stone2083/comments/323205.html</wfw:comment><comments>http://www.blogjava.net/stone2083/archive/2010/06/10/323205.html#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://www.blogjava.net/stone2083/comments/commentRss/323205.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/stone2083/services/trackbacks/323205.html</trackback:ping><description><![CDATA[背景:<br />
1.团队成员对质量意识逐渐提升;单元测试意识提升;<br />
2.性能意识不足,往往到最后提交性能测试的时候,才发现性能问题;在开发阶段忽视对性能的考虑.<br />
尤其在做对外服务的需求中,危害特别明显.<br />
<br />
基于这两个原因,希望有一个在单元测试下的性能测试工具.提供最简单的性能指标报表.在开发阶段让开发对性能情况有个感性的认识.<br />
<br />
设计思路:<br />
<img alt="" src="http://www.blogjava.net/images/blogjava_net/stone2083/java/Performance.jpg" width="522" height="380" /><br />
<br />
概念说明:<br />
<table border="2" bordercolor="#020202" cellpadding="2" cellspacing="2" width="500">
    <tbody>
        <tr style="margin: 2px;">
            <td><strong>&nbsp;类名</strong></td>
            <td><strong>方法 <br />
            </strong></td>
            <td><strong>说明 <br />
            </strong></td>
        </tr>
        <tr>
            <td><span style="border-collapse: separate; color: #000000; font-family: Simsun; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; font-size: medium;"><span style="border-collapse: collapse; font-family: Verdana,arial,sans-serif; font-size: 14px; line-height: 21px;"><strong>Statistics</strong>&nbsp;<br clear="all" />
            说明:性能统计信息</span></span></td>
            <td><span style="border-collapse: separate; color: #000000; font-family: Simsun; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; font-size: medium;"><span style="border-collapse: collapse; font-family: Verdana,arial,sans-serif; font-size: 14px; line-height: 21px;">tps()</span></span></td>
            <td><span style="border-collapse: separate; color: #000000; font-family: Simsun; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; font-size: medium;"><span style="border-collapse: collapse; font-family: Verdana,arial,sans-serif; font-size: 14px; line-height: 21px;">提供tps</span></span></td>
        </tr>
        <tr>
            <td>&nbsp;</td>
            <td><span style="border-collapse: separate; color: #000000; font-family: Simsun; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; font-size: medium;"><span style="border-collapse: collapse; font-family: Verdana,arial,sans-serif; font-size: 14px; line-height: 21px;">average()</span></span></td>
            <td><span style="border-collapse: separate; color: #000000; font-family: Simsun; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; font-size: medium;"><span style="border-collapse: collapse; font-family: Verdana,arial,sans-serif; font-size: 14px; line-height: 21px;">提供平均响应时间,单位毫秒</span></span></td>
        </tr>
        <tr>
            <td>&nbsp;</td>
            <td><span style="border-collapse: separate; color: #000000; font-family: Simsun; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; font-size: medium;"><span style="border-collapse: collapse; font-family: Verdana,arial,sans-serif; font-size: 14px; line-height: 21px;">total()</span></span></td>
            <td><span style="border-collapse: separate; color: #000000; font-family: Simsun; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; font-size: medium;"><span style="border-collapse: collapse; font-family: Verdana,arial,sans-serif; font-size: 14px; line-height: 21px;">提供总耗时,单位毫秒</span></span></td>
        </tr>
        <tr>
            <td valign="top"><span style="border-collapse: separate; color: #000000; font-family: Simsun; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; font-size: medium;"><span style="border-collapse: collapse; font-family: Verdana,arial,sans-serif; font-size: 14px; line-height: 21px;"><strong>Job</strong>&nbsp;<br clear="all" />
            说明:测试单元逻辑</span></span></td>
            <td valign="top"><span style="border-collapse: separate; color: #000000; font-family: Simsun; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; font-size: medium;"><span style="border-collapse: collapse; font-family: Verdana,arial,sans-serif; font-size: 14px; line-height: 21px;">execute()</span></span></td>
            <td valign="top"><span style="border-collapse: separate; color: #000000; font-family: Simsun; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; font-size: medium;"><span style="border-collapse: collapse; font-family: Verdana,arial,sans-serif; font-size: 14px; line-height: 21px;">性能测试逻辑</span></span></td>
        </tr>
        <tr>
            <td valign="top"><span style="border-collapse: separate; color: #000000; font-family: Simsun; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; font-size: medium;"><span style="border-collapse: collapse; font-family: Verdana,arial,sans-serif; font-size: 14px; line-height: 21px;"><strong>Warn</strong>&nbsp;<br clear="all" />
            说明:性能未达标警告</span></span></td>
            <td valign="top"><br />
            </td>
            <td valign="top"><br />
            </td>
        </tr>
        <tr>
            <td valign="top"><span style="border-collapse: separate; color: #000000; font-family: Simsun; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; font-size: medium;"><span style="border-collapse: collapse; font-family: Verdana,arial,sans-serif; font-size: 14px; line-height: 21px;"><strong>PerformanceTester</strong> (核心)<br clear="all" />
            说明:性能测试工具,根据制定的并发数和单个并发循环次数,进行性能测试;根据提供的平均响应时间,分析是否达标</span></span></td>
            <td valign="top"><span style="border-collapse: separate; color: #000000; font-family: Simsun; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; font-size: medium;"><span style="border-collapse: collapse; font-family: Verdana,arial,sans-serif; font-size: 14px; line-height: 21px;">test(Job job)</span></span></td>
            <td valign="top"><span style="border-collapse: separate; color: #000000; font-family: Simsun; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; font-size: medium;"><span style="border-collapse: collapse; font-family: Verdana,arial,sans-serif; font-size: 14px; line-height: 21px;">性能测试,打印性能报表,分析是否达标</span></span></td>
        </tr>
        <tr>
            <td valign="top"><span style="border-collapse: separate; color: #000000; font-family: Simsun; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; font-size: medium;"><span style="border-collapse: collapse; font-family: Verdana,arial,sans-serif; font-size: 14px; line-height: 21px;"><strong>JTesterxPerformance</strong>&nbsp;<br clear="all" />
            说明:基于JTester的性能测试基类,统一执行性能测试计划<br />
            备注:<br />
            JTester是我们公司同事编写的一套单元测试框架.我们同样可以提供基于JUnit的实现,比如JUnitPerformance<br />
            </span></span></td>
            <td valign="top"><span style="border-collapse: separate; color: #000000; font-family: Simsun; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; font-size: medium;"><span style="border-collapse: collapse; font-family: Verdana,arial,sans-serif; font-size: 14px; line-height: 21px;">performance()</span></span></td>
            <td valign="top"><span style="border-collapse: separate; color: #000000; font-family: Simsun; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; font-size: medium;"><span style="border-collapse: collapse; font-family: Verdana,arial,sans-serif; font-size: 14px; line-height: 21px;">根据提供的性能策略,指标 和 测试逻辑,进行性能测试</span></span></td>
        </tr>
        <tr>
            <td valign="top"><br />
            </td>
            <td valign="top"><span style="border-collapse: separate; color: #000000; font-family: Simsun; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; font-size: medium;"><span style="border-collapse: collapse; font-family: Verdana,arial,sans-serif; font-size: 14px; line-height: 21px;">job()</span></span></td>
            <td valign="top"><span style="border-collapse: separate; color: #000000; font-family: Simsun; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; font-size: medium;"><span style="border-collapse: collapse; font-family: Verdana,arial,sans-serif; font-size: 14px; line-height: 21px;">需要子类覆写,提供测试逻辑</span></span></td>
        </tr>
        <tr>
            <td valign="top"><br />
            </td>
            <td valign="top"><span style="border-collapse: separate; color: #000000; font-family: Simsun; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; font-size: medium;"><span style="border-collapse: collapse; font-family: Verdana,arial,sans-serif; font-size: 14px; line-height: 21px;">testers()</span></span></td>
            <td valign="top"><span style="border-collapse: separate; color: #000000; font-family: Simsun; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; font-size: medium;"><span style="border-collapse: collapse; font-family: Verdana,arial,sans-serif; font-size: 14px; line-height: 21px;">需要子类覆写,提供性能测试策略和指标要求</span></span></td>
        </tr>
    </tbody>
</table>
<br />
<br />
<strong>User Guide:</strong><br />
<ul>
    <li><strong>Step1:</strong></li>
</ul>
&nbsp;&nbsp;&nbsp; 创建一个性能测试类,继承com.alibaba.tpsc.common.test.jtesterx.JTesterxPerformance<br />
&nbsp;&nbsp;&nbsp; 在类名标注@Test (org.testng.annotations.Test),表明需要进行TestNG的单元测试<br />
&nbsp;&nbsp;&nbsp; 备注:如果是在其他单元测试框架下,请自行扩展类似JUnitPerformacne实现<br />
<ul>
    <li><strong>Step2:</strong></li>
</ul>
&nbsp;&nbsp;&nbsp; <span style="border-collapse: separate; color: #000000; font-family: Simsun; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; font-size: medium;"><span style="font-family: Verdana,arial,sans-serif; font-size: 14px; line-height: 21px;">覆写public Job job()方法.提供 性能测试名 和 性能测试逻辑<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><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;">@Override<br />
</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;Job&nbsp;job()&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;Job(</span><span style="color: #000000;">"</span><span style="color: #000000;">SampleService.hello</span><span style="color: #000000;">"</span><span style="color: #000000;">)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@Override<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;execute()&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SampleService.hello();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;};<br />
}</span></div>
<ul>
    <li><strong>Step3:</strong></li>
</ul>
&nbsp;&nbsp;&nbsp; 覆写public Collection&lt;PerformanceTester&gt; testers().提供一组性能测试策略(并发数,单个并发循环次数) 和 性&nbsp; 能测试指标(平均响应时间)<br />
&nbsp;&nbsp;&nbsp; 性能测试工具会根据提供策略和指标,依次进行性能测试.<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;Collection</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">PerformanceTester</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">&nbsp;testers()&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;Collection</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">PerformanceTester</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">&nbsp;testers&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;ArrayList</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">PerformanceTester</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">();<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;20个并发,单个并发循环1000次,平均响应时间阀值10ms</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;testers.add(</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;PerformanceTester(</span><span style="color: #000000;">20</span><span style="color: #000000;">,&nbsp;</span><span style="color: #000000;">1000</span><span style="color: #000000;">,&nbsp;</span><span style="color: #000000;">10</span><span style="color: #000000;">));<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;10个并发,单个并发循环1000次,平均响应时间阀值5ms</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;testers.add(</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;PerformanceTester(</span><span style="color: #000000;">10</span><span style="color: #000000;">,&nbsp;</span><span style="color: #000000;">1000</span><span style="color: #000000;">,&nbsp;</span><span style="color: #000000;">5</span><span style="color: #000000;">));<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;testers;<br />
}</span></div>
<ul>
    <li><strong>Step4:</strong></li>
</ul>
&nbsp;&nbsp;&nbsp; 右键点击Eclipse-&gt;Run As-&gt;TestNG Test.<br />
&nbsp;&nbsp;&nbsp; 如果测试通过,则显示Green Bar<br />
&nbsp;&nbsp;&nbsp; 如果测试未通过,则在Red Bar中显示:java.lang.AssertionError: performance expected is 1ms,but actual is 2.938ms.<br />
<br />
<br />
工具代码和演示代码如下:<br />
<a href="/Files/stone2083/java/performance.zip" title="Demo">Demo下载</a><br />
<br />

 
<img src ="http://www.blogjava.net/stone2083/aggbug/323205.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/stone2083/" target="_blank">stone2083</a> 2010-06-10 09:13 <a href="http://www.blogjava.net/stone2083/archive/2010/06/10/323205.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>编程方式实现SpringBean LazyInit</title><link>http://www.blogjava.net/stone2083/archive/2010/06/03/322608.html</link><dc:creator>stone2083</dc:creator><author>stone2083</author><pubDate>Thu, 03 Jun 2010 04:46:00 GMT</pubDate><guid>http://www.blogjava.net/stone2083/archive/2010/06/03/322608.html</guid><wfw:comment>http://www.blogjava.net/stone2083/comments/322608.html</wfw:comment><comments>http://www.blogjava.net/stone2083/archive/2010/06/03/322608.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/stone2083/comments/commentRss/322608.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/stone2083/services/trackbacks/322608.html</trackback:ping><description><![CDATA[Tags:<br />
Spring&nbsp; LazyInit DocumentDefaultsDefinition ReaderEventListener AbstractXmlApplicationContext<br />
<br />
背景:<br />
工程单元测试希望和生产环境应用共用一份Spring配置文件.<br />
生产环境应用为了客户体验使用非LazyInit模式,但是单元测试下为了当前测试提高响应时间,希望设置LazyInit.<br />
<br />
分析源代码,得知,Spring在解析XML时,会将Bean默认配置,放入到DocumentDefaultsDefinition对象中,其中包含lazyInit.<br />
DocumentDefaultsDefinition注释如下:<br />
Simple JavaBean that holds the defaults specified at the &lt;beans&gt; level in a standard Spring XML bean definition document: default-lazy-init, default-autowire, etc<br />
<br />
Spring是否提供了入口点,进行DocumentDefaultsDefinition的修改呢?<br />
详见:ReaderEventListener,注释如下:<br />
Interface that receives callbacks for component, alias and import registrations during a bean definition reading process<br />
在BeanDefinition分析过程中,对component,alias,import registrations,defaults registrations提供一组callbacks.<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: #008080;">&nbsp;1</span>&nbsp;<span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">interface</span><span style="color: #000000;">&nbsp;ReaderEventListener&nbsp;</span><span style="color: #0000ff;">extends</span><span style="color: #000000;">&nbsp;EventListener&nbsp;{<br />
</span><span style="color: #008080;">&nbsp;2</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">&nbsp;3</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">/**</span><span style="color: #008000;"><br />
</span><span style="color: #008080;">&nbsp;4</span>&nbsp;<span style="color: #008000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Notification&nbsp;that&nbsp;the&nbsp;given&nbsp;defaults&nbsp;has&nbsp;been&nbsp;registered.<br />
</span><span style="color: #008080;">&nbsp;5</span>&nbsp;<span style="color: #008000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: #808080;">@param</span><span style="color: #008000;">&nbsp;defaultsDefinition&nbsp;a&nbsp;descriptor&nbsp;for&nbsp;the&nbsp;defaults<br />
</span><span style="color: #008080;">&nbsp;6</span>&nbsp;<span style="color: #008000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: #808080;">@see</span><span style="color: #008000;">&nbsp;org.springframework.beans.factory.xml.DocumentDefaultsDefinition<br />
</span><span style="color: #008080;">&nbsp;7</span>&nbsp;<span style="color: #008000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">*/</span><span style="color: #000000;"><br />
</span><span style="color: #008080;">&nbsp;8</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;defaultsRegistered(DefaultsDefinition&nbsp;defaultsDefinition);<br />
</span><span style="color: #008080;">&nbsp;9</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">10</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">/**</span><span style="color: #008000;"><br />
</span><span style="color: #008080;">11</span>&nbsp;<span style="color: #008000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Notification&nbsp;that&nbsp;the&nbsp;given&nbsp;component&nbsp;has&nbsp;been&nbsp;registered.<br />
</span><span style="color: #008080;">12</span>&nbsp;<span style="color: #008000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: #808080;">@param</span><span style="color: #008000;">&nbsp;componentDefinition&nbsp;a&nbsp;descriptor&nbsp;for&nbsp;the&nbsp;new&nbsp;component<br />
</span><span style="color: #008080;">13</span>&nbsp;<span style="color: #008000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: #808080;">@see</span><span style="color: #008000;">&nbsp;BeanComponentDefinition<br />
</span><span style="color: #008080;">14</span>&nbsp;<span style="color: #008000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">*/</span><span style="color: #000000;"><br />
</span><span style="color: #008080;">15</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;componentRegistered(ComponentDefinition&nbsp;componentDefinition);<br />
</span><span style="color: #008080;">16</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">17</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">/**</span><span style="color: #008000;"><br />
</span><span style="color: #008080;">18</span>&nbsp;<span style="color: #008000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Notification&nbsp;that&nbsp;the&nbsp;given&nbsp;alias&nbsp;has&nbsp;been&nbsp;registered.<br />
</span><span style="color: #008080;">19</span>&nbsp;<span style="color: #008000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: #808080;">@param</span><span style="color: #008000;">&nbsp;aliasDefinition&nbsp;a&nbsp;descriptor&nbsp;for&nbsp;the&nbsp;new&nbsp;alias<br />
</span><span style="color: #008080;">20</span>&nbsp;<span style="color: #008000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">*/</span><span style="color: #000000;"><br />
</span><span style="color: #008080;">21</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;aliasRegistered(AliasDefinition&nbsp;aliasDefinition);<br />
</span><span style="color: #008080;">22</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">23</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">/**</span><span style="color: #008000;"><br />
</span><span style="color: #008080;">24</span>&nbsp;<span style="color: #008000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Notification&nbsp;that&nbsp;the&nbsp;given&nbsp;import&nbsp;has&nbsp;been&nbsp;processed.<br />
</span><span style="color: #008080;">25</span>&nbsp;<span style="color: #008000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: #808080;">@param</span><span style="color: #008000;">&nbsp;importDefinition&nbsp;a&nbsp;descriptor&nbsp;for&nbsp;the&nbsp;import<br />
</span><span style="color: #008080;">26</span>&nbsp;<span style="color: #008000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">*/</span><span style="color: #000000;"><br />
</span><span style="color: #008080;">27</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;importProcessed(ImportDefinition&nbsp;importDefinition);<br />
</span><span style="color: #008080;">28</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;<br />
</span><span style="color: #008080;">29</span>&nbsp;<span style="color: #000000;">}</span></div>
<br />
接下去分析,ReaderEventListener是在哪个入口点,提供了回调.答案是XmlBeanDefinitionReader.<br />
在AbstractXmlApplicationContext,创建了XmlBeanDefinitionReader对象,见:<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;">&nbsp;1</span>&nbsp;<span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">abstract</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;AbstractXmlApplicationContext&nbsp;</span><span style="color: #0000ff;">extends</span><span style="color: #000000;">&nbsp;AbstractRefreshableConfigApplicationContext&nbsp;{<br />
</span><span style="color: #008080;">&nbsp;2</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;<br />
</span><span style="color: #008080;">&nbsp;3</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">/**</span><span style="color: #008000;"><br />
</span><span style="color: #008080;">&nbsp;4</span>&nbsp;<span style="color: #008000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Loads&nbsp;the&nbsp;bean&nbsp;definitions&nbsp;via&nbsp;an&nbsp;XmlBeanDefinitionReader.<br />
</span><span style="color: #008080;">&nbsp;5</span>&nbsp;<span style="color: #008000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: #808080;">@see</span><span style="color: #008000;">&nbsp;org.springframework.beans.factory.xml.XmlBeanDefinitionReader<br />
</span><span style="color: #008080;">&nbsp;6</span>&nbsp;<span style="color: #008000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: #808080;">@see</span><span style="color: #008000;">&nbsp;#initBeanDefinitionReader<br />
</span><span style="color: #008080;">&nbsp;7</span>&nbsp;<span style="color: #008000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: #808080;">@see</span><span style="color: #008000;">&nbsp;#loadBeanDefinitions<br />
</span><span style="color: #008080;">&nbsp;8</span>&nbsp;<span style="color: #008000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">*/</span><span style="color: #000000;"><br />
</span><span style="color: #008080;">&nbsp;9</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">protected</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;loadBeanDefinitions(DefaultListableBeanFactory&nbsp;beanFactory)&nbsp;</span><span style="color: #0000ff;">throws</span><span style="color: #000000;">&nbsp;IOException&nbsp;{<br />
</span><span style="color: #008080;">10</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;Create&nbsp;a&nbsp;new&nbsp;XmlBeanDefinitionReader&nbsp;for&nbsp;the&nbsp;given&nbsp;BeanFactory.</span><span style="color: #008000;"><br />
</span><span style="color: #008080;">11</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;XmlBeanDefinitionReader&nbsp;beanDefinitionReader&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;XmlBeanDefinitionReader(beanFactory);<br />
</span><span style="color: #008080;">12</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">13</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;Configure&nbsp;the&nbsp;bean&nbsp;definition&nbsp;reader&nbsp;with&nbsp;this&nbsp;context's<br />
</span><span style="color: #008080;">14</span>&nbsp;<span style="color: #008000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;resource&nbsp;loading&nbsp;environment.</span><span style="color: #008000;"><br />
</span><span style="color: #008080;">15</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;beanDefinitionReader.setResourceLoader(</span><span style="color: #0000ff;">this</span><span style="color: #000000;">);<br />
</span><span style="color: #008080;">16</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;beanDefinitionReader.setEntityResolver(</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;ResourceEntityResolver(</span><span style="color: #0000ff;">this</span><span style="color: #000000;">));<br />
</span><span style="color: #008080;">17</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">18</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;Allow&nbsp;a&nbsp;subclass&nbsp;to&nbsp;provide&nbsp;custom&nbsp;initialization&nbsp;of&nbsp;the&nbsp;reader,<br />
</span><span style="color: #008080;">19</span>&nbsp;<span style="color: #008000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;then&nbsp;proceed&nbsp;with&nbsp;actually&nbsp;loading&nbsp;the&nbsp;bean&nbsp;definitions.</span><span style="color: #008000;"><br />
</span><span style="color: #008080;">20</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;initBeanDefinitionReader(beanDefinitionReader);<br />
</span><span style="color: #008080;">21</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;loadBeanDefinitions(beanDefinitionReader);<br />
</span><span style="color: #008080;">22</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;}<br />
</span><span style="color: #008080;">23</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">24</span>&nbsp;<span style="color: #000000;">}</span></div>
<br />
我们只需要去复写这个方法,在创建XmlBeanDefinitionReader的时候,去注入EventListener即可.<br />
<br />
扩展代码如下:<br />
LazyInitListener.java (不管配置文件如何配置,设置默认的LazyInit为true)<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;LazyInitListener&nbsp;</span><span style="color: #0000ff;">implements</span><span style="color: #000000;">&nbsp;ReaderEventListener&nbsp;{<br />
<br />
&nbsp;&nbsp;&nbsp;&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;String&nbsp;LAZY_INIT&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">true</span><span style="color: #000000;">"</span><span style="color: #000000;">;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;@Override<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;defaultsRegistered(DefaultsDefinition&nbsp;defaultsDefinition)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">set&nbsp;lazy&nbsp;init&nbsp;true</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(defaultsDefinition&nbsp;</span><span style="color: #0000ff;">instanceof</span><span style="color: #000000;">&nbsp;DocumentDefaultsDefinition)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DocumentDefaultsDefinition&nbsp;defaults&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;(DocumentDefaultsDefinition)&nbsp;defaultsDefinition;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;defaults.setLazyInit(LAZY_INIT);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;@Override<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;aliasRegistered(AliasDefinition&nbsp;aliasDefinition)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">no-op</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;@Override<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;componentRegistered(ComponentDefinition&nbsp;componentDefinition)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">no-op</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;@Override<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;importProcessed(ImportDefinition&nbsp;importDefinition)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">no-op</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
}</span></div>
<br />
LazyInitClasspathXmlApplicationContext.java (复写AbstractXmlApplicationContext,创建XmlBeanDefinitionReader的时候注入LazyInitListener)<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;">&nbsp;1</span>&nbsp;<span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;LazyInitClasspathXmlApplicationContext&nbsp;</span><span style="color: #0000ff;">extends</span><span style="color: #000000;">&nbsp;ClassPathXmlApplicationContext&nbsp;{<br />
</span><span style="color: #008080;">&nbsp;2</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">&nbsp;3</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;LazyInitClasspathXmlApplicationContext(String&nbsp;location)&nbsp;{<br />
</span><span style="color: #008080;">&nbsp;4</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">super</span><span style="color: #000000;">(location);<br />
</span><span style="color: #008080;">&nbsp;5</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;}<br />
</span><span style="color: #008080;">&nbsp;6</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">&nbsp;7</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;@Override<br />
</span><span style="color: #008080;">&nbsp;8</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">protected</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;loadBeanDefinitions(DefaultListableBeanFactory&nbsp;beanFactory)&nbsp;</span><span style="color: #0000ff;">throws</span><span style="color: #000000;">&nbsp;IOException&nbsp;{<br />
</span><span style="color: #008080;">&nbsp;9</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;Create&nbsp;a&nbsp;new&nbsp;XmlBeanDefinitionReader&nbsp;for&nbsp;the&nbsp;given&nbsp;BeanFactory.</span><span style="color: #008000;"><br />
</span><span style="color: #008080;">10</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;XmlBeanDefinitionReader&nbsp;beanDefinitionReader&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;XmlBeanDefinitionReader(beanFactory);<br />
</span><span style="color: #008080;">11</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">12</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;Configure&nbsp;the&nbsp;bean&nbsp;definition&nbsp;reader&nbsp;with&nbsp;this&nbsp;context's<br />
</span><span style="color: #008080;">13</span>&nbsp;<span style="color: #008000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;resource&nbsp;loading&nbsp;environment.</span><span style="color: #008000;"><br />
</span><span style="color: #008080;">14</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;beanDefinitionReader.setResourceLoader(</span><span style="color: #0000ff;">this</span><span style="color: #000000;">);<br />
</span><span style="color: #008080;">15</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;beanDefinitionReader.setEntityResolver(</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;ResourceEntityResolver(</span><span style="color: #0000ff;">this</span><span style="color: #000000;">));<br />
</span><span style="color: #008080;">16</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">17</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;添加的代码,设置LazyInitListener</span><span style="color: #008000;"><br />
</span><span style="color: #008080;">18</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;beanDefinitionReader.setEventListener(</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;LazyInitListener());<br />
</span><span style="color: #008080;">19</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">20</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;Allow&nbsp;a&nbsp;subclass&nbsp;to&nbsp;provide&nbsp;custom&nbsp;initialization&nbsp;of&nbsp;the&nbsp;reader,<br />
</span><span style="color: #008080;">21</span>&nbsp;<span style="color: #008000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;then&nbsp;proceed&nbsp;with&nbsp;actually&nbsp;loading&nbsp;the&nbsp;bean&nbsp;definitions.</span><span style="color: #008000;"><br />
</span><span style="color: #008080;">22</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;initBeanDefinitionReader(beanDefinitionReader);<br />
</span><span style="color: #008080;">23</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;loadBeanDefinitions(beanDefinitionReader);<br />
</span><span style="color: #008080;">24</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;}<br />
</span><span style="color: #008080;">25</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">26</span>&nbsp;<span style="color: #000000;">}</span></div>
<br />
演示代码如下:<br />
TestBean:一个Spring Bean对象<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;TestBean&nbsp;{<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;init()&nbsp;{<br />
&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;Thread.sleep(</span><span style="color: #000000;">5000</span><span style="color: #000000;">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span><span style="color: #0000ff;">catch</span><span style="color: #000000;">&nbsp;(InterruptedException&nbsp;e)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">ignore</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(e);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="color: #000000;">"</span><span style="color: #000000;">TestBean&nbsp;Init</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
}</span></div>
<br />
Spring配置文件:<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;">1</span>&nbsp;<span style="color: #0000ff;">&lt;?</span><span style="color: #ff00ff;">xml&nbsp;version="1.0"&nbsp;encoding="UTF-8"</span><span style="color: #0000ff;">?&gt;</span><span style="color: #000000;"><br />
</span><span style="color: #008080;">2</span>&nbsp;<span style="color: #0000ff;">&lt;</span><span style="color: #800000;">beans&nbsp;</span><span style="color: #ff0000;">xmlns</span><span style="color: #0000ff;">="http://www.springframework.org/schema/beans"</span><span style="color: #ff0000;"><br />
</span><span style="color: #008080;">3</span>&nbsp;<span style="color: #ff0000;">&nbsp;&nbsp;&nbsp;&nbsp;xmlns:xsi</span><span style="color: #0000ff;">="http://www.w3.org/2001/XMLSchema-instance"</span><span style="color: #ff0000;"><br />
</span><span style="color: #008080;">4</span>&nbsp;<span style="color: #ff0000;">&nbsp;&nbsp;&nbsp;&nbsp;xsi:schemaLocation</span><span style="color: #0000ff;">="http://www.springframework.org/schema/beans&nbsp;http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
</span><span style="color: #008080;">5</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">6</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">bean&nbsp;</span><span style="color: #ff0000;">id</span><span style="color: #0000ff;">="testBean"</span><span style="color: #ff0000;">&nbsp;class</span><span style="color: #0000ff;">="com.alibaba.javalab.spring.lazy.TestBean"</span><span style="color: #ff0000;">&nbsp;init-method</span><span style="color: #0000ff;">="init"</span><span style="color: #ff0000;">&nbsp;</span><span style="color: #0000ff;">/&gt;</span><span style="color: #000000;"><br />
</span><span style="color: #008080;">7</span>&nbsp;<span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">beans</span><span style="color: #0000ff;">&gt;</span></div>
<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;">&nbsp;1</span>&nbsp;<span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;Run&nbsp;{<br />
</span><span style="color: #008080;">&nbsp;2</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">&nbsp;3</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&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;String&nbsp;CONFIG&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">classpath:spring/bean.xml</span><span style="color: #000000;">"</span><span style="color: #000000;">;<br />
</span><span style="color: #008080;">&nbsp;4</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">&nbsp;5</span>&nbsp;<span style="color: #000000;">&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;{<br />
</span><span style="color: #008080;">&nbsp;6</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;testInit();<br />
</span><span style="color: #008080;">&nbsp;7</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="color: #000000;">"</span><span style="color: #000000;">===============================</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br />
</span><span style="color: #008080;">&nbsp;8</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;testLazyInit();<br />
</span><span style="color: #008080;">&nbsp;9</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;}<br />
</span><span style="color: #008080;">10</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">11</span>&nbsp;<span style="color: #000000;">&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;testInit()&nbsp;{<br />
</span><span style="color: #008080;">12</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;ClassPathXmlApplicationContext(CONFIG);<br />
</span><span style="color: #008080;">13</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;}<br />
</span><span style="color: #008080;">14</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">15</span>&nbsp;<span style="color: #000000;">&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;testLazyInit()&nbsp;{<br />
</span><span style="color: #008080;">16</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;LazyInitClasspathXmlApplicationContext(CONFIG);<br />
</span><span style="color: #008080;">17</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;}<br />
</span><span style="color: #008080;">18</span>&nbsp;<span style="color: #000000;">}</span></div>
<br />
<br />
大功告成.收工. :)<br />
<br />
<img src ="http://www.blogjava.net/stone2083/aggbug/322608.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/stone2083/" target="_blank">stone2083</a> 2010-06-03 12:46 <a href="http://www.blogjava.net/stone2083/archive/2010/06/03/322608.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Tomcat(6.0.14) Session创建机制简介</title><link>http://www.blogjava.net/stone2083/archive/2010/02/26/314009.html</link><dc:creator>stone2083</dc:creator><author>stone2083</author><pubDate>Fri, 26 Feb 2010 08:12:00 GMT</pubDate><guid>http://www.blogjava.net/stone2083/archive/2010/02/26/314009.html</guid><wfw:comment>http://www.blogjava.net/stone2083/comments/314009.html</wfw:comment><comments>http://www.blogjava.net/stone2083/archive/2010/02/26/314009.html#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://www.blogjava.net/stone2083/comments/commentRss/314009.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/stone2083/services/trackbacks/314009.html</trackback:ping><description><![CDATA[<strong>背景:</strong><br />
公司的一个web应用,提交给测试部门做压力测试(由于不是我负责的,不清楚如何做的压力测试,以及测试指标),结果没压多久,就出现OutOfMemory.<br />
接手协助原因查找,通过监控工具,发现<strong>StandardSession</strong>(org.apache.catalina.session.<strong>StandardSession</strong>)对象不断增长,毫无疑问,肯定是在不断创建Session对象.<br />
备注:<span style="border-collapse: separate; color: #000000; font-family: Simsun; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; font-size: medium;">一般做压力测试,每次请求都不会指定JESSESIONID值,导致Web容器认为每次请求都是新的请求,于是创建Session对象.</span><br />
同事负责代码Review,发现应用没有任何一个地方存放Session内容.困惑之...<br />
<br />
<strong>问题:Tomcat容器何时创建Session对象?</strong><br />
想当然认为,只有动态存放Session内容的时候,才会创建Session对象.但是事实真得如此吗?<br />
<br />
先看Servlet协议描述:<br />
请看:<br />
<span style="color: #000000;">getSession(</span><span style="color: #0000ff;">boolean</span><span style="color: #000000;">&nbsp;create)</span>方法:<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">javax.servlet.http.HttpServletRequest.getSession(</span><span style="color: #0000ff;">boolean</span><span style="color: #000000;">&nbsp;create)</span></div>
<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">Returns&nbsp;the&nbsp;current&nbsp;HttpSession&nbsp;associated&nbsp;with&nbsp;this&nbsp;request&nbsp;or,&nbsp;if&nbsp;if&nbsp;there&nbsp;is&nbsp;no&nbsp;current&nbsp;session&nbsp;and&nbsp;create&nbsp;is&nbsp;true,&nbsp;returns&nbsp;a&nbsp;new&nbsp;session.&nbsp;<br />
<br />
If&nbsp;create&nbsp;is&nbsp;false&nbsp;and&nbsp;the&nbsp;request&nbsp;has&nbsp;no&nbsp;valid&nbsp;HttpSession,&nbsp;this&nbsp;method&nbsp;returns&nbsp;null.&nbsp;<br />
<br />
To&nbsp;make&nbsp;sure&nbsp;the&nbsp;session&nbsp;is&nbsp;properly&nbsp;maintained,&nbsp;you&nbsp;must&nbsp;call&nbsp;this&nbsp;method&nbsp;before&nbsp;the&nbsp;response&nbsp;is&nbsp;committed.<br />
</span></div>
<br />
简单地说:当create变量为true时,如果当前Session不存在,创建一个新的Session并且返回.<br />
<br />
getSession()方法:<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">javax.servlet.http.</span><span style="color: #000000;">HttpSession&nbsp;getSession();</span></div>
<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">Returns&nbsp;the&nbsp;current&nbsp;session&nbsp;associated&nbsp;with&nbsp;this&nbsp;request,&nbsp;or&nbsp;if&nbsp;the&nbsp;request&nbsp;does&nbsp;not&nbsp;have&nbsp;a&nbsp;session,&nbsp;creates&nbsp;one.<br />
</span></div>
简单的说:当当前Session不存在,创建并且返回.<br />
<br />
<br />
所以说,协议规定,在调用getSession方法的时候,就会创建Session对象.<br />
<br />
<br />
<br />
既然协议这么定了,我们再来看看Tomcat是如何实现的:(下面的描述,是基于Tomcat6.0.14版本源码)<br />
先看一张简单的类图:<br />
<img alt="" src="http://www.blogjava.net/images/blogjava_net/stone2083/java/tomcat.jpg" width="709" height="414" /><br />
<br />
<strong>ApplicationContext</strong>:Servlet规范中ServletContext的实现<br />
<strong>StandardContext</strong>:Tomcat定义的Context默认实现.维护了一份SessionManager对象,管理Session对象.所有的Session对象都存放在Manager定义的Map&lt;String,Session&gt;容器中.<br />
<strong>StanardManager</strong>:标准的Session管理,将Session存放在内容,Web容器关闭的时候,持久化到本地文件<br />
<strong>PersistentManager</strong>:持久化实现的Session管理,默认有两种实现方式:<br />
--持久化到本地文件<br />
--持久化到数据库<br />
<br />
了解了大概的概念后,回头再来看看org.apache.catalina.connector.<strong>Request</strong>.getSession()是如何实现的.<br />
最终调用的是doGetSession(boolean create)方法,请看:<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #0000ff;">protected</span><span style="color: #000000;">&nbsp;Session&nbsp;doGetSession(</span><span style="color: #0000ff;">boolean</span><span style="color: #000000;">&nbsp;create)&nbsp;{<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;There&nbsp;cannot&nbsp;be&nbsp;a&nbsp;session&nbsp;if&nbsp;no&nbsp;context&nbsp;has&nbsp;been&nbsp;assigned&nbsp;yet</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(context&nbsp;</span><span style="color: #000000;">==</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">null</span><span style="color: #000000;">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;(</span><span style="color: #0000ff;">null</span><span style="color: #000000;">);<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;Return&nbsp;the&nbsp;current&nbsp;session&nbsp;if&nbsp;it&nbsp;exists&nbsp;and&nbsp;is&nbsp;valid</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;((session&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;">&amp;&amp;</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">!</span><span style="color: #000000;">session.isValid())<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;session&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">null</span><span style="color: #000000;">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(session&nbsp;</span><span style="color: #000000;">!=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">null</span><span style="color: #000000;">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;(session);<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;Return&nbsp;the&nbsp;requested&nbsp;session&nbsp;if&nbsp;it&nbsp;exists&nbsp;and&nbsp;is&nbsp;valid</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Manager&nbsp;manager&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">null</span><span style="color: #000000;">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(context&nbsp;</span><span style="color: #000000;">!=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">null</span><span style="color: #000000;">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;manager&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;context.getManager();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(manager&nbsp;</span><span style="color: #000000;">==</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">null</span><span style="color: #000000;">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;(</span><span style="color: #0000ff;">null</span><span style="color: #000000;">);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;Sessions&nbsp;are&nbsp;not&nbsp;supported</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(requestedSessionId&nbsp;</span><span style="color: #000000;">!=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">null</span><span style="color: #000000;">)&nbsp;{<br />
&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;session&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;manager.findSession(requestedSessionId);<br />
&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;(IOException&nbsp;e)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;session&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">null</span><span style="color: #000000;">;<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;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;((session&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;">&amp;&amp;</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">!</span><span style="color: #000000;">session.isValid())<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;session&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">null</span><span style="color: #000000;">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(session&nbsp;</span><span style="color: #000000;">!=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">null</span><span style="color: #000000;">)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;session.access();<br />
&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;(session);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;Create&nbsp;a&nbsp;new&nbsp;session&nbsp;if&nbsp;requested&nbsp;and&nbsp;the&nbsp;response&nbsp;is&nbsp;not&nbsp;committed</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(</span><span style="color: #000000;">!</span><span style="color: #000000;">create)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;(</span><span style="color: #0000ff;">null</span><span style="color: #000000;">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;((context&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;">&amp;&amp;</span><span style="color: #000000;">&nbsp;(response&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;">&amp;&amp;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;context.getCookies()&nbsp;</span><span style="color: #000000;">&amp;&amp;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;response.getResponse().isCommitted())&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;IllegalStateException<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(sm.getString(</span><span style="color: #000000;">"</span><span style="color: #000000;">coyoteRequest.sessionCreateCommitted</span><span style="color: #000000;">"</span><span style="color: #000000;">));<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;Attempt&nbsp;to&nbsp;reuse&nbsp;session&nbsp;id&nbsp;if&nbsp;one&nbsp;was&nbsp;submitted&nbsp;in&nbsp;a&nbsp;cookie<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;Do&nbsp;not&nbsp;reuse&nbsp;the&nbsp;session&nbsp;id&nbsp;if&nbsp;it&nbsp;is&nbsp;from&nbsp;a&nbsp;URL,&nbsp;to&nbsp;prevent&nbsp;possible<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;phishing&nbsp;attacks</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(connector.getEmptySessionPath()&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">&amp;&amp;</span><span style="color: #000000;">&nbsp;isRequestedSessionIdFromCookie())&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;session&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;manager.createSession(getRequestedSessionId());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span><span style="color: #0000ff;">else</span><span style="color: #000000;">&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;session&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;manager.createSession(</span><span style="color: #0000ff;">null</span><span style="color: #000000;">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;Creating&nbsp;a&nbsp;new&nbsp;session&nbsp;cookie&nbsp;based&nbsp;on&nbsp;that&nbsp;session</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;((session&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;">&amp;&amp;</span><span style="color: #000000;">&nbsp;(getContext()&nbsp;</span><span style="color: #000000;">!=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">null</span><span style="color: #000000;">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">&amp;&amp;</span><span style="color: #000000;">&nbsp;getContext().getCookies())&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Cookie&nbsp;cookie&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;Cookie(Globals.SESSION_COOKIE_NAME,<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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;session.getIdInternal());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;configureSessionCookie(cookie);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;response.addCookieInternal(cookie,&nbsp;context.getUseHttpOnly());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(session&nbsp;</span><span style="color: #000000;">!=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">null</span><span style="color: #000000;">)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;session.access();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;(session);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span><span style="color: #0000ff;">else</span><span style="color: #000000;">&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;(</span><span style="color: #0000ff;">null</span><span style="color: #000000;">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;}</span></div>
<br />
<br />
至此,简单地描述了Tomcat Session创建的机制,有兴趣的同学要深入了解,不妨看看Tomcat源码实现.<br />
<br />
<br />
<br />
补充说明,顺便提一下Session的过期策略.<br />
过期方法在:<br />
org.apache.catalina.session.<strong>ManagerBase</strong>(StandardManager基类) processExpires方法:<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; 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;">void</span><span style="color: #000000;">&nbsp;processExpires()&nbsp;{<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">long</span><span style="color: #000000;">&nbsp;timeNow&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;System.currentTimeMillis();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Session&nbsp;sessions[]&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;findSessions();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;expireHere&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">&nbsp;;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">(log.isDebugEnabled())<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;log.debug(</span><span style="color: #000000;">"</span><span style="color: #000000;">Start&nbsp;expire&nbsp;sessions&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;getName()&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">&nbsp;at&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;timeNow&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">&nbsp;sessioncount&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;sessions.length);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">for</span><span style="color: #000000;">&nbsp;(</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;i&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">;&nbsp;i&nbsp;</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">&nbsp;sessions.length;&nbsp;i</span><span style="color: #000000;">++</span><span style="color: #000000;">)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(sessions[i]</span><span style="color: #000000;">!=</span><span style="color: #0000ff;">null</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">&amp;&amp;</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">!</span><span style="color: #000000;">sessions[i].isValid())&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;expireHere</span><span style="color: #000000;">++</span><span style="color: #000000;">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&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;">long</span><span style="color: #000000;">&nbsp;timeEnd&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;System.currentTimeMillis();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">(log.isDebugEnabled())<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;log.debug(</span><span style="color: #000000;">"</span><span style="color: #000000;">End&nbsp;expire&nbsp;sessions&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;getName()&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">&nbsp;processingTime&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;(timeEnd&nbsp;</span><span style="color: #000000;">-</span><span style="color: #000000;">&nbsp;timeNow)&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">&nbsp;expired&nbsp;sessions:&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;expireHere);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;processingTime&nbsp;</span><span style="color: #000000;">+=</span><span style="color: #000000;">&nbsp;(&nbsp;timeEnd&nbsp;</span><span style="color: #000000;">-</span><span style="color: #000000;">&nbsp;timeNow&nbsp;);<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;}</span></div>
<br />
其中,Session.isValid()方法会做Session的清除工作.<br />
<br />
<br />
在org.apache.catalina.core.ContainerBase中,会启动一个后台线程,跑一些后台任务,Session过期任务是其中之一:<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #0000ff;">protected</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;threadStart()&nbsp;{<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(thread&nbsp;</span><span style="color: #000000;">!=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">null</span><span style="color: #000000;">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(backgroundProcessorDelay&nbsp;</span><span style="color: #000000;">&lt;=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;threadDone&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;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;threadName&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">ContainerBackgroundProcessor[</span><span style="color: #000000;">"</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;toString()&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">]</span><span style="color: #000000;">"</span><span style="color: #000000;">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;thread&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;Thread(</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;ContainerBackgroundProcessor(),&nbsp;threadName);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;thread.setDaemon(</span><span style="color: #0000ff;">true</span><span style="color: #000000;">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;thread.start();<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;}</span></div>
<br />
<br />
OVER :)<br />
<img src ="http://www.blogjava.net/stone2083/aggbug/314009.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/stone2083/" target="_blank">stone2083</a> 2010-02-26 16:12 <a href="http://www.blogjava.net/stone2083/archive/2010/02/26/314009.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>布隆过滤器（BloomFilter）</title><link>http://www.blogjava.net/stone2083/archive/2010/01/30/311329.html</link><dc:creator>stone2083</dc:creator><author>stone2083</author><pubDate>Sat, 30 Jan 2010 07:00:00 GMT</pubDate><guid>http://www.blogjava.net/stone2083/archive/2010/01/30/311329.html</guid><wfw:comment>http://www.blogjava.net/stone2083/comments/311329.html</wfw:comment><comments>http://www.blogjava.net/stone2083/archive/2010/01/30/311329.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/stone2083/comments/commentRss/311329.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/stone2083/services/trackbacks/311329.html</trackback:ping><description><![CDATA[资料：<br />
<a title="wikipedia--bloom filter" href="http://en.wikipedia.org/wiki/Bloom_filter">wikipedia--bloom filter</a><br />
<br />
使用场景，原理简介之中文资料：<br />
<a title="数学之美系列二十一 － 布隆过滤器（Bloom Filter）" href="http://googlechinablog.com/2007/07/bloom-filter.html">数学之美系列二十一 － 布隆过滤器（Bloom Filter）</a><br />
<br />
核心内容（摘自Google黑板报文章内容）：<br />
<img alt="" src="http://googlechinablog.com/uploaded_images/bloomfilter-730334.jpg" /><br />
<br />
BloomFilter简易实现：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; 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;SimpleBloomFilter&nbsp;{<br />
<br />
&nbsp;&nbsp;&nbsp;&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;&nbsp;&nbsp;DEFAULT_SIZE&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">2</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">&lt;&lt;</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">24</span><span style="color: #000000;">;<br />
&nbsp;&nbsp;&nbsp;&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;seeds&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">[]&nbsp;{&nbsp;</span><span style="color: #000000;">7</span><span style="color: #000000;">,&nbsp;</span><span style="color: #000000;">11</span><span style="color: #000000;">,&nbsp;</span><span style="color: #000000;">13</span><span style="color: #000000;">,&nbsp;</span><span style="color: #000000;">31</span><span style="color: #000000;">,&nbsp;</span><span style="color: #000000;">37</span><span style="color: #000000;">,&nbsp;</span><span style="color: #000000;">61</span><span style="color: #000000;">,&nbsp;};<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">private</span><span style="color: #000000;">&nbsp;BitSet&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;bits&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;BitSet(DEFAULT_SIZE);<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">private</span><span style="color: #000000;">&nbsp;SimpleHash[]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;func&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;SimpleHash[seeds.length];<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;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;value&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">stone2083@yahoo.cn</span><span style="color: #000000;">"</span><span style="color: #000000;">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SimpleBloomFilter&nbsp;filter&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;SimpleBloomFilter();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(filter.contains(value));<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;filter.add(value);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(filter.contains(value));<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;SimpleBloomFilter()&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">for</span><span style="color: #000000;">&nbsp;(</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;i&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">;&nbsp;i&nbsp;</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">&nbsp;seeds.length;&nbsp;i</span><span style="color: #000000;">++</span><span style="color: #000000;">)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;func[i]&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;SimpleHash(DEFAULT_SIZE,&nbsp;seeds[i]);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;add(String&nbsp;value)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">for</span><span style="color: #000000;">&nbsp;(SimpleHash&nbsp;f&nbsp;:&nbsp;func)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;bits.set(f.hash(value),&nbsp;</span><span style="color: #0000ff;">true</span><span style="color: #000000;">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">boolean</span><span style="color: #000000;">&nbsp;contains(String&nbsp;value)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(value&nbsp;</span><span style="color: #000000;">==</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">null</span><span style="color: #000000;">)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">false</span><span style="color: #000000;">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">boolean</span><span style="color: #000000;">&nbsp;ret&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;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">for</span><span style="color: #000000;">&nbsp;(SimpleHash&nbsp;f&nbsp;:&nbsp;func)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ret&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;ret&nbsp;</span><span style="color: #000000;">&amp;&amp;</span><span style="color: #000000;">&nbsp;bits.get(f.hash(value));<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;ret;<br />
&nbsp;&nbsp;&nbsp;&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;">class</span><span style="color: #000000;">&nbsp;SimpleHash&nbsp;{<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">private</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;cap;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">private</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;seed;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;SimpleHash(</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;cap,&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;seed)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">this</span><span style="color: #000000;">.cap&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;cap;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">this</span><span style="color: #000000;">.seed&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;seed;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;hash(String&nbsp;value)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;result&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;len&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;value.length();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">for</span><span style="color: #000000;">&nbsp;(</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;i&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">;&nbsp;i&nbsp;</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">&nbsp;len;&nbsp;i</span><span style="color: #000000;">++</span><span style="color: #000000;">)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;result&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;seed&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">&nbsp;result&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;value.charAt(i);<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;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;(cap&nbsp;</span><span style="color: #000000;">-</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">1</span><span style="color: #000000;">)&nbsp;</span><span style="color: #000000;">&amp;</span><span style="color: #000000;">&nbsp;result;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
}</span></div>
<br />
<br />
<br />
<img src ="http://www.blogjava.net/stone2083/aggbug/311329.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/stone2083/" target="_blank">stone2083</a> 2010-01-30 15:00 <a href="http://www.blogjava.net/stone2083/archive/2010/01/30/311329.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>httpclient ssl support</title><link>http://www.blogjava.net/stone2083/archive/2010/01/30/311328.html</link><dc:creator>stone2083</dc:creator><author>stone2083</author><pubDate>Sat, 30 Jan 2010 06:39:00 GMT</pubDate><guid>http://www.blogjava.net/stone2083/archive/2010/01/30/311328.html</guid><wfw:comment>http://www.blogjava.net/stone2083/comments/311328.html</wfw:comment><comments>http://www.blogjava.net/stone2083/archive/2010/01/30/311328.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/stone2083/comments/commentRss/311328.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/stone2083/services/trackbacks/311328.html</trackback:ping><description><![CDATA[手头上一些工作，需要经常访问公司内网的数据，为了减少重复的劳动力，就考虑程序帮忙爬取信息数据。<br />
apache下httpclient是一个很好的工具，不过公司内网是使用HTTPS协议的，于是乎，就需要考虑如何让httpclient支持https。<br />
支持ssl的关键，在于如何创建一个SSLSocket，幸好，httpclient提供了支持。<br />
<br />
请看：<br />
org.apache.commons.httpclient.protocol.ProtocolSocketFactory<br />
javadocs:A factory for creating Sockets. <br />
<br />
实现一个简单的EasySSLProtocolSocketFactory，详见代码：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; 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;EasySSLProtocolSocketFactory&nbsp;</span><span style="color: #0000ff;">implements</span><span style="color: #000000;">&nbsp;ProtocolSocketFactory&nbsp;{<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">private</span><span style="color: #000000;">&nbsp;SSLContext&nbsp;sslcontext&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">null</span><span style="color: #000000;">;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">private</span><span style="color: #000000;">&nbsp;String&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ksfile;<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">private</span><span style="color: #000000;">&nbsp;String&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tksfile;<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">private</span><span style="color: #000000;">&nbsp;String&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;kspwd;<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">private</span><span style="color: #000000;">&nbsp;String&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tkspwd;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;EasySSLProtocolSocketFactory(String&nbsp;ks,&nbsp;String&nbsp;kspwd,&nbsp;String&nbsp;tks,&nbsp;String&nbsp;tkspwd){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">this</span><span style="color: #000000;">.ksfile&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;ks;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">this</span><span style="color: #000000;">.kspwd&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;kspwd;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">this</span><span style="color: #000000;">.tksfile&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;tks;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">this</span><span style="color: #000000;">.tkspwd&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;tkspwd;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;Socket&nbsp;createSocket(String&nbsp;host,&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;port,&nbsp;InetAddress&nbsp;clientHost,&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;clientPort)&nbsp;</span><span style="color: #0000ff;">throws</span><span style="color: #000000;">&nbsp;IOException,<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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;UnknownHostException&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;getSSLContext().getSocketFactory().createSocket(host,&nbsp;port,&nbsp;clientHost,&nbsp;clientPort);<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;Socket&nbsp;createSocket(</span><span style="color: #0000ff;">final</span><span style="color: #000000;">&nbsp;String&nbsp;host,&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;port,&nbsp;</span><span style="color: #0000ff;">final</span><span style="color: #000000;">&nbsp;InetAddress&nbsp;localAddress,&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;localPort,<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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">final</span><span style="color: #000000;">&nbsp;HttpConnectionParams&nbsp;params)&nbsp;</span><span style="color: #0000ff;">throws</span><span style="color: #000000;">&nbsp;IOException,&nbsp;UnknownHostException,<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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ConnectTimeoutException&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(params&nbsp;</span><span style="color: #000000;">==</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">null</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(</span><span style="color: #000000;">"</span><span style="color: #000000;">Parameters&nbsp;may&nbsp;not&nbsp;be&nbsp;null</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;timeout&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;params.getConnectionTimeout();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SocketFactory&nbsp;socketfactory&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;getSSLContext().getSocketFactory();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(timeout&nbsp;</span><span style="color: #000000;">==</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;socketfactory.createSocket(host,&nbsp;port,&nbsp;localAddress,&nbsp;localPort);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span><span style="color: #0000ff;">else</span><span style="color: #000000;">&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Socket&nbsp;socket&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;socketfactory.createSocket();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SocketAddress&nbsp;localaddr&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;InetSocketAddress(localAddress,&nbsp;localPort);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SocketAddress&nbsp;remoteaddr&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;InetSocketAddress(host,&nbsp;port);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;socket.bind(localaddr);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;socket.connect(remoteaddr,&nbsp;timeout);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;socket;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;Socket&nbsp;createSocket(String&nbsp;host,&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;port)&nbsp;</span><span style="color: #0000ff;">throws</span><span style="color: #000000;">&nbsp;IOException,&nbsp;UnknownHostException&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;getSSLContext().getSocketFactory().createSocket(host,&nbsp;port);<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;Socket&nbsp;createSocket(Socket&nbsp;socket,&nbsp;String&nbsp;host,&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;port,&nbsp;</span><span style="color: #0000ff;">boolean</span><span style="color: #000000;">&nbsp;autoClose)&nbsp;</span><span style="color: #0000ff;">throws</span><span style="color: #000000;">&nbsp;IOException,<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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;UnknownHostException&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;getSSLContext().getSocketFactory().createSocket(socket,&nbsp;host,&nbsp;port,&nbsp;autoClose);<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">private</span><span style="color: #000000;">&nbsp;SSLContext&nbsp;createEasySSLContext()&nbsp;{<br />
&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;SSLContext&nbsp;context&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;SSLContext.getInstance(</span><span style="color: #000000;">"</span><span style="color: #000000;">SSL</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;KeyManagerFactory&nbsp;kmf&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;KeyManagerFactory.getInstance(</span><span style="color: #000000;">"</span><span style="color: #000000;">SunX509</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TrustManagerFactory&nbsp;tmf&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;TrustManagerFactory.getInstance(</span><span style="color: #000000;">"</span><span style="color: #000000;">SunX509</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;KeyStore&nbsp;ks&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;KeyStore.getInstance(</span><span style="color: #000000;">"</span><span style="color: #000000;">JKS</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;KeyStore&nbsp;tks&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;KeyStore.getInstance(</span><span style="color: #000000;">"</span><span style="color: #000000;">JKS</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ks.load(</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;FileInputStream(ksfile),&nbsp;kspwd.toCharArray());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tks.load(</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;FileInputStream(tksfile),&nbsp;tkspwd.toCharArray());<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;kmf.init(ks,&nbsp;kspwd.toCharArray());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tmf.init(tks);<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;context.init(kmf.getKeyManagers(),&nbsp;tmf.getTrustManagers(),&nbsp;</span><span style="color: #0000ff;">null</span><span style="color: #000000;">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;context;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span><span style="color: #0000ff;">catch</span><span style="color: #000000;">&nbsp;(Exception&nbsp;e)&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;HttpClientError(e.toString());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">private</span><span style="color: #000000;">&nbsp;SSLContext&nbsp;getSSLContext()&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(</span><span style="color: #0000ff;">this</span><span style="color: #000000;">.sslcontext&nbsp;</span><span style="color: #000000;">==</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">null</span><span style="color: #000000;">)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">this</span><span style="color: #000000;">.sslcontext&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;createEasySSLContext();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">this</span><span style="color: #000000;">.sslcontext;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
}</span></div>
<br />
备注：<br />
至于ssl相关的知识，和如何创建java key store，可见：<br />
<a title="SSL双向认证java实现" href="http://www.blogjava.net/stone2083/archive/2007/12/20/169015.html">SSL双向认证java实现</a><br />
<br />
<br />
如何使用，也简单：<br />
Protocol.registerProtocol("https", new Protocol("https", new EasySSLProtocolSocketFactory(KS_FILE, KS_PWD, TKS_FILE, TKS_PWD), 443))<br />
<br />
官方资料：<br />
<a href="http://hc.apache.org/httpclient-3.x/sslguide.html">http://hc.apache.org/httpclient-3.x/sslguide.html</a><br />
<br />
演示代码：<br />
<a href="/Files/stone2083/java/httpclient-ssl.zip">httpclient-ssl.zip</a><br />
<img src ="http://www.blogjava.net/stone2083/aggbug/311328.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/stone2083/" target="_blank">stone2083</a> 2010-01-30 14:39 <a href="http://www.blogjava.net/stone2083/archive/2010/01/30/311328.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Struts2.1.6--想用通配符，不容易</title><link>http://www.blogjava.net/stone2083/archive/2009/09/26/296519.html</link><dc:creator>stone2083</dc:creator><author>stone2083</author><pubDate>Sat, 26 Sep 2009 06:06:00 GMT</pubDate><guid>http://www.blogjava.net/stone2083/archive/2009/09/26/296519.html</guid><wfw:comment>http://www.blogjava.net/stone2083/comments/296519.html</wfw:comment><comments>http://www.blogjava.net/stone2083/archive/2009/09/26/296519.html#Feedback</comments><slash:comments>5</slash:comments><wfw:commentRss>http://www.blogjava.net/stone2083/comments/commentRss/296519.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/stone2083/services/trackbacks/296519.html</trackback:ping><description><![CDATA[初次使用Struts2，老老实实为每个action method配置url mapping文件。<br />
时间长了，难为觉得繁琐，为何不使用COC的方式呢？终于，想到了使用通配符。<br />
查看Struts2 Docs，找到相关配置方法：<br />
<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">package&nbsp;</span><span style="color: #ff0000;">name</span><span style="color: #0000ff;">="alliance"</span><span style="color: #ff0000;">&nbsp;namespace</span><span style="color: #0000ff;">="/alliance"</span><span style="color: #ff0000;">&nbsp;extends</span><span style="color: #0000ff;">="struts-default"</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">action&nbsp;</span><span style="color: #ff0000;">name</span><span style="color: #0000ff;">="*/*"</span><span style="color: #ff0000;">&nbsp;class</span><span style="color: #0000ff;">="cn.zeroall.cow.web.alliance.action.{1}Action"</span><span style="color: #ff0000;">&nbsp;method</span><span style="color: #0000ff;">="{2}"</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">result&nbsp;</span><span style="color: #ff0000;">name</span><span style="color: #0000ff;">="target"</span><span style="color: #ff0000;">&nbsp;type</span><span style="color: #0000ff;">="velocity"</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;">/templates/alliance/{1}/${target}.vm</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">result</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">result&nbsp;</span><span style="color: #ff0000;">name</span><span style="color: #0000ff;">="success"</span><span style="color: #ff0000;">&nbsp;type</span><span style="color: #0000ff;">="velocity"</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;">/templates/alliance/{1}/{2}.vm</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">result</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">result&nbsp;</span><span style="color: #ff0000;">name</span><span style="color: #0000ff;">="input"</span><span style="color: #ff0000;">&nbsp;type</span><span style="color: #0000ff;">="velocity"</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;">/templates/alliance/{1}/{2}.vm</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">result</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">result&nbsp;</span><span style="color: #ff0000;">name</span><span style="color: #0000ff;">="fail"</span><span style="color: #ff0000;">&nbsp;type</span><span style="color: #0000ff;">="velocity"</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;">/templates/common/error.vm</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">result</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">action</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">package</span><span style="color: #0000ff;">&gt;</span></div>
<br />
恩，非常方便，可是启动jetty，发现满足正则的url，就是找不到Action。<br />
无奈，debug代码，找到原因，需要在struts.properties中，配置：<br />
struts.enable.SlashesInActionNames = true<br />
见注释：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">###&nbsp;Set&nbsp;this&nbsp;to&nbsp;true&nbsp;if&nbsp;you&nbsp;wish&nbsp;to&nbsp;allow&nbsp;slashes&nbsp;in&nbsp;your&nbsp;action&nbsp;names.&nbsp;&nbsp;If&nbsp;false,<br />
###&nbsp;Actions&nbsp;names&nbsp;cannot&nbsp;have&nbsp;slashes,&nbsp;and&nbsp;will&nbsp;be&nbsp;accessible&nbsp;via&nbsp;any&nbsp;directory<br />
###&nbsp;prefix.&nbsp;&nbsp;This&nbsp;is&nbsp;the&nbsp;traditional&nbsp;behavior&nbsp;expected&nbsp;of&nbsp;WebWork&nbsp;applications.<br />
###&nbsp;Setting&nbsp;to&nbsp;true&nbsp;is&nbsp;useful&nbsp;when&nbsp;you&nbsp;want&nbsp;to&nbsp;use&nbsp;wildcards&nbsp;and&nbsp;store&nbsp;values<br />
###&nbsp;in&nbsp;the&nbsp;URL,&nbsp;to&nbsp;be&nbsp;extracted&nbsp;by&nbsp;wildcard&nbsp;patterns,&nbsp;such&nbsp;as&nbsp;<br />
###&nbsp;</span><span style="color: #0000ff;"><span style="color: #000000;"><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">action&nbsp;</span><span style="color: #ff0000;">name</span><span style="color: #0000ff;">="*/*"</span><span style="color: #ff0000;">&nbsp;method</span><span style="color: #0000ff;">="{2}"</span><span style="color: #ff0000;">&nbsp;class</span><span style="color: #0000ff;">="actions.{1}"</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;">&nbsp;to&nbsp;match&nbsp;"/foo/edit"&nbsp;or&nbsp;</span></span></span><span style="color: #000000;"><br />
###&nbsp;"/foo/save".</span></div>
<br />
启动，COC终于成功。<br />
<br />
但是（又冒出一个但是），针对*/*正则的url mapping，如何做validation呢？<br />
按照struts2的约定，是通过：<br />
[package/]ActionName-${配置中的action name=""中的名字}-validation.xml<br />
<br />
如何把"/"这个符号放入到${配置中的action name=""中的名字}呢？<br />
"/"可不是一个合法的文件名。<br />
<br />
比如，我要为AlliedMemberAction/doRegister做validation，那么约定的校验文件名应该是：<br />
cn/zeroall/cow/web/alliance/action/AlliedMemberAction-AlliedMember<span style="color: #ff0000;">/</span>doRegister-validation.xml<br />
这个特殊符号，可难刹我也。<br />
<br />
无奈，继续debug，发现在代码：<br />
xwork框架中的，AnnotationActionValidatorManager：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">private&nbsp;&nbsp;List</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">ValidatorConfig</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;">&nbsp;buildAliasValidatorConfigs(Class&nbsp;aClass,&nbsp;String&nbsp;context,&nbsp;boolean&nbsp;checkFile)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;fileName&nbsp;=&nbsp;aClass.getName().replace('.',&nbsp;'/')&nbsp;+&nbsp;"-"&nbsp;+&nbsp;context +&nbsp;VALIDATION_CONFIG_SUFFIX;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;loadFile(fileName,&nbsp;aClass,&nbsp;checkFile);<br />
}</span></div>
这个context就是action name=""中的url表达式。<br />
<br />
思想斗争后，由于我不喜欢使用*-*的pattern,更喜欢使用*/*pattern，只好修改了源码：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">private&nbsp;&nbsp;List</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">ValidatorConfig</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;">&nbsp;buildAliasValidatorConfigs(Class&nbsp;aClass,&nbsp;String&nbsp;context,&nbsp;boolean&nbsp;checkFile)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;fileName&nbsp;=&nbsp;aClass.getName().replace('.',&nbsp;'/')&nbsp;+&nbsp;"-"&nbsp;+&nbsp;context.replace("/",&nbsp;"-")&nbsp;+&nbsp;VALIDATION_CONFIG_SUFFIX;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;loadFile(fileName,&nbsp;aClass,&nbsp;checkFile);<br />
}</span></div>
将context中的&#8220;/&#8221;变成"-"解决这个问题。<br />
<br />
不清楚struts2官方怎么看待这个问题。<br />
<br />
大家是否有更好的方案，请指教<br />
<br />
<br />
<img src ="http://www.blogjava.net/stone2083/aggbug/296519.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/stone2083/" target="_blank">stone2083</a> 2009-09-26 14:06 <a href="http://www.blogjava.net/stone2083/archive/2009/09/26/296519.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>支付宝接口demo代码读后感</title><link>http://www.blogjava.net/stone2083/archive/2009/09/18/295559.html</link><dc:creator>stone2083</dc:creator><author>stone2083</author><pubDate>Fri, 18 Sep 2009 05:10:00 GMT</pubDate><guid>http://www.blogjava.net/stone2083/archive/2009/09/18/295559.html</guid><wfw:comment>http://www.blogjava.net/stone2083/comments/295559.html</wfw:comment><comments>http://www.blogjava.net/stone2083/archive/2009/09/18/295559.html#Feedback</comments><slash:comments>10</slash:comments><wfw:commentRss>http://www.blogjava.net/stone2083/comments/commentRss/295559.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/stone2083/services/trackbacks/295559.html</trackback:ping><description><![CDATA[最近在帮朋友做一个支付功能，用到了支付宝。<br />
从支付宝管理界面，下载到商户合作文档，看了demo程序后，心是拔凉拔凉的。<br />
说说review代码后的问题吧:<br />
CheckURL.java<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; 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;">static</span><span style="color: #000000;">&nbsp;String&nbsp;check(String&nbsp;urlvalue&nbsp;)&nbsp;{<br />
<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;inputLine</span><span style="color: #000000;">=</span><span style="color: #000000;">""</span><span style="color: #000000;">;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">try</span><span style="color: #000000;">{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;URL&nbsp;url&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;URL(urlvalue);<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;HttpURLConnection&nbsp;urlConnection&nbsp;&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;(HttpURLConnection)url.openConnection();<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;BufferedReader&nbsp;in&nbsp;&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;BufferedReader(<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;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;InputStreamReader(<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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;urlConnection.getInputStream()));<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;inputLine&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;in.readLine().toString();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span><span style="color: #0000ff;">catch</span><span style="color: #000000;">(Exception&nbsp;e){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e.printStackTrace();<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;</span><span style="color: #008000;">//</span><span style="color: #008000;">System.out.println(inputLine);&nbsp;&nbsp;系统打印出抓取得验证结果</span><span style="color: #008000;"><br />
</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;inputLine;<br />
&nbsp;&nbsp;}</span></div>
＊Inputstream不需要close？<br />
＊知道e.printStackTrace()的性能代价？<br />
<br />
Md5Encrypt.java<br />
＊是采用什么编码的？我下载的是UTF8编码版本的，请问Md5Encrypt.java是什么编码？<br />
<br />
Payment.java<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; 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;">static</span><span style="color: #000000;">&nbsp;String&nbsp;CreateUrl(String&nbsp;paygateway,String&nbsp;service,String&nbsp;sign_type,String&nbsp;out_trade_no,<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;input_charset,String&nbsp;partner,String&nbsp;key,String&nbsp;seller_email,<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;body,String&nbsp;subject,String&nbsp;price,String&nbsp;quantity,String&nbsp;show_url,String&nbsp;payment_type,<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;discount,String&nbsp;logistics_type,String&nbsp;logistics_fee,String&nbsp;logistics_payment,<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;return_url)&nbsp;{<br />
<br />
&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;">String&nbsp;notify_url,需要的请把参数加入以上的createurl</span><span style="color: #008000;"><br />
</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Map&nbsp;params&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;HashMap();<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;params.put(</span><span style="color: #000000;">"</span><span style="color: #000000;">service</span><span style="color: #000000;">"</span><span style="color: #000000;">,&nbsp;service);<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;params.put(</span><span style="color: #000000;">"</span><span style="color: #000000;">out_trade_no</span><span style="color: #000000;">"</span><span style="color: #000000;">,&nbsp;out_trade_no);<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;params.put(</span><span style="color: #000000;">"</span><span style="color: #000000;">show_url</span><span style="color: #000000;">"</span><span style="color: #000000;">,&nbsp;show_url);<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;params.put(</span><span style="color: #000000;">"</span><span style="color: #000000;">quantity</span><span style="color: #000000;">"</span><span style="color: #000000;">,&nbsp;quantity);<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;params.put(</span><span style="color: #000000;">"</span><span style="color: #000000;">partner</span><span style="color: #000000;">"</span><span style="color: #000000;">,&nbsp;partner);<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;params.put(</span><span style="color: #000000;">"</span><span style="color: #000000;">payment_type</span><span style="color: #000000;">"</span><span style="color: #000000;">,&nbsp;payment_type);<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;params.put(</span><span style="color: #000000;">"</span><span style="color: #000000;">discount</span><span style="color: #000000;">"</span><span style="color: #000000;">,&nbsp;discount);<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;params.put(</span><span style="color: #000000;">"</span><span style="color: #000000;">body</span><span style="color: #000000;">"</span><span style="color: #000000;">,&nbsp;body);<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;params.put("notify_url",&nbsp;notify_url);</span><span style="color: #008000;"><br />
</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;params.put(</span><span style="color: #000000;">"</span><span style="color: #000000;">price</span><span style="color: #000000;">"</span><span style="color: #000000;">,&nbsp;price);<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;params.put(</span><span style="color: #000000;">"</span><span style="color: #000000;">return_url</span><span style="color: #000000;">"</span><span style="color: #000000;">,&nbsp;return_url);<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;params.put(</span><span style="color: #000000;">"</span><span style="color: #000000;">seller_email</span><span style="color: #000000;">"</span><span style="color: #000000;">,&nbsp;seller_email);<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;params.put(</span><span style="color: #000000;">"</span><span style="color: #000000;">logistics_type</span><span style="color: #000000;">"</span><span style="color: #000000;">,&nbsp;logistics_type);<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;params.put(</span><span style="color: #000000;">"</span><span style="color: #000000;">logistics_fee</span><span style="color: #000000;">"</span><span style="color: #000000;">,&nbsp;logistics_fee);<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;params.put(</span><span style="color: #000000;">"</span><span style="color: #000000;">logistics_payment</span><span style="color: #000000;">"</span><span style="color: #000000;">,&nbsp;logistics_payment);<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;params.put(</span><span style="color: #000000;">"</span><span style="color: #000000;">subject</span><span style="color: #000000;">"</span><span style="color: #000000;">,&nbsp;subject);<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;params.put(</span><span style="color: #000000;">"</span><span style="color: #000000;">_input_charset</span><span style="color: #000000;">"</span><span style="color: #000000;">,&nbsp;input_charset);<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;prestr&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">""</span><span style="color: #000000;">;<br />
<br />
<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;prestr&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;prestr&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;key;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">System.out.println("prestr="&nbsp;+&nbsp;prestr);</span><span style="color: #008000;"><br />
</span><span style="color: #000000;"><br />
<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;sign&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;com.alipay.util.Md5Encrypt.md5(getContent(params,&nbsp;key));<br />
<br />
<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;parameter&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">""</span><span style="color: #000000;">;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;parameter&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;parameter&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;paygateway;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">System.out.println("prestr="&nbsp;&nbsp;+&nbsp;parameter);</span><span style="color: #008000;"><br />
</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;List&nbsp;keys&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;ArrayList(params.keySet());<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">for</span><span style="color: #000000;">&nbsp;(</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;i&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">;&nbsp;i&nbsp;</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">&nbsp;keys.size();&nbsp;i</span><span style="color: #000000;">++</span><span style="color: #000000;">)&nbsp;{<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;value&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">(String)&nbsp;params.get(keys.get(i));<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">(value&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;value.trim().length()&nbsp;</span><span style="color: #000000;">==</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;</span><span style="color: #0000ff;">continue</span><span style="color: #000000;">;<br />
<br />
&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;</span><span style="color: #0000ff;">try</span><span style="color: #000000;">&nbsp;{<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;parameter&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;parameter&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;keys.get(i)&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">=</span><span style="color: #000000;">"</span><span style="color: #000000;"><br />
<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: #000000;">+</span><span style="color: #000000;">&nbsp;URLEncoder.encode(value,&nbsp;input_charset)&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">&amp;</span><span style="color: #000000;">"</span><span style="color: #000000;">;<br />
<br />
&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;(UnsupportedEncodingException&nbsp;e)&nbsp;{<br />
<br />
<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e.printStackTrace();<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;parameter&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;parameter&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">sign=</span><span style="color: #000000;">"</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;sign&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">&amp;sign_type=</span><span style="color: #000000;">"</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;sign_type;<br />
<br />
<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;sign;<br />
<br />
<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;}</span></div>
＊多少个参数啊？超过3，4个参数，都不使用ParameterClass吗？方便client调用吗？<br />
＊这个方法做什么？createUrl?得到url。可事实上呢？return sign。sign是什么？是参数的加密窜。<br />
方法中的<span style="color: #000000;">parameter不知道要来干吗用？<br />
＊又看到</span><span style="color: #000000;">e.printStackTrace();<br />
<br />
</span>SignatureHelper.java<br />
哇，总算看到一个过得去的代码，可以eclipse上，发现一个warning：import java.io.UnsupportedEncodingException;<br />
有用到UnsupportedEncodingException这个吗？<br />
<br />
SignatureHelper_return.java<br />
＊看看这个类名，符合java类名的规范吗？<br />
＊和SignatureHelper.java有什么区别？<br />
<br />
SetCharacterEncodingFilter.java<br />
哇塞，总算看到非常标准的代码了。可是：@author Craig McClanahan，原来是copy过来的。呜呼。<br />
<br />
并且整个demo工程，是用myeclipse的。哎。。。<br />
<br />
看不下去了，实在看不下去了。<br />
我不清楚支付宝公司提供的demo程序的目的是什么？<br />
－－提供的java文件是允许打成lib包使用的？<br />
－－仅仅提供学习的？<br />
<br />
就算是提供学习的，写得标准些，行不？<br />
<br />
最后，我真希望，是我自己下错了demo程序－－这个demo程序不是支付宝官方的demo。希望如此吧，阿门～<br />
<br />
备注：<br />
除了demo，那份接口文档，写得还是非常规范的。<br />
<img src ="http://www.blogjava.net/stone2083/aggbug/295559.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/stone2083/" target="_blank">stone2083</a> 2009-09-18 13:10 <a href="http://www.blogjava.net/stone2083/archive/2009/09/18/295559.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Struts2.1.6 StrutsPrepareAndExecuteFilter bug</title><link>http://www.blogjava.net/stone2083/archive/2009/06/08/280724.html</link><dc:creator>stone2083</dc:creator><author>stone2083</author><pubDate>Mon, 08 Jun 2009 12:37:00 GMT</pubDate><guid>http://www.blogjava.net/stone2083/archive/2009/06/08/280724.html</guid><wfw:comment>http://www.blogjava.net/stone2083/comments/280724.html</wfw:comment><comments>http://www.blogjava.net/stone2083/archive/2009/06/08/280724.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.blogjava.net/stone2083/comments/commentRss/280724.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/stone2083/services/trackbacks/280724.html</trackback:ping><description><![CDATA[在用strust2.1.6做小项目，结果居然发现在post数据的时候，居然有乱码。<br />
自认为对编码也算了解，立马check应用的content type，struts2配置的struts.locale，struts.i18n.encoding，没错，都是统一使用了UTF-8。<br />
那是为什么呢？没办法，只能debug应用，结果发现：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; 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;">void</span><span style="color: #000000;">&nbsp;doFilter(ServletRequest&nbsp;req,&nbsp;ServletResponse&nbsp;res,&nbsp;FilterChain&nbsp;chain)&nbsp;</span><span style="color: #0000ff;">throws</span><span style="color: #000000;">&nbsp;IOException,&nbsp;ServletException&nbsp;{<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;HttpServletRequest&nbsp;request&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;(HttpServletRequest)&nbsp;req;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;HttpServletResponse&nbsp;response&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;(HttpServletResponse)&nbsp;res;<br />
<br />
&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;<span style="color: red;">prepare.createActionContext(request,&nbsp;response);</span><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;prepare.assignDispatcherToThread();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: red;">prepare.setEncodingAndLocale(request,&nbsp;response);</span><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;request&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;prepare.wrapRequest(request);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ActionMapping&nbsp;mapping&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;prepare.findActionMapping(request,&nbsp;response);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(mapping&nbsp;</span><span style="color: #000000;">==</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">null</span><span style="color: #000000;">)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">boolean</span><span style="color: #000000;">&nbsp;handled&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;execute.executeStaticResourceRequest(request,&nbsp;response);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(</span><span style="color: #000000;">!</span><span style="color: #000000;">handled)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;chain.doFilter(request,&nbsp;response);<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;</span><span style="color: #0000ff;">else</span><span style="color: #000000;">&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;execute.executeAction(request,&nbsp;response,&nbsp;mapping);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span><span style="color: #0000ff;">finally</span><span style="color: #000000;">&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;prepare.cleanupRequest(request);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;}</span></div>
看到没？<br />
1）<span style="color: #000000;"> prepare.createActionContext(request,&nbsp;response);<br />
2） </span><span style="color: #000000;">prepare.setEncodingAndLocale(request,&nbsp;response);<br />
</span><span style="color: #000000;">setEncodingAndLocale居然在</span><span style="color: #000000;">createActionContext之后，在没有设置正确的encoding之前，解析request中的parameters，能成吗？<br />
<br />
无奈之下，只能暂时用</span>CharacterEncodingFilter这个filter设置request的character，猥琐地临时解决问题。<br />
<br />
今天打算向Struts提交bug的时候，发现该bug在2.1.7版本中被修复，详见：https://issues.apache.org/struts/browse/WW-3075%3Bjsessionid=3EAC5B44A949CA77B4471AA0D45754E9?page=com.atlassian.jira.plugin.ext.subversion%3Asubversion-commits-tabpanel<br />
<br />
哎，在使用2.1.7之前，先用CharacterEncodingFilter吧 ：）<br />
<br />
<br />
<img src ="http://www.blogjava.net/stone2083/aggbug/280724.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/stone2083/" target="_blank">stone2083</a> 2009-06-08 20:37 <a href="http://www.blogjava.net/stone2083/archive/2009/06/08/280724.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>事件消息通知系统</title><link>http://www.blogjava.net/stone2083/archive/2009/05/07/269491.html</link><dc:creator>stone2083</dc:creator><author>stone2083</author><pubDate>Thu, 07 May 2009 13:49:00 GMT</pubDate><guid>http://www.blogjava.net/stone2083/archive/2009/05/07/269491.html</guid><wfw:comment>http://www.blogjava.net/stone2083/comments/269491.html</wfw:comment><comments>http://www.blogjava.net/stone2083/archive/2009/05/07/269491.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/stone2083/comments/commentRss/269491.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/stone2083/services/trackbacks/269491.html</trackback:ping><description><![CDATA[在SOA架构中，JMS协议中的&#8220;点对点&#8221;消息方式，已经能够很好的支持1对1系统之间的通讯；<br />
但是，类似事件消息的通知（应用产生一个事件消息，其他多个系统做相应处理），理论上JMS协议中的&#8220;订阅&#8221;方式，能够支持此类场景，不过协议说：在消息产生通知订阅者的时候，如果某个订阅者系统不在线，则消息丢失－－此订阅者接受不到消息。<br />
并且，始终抱着对客户端简单，友好的态度，我希望client（应用）本身只要发出事件消息，并不需要去关注消息通知哪些订阅者，而这一切，应该由&#8220;事件消息通知系统&#8221;，代为完成。<br />
<br />
经过昨天晚上空闲时间的思考，大概设计了&#8220;事件消息通知系统&#8221;的概念模型。（此概念模型，基于IP，路由，DNS思考得来）<br />
详见下图：<br />
<br />
<br />
<img alt="事件消息通知系统" src="http://www.blogjava.net/images/blogjava_net/stone2083/java/eventMessageNotifySystem.jpg" height="1280" width="1280" /><br />
<br />
<br />
概念解释：<br />
1）Application：业务应用，一旦有事件消息产生，不再关注需要发送到哪些目的地，只需要统一发送到Event Message Center；<br />
<br />
2）Event Message Center：一切事件消息的暂存地；<br />
<br />
3）Event Message Router：事件消息路由器，根据Event Message Configuration Center（事件消息配置中心，即事件消息路由配置中心），将不同的消息，路由分发到不同的订阅者目的地；<br />
<br />
4）Event Message Configuration Center：事件消息配置中心，即事件消息路由配置中心；<br />
<br />
5）Event Message Registrar：事件消息登记中心，通过GUI界面，将Event Message Configuration Center中的路由信息展现给用户，并且允许用户进行事件消息路由信息的配置；<br />
<br />
6）Event Message Subscription：事件消息订阅中心，同一类事件消息的暂存地；<br />
<br />
7）Event Message Subscription Distributer：事件消息订阅分发者，根据Event Message Subscription Configuration Center（事件消息订阅配置中心）的配置信息，讲事件消息分发到不同的订阅者目的地；<br />
<br />
8）Event Message Subscription Configuration Center：事件消息订阅配置中心，即事件消息订阅分发路由信息配置；<br />
<br />
9）Event Message Subscription Registrar：事件消息订阅登记中心，通过GUI界面，将 Event Message Subscription Configuration Center中的分发路由信息展现给用户，并且允许用户进行事件消息订阅路由信息的配置；<br />
<br />
10）Event Message Destination:事件消息目的地；<br />
<br />
11）Event Message Consumer:不同订阅者的消费端<br />
<br />
<br />
写下此随笔，仅仅把把自己对&#8220;事件消息系统&#8221;的感观认识记录。<br />
由于思考和整理时间很短，此概念模型存在很多缺陷之处，还望大家多多指点。<br />
<img src ="http://www.blogjava.net/stone2083/aggbug/269491.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/stone2083/" target="_blank">stone2083</a> 2009-05-07 21:49 <a href="http://www.blogjava.net/stone2083/archive/2009/05/07/269491.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Velocity之EventHandler</title><link>http://www.blogjava.net/stone2083/archive/2009/02/05/253452.html</link><dc:creator>stone2083</dc:creator><author>stone2083</author><pubDate>Thu, 05 Feb 2009 14:26:00 GMT</pubDate><guid>http://www.blogjava.net/stone2083/archive/2009/02/05/253452.html</guid><wfw:comment>http://www.blogjava.net/stone2083/comments/253452.html</wfw:comment><comments>http://www.blogjava.net/stone2083/archive/2009/02/05/253452.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/stone2083/comments/commentRss/253452.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/stone2083/services/trackbacks/253452.html</trackback:ping><description><![CDATA[Velocity在渲染页面的时候，提供了不同的EventHanlder，供开发者callback。<br />
本文简要说明下，在Velocity1.6.1版本下，不同EventHanlder的作用：<br />
<br />
<strong>EventHandler</strong>（接口）：<br />
Base interface for all event handlers<br />
仅仅是一个事件侦听标志<br />
<br />
<br />
<strong><br />
IncludeEventHandler</strong>（接口）：<br />
Event handler for include type directives (e.g. <code>#include()</code>, <code>#parse()</code>)
Allows the developer to modify the path of the resource returned.<br />
在使用#include(),#parse()语法的时候，允许开发修改include或者parse文件的路径（一般用于资源找不到的情况）<br />
<strong>IncludeNotFound</strong>（IncludeEventHandler实现类）：<br />
<p>Simple event handler that checks to see if an included page is available.
If not, it includes a designated replacement page instead.By default, the name of the replacement page is "notfound.vm", however this
page name can be changed by setting the Velocity property
<code>eventhandler.include.notfound</code>, for example:<code></code><br />
</p>
<p>eventhandler.include.notfound = error.vm</p>
<p>当使用#include(),#parse()语法的时候，如果提供的资源文件找不到，则默认使用notfound.vm模板代替。</p>
<p>开发者可以通过设置<code>eventhandler.include.notfound</code>属性，修改替代模板的路径。<br />
</p>
<p><strong>IncludeRelativePath</strong>（IncludeEventHandler实现类）：</p>
<p>Event handler that looks for included files relative to the path of the
current template. The handler assumes that paths are separated by a forward
slash "/" or backwards slash "\".</p>
<p>使用相对路径方式，寻找#include或者#parse()中指定的资源文件<br />
</p>
<p><br />
</p>
<p><strong><br />
</strong>
</p>
<p><strong>InvalidReferenceEventHandler</strong>（接口）：</p>
<p>Event handler called when an invalid reference is encountered.  Allows
the application to report errors or substitute return values</p>
<p>当渲染页面的时候，一旦遇到非法的reference，就会触发此事件。开发者可以侦听此事件，用于错误的报告，或者修改返回的内容。</p>
<p><strong>ReportInvalidReferences</strong>（InvalidReferenceEventHandler实现类）：</p>
<p>Use this event handler to flag invalid references.</p>
<p>使用这个实现类用于标志非法的references。修改eventhandler.invalidreference.exception属性，可以在捕捉到第一个非法references的时候，停止模板的渲染。</p>
<p><br />
</p>
<p><strong><br />
</strong></p>
<p><strong>MethodExceptionEventHandler</strong>（接口）：</p>
<p>Event handler called when a method throws an exception.  This gives the
application a chance to deal with it and either
return something nice, or throw.
Please return what you want rendered into the output stream.</p>
<p>渲染模板，一旦发现调用的方法抛出异常的时候，就会触发此事件。允许开发者处理这个异常，输出友好信息或者抛出异常。必须返回一个值用于模板的渲染。</p>
<p><strong>PrintExceptions</strong>（MethodExceptionEventHandler实现类）：</p>
<p>Simple event handler that renders method exceptions in the page
rather than throwing the exception.  Useful for debugging.
</p>
<p>By default this event handler renders the exception name only.
To include both the exception name and the message, set the property
<code>eventhandler.methodexception.message</code> to <code>true</code>.  To render
the stack trace, set the property <code>eventhandler.methodexception.stacktrace</code>
to <code>true</code>.</p>
<p>模板渲染时，遇到方法异常，输出异常名，而不是抛出这个异常。对于调式，非常有帮助。</p>
<p>通过<code>eventhandler.methodexception.message</code>和<code>eventhandler.methodexception.stacktrace</code>属性的设置，可以输出异常message和stacktrace.</p>
<p><br />
</p>
<p><br />
</p>
<p><strong>NullSetEventHandler</strong>（接口）：<br />
</p>
<p>Event handler called when the RHS of #set is null.  Lets an app approve / veto
writing a log message based on the specific reference.</p>
<p>当使用#set()语法，设置一个null值的时候，会触发此事件。－－目前Velocity官方没有提供默认实现。</p>
<br />
<br />
<strong>ReferenceInsertionEventHandler</strong>（接口）：<br />
<p>Reference 'Stream insertion' event handler.  Called with object
that will be inserted into stream via value.toString().
Please return an Object that will toString() nicely</p>
<p>当渲染变量（reference）的时候，就会触发此事件。允许开发者返回更加友好的值－－一般用于内容的escape，比如HtmlEscape等。</p>
<p><strong>EscapeHtmlReference</strong>（ReferenceInsertionEventHandler实现类）：</p>
<p>html escape<br />
</p>
<p><strong>EscapeJavaScriptReference</strong>（ReferenceInsertionEventHandler实现类）：</p>
<p>javascript escape<br />
</p>
<p><strong>EscapeSqlReference</strong>（ReferenceInsertionEventHandler实现类）：</p>
<p>sql escape<br />
</p>
<p><strong>EscapeXmlReference</strong>（ReferenceInsertionEventHandler实现类）：</p>
<p>xml escape</p>
<p><br />
</p>
<p>以上是Velocity组件中提供的EventHandler介绍。下面写一个简单的例子来说明EventHandler的使用。</p>
<p>模拟需求，假如输出的内容带有html标签，而输出的内容需要过滤这些标签。如果我们手工对输出变量通过StringEscapeUtils.escapeHtml()来实现，则太过繁琐。所以，我们就可以使用Velocity中的<strong>EscapeHtmlReference</strong>。demo代码如下：</p>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">VelocityEngine&nbsp;ve&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;VelocityEngine();<br />
EventCartridge&nbsp;eventCartridge&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;EventCartridge();<br />
eventCartridge.addEventHandler(</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;EscapeHtmlReference());<br />
<br />
Context&nbsp;context&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;VelocityContext();<br />
context.put(</span><span style="color: #000000;">"</span><span style="color: #000000;">name</span><span style="color: #000000;">"</span><span style="color: #000000;">,&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">&lt;table&gt;&lt;/table&gt;</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br />
eventCartridge.attachToContext(context);<br />
<br />
StringWriter&nbsp;writer&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;StringWriter();<br />
ve.mergeTemplate(VM_LOCATION,&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">utf-8</span><span style="color: #000000;">"</span><span style="color: #000000;">,&nbsp;context,&nbsp;writer);<br />
System.out.println(</span><span style="color: #000000;">"</span><span style="color: #000000;">================================</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br />
System.out.println(writer.toString());<br />
System.out.println(</span><span style="color: #000000;">"</span><span style="color: #000000;">================================</span><span style="color: #000000;">"</span><span style="color: #000000;">);</span></div>
<p><br />
</p>
<p>模板文件中，仅仅为 $name</p>
<p>则输出内容如下：</p>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">================================<br />
</span><span style="color: #ff0000;">&amp;lt;</span><span style="color: #000000;">table</span><span style="color: #ff0000;">&amp;gt;&amp;lt;</span><span style="color: #000000;">/table</span><span style="color: #ff0000;">&amp;gt;</span><span style="color: #000000;"><br />
================================</span></div>
<p>
</p>
<p>
</p>
<img src ="http://www.blogjava.net/stone2083/aggbug/253452.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/stone2083/" target="_blank">stone2083</a> 2009-02-05 22:26 <a href="http://www.blogjava.net/stone2083/archive/2009/02/05/253452.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ibatis支持枚举类型</title><link>http://www.blogjava.net/stone2083/archive/2008/11/05/238899.html</link><dc:creator>stone2083</dc:creator><author>stone2083</author><pubDate>Wed, 05 Nov 2008 15:08:00 GMT</pubDate><guid>http://www.blogjava.net/stone2083/archive/2008/11/05/238899.html</guid><wfw:comment>http://www.blogjava.net/stone2083/comments/238899.html</wfw:comment><comments>http://www.blogjava.net/stone2083/archive/2008/11/05/238899.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/stone2083/comments/commentRss/238899.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/stone2083/services/trackbacks/238899.html</trackback:ping><description><![CDATA[很多应用中，数据库表结构都会存在一些状态字段。在关系性数据库中，一般会用VARCHAR类型。使用ibatis的应用，传统做法，往往会使用String的属性，与之对应。<br />
例如一张member表，结构设计如下：<br />
<img alt="" src="http://www.blogjava.net/images/blogjava_net/stone2083/java/db_member.png" height="39" width="805" /><br />
其中status为状态字段。<br />
<br />
ibatis中，使用class MemberPO 与之mapping，设计往往如下：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; 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;MemberPO&nbsp;</span><span style="color: #0000ff;">implements</span><span style="color: #000000;">&nbsp;Serializable&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">private</span><span style="color: #000000;">&nbsp;Integer&nbsp;id;<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">private</span><span style="color: #000000;">&nbsp;String&nbsp;loginId;<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">private</span><span style="color: #000000;">&nbsp;String&nbsp;password;<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">private</span><span style="color: #000000;">&nbsp;String&nbsp;name;<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">private</span><span style="color: #000000;">&nbsp;String&nbsp;profile;<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">private</span><span style="color: #000000;">&nbsp;Date&nbsp;gmtCreated;<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">private</span><span style="color: #000000;">&nbsp;Date&nbsp;gmtModified;<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">private</span><span style="color: #000000;">&nbsp;String&nbsp;status;<br />
<br />
&nbsp;&nbsp;&nbsp; </span><span style="color: #008000;">//</span><span style="color: #008000;">getter/setters<img src="http://www.blogjava.net/Images/dot.gif" alt="" /></span><br />
<span style="color: #000000;">｝</span></div>
<br />
缺点：<br />
1）不直观，没人会知道status具体有哪些值。在缺乏文档，并且历史悠久的系统中，只能使用&#8220;select distinct(status) from member&#8221;，才能得到想要的数据。如果是在千万级数据中，代价太大了；<br />
2）类型不安全，如果有人不小心拼写错误，将会导致错误状态。假设上面列子中，status只允许ENABLED／DISABLED，如果一不小心，memberPO.setStatus("ENABLEDD"),那么将会造成脏数据。<br />
<br />
既然jdk5之后，引入了enum，是否可以让ibatis支持enum类型呢？事实上，最新的ibatis版本，已经支持enum类型（本文使用的是2.3.4.726版本－－mvn repsitory上最新的版本）。<br />
以上代码可以修改成：<br />
1）Status类：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; 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;">enum</span><span style="color: #000000;">&nbsp;Status&nbsp;{<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">/**</span><span style="color: #008000;">&nbsp;enabled&nbsp;</span><span style="color: #008000;">*/</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;ENABLED,<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">/**</span><span style="color: #008000;">&nbsp;disabled&nbsp;</span><span style="color: #008000;">*/</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;DISABLED;<br />
<br />
｝</span></div>
2）MemberPO类：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; 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;MemberPO&nbsp;</span><span style="color: #0000ff;">implements</span><span style="color: #000000;">&nbsp;Serializable&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">private</span><span style="color: #000000;">&nbsp;Integer&nbsp;id;<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">private</span><span style="color: #000000;">&nbsp;String&nbsp;loginId;<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">private</span><span style="color: #000000;">&nbsp;String&nbsp;password;<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">private</span><span style="color: #000000;">&nbsp;String&nbsp;name;<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">private</span><span style="color: #000000;">&nbsp;String&nbsp;profile;<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">private</span><span style="color: #000000;">&nbsp;Date&nbsp;gmtCreated;<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">private</span><span style="color: #000000;">&nbsp;Date&nbsp;gmtModified;<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">private</span><span style="color: #000000;">&nbsp;Status&nbsp;status;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">getter/setters<img src="http://www.blogjava.net/Images/dot.gif" alt="" /></span><span style="color: #008000;"><br />
</span><span style="color: #000000;">｝</span></div>
<br />
除此之外，其他均无需改动。<br />
为什么呢？ibatis如何知道VARCHAR／Enum的mapping呢？<br />
看过ibatis源码的同学，知道，ibatis是通过jdbcType/javaType得到对应的TypeHandler做mapping处理的。ibatis有基本类型的TypeHandler，比如StringTypeHandler,IntegerTypeHandler等等。在最新版本中，为了支持enum，增加了一个EnumTypeHandler。<br />
<br />
并且在TypeHandlerFactory中，加了对enum类型的判断，请看：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; 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;TypeHandler&nbsp;getTypeHandler(Class&nbsp;type,&nbsp;String&nbsp;jdbcType)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;Map&nbsp;jdbcHandlerMap&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;(Map)&nbsp;typeHandlerMap.get(type);<br />
&nbsp;&nbsp;&nbsp;&nbsp;TypeHandler&nbsp;handler&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">null</span><span style="color: #000000;">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(jdbcHandlerMap&nbsp;</span><span style="color: #000000;">!=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">null</span><span style="color: #000000;">)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;handler&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;(TypeHandler)&nbsp;jdbcHandlerMap.get(jdbcType);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(handler&nbsp;</span><span style="color: #000000;">==</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">null</span><span style="color: #000000;">)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;handler&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;(TypeHandler)&nbsp;jdbcHandlerMap.get(</span><span style="color: #0000ff;">null</span><span style="color: #000000;">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(handler&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;">&amp;&amp;</span><span style="color: #000000;">&nbsp;type&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;">&amp;&amp;</span><span style="color: #000000;">&nbsp;Enum.</span><span style="color: #0000ff;">class</span><span style="color: #000000;">.isAssignableFrom(type))&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;handler&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;EnumTypeHandler(type);<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;handler;<br />
&nbsp;&nbsp;}</span></div>
ibatis使用了取巧的方法，当取不到基本类型的handler时候，判断javaType是否是Enum类型－－<span style="color: #000000;">Enum.</span><span style="color: #0000ff;">class</span><span style="color: #000000;">.isAssignableFrom(type)，如果是，则使用</span><span style="color: #000000;"> EnumTypeHandler进行mapping处理。<br />
<br />
为什么说它取巧，原因是早期ibatis设计过程中，自定义的接口无法得到具体的java class type。故早期的ibatis中，要实现对enmu的支持，非常苦难。而新版本中，为了达到这个功能，作者直接修改了TypeHandlerFactory的实现，打了一个补丁，如下：<br />
</span>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(handler&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;">&amp;&amp;</span><span style="color: #000000;">&nbsp;type&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;">&amp;&amp;</span><span style="color: #000000;">&nbsp;Enum.</span><span style="color: #0000ff;">class</span><span style="color: #000000;">.isAssignableFrom(type))&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;handler&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;EnumTypeHandler(type);<br />
}</span></div>
这个设计有悖于和早前的设计思想。早期，TypeHandler都是通过public void register(Class type, String jdbcType, TypeHandler handler)方式事先注册到factory中的，而这次，是在运行期，通过new方法动态得到<span style="color: #000000;">EnumTypeHandler。<br />
当然，新版本ibatis能支持enum，已经是一件开心的事情了。<br />
<br />
Status枚举类除了描述状态，就足够了吗？回想起很多应用，我是做web开发的，在view层（velocity，jsp，等），见多了类似这样的代码：<br />
</span>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">#if($member.getStatus()==Status.ENABLED)开通#elseif($member.getStatus()==Status.DISABLED)关闭#end<br />
<br />
</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">select</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">option&nbsp;</span><span style="color: #ff0000;">value</span><span style="color: #0000ff;">="ENABLED"</span><span style="color: #ff0000;">&nbsp;#if($member.getStatus()</span><span style="color: #0000ff;">==Status.ENABLED)&nbsp;</span><span style="color: #ff0000;">selected</span><span style="color: #0000ff;">="selected"</span><span style="color: #ff0000;">#end&nbsp;</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;">开通</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">option</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">option&nbsp;</span><span style="color: #ff0000;">value</span><span style="color: #0000ff;">="DISABLED"</span><span style="color: #ff0000;">&nbsp;#if($member.getStatus()</span><span style="color: #0000ff;">==Status.DISABLED)&nbsp;</span><span style="color: #ff0000;">selected</span><span style="color: #0000ff;">="selected"</span><span style="color: #ff0000;">#end&nbsp;</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;">关闭</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">option</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">select</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
<br />
</span></div>
web层需要多少个页面，就需要维护多少份这样的代码；以后每添加／删除一种状态，多个地方都需要修改，还要担心逻辑不一致。<br />
<br />
而事实上，关于状态的信息描述，按照职责分，就应该由枚举类来维护：<br />
1）制定一个接口，<span style="color: #000000;">EnumDescription.java<br />
</span>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; 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;">interface</span><span style="color: #000000;">&nbsp;EnumDescription&nbsp;{<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;String&nbsp;getDescription();<br />
<br />
}</span></div>
2）写一个ResourceBundleUtil.java，通过Properties文件得到描述信息：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; 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;ResourceBundleUtil&nbsp;{<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">private</span><span style="color: #000000;">&nbsp;ResourceBundle&nbsp;resourceBundle;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;ResourceBundleUtil(String&nbsp;resource)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">this</span><span style="color: #000000;">.resourceBundle&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;ResourceBundle.getBundle(resource);<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;ResourceBundleUtil(String&nbsp;resource,&nbsp;Locale&nbsp;locale)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">this</span><span style="color: #000000;">.resourceBundle&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;ResourceBundle.getBundle(resource,&nbsp;locale);<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;String&nbsp;getProperty(String&nbsp;key)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;resourceBundle.getString(key);<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
}</span></div>
3）Status等枚举类实现<span style="color: #000000;">EnumDescription：<br />
</span>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; 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;">enum</span><span style="color: #000000;">&nbsp;Status&nbsp;</span><span style="color: #0000ff;">implements</span><span style="color: #000000;">&nbsp;EnumDescription&nbsp;{<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">/**</span><span style="color: #008000;">&nbsp;enabled&nbsp;</span><span style="color: #008000;">*/</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;ENABLED,<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">/**</span><span style="color: #008000;">&nbsp;disabled&nbsp;</span><span style="color: #008000;">*/</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;DISABLED;<br />
<br />
&nbsp;&nbsp;&nbsp;&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;ResourceBundleUtil&nbsp;util&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;ResourceBundleUtil(Status.</span><span style="color: #0000ff;">class</span><span style="color: #000000;">.getName());<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;String&nbsp;getDescription()&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;util.getProperty(</span><span style="color: #0000ff;">this</span><span style="color: #000000;">.toString());<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
}</span></div>
<br />
这样，有什么好处：<br />
1）通过Properties文件，支持国际化。<br />
2）描述信息统一由自己来维护，方便维护，并且显示层逻辑简化，如：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">$member.getStatus().getDescription()<br />
<br />
</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">select</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;#foreach($status&nbsp;in&nbsp;$Status.values())<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">option&nbsp;</span><span style="color: #ff0000;">value</span><span style="color: #0000ff;">="$status"</span><span style="color: #ff0000;">&nbsp;#if($member.getStatus()</span><span style="color: #0000ff;">==$status)selected="selected"#end&nbsp;</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;">$status.getDescription()</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">option</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;#end<br />
</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">select</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
</span></div>
<span style="color: #000000;"><br />
##############################################################################<br />
那么使用老版本ibatis的客户怎么办呢？就像我们公司使用ibatis 2.3.0，难道只能眼馋着？解决方案：<br />
1）升级到最新版本。 ：）<br />
2）ibatis提供了TypeHandler/TypeHandlerCallback接口，针对每种枚举类型，写相应的TypeHandler/TypeHandlerCallback的接口实现即可－－工作量大，重复的劳动力。<br />
主要是早期ibatis TypeHandler无法得到javaType类型，无法从jdbc value转成对应的枚举。在我看来，TypeHandler是作mapping用的，它至少有权知道javaType。<br />
3）实现伪枚举类型（允许继承）来实现状态类型安全，而抛弃jdk5的方式－－不方便日后升级。<br />
<br />
<br />
不知道大家是否还有更好的方案？<br />
<br />
本文涉及演示代码如下：<br />
</span><span style="color: #000000;"><a href="http://www.blogjava.net/Files/stone2083/java/ibatis-enum.zip" title="演示代码">演示代码</a><br />
workspace file encoding：utf-8<br />
build tool: maven<br />
repository:spring/2.5.5;ibatis/2.3.4.726</span><br />
<img src ="http://www.blogjava.net/stone2083/aggbug/238899.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/stone2083/" target="_blank">stone2083</a> 2008-11-05 23:08 <a href="http://www.blogjava.net/stone2083/archive/2008/11/05/238899.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ajax原理简介以及简单demo演示</title><link>http://www.blogjava.net/stone2083/archive/2008/09/21/230278.html</link><dc:creator>stone2083</dc:creator><author>stone2083</author><pubDate>Sun, 21 Sep 2008 11:05:00 GMT</pubDate><guid>http://www.blogjava.net/stone2083/archive/2008/09/21/230278.html</guid><wfw:comment>http://www.blogjava.net/stone2083/comments/230278.html</wfw:comment><comments>http://www.blogjava.net/stone2083/archive/2008/09/21/230278.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/stone2083/comments/commentRss/230278.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/stone2083/services/trackbacks/230278.html</trackback:ping><description><![CDATA[如今web应用上，ajax技术是大行其道。<br />
ajax框架层出不穷，prototype，dojo，jquery，mootools，dwr，buffalo，ext，yui，spry。。。<br />
ajax框架的出现，在提升开发生产效率的同时，也让不少同学不明其内在原理，仅仅成为了某些框架的使用者。<br />
（对于产品生产是好事，对于技术追求是坏事）<br />
<br />
本文不涉及任何ajax框架的使用，本文仅通过一个模拟需求，在不使用任何ajax框架的前提下，以demo演示的方式，<br />
向大家介绍ajax的原理以及应用场景。<br />
<br />
ajax全称是：<a title="AsynchronousJavaScript And XML " href="http://en.wikipedia.org/wiki/AJAX">Asynchronous JavaScript And XML。</a><br />
其本意是，通过javascript技术（JavaScript），通过异步http请求方式（Asynchronous），得到XML文本内容（XML）之后，通过javascript技术局部刷新web页面内容。<br />
从广义的概念看，只要符合&#8220;异步请求，局部刷新web页面&#8221;的技术，都可以成为ajax。<br />
未必一定要使用javascript，一般情况下，大多数client端脚本代码都可以；返回内容也未必一定要是xml，目前json格式，更为流行。<br />
<br />
如何异步请求内容呢？<br />
以javascript代码作演示，如下：<br />
<div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; 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);">function</span><span style="color: rgb(0, 0, 0);">&nbsp;xmlhttpPost(url,func)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">var</span><span style="color: rgb(0, 0, 0);">&nbsp;xmlHttpReq&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);">false</span><span style="color: rgb(0, 0, 0);">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">var</span><span style="color: rgb(0, 0, 0);">&nbsp;self&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);">this</span><span style="color: rgb(0, 0, 0);">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">&nbsp;Mozilla/Safari</span><span style="color: rgb(0, 128, 0);"><br />
</span><span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);">&nbsp;(window.XMLHttpRequest)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.xmlHttpReq&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;XMLHttpRequest();<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">&nbsp;IE</span><span style="color: rgb(0, 128, 0);"><br />
</span><span style="color: rgb(0, 0, 0);">&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;(window.ActiveXObject)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.xmlHttpReq&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;ActiveXObject(</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">Microsoft.XMLHTTP</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;self.xmlHttpReq.open('POST',&nbsp;url,&nbsp;</span><span style="color: rgb(0, 0, 255);">true</span><span style="color: rgb(0, 0, 0);">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;self.xmlHttpReq.setRequestHeader('Content</span><span style="color: rgb(0, 0, 0);">-</span><span style="color: rgb(0, 0, 0);">Type',&nbsp;'application</span><span style="color: rgb(0, 0, 0);">/</span><span style="color: rgb(0, 0, 0);">x</span><span style="color: rgb(0, 0, 0);">-</span><span style="color: rgb(0, 0, 0);">www</span><span style="color: rgb(0, 0, 0);">-</span><span style="color: rgb(0, 0, 0);">form</span><span style="color: rgb(0, 0, 0);">-</span><span style="color: rgb(0, 0, 0);">urlencoded');<br />
&nbsp;&nbsp;&nbsp;&nbsp;self.xmlHttpReq.onreadystatechange&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);">function</span><span style="color: rgb(0, 0, 0);">()&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;(self.xmlHttpReq.readyState&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);">4</span><span style="color: rgb(0, 0, 0);">)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;func(self.xmlHttpReq.responseText);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;self.xmlHttpReq.send(</span><span style="color: rgb(0, 0, 255);">null</span><span style="color: rgb(0, 0, 0);">);<br />
&nbsp;&nbsp;}</span></div>
参数一，url：表明异步请求的资源地址<br />
参数二，func：表明请求结束后，采用什么函数对请求结果内容进行回调处理<br />
<br />
其实，这一个js代码，就诠释了ajax的全部含义－－异步请求资源，将得到的资源内容，使用指定的function进行处理。<br />
所以，ajax很简单，大家千万别被如今层出不穷的ajax框架给吓怕了。要了解ajax的原理，就只要参看这段代码即可。<br />
如今的一些框架，仅仅在此基础上，是封装了一些公用的函数，方便开发人员调用。（当然，说说简单，其实所谓的这些函数，大大方便了开发人员使用ajax技术。具体请参看ajax framework的官方介绍。）<br />
<br />
特别说明：这个xmlhttpost方法改进了<a title="simple-ajax" href="http://www.degraeve.com/reference/simple-ajax-example.php">simple-ajax</a>。在原基础上，将回调方法作为参数传递。<br />
<br />
<br />
解释了原理性的内容之后，接下来，以一个模拟的应用场景，demo说明ajax的使用，以及它的主要应用场景。<br />
模拟场景：<br />
目录选择，即当选择一个目录的时候，需要显示这个目录下的所有子目录。<br />
<br />
首先，我们来虚拟一个目录结构，如下：<br />
<img alt="" src="http://www.blogjava.net/images/blogjava_net/stone2083/java/tree_node.png" height="245" width="184" /><br />
<br />
那么，要实现目录选择，有三个方式：<br />
1）页面初始化的时候，服务端将所有的目录信息都put到页面中。<br />
&nbsp;&nbsp; 优点：选择操作简单，有了全部的目录信息，做选择操作，都可以使用js完成，无需和服务端进行交互<br />
&nbsp;&nbsp; 缺点：当目录信息很大的时候，比如有上万个节点，整个目录信息有1m左右大小，那么要渲染这个页面，估计得20秒左右（视网速）<br />
并且，很可能用户仅仅只要选择有限的几个节点就可以，比如上万个节点中选择6－7个节点，那么浪费太大了；<br />
2）页面初始化的时候，服务端将当前需要的节点信息put到页面上，一旦有选择操作，重新刷新页面。<br />
&nbsp;&nbsp; 优点：选择操作简单，对于节点信息，每次取需要的内容，不存在浪费现象<br />
&nbsp;&nbsp; 缺点：每次都要刷新整个页面，除节点信息外，其他不变的东西都需要重新从服务端取，增加无谓的消耗。<br />
3）页面初始化的时候，服务端将当前需要的节点信息put到页面上，一旦有选择操作，只刷新节点相关的内容；<br />
&nbsp;&nbsp; 优点：每次只load需要的信息，局部刷新页面内容，不存在任何浪费现象<br />
&nbsp;&nbsp; 缺点：需要异步请求数据，每次请求都需要和服务器交互，选择操作稍显复杂（异步请求，局部刷新）<br />
<br />
通过这三种方式做对比，发现ajax主要适用的场景如下：<br />
1）整体内容量大（几百k，几m，甚至几十m），而页面只需要其中一小部分信息即可；<br />
2）数据显示，只涉及一个页面中部分数据信息的变动；<br />
<br />
特别说明：至于使用ajax性能如何，需要对1，3两个情况做性能测试，权衡使用。<br />
<br />
针对第三种方案，<br />
首先需要一个取节点资源的url，<br />
演示代码中，为了演示方便，使用php语言，而非使用主要语言java；<br />
tree_node.php<br />
<div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; 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);">&lt;?</span><span style="color: rgb(0, 0, 0);">php<br />
</span><span style="color: rgb(128, 0, 128);">$id</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;&nbsp;</span><span style="color: rgb(128, 0, 128);">$_GET</span><span style="color: rgb(0, 0, 0);">[</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">id</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">];&nbsp;<br />
</span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);">(</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">1</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;</span><span style="color: rgb(128, 0, 128);">$id</span><span style="color: rgb(0, 0, 0);">)&nbsp;{<br />
&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">echo</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);">"</span><span style="color: rgb(0, 0, 0);">id\</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">:1,\</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">parentId\</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">:-1,\</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">name\</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);">1</span><span style="color: rgb(0, 0, 0);">-</span><span style="color: rgb(0, 0, 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);">"</span><span style="color: rgb(0, 0, 0);">children\</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);">id\</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">:2,\</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">name\</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);">2</span><span style="color: rgb(0, 0, 0);">-</span><span style="color: rgb(0, 0, 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);">"</span><span style="color: rgb(0, 0, 0);">id\</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">:3,\</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">name\</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);">2</span><span style="color: rgb(0, 0, 0);">-</span><span style="color: rgb(0, 0, 0);">2</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);">"</span><span style="color: rgb(0, 0, 0);">id\</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">:4,\</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">name\</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);">2</span><span style="color: rgb(0, 0, 0);">-</span><span style="color: rgb(0, 0, 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);">"</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);">(</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">2</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;</span><span style="color: rgb(128, 0, 128);">$id</span><span style="color: rgb(0, 0, 0);">)&nbsp;{<br />
&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">echo</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);">"</span><span style="color: rgb(0, 0, 0);">id\</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">:2,\</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">parentId\</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">:1,\</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">name\</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);">2</span><span style="color: rgb(0, 0, 0);">-</span><span style="color: rgb(0, 0, 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);">"</span><span style="color: rgb(0, 0, 0);">children\</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 />
}&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);">(</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">3</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;</span><span style="color: rgb(128, 0, 128);">$id</span><span style="color: rgb(0, 0, 0);">)&nbsp;{<br />
&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">echo</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);">"</span><span style="color: rgb(0, 0, 0);">id\</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">:3,\</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">parentId\</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">:1,\</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">name\</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);">2</span><span style="color: rgb(0, 0, 0);">-</span><span style="color: rgb(0, 0, 0);">2</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);">"</span><span style="color: rgb(0, 0, 0);">children\</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 />
}&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);">(</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">4</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;</span><span style="color: rgb(128, 0, 128);">$id</span><span style="color: rgb(0, 0, 0);">)&nbsp;{<br />
&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">echo</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);">"</span><span style="color: rgb(0, 0, 0);">id\</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">:4,\</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">parentId\</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">:1,\</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">name\</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);">2</span><span style="color: rgb(0, 0, 0);">-</span><span style="color: rgb(0, 0, 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);">"</span><span style="color: rgb(0, 0, 0);">children\</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);">id\</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">:5,\</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">name\</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);">3</span><span style="color: rgb(0, 0, 0);">-</span><span style="color: rgb(0, 0, 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);">"</span><span style="color: rgb(0, 0, 0);">id\</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">:6,\</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">name\</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);">3</span><span style="color: rgb(0, 0, 0);">-</span><span style="color: rgb(0, 0, 0);">2</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);">"</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);">(</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">5</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;</span><span style="color: rgb(128, 0, 128);">$id</span><span style="color: rgb(0, 0, 0);">)&nbsp;{<br />
&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">echo</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);">"</span><span style="color: rgb(0, 0, 0);">id\</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">:5,\</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">parentId\</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">:4,\</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">name\</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);">3</span><span style="color: rgb(0, 0, 0);">-</span><span style="color: rgb(0, 0, 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);">"</span><span style="color: rgb(0, 0, 0);">children\</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 />
}&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);">(</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">6</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;</span><span style="color: rgb(128, 0, 128);">$id</span><span style="color: rgb(0, 0, 0);">)&nbsp;{<br />
&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">echo</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);">"</span><span style="color: rgb(0, 0, 0);">id\</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">:6,\</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">parentId\</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">:4,\</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">name\</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);">3</span><span style="color: rgb(0, 0, 0);">-</span><span style="color: rgb(0, 0, 0);">2</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);">"</span><span style="color: rgb(0, 0, 0);">children\</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);">id\</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">:7,\</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">name\</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);">4</span><span style="color: rgb(0, 0, 0);">-</span><span style="color: rgb(0, 0, 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);">"</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);">(</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">7</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;</span><span style="color: rgb(128, 0, 128);">$id</span><span style="color: rgb(0, 0, 0);">)&nbsp;{<br />
&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">echo</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);">"</span><span style="color: rgb(0, 0, 0);">id\</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">:7,\</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">parentId\</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">:6,\</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">name\</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);">4</span><span style="color: rgb(0, 0, 0);">-</span><span style="color: rgb(0, 0, 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);">"</span><span style="color: rgb(0, 0, 0);">children\</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 />
}&nbsp;</span><span style="color: rgb(0, 0, 255);">else</span><span style="color: rgb(0, 0, 0);">&nbsp;{<br />
&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">echo</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 />
}<br />
</span><span style="color: rgb(0, 0, 0);">?&gt;</span></div>
该文件中，写死了目录结构（一般情况下，往往根据树对象，动态取得需要的节点）。<br />
<br />
<br />
通过js，动态请求节点信息，部分刷新页面内容：<br />
<div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; 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;</span><span style="color: rgb(0, 0, 0);">&lt;</span><span style="color: rgb(0, 0, 0);">script&nbsp;type</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">text/javascript</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">&gt;</span><span style="color: rgb(0, 0, 0);"><br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">模拟需求js</span><span style="color: rgb(0, 128, 0);"><br />
</span><span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">var</span><span style="color: rgb(0, 0, 0);">&nbsp;nodeSelect&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);">function</span><span style="color: rgb(0, 0, 0);">(text)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">var</span><span style="color: rgb(0, 0, 0);">&nbsp;tree&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;toJsonObje(text);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">var</span><span style="color: rgb(0, 0, 0);">&nbsp;options&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;document.getElementById(</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">tree</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">).options;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;options.length&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;options.add(</span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);">&nbsp;Option(</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);">,</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">-1</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">));<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);">(tree&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;</span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);">;<br />
&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;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">var</span><span style="color: rgb(0, 0, 0);">&nbsp;children&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;tree.children;<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);">(i&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);">;&nbsp;i&nbsp;</span><span style="color: rgb(0, 0, 0);">&lt;</span><span style="color: rgb(0, 0, 0);">&nbsp;children.length;&nbsp;i</span><span style="color: rgb(0, 0, 0);">++</span><span style="color: rgb(0, 0, 0);">)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">var</span><span style="color: rgb(0, 0, 0);">&nbsp;child&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;children[i];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;options.add(</span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);">&nbsp;Option(child.name,child.id));<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);">(tree.parentId&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);">-1</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;options.add(</span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);">&nbsp;Option(</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);">,tree.parentId));<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;document.getElementById(</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">l</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">).innerHTML&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;tree.name;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">function</span><span style="color: rgb(0, 0, 0);">&nbsp;nodeSelectAjax(id)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">var</span><span style="color: rgb(0, 0, 0);">&nbsp;TREE_NODE_URL&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);">tree_node.php</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">var</span><span style="color: rgb(0, 0, 0);">&nbsp;url&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;TREE_NODE_URL&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);">?id=</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;id;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;xmlhttpPost(url,nodeSelect);<br />
&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 0);">&lt;/</span><span style="color: rgb(0, 0, 0);">script</span><span style="color: rgb(0, 0, 0);">&gt;</span></div>
nodeSelectAjax，异步请求节点资源<br />
<span style="color: rgb(0, 0, 0);">nodeSelect，回调函数，根据请求信息，局部刷新页面<br />
<br />
<br />
至于请求资源信息格式，任何方式都可以，只要client端能解析就行。<br />
目前json格式，比较流行。<br />
最后，附上java使用<a title="json" href="http://www.json.org/">json</a>库，生成json格式的方法：<br />
</span>
<div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; 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);">JSONObject&nbsp;node&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;JSONObject();<br />
node.put(</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">id</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);">1</span><span style="color: rgb(0, 0, 0);">);<br />
node.put(</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">parentId</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);">1</span><span style="color: rgb(0, 0, 0);">);<br />
node.put(</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">name</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);">1-1</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">);<br />
JSONArray&nbsp;children&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;JSONArray();<br />
JSONObject&nbsp;c1&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;JSONObject();<br />
c1.put(</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">id</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);">2</span><span style="color: rgb(0, 0, 0);">);<br />
c1.put(</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">name</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);">2-1</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">);<br />
JSONObject&nbsp;c2&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;JSONObject();<br />
c2.put(</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">id</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);">3</span><span style="color: rgb(0, 0, 0);">);<br />
c2.put(</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">name</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);">2-2</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">);<br />
children.put(c1);<br />
children.put(c2);<br />
node.put(</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">children</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">,&nbsp;children);<br />
System.out.println(node.toString());</span></div>
<br />
<br />
<br />
<span style="color: rgb(0, 0, 0);"><a href="/Files/stone2083/java/ajax.zip" title="ajax demo">ajax demo</a><br />
工程文件编码：utf－8<br />
工程运行：http server with php supported<br />
ubuntu firefox下测试通过<br />
<br />
<br />
其他：<br />
不知道是不是ie的bug，居然不支持 select.innerHTML = value的方式<br />
只能通过select.options.add(new Option("content","value") 动态往select中添加选项。<br />
<br />
</span>
<img src ="http://www.blogjava.net/stone2083/aggbug/230278.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/stone2083/" target="_blank">stone2083</a> 2008-09-21 19:05 <a href="http://www.blogjava.net/stone2083/archive/2008/09/21/230278.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>单元测试分享</title><link>http://www.blogjava.net/stone2083/archive/2008/07/17/215302.html</link><dc:creator>stone2083</dc:creator><author>stone2083</author><pubDate>Thu, 17 Jul 2008 14:04:00 GMT</pubDate><guid>http://www.blogjava.net/stone2083/archive/2008/07/17/215302.html</guid><wfw:comment>http://www.blogjava.net/stone2083/comments/215302.html</wfw:comment><comments>http://www.blogjava.net/stone2083/archive/2008/07/17/215302.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/stone2083/comments/commentRss/215302.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/stone2083/services/trackbacks/215302.html</trackback:ping><description><![CDATA[最近，在小组内部做了一次关于&#8220;单元测试&#8221;的分享。把自己两年来做单元测试遇到的问题和对单元测试的认识做了一次总结和讨论。<br />
<br />
本文不会详细地讲述分享的内容，仅仅是ppt的大纲显示：<br />
<span style="color: #0010ff;"><br />
使用单元测试前提：<br />
</span>最小的成本，换来最大的收益<br />
<span style="color: #0010ff;"><br />
单元测试目的</span>：<br />
1）测试代码错误(?) －－ 不是主要目的<br />
2）便于重构时的测试<br />
3）改善既有代码的设计<br />
<br />
<span style="color: #0010ff;">分享核心</span>：<br />
1）如何脱离&#8220;webx&#8220;－－做隔离测试<br />
2）dal／biz／web 层如何做单元测试<br />
3）如何通过改善代码设计，更方便测试<br />
<br />
<span style="color: #0010ff;">dal层</span><span style="color: #0010ff;">（数据库访问层）</span><span style="color: #0010ff;">特点：</span><br />
1)独立，逻辑单一，对表做操作<br />
2)业务相对比较稳定<br />
3)采用ibatis，写sql的方式<br />
<br />
<span style="color: #0010ff;">dal层测试方式</span>：<br />
1）压根儿就不需要测试<br />
2）仅仅配置spring bean，通过日志打印的方式（无法达到自检）<br />
3) 自检方式 -- AbstractTransactionalDataSourceSpringContextTests （高成本，不轻易使用）<br />
需要权衡<br />
<br />
<span style="color: #0010ff;">biz</span><span style="color: #0010ff;">层</span><span style="color: #0010ff;">（业务层）测试方式－－分BO和AO：<br />
BO：（即所谓的Service／Manager）<br />
AO：（一个UseCase对应的业务流）<br />
</span>隔离 ＋ 设计 （主要通过代码演示－－见附件）<br />
<br />
<span style="color: #0010ff;">单元测试的缺点</span>：<br />
专注于单一业务测试，衔接点容易出错<br />
<br />
<span style="color: #0010ff;">解决</span><span style="color: #0010ff;">方案</span>：<br />
接口输入输出明确<br />
集成测试<br />
<br />
<span style="color: #0010ff;">web层：<br />
</span>
集成测试的入口<br />
<br />
<a href="/Files/stone2083/java/webx_test.zip" title="分享文档和演示代码">分享文档和演示代码</a> （ppt是在ubuntu下制作，可能效果并不是很好）<br />
<br />
备注：<br />
自己对单元测试了解也比较肤浅，欢迎一起探讨<br />
<img src ="http://www.blogjava.net/stone2083/aggbug/215302.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/stone2083/" target="_blank">stone2083</a> 2008-07-17 22:04 <a href="http://www.blogjava.net/stone2083/archive/2008/07/17/215302.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>