﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-小程序员之歌-文章分类-Java基础</title><link>http://www.blogjava.net/tbest/category/32708.html</link><description>java先（我应该为它写点什么了！）</description><language>zh-cn</language><lastBuildDate>Wed, 04 May 2011 21:33:00 GMT</lastBuildDate><pubDate>Wed, 04 May 2011 21:33:00 GMT</pubDate><ttl>60</ttl><item><title>（转）reflect</title><link>http://www.blogjava.net/tbest/articles/349537.html</link><dc:creator>liujg</dc:creator><author>liujg</author><pubDate>Wed, 04 May 2011 15:16:00 GMT</pubDate><guid>http://www.blogjava.net/tbest/articles/349537.html</guid><wfw:comment>http://www.blogjava.net/tbest/comments/349537.html</wfw:comment><comments>http://www.blogjava.net/tbest/articles/349537.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/tbest/comments/commentRss/349537.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/tbest/services/trackbacks/349537.html</trackback:ping><description><![CDATA[<p align="center">&nbsp;</p>
<span style="color: rgb(0,0,255)">import</span><span style="color: rgb(0,0,0)">&nbsp;java.lang.reflect.Constructor;<br />
<br />
</span><span style="color: rgb(0,0,255)">import</span><span style="color: rgb(0,0,0)">&nbsp;java.lang.reflect.Field;<br />
<br />
</span><span style="color: rgb(0,0,255)">import</span><span style="color: rgb(0,0,0)">&nbsp;java.lang.reflect.Method;<br />
<br />
<br />
<br />
<br />
<br />
</span><span style="color: rgb(0,128,0)">/**</span><span style="color: rgb(0,128,0)"><br />
<br />
&nbsp;*&nbsp;Java&nbsp;Reflection&nbsp;Cookbook<br />
<br />
&nbsp;*<br />
<br />
&nbsp;*&nbsp;</span><span style="color: rgb(128,128,128)">@author</span><span style="color: rgb(0,128,0)">&nbsp;Michael&nbsp;Lee<br />
<br />
&nbsp;*&nbsp;</span><span style="color: rgb(128,128,128)">@since</span><span style="color: rgb(0,128,0)">&nbsp;2006-8-23<br />
<br />
&nbsp;*&nbsp;</span><span style="color: rgb(128,128,128)">@version</span><span style="color: rgb(0,128,0)">&nbsp;0.1a<br />
<br />
&nbsp;</span><span style="color: rgb(0,128,0)">*/</span><span style="color: rgb(0,0,0)"><br />
<br />
<br />
<br />
</span><span style="color: rgb(0,0,255)">public</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">class</span><span style="color: rgb(0,0,0)">&nbsp;Reflection&nbsp;{<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,128,0)">/**</span><span style="color: rgb(0,128,0)"><br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;得到某个对象的公共属性<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: rgb(128,128,128)">@param</span><span style="color: rgb(0,128,0)">&nbsp;owner,&nbsp;fieldName<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: rgb(128,128,128)">@return</span><span style="color: rgb(0,128,0)">&nbsp;该属性对象<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: rgb(128,128,128)">@throws</span><span style="color: rgb(0,128,0)">&nbsp;Exception<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,128,0)">*/</span><span style="color: rgb(0,0,0)"><br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">public</span><span style="color: rgb(0,0,0)">&nbsp;Object&nbsp;getProperty(Object&nbsp;owner,&nbsp;String&nbsp;fieldName)&nbsp;</span><span style="color: rgb(0,0,255)">throws</span><span style="color: rgb(0,0,0)">&nbsp;Exception&nbsp;{<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Class&nbsp;ownerClass&nbsp;</span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)">&nbsp;owner.getClass();<br />
<br />
<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Field&nbsp;field&nbsp;</span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)">&nbsp;ownerClass.getField(fieldName);<br />
<br />
<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Object&nbsp;property&nbsp;</span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)">&nbsp;field.get(owner);<br />
<br />
<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">return</span><span style="color: rgb(0,0,0)">&nbsp;property;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,128,0)">/**</span><span style="color: rgb(0,128,0)"><br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;得到某类的静态公共属性<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: rgb(128,128,128)">@param</span><span style="color: rgb(0,128,0)">&nbsp;className&nbsp;&nbsp;&nbsp;类名<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: rgb(128,128,128)">@param</span><span style="color: rgb(0,128,0)">&nbsp;fieldName&nbsp;&nbsp;&nbsp;属性名<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: rgb(128,128,128)">@return</span><span style="color: rgb(0,128,0)">&nbsp;该属性对象<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: rgb(128,128,128)">@throws</span><span style="color: rgb(0,128,0)">&nbsp;Exception<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,128,0)">*/</span><span style="color: rgb(0,0,0)"><br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">public</span><span style="color: rgb(0,0,0)">&nbsp;Object&nbsp;getStaticProperty(String&nbsp;className,&nbsp;String&nbsp;fieldName)<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">throws</span><span style="color: rgb(0,0,0)">&nbsp;Exception&nbsp;{<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Class&nbsp;ownerClass&nbsp;</span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)">&nbsp;Class.forName(className);<br />
<br />
<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Field&nbsp;field&nbsp;</span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)">&nbsp;ownerClass.getField(fieldName);<br />
<br />
<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Object&nbsp;property&nbsp;</span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)">&nbsp;field.get(ownerClass);<br />
<br />
<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">return</span><span style="color: rgb(0,0,0)">&nbsp;property;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
<br />
<br />
<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,128,0)">/**</span><span style="color: rgb(0,128,0)"><br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;执行某对象方法<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: rgb(128,128,128)">@param</span><span style="color: rgb(0,128,0)">&nbsp;owner<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;对象<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: rgb(128,128,128)">@param</span><span style="color: rgb(0,128,0)">&nbsp;methodName<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;方法名<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: rgb(128,128,128)">@param</span><span style="color: rgb(0,128,0)">&nbsp;args<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;参数<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: rgb(128,128,128)">@return</span><span style="color: rgb(0,128,0)">&nbsp;方法返回值<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: rgb(128,128,128)">@throws</span><span style="color: rgb(0,128,0)">&nbsp;Exception<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,128,0)">*/</span><span style="color: rgb(0,0,0)"><br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">public</span><span style="color: rgb(0,0,0)">&nbsp;Object&nbsp;invokeMethod(Object&nbsp;owner,&nbsp;String&nbsp;methodName,&nbsp;Object[]&nbsp;args)<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">throws</span><span style="color: rgb(0,0,0)">&nbsp;Exception&nbsp;{<br />
<br />
<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Class&nbsp;ownerClass&nbsp;</span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)">&nbsp;owner.getClass();<br />
<br />
<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Class[]&nbsp;argsClass&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;Class[args.length];<br />
<br />
<br />
<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)">&nbsp;(</span><span style="color: rgb(0,0,255)">int</span><span style="color: rgb(0,0,0)">&nbsp;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;j&nbsp;</span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)">&nbsp;args.length;&nbsp;i&nbsp;</span><span style="color: rgb(0,0,0)">&lt;</span><span style="color: rgb(0,0,0)">&nbsp;j;&nbsp;i</span><span style="color: rgb(0,0,0)">++</span><span style="color: rgb(0,0,0)">)&nbsp;{<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;argsClass[i]&nbsp;</span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)">&nbsp;args[i].getClass();<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Method&nbsp;method&nbsp;</span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)">&nbsp;ownerClass.getMethod(methodName,&nbsp;argsClass);<br />
<br />
<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">return</span><span style="color: rgb(0,0,0)">&nbsp;method.invoke(owner,&nbsp;args);<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
<br />
<br />
<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,128,0)">/**</span><span style="color: rgb(0,128,0)"><br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;执行某类的静态方法<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: rgb(128,128,128)">@param</span><span style="color: rgb(0,128,0)">&nbsp;className<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;类名<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: rgb(128,128,128)">@param</span><span style="color: rgb(0,128,0)">&nbsp;methodName<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;方法名<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: rgb(128,128,128)">@param</span><span style="color: rgb(0,128,0)">&nbsp;args<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;参数数组<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: rgb(128,128,128)">@return</span><span style="color: rgb(0,128,0)">&nbsp;执行方法返回的结果<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: rgb(128,128,128)">@throws</span><span style="color: rgb(0,128,0)">&nbsp;Exception<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,128,0)">*/</span><span style="color: rgb(0,0,0)"><br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">public</span><span style="color: rgb(0,0,0)">&nbsp;Object&nbsp;invokeStaticMethod(String&nbsp;className,&nbsp;String&nbsp;methodName,<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Object[]&nbsp;args)&nbsp;</span><span style="color: rgb(0,0,255)">throws</span><span style="color: rgb(0,0,0)">&nbsp;Exception&nbsp;{<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Class&nbsp;ownerClass&nbsp;</span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)">&nbsp;Class.forName(className);<br />
<br />
<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Class[]&nbsp;argsClass&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;Class[args.length];<br />
<br />
<br />
<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)">&nbsp;(</span><span style="color: rgb(0,0,255)">int</span><span style="color: rgb(0,0,0)">&nbsp;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;j&nbsp;</span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)">&nbsp;args.length;&nbsp;i&nbsp;</span><span style="color: rgb(0,0,0)">&lt;</span><span style="color: rgb(0,0,0)">&nbsp;j;&nbsp;i</span><span style="color: rgb(0,0,0)">++</span><span style="color: rgb(0,0,0)">)&nbsp;{<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;argsClass[i]&nbsp;</span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)">&nbsp;args[i].getClass();<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Method&nbsp;method&nbsp;</span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)">&nbsp;ownerClass.getMethod(methodName,&nbsp;argsClass);<br />
<br />
<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">return</span><span style="color: rgb(0,0,0)">&nbsp;method.invoke(</span><span style="color: rgb(0,0,255)">null</span><span style="color: rgb(0,0,0)">,&nbsp;args);<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,128,0)">/**</span><span style="color: rgb(0,128,0)"><br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;新建实例<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: rgb(128,128,128)">@param</span><span style="color: rgb(0,128,0)">&nbsp;className<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;类名<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: rgb(128,128,128)">@param</span><span style="color: rgb(0,128,0)">&nbsp;args<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;构造函数的参数<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: rgb(128,128,128)">@return</span><span style="color: rgb(0,128,0)">&nbsp;新建的实例<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: rgb(128,128,128)">@throws</span><span style="color: rgb(0,128,0)">&nbsp;Exception<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,128,0)">*/</span><span style="color: rgb(0,0,0)"><br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">public</span><span style="color: rgb(0,0,0)">&nbsp;Object&nbsp;newInstance(String&nbsp;className,&nbsp;Object[]&nbsp;args)&nbsp;</span><span style="color: rgb(0,0,255)">throws</span><span style="color: rgb(0,0,0)">&nbsp;Exception&nbsp;{<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Class&nbsp;newoneClass&nbsp;</span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)">&nbsp;Class.forName(className);<br />
<br />
<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Class[]&nbsp;argsClass&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;Class[args.length];<br />
<br />
<br />
<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)">&nbsp;(</span><span style="color: rgb(0,0,255)">int</span><span style="color: rgb(0,0,0)">&nbsp;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;j&nbsp;</span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)">&nbsp;args.length;&nbsp;i&nbsp;</span><span style="color: rgb(0,0,0)">&lt;</span><span style="color: rgb(0,0,0)">&nbsp;j;&nbsp;i</span><span style="color: rgb(0,0,0)">++</span><span style="color: rgb(0,0,0)">)&nbsp;{<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;argsClass[i]&nbsp;</span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)">&nbsp;args[i].getClass();<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Constructor&nbsp;cons&nbsp;</span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)">&nbsp;newoneClass.getConstructor(argsClass);<br />
<br />
<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">return</span><span style="color: rgb(0,0,0)">&nbsp;cons.newInstance(args);<br />
<br />
<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
<br />
<br />
<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,128,0)">/**</span><span style="color: rgb(0,128,0)"><br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;是不是某个类的实例<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: rgb(128,128,128)">@param</span><span style="color: rgb(0,128,0)">&nbsp;obj&nbsp;实例<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: rgb(128,128,128)">@param</span><span style="color: rgb(0,128,0)">&nbsp;cls&nbsp;类<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: rgb(128,128,128)">@return</span><span style="color: rgb(0,128,0)">&nbsp;如果&nbsp;obj&nbsp;是此类的实例，则返回&nbsp;true<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,128,0)">*/</span><span style="color: rgb(0,0,0)"><br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">public</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">boolean</span><span style="color: rgb(0,0,0)">&nbsp;isInstance(Object&nbsp;obj,&nbsp;Class&nbsp;cls)&nbsp;{<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">return</span><span style="color: rgb(0,0,0)">&nbsp;cls.isInstance(obj);<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,128,0)">/**</span><span style="color: rgb(0,128,0)"><br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;得到数组中的某个元素<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: rgb(128,128,128)">@param</span><span style="color: rgb(0,128,0)">&nbsp;array&nbsp;数组<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: rgb(128,128,128)">@param</span><span style="color: rgb(0,128,0)">&nbsp;index&nbsp;索引<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: rgb(128,128,128)">@return</span><span style="color: rgb(0,128,0)">&nbsp;返回指定数组对象中索引组件的值<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,128,0)">*/</span><span style="color: rgb(0,0,0)"><br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">public</span><span style="color: rgb(0,0,0)">&nbsp;Object&nbsp;getByArray(Object&nbsp;array,&nbsp;</span><span style="color: rgb(0,0,255)">int</span><span style="color: rgb(0,0,0)">&nbsp;index)&nbsp;{<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">return</span><span style="color: rgb(0,0,0)">&nbsp;Array.get(array,index);<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
}</span><br />
<img src ="http://www.blogjava.net/tbest/aggbug/349537.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/tbest/" target="_blank">liujg</a> 2011-05-04 23:16 <a href="http://www.blogjava.net/tbest/articles/349537.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>面试基础题目</title><link>http://www.blogjava.net/tbest/articles/349532.html</link><dc:creator>liujg</dc:creator><author>liujg</author><pubDate>Wed, 04 May 2011 14:24:00 GMT</pubDate><guid>http://www.blogjava.net/tbest/articles/349532.html</guid><wfw:comment>http://www.blogjava.net/tbest/comments/349532.html</wfw:comment><comments>http://www.blogjava.net/tbest/articles/349532.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/tbest/comments/commentRss/349532.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/tbest/services/trackbacks/349532.html</trackback:ping><description><![CDATA[<div style="border-bottom-style: none; padding-bottom: 15px; border-right-style: none; margin: 20px 0px; padding-left: 15px; padding-right: 15px; border-left-style: none; border-top: #ccc 1px dotted; padding-top: 15px" class="blogzz_abstract borderc">
<div style="margin-bottom: 12px" class="blogzz_ainfo"><span style="margin-right: 25px"><strong><span style="margin-right: 25px"><strong></strong></span>原文地址：</strong><a title="华为Java面试题集第二部分:编程题" href="http://blog.sina.com.cn/s/blog_4a3ada4d0100d3vb.html" target="_blank">华为Java面试题集第二部分:编程题</a></span><span><strong>作者：</strong><a title="向前走（范新灿）" href="http://blog.sina.com.cn/u/1245370957" target="_blank">向前走（范新灿）</a></span></div>
<div class="blogzz_acon">1．现在输入n个数字，以逗号，分开；<br />
然后可选择升或者降序排序；<br />
按提交键就在另一页面显示<br />
&nbsp;<wbr>&nbsp;<wbr>按什么排序，结果为，&nbsp;<wbr>&nbsp;<wbr>，<br />
提供reset<br />
答案（1）&nbsp;<wbr>&nbsp;<wbr>public static String[] splitStringByComma(String source){<br />
&nbsp;<wbr> &nbsp;<wbr>&nbsp;<wbr> &nbsp;<wbr>&nbsp;<wbr> &nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>if(source==null||source.trim().equals(""))<br />
&nbsp;<wbr> &nbsp;<wbr>&nbsp;<wbr> &nbsp;<wbr>&nbsp;<wbr> &nbsp;<wbr>&nbsp;<wbr> &nbsp;<wbr>&nbsp;<wbr> &nbsp;<wbr>&nbsp;<wbr> &nbsp;<wbr> return null;<br />
&nbsp;<wbr> &nbsp;<wbr>&nbsp;<wbr> &nbsp;<wbr>&nbsp;<wbr> &nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>StringTokenizer commaToker =&nbsp;<wbr>&nbsp;<wbr>new StringTokenizer(source,",");<br />
&nbsp;<wbr> &nbsp;<wbr>&nbsp;<wbr> &nbsp;<wbr>&nbsp;<wbr> &nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>String[] result = new String[commaToker.countTokens()];<br />
&nbsp;<wbr> &nbsp;<wbr>&nbsp;<wbr> &nbsp;<wbr>&nbsp;<wbr> &nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>int i=0;<br />
&nbsp;<wbr> &nbsp;<wbr>&nbsp;<wbr> &nbsp;<wbr>&nbsp;<wbr> &nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>while(commaToker.hasMoreTokens()){<br />
&nbsp;<wbr> &nbsp;<wbr>&nbsp;<wbr> &nbsp;<wbr>&nbsp;<wbr> &nbsp;<wbr>&nbsp;<wbr> &nbsp;<wbr>&nbsp;<wbr> &nbsp;<wbr>&nbsp;<wbr> &nbsp;<wbr> result[i] = commaToker.nextToken();<br />
&nbsp;<wbr> &nbsp;<wbr>&nbsp;<wbr> &nbsp;<wbr>&nbsp;<wbr> &nbsp;<wbr>&nbsp;<wbr> &nbsp;<wbr>&nbsp;<wbr> &nbsp;<wbr>&nbsp;<wbr> &nbsp;<wbr> i++;<br />
&nbsp;<wbr> &nbsp;<wbr>&nbsp;<wbr> &nbsp;<wbr>&nbsp;<wbr> &nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>}<br />
&nbsp;<wbr> &nbsp;<wbr>&nbsp;<wbr> &nbsp;<wbr>&nbsp;<wbr> &nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>return result;<br />
&nbsp;<wbr>&nbsp;<wbr>}<br />
循环遍历String数组<br />
Integer.parseInt(String s)变成int类型<br />
组成int数组<br />
Arrays.sort(int[] a),<br />
a数组升序<br />
降序可以从尾部开始输出<br />
<br />
2．金额转换，阿拉伯数字的金额转换成中国传统的形式如：<br />
（￥1011）－&gt;（一千零一拾一元整）输出。<br />
3、继承时候类的执行顺序问题,一般都是选择题,问你将会打印出什么?<br />
答:父类：<br />
package test;<br />
public class FatherClass<br />
{<br />
public FatherClass()<br />
{<br />
System.out.println("FatherClass Create");<br />
}<br />
}<br />
子类:<br />
package test;<br />
import test.FatherClass;<br />
public class ChildClass extends FatherClass<br />
{<br />
public ChildClass()<br />
{<br />
System.out.println("ChildClass Create");<br />
}<br />
public static void main(String[] args)<br />
{<br />
FatherClass fc = new FatherClass();<br />
ChildClass cc = new ChildClass();<br />
}<br />
}<br />
输出结果：<br />
C:&gt;java test.ChildClass<br />
FatherClass Create<br />
FatherClass Create<br />
ChildClass Create<br />
<br />
4、内部类的实现方式?<br />
答：示例代码如下：<br />
package test;<br />
public class OuterClass<br />
{<br />
** class InterClass<br />
{<br />
public InterClass()<br />
{<br />
System.out.println("InterClass Create");<br />
}<br />
}<br />
public OuterClass()<br />
{<br />
InterClass ic = new InterClass();<br />
System.out.println("OuterClass Create");<br />
}<br />
public static void main(String[] args)<br />
{<br />
OuterClass oc = new OuterClass();<br />
}<br />
}<br />
输出结果:<br />
C:&gt;java test/OuterClass<br />
InterClass Create<br />
OuterClass Create<br />
再一个例题：<br />
public class OuterClass {<br />
** double d1 = 1.0;<br />
//insert code here<br />
}<br />
You need to insert an inner class declaration at line 3. Which two inner class declarations are<br />
<br />
valid?(Choose two.)<br />
A. class InnerOne{<br />
public static double methoda() {return d1;}<br />
}<br />
B. public class InnerOne{<br />
static double methoda() {return d1;}<br />
}<br />
C. ** class InnerOne{<br />
double methoda() {return d1;}<br />
}<br />
D. static class InnerOne{<br />
protected double methoda() {return d1;}<br />
}<br />
E. abstract class InnerOne{<br />
public abstract double methoda();<br />
}<br />
说明如下：<br />
一.静态内部类可以有静态成员，而非静态内部类则不能有静态成员。 故 A、B 错<br />
二.静态内部类的非静态成员可以访问外部类的静态变量，而不可访问外部类的非静态变量；return d1 出错。<br />
<br />
故 D 错<br />
三.非静态内部类的非静态成员可以访问外部类的非静态变量。 故 C 正确<br />
四.答案为C、E<br />
<br />
<br />
5、Java 的通信编程，编程题(或问答)，用JAVA SOCKET编程，读服务器几个字符，再写入本地显示？<br />
答:Server端程序:<br />
package test;<br />
import java.net.*;<br />
import java.io.*;<br />
public class Server<br />
{<br />
** ServerSocket ss;<br />
** Socket socket;<br />
** BufferedReader in;<br />
** PrintWriter out;<br />
public Server()<br />
{<br />
try<br />
{<br />
ss=new ServerSocket(10000);<br />
while(true)<br />
{<br />
socket = ss.accept();<br />
String RemoteIP = socket.getInetAddress().getHostAddress();<br />
String RemotePort = ":"+socket.getLocalPort();<br />
System.out.println("A client come in!IP:"+RemoteIP+RemotePort);<br />
in = new BufferedReader(new<br />
<br />
InputStreamReader(socket.getInputStream()));<br />
String line = in.readLine();<br />
System.out.println("Cleint send is :" + line);<br />
out = new PrintWriter(socket.getOutputStream(),true);<br />
out.println("Your Message Received!");<br />
out.close();<br />
in.close();<br />
socket.close();<br />
}<br />
}catch (IOException e)<br />
{<br />
out.println("wrong");<br />
}<br />
}<br />
public static void main(String[] args)<br />
{<br />
new Server();<br />
}<br />
};<br />
Client端程序:<br />
package test;<br />
import java.io.*;<br />
import java.net.*;<br />
<br />
public class Client<br />
{<br />
Socket socket;<br />
BufferedReader in;<br />
PrintWriter out;<br />
public Client()<br />
{<br />
try<br />
{<br />
System.out.println("Try to Connect to 127.0.0.1:10000");<br />
socket = new Socket("127.0.0.1",10000);<br />
System.out.println("The Server Connected!");<br />
System.out.println("Please enter some Character:");<br />
BufferedReader line = new BufferedReader(new<br />
<br />
InputStreamReader(System.in));<br />
out = new PrintWriter(socket.getOutputStream(),true);<br />
out.println(line.readLine());<br />
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));<br />
System.out.println(in.readLine());<br />
out.close();<br />
in.close();<br />
socket.close();<br />
}catch(IOException e)<br />
{<br />
out.println("Wrong");<br />
}<br />
}<br />
public static void main(String[] args)<br />
{<br />
new Client();<br />
}<br />
};<br />
6、用JAVA实现一种排序，JAVA类实现序列化的方法(二种)？如在COLLECTION框架中，实现比较要实现什么样的接口？<br />
答:用插入法进行排序代码如下<br />
package test;<br />
import java.util.*;<br />
class InsertSort<br />
{<br />
ArrayList al;<br />
public InsertSort(int num,int mod)<br />
{<br />
al = new ArrayList(num);<br />
Random rand = new Random();<br />
System.out.println("The ArrayList Sort Before:");<br />
for (int i=0;i&lt;num ;i++ )<br />
{<br />
al.add(new Integer(Math.abs(rand.nextInt()) % mod + 1));<br />
System.out.println("al["+i+"]="+al.get(i));<br />
}<br />
}<br />
public void SortIt()<br />
{<br />
Integer tempInt;<br />
int MaxSize=1;<br />
for(int i=1;i&lt;al.size();i++)<br />
{<br />
tempInt = (Integer)al.remove(i);<br />
if(tempInt.intValue()&gt;=((Integer)al.get(MaxSize-1)).intValue())<br />
{<br />
al.add(MaxSize,tempInt);<br />
MaxSize++;<br />
System.out.println(al.toString());<br />
} else {<br />
for (int j=0;j&lt;MaxSize ;j++ )<br />
{<br />
if<br />
<br />
(((Integer)al.get(j)).intValue()&gt;=tempInt.intValue())<br />
{<br />
al.add(j,tempInt);<br />
MaxSize++;<br />
System.out.println(al.toString());<br />
break;<br />
}<br />
}<br />
}<br />
}<br />
System.out.println("The ArrayList Sort After:");<br />
for(int i=0;i&lt;al.size();i++)<br />
{<br />
System.out.println("al["+i+"]="+al.get(i));<br />
}<br />
}<br />
public static void main(String[] args)<br />
{<br />
InsertSort is = new InsertSort(10,100);<br />
is.SortIt();<br />
}<br />
}<br />
JAVA类实现序例化的方法是实现java.io.Serializable接口<br />
Collection框架中实现比较要实现Comparable 接口和 Comparator 接口<br />
7、编程：编写一个截取字符串的函数，输入为一个字符串和字节数，输出为按字节截取的字符串。但是要保证汉字不被截半个，如"我ABC"4，应该截为"我AB"，输入"我ABC汉DEF"，6，应该输出为"我ABC"而不是"我ABC+汉的半个"。<br />
答：代码如下：<br />
package test;<br />
<br />
class SplitString<br />
{<br />
String SplitStr;<br />
int SplitByte;<br />
public SplitString(String str,int bytes)<br />
{<br />
SplitStr=str;<br />
SplitByte=bytes;<br />
System.out.println("The String is:&#8242;"+SplitStr+"&#8242;;SplitBytes="+SplitByte);<br />
}<br />
public void SplitIt()<br />
{<br />
int loopCount;<br />
loopCount=(SplitStr.length()%SplitByte==0)?(SplitStr.length()/SplitByte):(SplitStr.length()/Split<br />
Byte+1);<br />
System.out.println("Will Split into "+loopCount);<br />
for (int i=1;i&lt;=loopCount ;i++ )<br />
{<br />
if (i==loopCount){<br />
System.out.println(SplitStr.substring((i-1)*SplitByte,SplitStr.length()));<br />
} else {<br />
System.out.println(SplitStr.substring((i-1)*SplitByte,(i*SplitByte)));<br />
}<br />
}<br />
}<br />
public static void main(String[] args)<br />
{<br />
SplitString ss = new SplitString("test中dd文dsaf中男大3443n中国43中国人<br />
<br />
0ewldfls=103",4);<br />
ss.SplitIt();<br />
}<br />
}<br />
8、JAVA多线程编程。 用JAVA写一个多线程程序，如写四个线程，二个加1，二个对一个变量减一，输出。<br />
希望大家补上，谢谢<br />
9、STRING与STRINGBUFFER的区别。<br />
答：STRING的长度是不可变的，STRINGBUFFER的长度是可变的。如果你对字符串中的内容经常进行操作，特别是内容要修改时，那么使用StringBuffer，如果最后需要String，那么使用StringBuffer的toString()方法<br />
Jsp方面<br />
1、jsp有哪些内置对象?作用分别是什么?<br />
答:JSP共有以下9种基本内置组件（可与ASP的6种内部组件相对应）：<br />
　request 用户端请求，此请求会包含来自GET/POST请求的参数<br />
response 网页传回用户端的回应<br />
pageContext 网页的属性是在这里管理<br />
session 与请求有关的会话期<br />
application servlet 正在执行的内容<br />
out 用来传送回应的输出<br />
config servlet的构架部件<br />
page JSP网页本身<br />
exception 针对错误网页，未捕捉的例外<br />
2、jsp有哪些动作?作用分别是什么?<br />
答:JSP共有以下6种基本动作<br />
jsp:include：在页面被请求的时候引入一个文件。<br />
jsp:useBean：寻找或者实例化一个JavaBean。<br />
jsp:setProperty：设置JavaBean的属性。<br />
jsp:getProperty：输出某个JavaBean的属性。<br />
jsp:forward：把请求转到一个新的页面。<br />
jsp:plugin：根据浏览器类型为Java插件生成OBJECT或EMBED标记<br />
3、JSP中动态INCLUDE与静态INCLUDE的区别？<br />
答：动态INCLUDE用jsp:include动作实现<br />
&lt;jsp:include page="included.jsp" flush="true" /&gt;它总是会检查所含文件中的变化，适合用于包含动态页面，并且可以带参数<br />
静态INCLUDE用include伪码实现,定不会检查所含文件的变化，适用于包含静态页面<br />
&lt;%@ include file="included.htm" %&gt;<br />
4、两种跳转方式分别是什么?有什么区别?<br />
答：有两种，分别为：<br />
&lt;jsp:include page="included.jsp" flush="true"&gt;<br />
&lt;jsp:forward page= "nextpage.jsp"/&gt;<br />
前者页面不会转向include所指的页面，只是显示该页的结果，主页面还是原来的页面。执行完后还会回来，相当于函数调用。并且可以带参数.后者完全转向新页面，不会再回来。相当于go to 语句。<br />
Servlet方面<br />
1、说一说Servlet的生命周期?<br />
答:servlet有良好的生存期的定义，包括加载和实例化、初始化、处理请求以及服务结束。这个生存期由javax.servlet.Servlet接口的init,service和destroy方法表达。<br />
2、Servlet版本间(忘了问的是哪两个版本了)的不同?<br />
希望大家补上，谢谢<br />
3、JAVA SERVLET API中forward() 与redirect()的区别？<br />
答:前者仅是容器中控制权的转向，在客户端浏览器地址栏中不会显示出转向后的地址；后者则是完全的跳转，浏览器将会得到跳转的地址，并重新发送请求链接。这样，从浏览器的地址栏中可以看到跳转后的链接地址。所以，前者更加高效，在前者可以满足需要时，尽量使用forward()方法，并且，这样也有助于隐藏实际的链接。在有些情况下，比如，需要跳转到一个其它服务器上的资源，则必须使用sendRedirect()方法。<br />
4、Servlet的基本架构<br />
public class ServletName extends HttpServlet {<br />
public void doPost(HttpServletRequest request, HttpServletResponse response) throws<br />
ServletException, IOException {<br />
}<br />
public void doGet(HttpServletRequest request, HttpServletResponse response) throws<br />
ServletException, IOException {<br />
}<br />
}<br />
<br />
Jdbc、Jdo方面<br />
1、可能会让你写一段Jdbc连Oracle的程序,并实现数据查询.<br />
答:程序如下：<br />
package hello.ant;<br />
import java.sql.*;<br />
public class jdbc<br />
{<br />
String dbUrl="jdbc:oracle:thin:@127.0.0.1:1521:orcl";<br />
String theUser="admin";<br />
String thePw="manager";<br />
Connection c=null;<br />
Statement conn;<br />
ResultSet rs=null;<br />
public jdbc()<br />
{<br />
try{<br />
Class.forName("oracle.jdbc.driver.OracleDriver").newInstance();<br />
c = DriverManager.getConnection(dbUrl,theUser,thePw);<br />
conn=c.createStatement();<br />
}catch(Exception e){<br />
e.printStackTrace();<br />
}<br />
}<br />
public boolean executeUpdate(String sql)<br />
{<br />
try<br />
{<br />
conn.executeUpdate(sql);<br />
return true;<br />
}<br />
catch (SQLException e)<br />
{<br />
e.printStackTrace();<br />
return false;<br />
}<br />
}<br />
public ResultSet executeQuery(String sql)<br />
{<br />
rs=null;<br />
try<br />
{<br />
rs=conn.executeQuery(sql);<br />
}<br />
catch (SQLException e)<br />
{<br />
e.printStackTrace();<br />
}<br />
return rs;<br />
}<br />
public void close()<br />
{<br />
try<br />
{<br />
conn.close();<br />
c.close();<br />
}<br />
catch (Exception e)<br />
{<br />
e.printStackTrace();<br />
}<br />
}<br />
public static void main(String[] args)<br />
{<br />
ResultSet rs;<br />
jdbc conn = new jdbc();<br />
rs=conn.executeQuery("select * from test");<br />
try{<br />
while (rs.next())<br />
{<br />
System.out.println(rs.getString("id"));<br />
System.out.println(rs.getString("name"));<br />
}<br />
}catch(Exception e)<br />
{<br />
e.printStackTrace();<br />
}<br />
}<br />
}<br />
2、Class.forName的作用?为什么要用?<br />
答：调用该访问返回一个以字符串指定类名的类的对象。<br />
3、Jdo是什么?<br />
答:JDO是Java对象持久化的新的规范，为java data object的简称,也是一个用于存取某种数据仓库中的对象的标准化API。JDO提供了透明的对象存储，因此对开发人员来说，存储数据对象完全不需要额外的代码（如JDBC API的使用）。这些繁琐的例行工作已经转移到JDO产品提供商身上，使开发人员解脱出来，从而集中时间和精力在业务逻辑上。另外，JDO很灵活，因为它可以在任何数据底层上运行。JDBC只是面向关系数据库（RDBMS)JDO更通用，提供到任何数据底层的存储功能，比如关系数据库、文件、XML以及对象数据库（ODBMS）等等，使得应用可移植性更强。<br />
4、在ORACLE大数据量下的分页解决方法。一般用截取ID方法，还有是三层嵌套方法。<br />
答:一种分页方法<br />
&lt;%<br />
int i=1;<br />
int numPages=14;<br />
String pages = request.getParameter("page") ;<br />
int currentPage = 1;<br />
currentPage=(pages==null)?(1):{Integer.parseInt(pages)}<br />
sql = "select count(*) from tables";<br />
ResultSet rs = DBLink.executeQuery(sql) ;<br />
while(rs.next()) i = rs.getInt(1) ;<br />
int intPageCount=1;<br />
intPageCount=(i%numPages==0)?(i/numPages):(i/numPages+1);<br />
int nextPage ;<br />
int upPage;<br />
nextPage = currentPage+1;<br />
if (nextPage&gt;=intPageCount) nextPage=intPageCount;<br />
upPage = currentPage-1;<br />
if (upPage&lt;=1) upPage=1;<br />
rs.close();<br />
sql="select * from tables";<br />
rs=DBLink.executeQuery(sql);<br />
i=0;<br />
while((i&lt;numPages*(currentPage-1))&amp;&amp;rs.next()){i++;}<br />
%&gt;<br />
//输出内容<br />
//输出翻页连接<br />
合计:&lt;%=currentPage%&gt;/&lt;%=intPageCount%&gt;&lt;a href="List.jsp?page=1"&gt;第一页&lt;/a&gt;&lt;a<br />
<br />
href="List.jsp?page=&lt;%=upPage%&gt;"&gt;上一页&lt;/a&gt;<br />
&lt;%<br />
for(int j=1;j&lt;=intPageCount;j++){<br />
if(currentPage!=j){<br />
%&gt;<br />
&lt;a href="list.jsp?page=&lt;%=j%&gt;"&gt;[&lt;%=j%&gt;]&lt;/a&gt;<br />
&lt;%<br />
}else{<br />
out.println(j);<br />
}<br />
}<br />
%&gt;<br />
&lt;a href="List.jsp?page=&lt;%=nextPage%&gt;"&gt;下一页&lt;/a&gt;&lt;a href="List.jsp?page=&lt;%=intPageCount%&gt;"&gt;最后页<br />
<br />
&lt;/a&gt;<br />
Xml方面<br />
1、xml有哪些解析技术?区别是什么?<br />
答:有DOM,SAX,STAX等<br />
DOM:处理大型文件时其性能下降的非常厉害。这个问题是由DOM的树结构所造成的，这种结构占用的内存较多，而且DOM必须在解析文件之前把整个文档装入内存,适合对XML的随机访问SAX:不现于DOM,SAX是事件驱动型的XML解析方式。它顺序读取XML文件，不需要一次全部装载整个文件。当遇到像文件开头，文档结束，或者标签开头与标签结束时，它会触发一个事件，用户通过在其回调事件中写入处理代码来处理XML文件，适合对XML的顺序访问<br />
STAX:Streaming API for XML (StAX)<br />
2、你在项目中用到了xml技术的哪些方面?如何实现的?<br />
答:用到了数据存贮，信息配置两方面。在做数据交换平台时，将不能数据源的数据组装成XML文件，然后将XML文件压缩打包加密后通过网络传送给接收者，接收解密与解压缩后再同XML文件中还原相关信息进行处理。在做软件配置时，利用XML可以很方便的进行，软件的各种配置参数都存贮在XML文件中。<br />
3、用jdom解析xml文件时如何解决中文问题?如何解析?<br />
答:看如下代码,用编码方式加以解决<br />
package test;<br />
import java.io.*;<br />
public class DOMTest<br />
{<br />
** String inFile = "c:people.xml";<br />
** String outFile = "c:people.xml";<br />
public static void main(String args[])<br />
{<br />
new DOMTest();<br />
}<br />
public DOMTest()<br />
{<br />
try<br />
{<br />
javax.xml.parsers.DocumentBuilder builder =<br />
javax.xml.parsers.DocumentBuilderFactory.newInstance().newDocumentBuilder();<br />
org.w3c.dom.Document doc = builder.newDocument();<br />
org.w3c.dom.Element root = doc.createElement("老师");<br />
org.w3c.dom.Element wang = doc.createElement("王");<br />
org.w3c.dom.Element liu = doc.createElement("刘");<br />
wang.appendChild(doc.createTextNode("我是王老师"));<br />
root.appendChild(wang);<br />
doc.appendChild(root);<br />
javax.xml.transform.Transformer transformer =<br />
javax.xml.transform.TransformerFactory.newInstance().newTransformer();<br />
transformer.setOutputProperty(javax.xml.transform.OutputKeys.ENCODING, "gb2312");<br />
transformer.setOutputProperty(javax.xml.transform.OutputKeys.INDENT, "yes");<br />
<br />
<br />
transformer.transform(new javax.xml.transform.dom.DOMSource(doc),<br />
new<br />
<br />
javax.xml.transform.stream.StreamResult(outFile));<br />
}<br />
catch (Exception e)<br />
{<br />
System.out.println (e.getMessage());<br />
}<br />
}<br />
}<br />
4、编程用JAVA解析XML的方式.<br />
答:用SAX方式解析XML，XML文件如下：<br />
&lt;?xml version="1.0" encoding="gb2312"?&gt;<br />
&lt;person&gt;<br />
&lt;name&gt;王小明&lt;/name&gt;<br />
&lt;college&gt;信息学院&lt;/college&gt;<br />
&lt;telephone&gt;6258113&lt;/telephone&gt;<br />
&lt;notes&gt;男,1955年生,博士，95年调入海南大学&lt;/notes&gt;<br />
&lt;/person&gt;<br />
事件回调类SAXHandler.java<br />
import java.io.*;<br />
import java.util.Hashtable;<br />
import org.xml.sax.*;<br />
public class SAXHandler extends HandlerBase<br />
{<br />
** Hashtable table = new Hashtable();<br />
** String currentElement = null;<br />
** String currentValue = null;<br />
public void setTable(Hashtable table)<br />
{<br />
this.table = table;<br />
}<br />
public Hashtable getTable()<br />
{<br />
return table;<br />
}<br />
public void startElement(String tag, AttributeList attrs)<br />
throws SAXException<br />
{<br />
currentElement = tag;<br />
}<br />
public void characters(char[] ch, int start, int length)<br />
throws SAXException<br />
{<br />
currentValue = new String(ch, start, length);<br />
}<br />
public void endElement(String name) throws SAXException<br />
{<br />
if (currentElement.equals(name))<br />
table.put(currentElement, currentValue);<br />
}<br />
}<br />
JSP内容显示源码,SaxXml.jsp:<br />
&lt;HTML&gt;<br />
&lt;HEAD&gt;<br />
&lt;TITLE&gt;剖析XML文件people.xml&lt;/TITLE&gt;<br />
&lt;/HEAD&gt;<br />
&lt;BODY&gt;<br />
&lt;%@ page errorPage="ErrPage.jsp"<br />
c %&gt;<br />
&lt;%@ page import="java.io.*" %&gt;<br />
&lt;%@ page import="java.util.Hashtable" %&gt;<br />
&lt;%@ page import="org.w3c.dom.*" %&gt;<br />
&lt;%@ page import="org.xml.sax.*" %&gt;<br />
&lt;%@ page import="javax.xml.parsers.SAXParserFactory" %&gt;<br />
&lt;%@ page import="javax.xml.parsers.SAXParser" %&gt;<br />
&lt;%@ page import="SAXHandler" %&gt;<br />
&lt;%<br />
File file = new File("c:people.xml");<br />
FileReader reader = new FileReader(file);<br />
Parser parser;<br />
SAXParserFactory spf = SAXParserFactory.newInstance();<br />
SAXParser sp = spf.newSAXParser();<br />
SAXHandler handler = new SAXHandler();<br />
sp.parse(new InputSource(reader), handler);<br />
Hashtable hashTable = handler.getTable();<br />
out.println("&lt;TABLE BORDER=2&gt;&lt;CAPTION&gt;教师信息表&lt;/CAPTION&gt;");<br />
out.println("&lt;TR&gt;&lt;TD&gt;姓名&lt;/TD&gt;" + "&lt;TD&gt;" +<br />
(String)hashTable.get(new String("name")) + "&lt;/TD&gt;&lt;/TR&gt;");<br />
out.println("&lt;TR&gt;&lt;TD&gt;学院&lt;/TD&gt;" + "&lt;TD&gt;" +<br />
(String)hashTable.get(new String("college"))+"&lt;/TD&gt;&lt;/TR&gt;");<br />
out.println("&lt;TR&gt;&lt;TD&gt;电话&lt;/TD&gt;" + "&lt;TD&gt;" +<br />
(String)hashTable.get(new String("telephone")) + "&lt;/TD&gt;&lt;/TR&gt;");<br />
out.println("&lt;TR&gt;&lt;TD&gt;备注&lt;/TD&gt;" + "&lt;TD&gt;" +<br />
(String)hashTable.get(new String("notes")) + "&lt;/TD&gt;&lt;/TR&gt;");<br />
out.println("&lt;/TABLE&gt;");<br />
%&gt;<br />
&lt;/BODY&gt;<br />
&lt;/HTML&gt;</div>
</div>
<img src ="http://www.blogjava.net/tbest/aggbug/349532.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/tbest/" target="_blank">liujg</a> 2011-05-04 22:24 <a href="http://www.blogjava.net/tbest/articles/349532.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>(转)读HTTP协议（RFC-2616）总结</title><link>http://www.blogjava.net/tbest/articles/321307.html</link><dc:creator>liujg</dc:creator><author>liujg</author><pubDate>Tue, 18 May 2010 13:31:00 GMT</pubDate><guid>http://www.blogjava.net/tbest/articles/321307.html</guid><wfw:comment>http://www.blogjava.net/tbest/comments/321307.html</wfw:comment><comments>http://www.blogjava.net/tbest/articles/321307.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/tbest/comments/commentRss/321307.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/tbest/services/trackbacks/321307.html</trackback:ping><description><![CDATA[<h3><a href="/blog/391812">读HTTP协议（RFC-2616）总结</a></h3>
<h3><br />
http://ayufox.javaeye.com/blog/391812</h3>
<p>关键字: http rest </p>
<div class="blog_content">
<p><span style="font-size: small">1.资源(Resource)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 什么是资源，首先我们看《架构风格与基于网络的软件架构设计》的作者：Roy Thomas Fielding对资源的一个说明<br />
</span></p>
<div class="quote_title"><span style="font-size: small">Roy Thomas Fielding 写道</span> </div>
<div class="quote_div"><span style="font-size: small">REST对于信息的核心抽象是资源。任何能够被命名的信息都能够作为一个资源：一份文档或一张图片、一个暂时性的服务（例如，&#8220;洛杉矶今日的天气&#8221;）、一个其他资源的集合、一个非虚拟的对象（例如，人）等等。换句话说，任何可能作为一个创作者的超文本引用的目标的概念都必须符合资源的定义。一个资源是到一组实体的概念上的映射，而不是在任何特定时刻与该映射相关联的实体本身。<br />
更精确地说，资源R是一个随时间变化的成员函数MR(t)，该函数将时间t映射到等价的一个实体或值的集合，集合中的值可能是资源的表现和/或资源的标识符。一个资源可以映射到空集，这允许在一个概念的任何实现存在之前引用这个概念——这一观念对于Web之前的大多数超文本系统来说比较陌生 [61]。一些资源在它们被创建后的任何时刻来检查，它们都对应着相同的值的集合，从这个意义上说它们是静态的。其他的资源所对应的值则会随时间而频繁地变化。对于一个资源来说，唯一必须是静态的是映射的语义，因为语义才是区别资源的关键。</span> </div>
<p><span style="font-size: small">&nbsp;</span> <span style="font-size: small">&nbsp;&nbsp;&nbsp;&nbsp; 简而言之，资源是一个抽象的东西，而在具体资源访问时，会根据内容协商的结果表示成一个具体表述(Representations)。每个资源由统一的资源标识符(URI)来描述，类似于资源的ID，或者说资源的地址。<br />
2.表述(Representations)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 表述是资源的具体表现形式，譬如，今天深圳的天气（资源），可以使用一副天气jpg图来描述，也可以XML数据来描述，也可以使用HTML的页面来描述，一种资源可以有多种表述，也就是说，通过同一个URI地址可以获取到多种表现形式，而具体怎么表现，则取决于Web客户端与Web服务端内容协商的一个结果。<br />
3.内容协商<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 客户端和服务端通过内容协商来协商请求内容和响应内容的格式，主要协商的内容包括：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 请求协商：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1)字符集(Accept-Charset)：客户端通过发送该协商建议服务端使用该字符集来发送响应结果，譬如<br />
Accept-Charset=gb2312,utf-8;q=0.7,*;q=0.7，客户端建议服务端优先使用gb2312或者utf-8来发送响应结果<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2)请求编码(Accept-Encoding)：客户端告诉服务端客户端所支持的编码格式，譬如Accept-Encoding&nbsp;&nbsp; =gzip,deflate表明客户端支持gzip压缩或者普通响应的结果<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 3)语言(Accept-Language)：客户端通过发送该协商告诉服务端客户端所使用的语言，譬如Accept-Language=zh-cn,zh;q=0.5表明客户端偏号的语言是中文，譬如对于&#8221;今天深圳的天气&#8220;这个资源来说，服务端可以通过该选项决定使用什么语言来表述资源<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 4)表述偏好(Accept)：客户端通过该选项告诉服务端其表述的偏号，譬如一个请求&#8221;今天深圳的天气&#8220;的Ajax程序，可以通过设置表述偏好为Accept=application/json来告诉服务端，希望得到Json描述的结果，而一个浏览器则可以通过传输表述偏好为Accept=text/html来告诉服务端，希望得到Html描述的结果<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 响应协商：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1)表述/表述字符集(Content-Type)：服务端通过该协商告诉客户端表述的格式和字符集的情况，譬如Content-Type=text/html; charset=utf-8表示响应内容格式为Html，字符集为utf-8<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2)表述编码(Accept-Encoding)：服务端通过该协商告诉客户端表述的编码，譬如Content-Encoding=gzip服务端告诉客户端内容使用gzip压缩<br />
4.方法<br />
&nbsp;&nbsp;&nbsp;&nbsp; 方法定义了对资源的操作，主要的方法包括GET、POST、UPDATE、DELETE等等，它们分别代表了对资源的读、建、改、删的操作<br />
5.缓存<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; HTTP协议支持在Web的各个节点对资源的表述进行缓存，譬如在浏览器客户端、代理服务器、反向代理服务器、目标服务器等上对表述进行缓存（注意，此处的缓存不仅仅是指在目标服务器上进行的业务级别的缓存）<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1)客户端请求<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 如果客户端缓存了某些表述，则在进行读请求(GET)时，携带请求条件(所谓的条件GET，使用Cache-Control指令)，服务端接收到客户端的请求条件，比较确认客户端的表述是否过时，如果没有，则返回304响应，否则则把最新的表述响应给客户端<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2)服务端响应<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 服务端对一些需要缓存的表述，则响应中携带缓存指令，告诉请求客户端如何对表述进行缓存<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 3)方法对缓存的影响<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 当对一个资源进行UPDATE或DELETE时，请求途经的所有服务器（如代理服务器、反向代理服务器、目标服务器）会自动将该资源对应的<strong><span style="color: #ff0000">所有表述</span> </strong>缓存失效。<br />
6.状态码<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 状态码描述了资源请求的结果，主要状态码包括：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1)1XX：信息类<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2)2XX：成功类<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 典型的成功响应包括：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 200 OK，表示请求正常处理<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 201 Created，表示POST请求已经接受，资源已创建，对于此响应，一般响应会携带新建资源的Reference给请求客户端<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 202 Accepted，表示POST/UDATE请求已经接受，但不一定处理，譬如对于POST/UPDATE请求为后台新建线程处理，可以使用该响应码<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 3)3XX: 重定向类<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 典型的重定向响应包括： <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 300 Multiple Choice：表明请求的资源有多种表述<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 301 Moved Permenently：表明所请求的资源已转移到其他位置，建议到新的位置上去请求资源<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 304 Not Modify：主要是针对携带条件的GET请求，服务端向客户端表明所请求的资源没有发生变化，可以继续使用客户端已缓存的数据<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 4)4XX: 客户端错误类<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 典型的客户端错误响应包括：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 400 Bad Request：表明客户端的请求格式服务端无法识别<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 403 Forbiden：客户端要访问的资源权限受限，不允许访问<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 404 Not found：客户端要访问的资源不存在<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 405 Method Not Allowed：客户端请求的方法不允许，譬如有可能一个资源不允许删除，则不允许进行DELETE请求<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 408 Request Timeout：请求超时<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 5)5XX: 服务端错误类<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 典型的服务端响应包括：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 500 Internal Server Error：服务器内部错误，无法响应<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 503 Service Unavailable：服务器无法处理当前请求<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 504 Gateway Timeout：网关超时</span> <br />
<br />
<br />
</p>
</div>
<img src ="http://www.blogjava.net/tbest/aggbug/321307.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/tbest/" target="_blank">liujg</a> 2010-05-18 21:31 <a href="http://www.blogjava.net/tbest/articles/321307.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>(转) 用JAVA 实现“生产者－消费者”问题</title><link>http://www.blogjava.net/tbest/articles/321107.html</link><dc:creator>liujg</dc:creator><author>liujg</author><pubDate>Sun, 16 May 2010 11:03:00 GMT</pubDate><guid>http://www.blogjava.net/tbest/articles/321107.html</guid><wfw:comment>http://www.blogjava.net/tbest/comments/321107.html</wfw:comment><comments>http://www.blogjava.net/tbest/articles/321107.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/tbest/comments/commentRss/321107.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/tbest/services/trackbacks/321107.html</trackback:ping><description><![CDATA[<p>生产者和消费者问题是从操作系统中的许多实际同步问题中抽象出来的具有 <br />
代表性的问题。它反映了操作系统中典型的同步例子。 </p>
<p>　　生产者进程(进程由多个线程组成)生产信息，例如它可以是计算进程。消费 <br />
者进程使用信息，它可以是输出打印进程。由于生产者和消费者彼此独立，且运 <br />
行速度不确定，所以很可能出现生产者已产生了信息而消费者却没有来得及接受 <br />
信息这种情况。为此，需要引入由一个或者若干个存储单元组成的临时存储区， <br />
以便存放生产者所产生的信息，平滑进程间由于速度不确定所带来的问题。这个 <br />
临时存储区叫做缓冲区，通常用一维数组来表示。 </p>
<p>　　由一个或若干个存储单元组成的缓冲区叫作&#8220;有穷缓冲区&#8221;。下面我们来分 <br />
析一下有穷缓冲的生产者和消费者的例子。 </p>
<p>　　假设有多个生产者和多个消费者，它们共享一个具有n个存储单元的有穷缓冲 <br />
区Buffer(0&#8230;&#8230;n-1)，这是一个环形队列。其队尾指针Rear指向当前信息应存放 <br />
的位置(Buffer[Rear])，队首指针Front指向当前取出信息的位置(Buffer[front <br />
])。生产者进程总是把信息存放在Buffer[Rear]中，消费者进程则总是从Buffer <br />
[Rear]中取出信息。如果想使生产者进程和消费者进程协调合作，则必须使它们 <br />
遵循如下规则: </p>
<p>　　1) 只要缓冲区有存储单元，生产者都可往其中存放信息；当缓冲区已满时， <br />
若任意生产者提出写要求，则都必须等待； </p>
<p>　　2) 只要缓冲区中有消息可取，消费者都可从缓冲区中取出消息；当缓冲区为 <br />
空时，若任意消费者想取出信息，则必须等待； </p>
<p>　　3) 生产者们和消费者们不能同时读、写缓冲区。 </p>
<p>　　用JAVA 实现&#8220;生产者－消费者&#8221;问题的代码如下: </p>
<p>public class ProducerConsumer {<br />
&nbsp;public static void main(String[] args) {<br />
&nbsp; SyncStack ss = new SyncStack();<br />
&nbsp; Producer p = new Producer(ss);<br />
&nbsp; Consumer c = new Consumer(ss);<br />
&nbsp; new Thread(p).start();<br />
&nbsp; new Thread(p).start();<br />
&nbsp; new Thread(p).start();<br />
&nbsp; new Thread(c).start();<br />
&nbsp;}<br />
}</p>
<p>class WoTou {<br />
&nbsp;int id; <br />
&nbsp;WoTou(int id) {<br />
&nbsp; this.id = id;<br />
&nbsp;}<br />
&nbsp;public String toString() {<br />
&nbsp; return "WoTou : " + id;<br />
&nbsp;}<br />
}</p>
<p>class SyncStack {<br />
&nbsp;int index = 0;<br />
&nbsp;WoTou[] arrWT = new WoTou[6];<br />
&nbsp;<br />
&nbsp;public synchronized void push(WoTou wt) {<br />
&nbsp; while(index == arrWT.length) {<br />
&nbsp;&nbsp; try {<br />
&nbsp;&nbsp;&nbsp; this.wait();<br />
&nbsp;&nbsp; } catch (InterruptedException e) {<br />
&nbsp;&nbsp;&nbsp; e.printStackTrace();<br />
&nbsp;&nbsp; }<br />
&nbsp; }<br />
&nbsp; this.notifyAll();&nbsp; <br />
&nbsp; arrWT[index] = wt;<br />
&nbsp; index ++;<br />
&nbsp;}<br />
&nbsp;<br />
&nbsp;public synchronized WoTou pop() {<br />
&nbsp; while(index == 0) {<br />
&nbsp;&nbsp; try {<br />
&nbsp;&nbsp;&nbsp; this.wait();<br />
&nbsp;&nbsp; } catch (InterruptedException e) {<br />
&nbsp;&nbsp;&nbsp; e.printStackTrace();<br />
&nbsp;&nbsp; }<br />
&nbsp; }<br />
&nbsp; this.notifyAll();<br />
&nbsp; index--;<br />
&nbsp; return arrWT[index];<br />
&nbsp;}<br />
}</p>
<p>class Producer implements Runnable {<br />
&nbsp;SyncStack ss = null;<br />
&nbsp;Producer(SyncStack ss) {<br />
&nbsp; this.ss = ss;<br />
&nbsp;}<br />
&nbsp;<br />
&nbsp;public void run() {<br />
&nbsp; for(int i=0; i&lt;20; i++) {<br />
&nbsp;&nbsp; WoTou wt = new WoTou(i);<br />
&nbsp;&nbsp; ss.push(wt);<br />
System.out.println("生产了：" + wt);<br />
&nbsp;&nbsp; try {<br />
&nbsp;&nbsp;&nbsp; Thread.sleep((int)(Math.random() * 200));<br />
&nbsp;&nbsp; } catch (InterruptedException e) {<br />
&nbsp;&nbsp;&nbsp; e.printStackTrace();<br />
&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp; }<br />
&nbsp;}<br />
}</p>
<p>class Consumer implements Runnable {<br />
&nbsp;SyncStack ss = null;<br />
&nbsp;Consumer(SyncStack ss) {<br />
&nbsp; this.ss = ss;<br />
&nbsp;}<br />
&nbsp;<br />
&nbsp;public void run() {<br />
&nbsp; for(int i=0; i&lt;20; i++) {<br />
&nbsp;&nbsp; WoTou wt = ss.pop();<br />
System.out.println("消费了: " + wt);<br />
&nbsp;&nbsp; try {<br />
&nbsp;&nbsp;&nbsp; Thread.sleep((int)(Math.random() * 1000));<br />
&nbsp;&nbsp; } catch (InterruptedException e) {<br />
&nbsp;&nbsp;&nbsp; e.printStackTrace();<br />
&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp; }<br />
&nbsp;}<br />
} </p>
<p>生产者消费者问题是研究多线程程序时绕不开的问题，它的描述是有一块生产者和消费者共享的有界缓冲区，生产者往缓冲区放入产品，消费者从缓冲区取走产品，这个过程可以无休止的执行，不能因缓冲区满生产者放不进产品而终止，也不能因缓冲区空消费者无产品可取而终止。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 解决生产者消费者问题的方法有两种，一种是采用某种机制保持生产者和消费者之间的同步，一种是在生产者和消费者之间建立一个管道。前一种有较高的效率并且可控制性较好，比较常用，后一种由于管道缓冲区不易控制及被传输数据对象不易封装等原因，比较少用。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 同步问题的核心在于，CPU是按时间片轮询的方式执行程序，我们无法知道某一个线程是否被执行、是否被抢占、是否结束等，因此生产者完全可能当缓冲区已满的时候还在放入产品，消费者也完全可能当缓冲区为空时还在取出产品。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 现在同步问题的解决方法一般是采用信号或者加锁机制，即生产者线程当缓冲区已满时放弃自己的执行权，进入等待状态，并通知消费者线程执行。消费者线程当缓冲区已空时放弃自己的执行权，进入等待状态，并通知生产者线程执行。这样一来就保持了线程的同步，并避免了线程间互相等待而进入死锁状态。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; JAVA语言提供了独立于平台的线程机制，保持了&#8221;write once, run anywhere&#8221;的特色。同时也提供了对同步机制的良好支持。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在JAVA中，一共有四种方法支持同步，其中三个是同步方法，一个是管道方法。<br />
1.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 方法wait()/notify()<br />
2.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 方法await()/signal()<br />
3.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 阻塞队列方法BlockingQueue<br />
4.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 管道方法PipedInputStream/PipedOutputStream<br />
下面我们看各个方法的实现：<br />
1.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 方法wait()/notify()<br />
wait()和notify()是根类Object的两个方法，也就意味着所有的JAVA类都会具有这个两个方法，为什么会被这样设计呢？我们可以认为所有的对象默认都具有一个锁，虽然我们看不到，也没有办法直接操作，但它是存在的。<br />
wait()方法表示：当缓冲区已满或空时，生产者或消费者线程停止自己的执行，放弃锁，使自己处于等待状态，让另一个线程开始执行；<br />
notify()方法表示：当生产者或消费者对缓冲区放入或取出一个产品时，向另一个线程发出可执行通知，同时放弃锁，使自己处于等待状态。<br />
下面是一个例子代码：<br />
import java.util.LinkedList;</p>
<p>public class Sycn1...{<br />
&nbsp;&nbsp;&nbsp; private LinkedList&lt;Object&gt; myList =new LinkedList&lt;Object&gt;();<br />
&nbsp;&nbsp;&nbsp; private int MAX = 10;<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; public Sycn1()...{<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; public void start()...{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; new Producer().start();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; new Consumer().start();<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; public static void main(String[] args) throws Exception...{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Sycn1 s1 = new Sycn1();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; s1.start();<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; class Producer extends Thread...{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public void run()...{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while(true)...{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; synchronized(myList)...{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try...{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while(myList.size() == MAX)...{<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; System.out.println("warning: it's full!");<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; myList.wait();<br />
&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; Object o = new Object();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(myList.add(o))...{<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; System.out.println("Producer: " + o);<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; myList.notify();<br />
&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; }catch(InterruptedException ie)...{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("producer is interrupted!");<br />
&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; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; class Consumer extends Thread...{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public void run()...{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while(true)...{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; synchronized(myList)...{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try...{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while(myList.size() == 0)...{<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; System.out.println("warning: it's empty!");<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; myList.wait();<br />
&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; Object o = myList.removeLast();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("Consumer: " + o);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; myList.notify();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }catch(InterruptedException ie)...{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("consumer is interrupted!");<br />
&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; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; <br />
}<br />
2.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 方法await()/signal()<br />
在JDK5.0以后，JAVA提供了新的更加健壮的线程处理机制，包括了同步、锁定、线程池等等，它们可以实现更小粒度上的控制。await()和signal()就是其中用来做同步的两种方法，它们的功能基本上和wait()/notify()相同，完全可以取代它们，但是它们和新引入的锁定机制Lock直接挂钩，具有更大的灵活性。<br />
下面是一个例子代码：<br />
import java.util.LinkedList;</p>
<p>import java.util.concurrent.locks.*;</p>
<p>public class Sycn2...{<br />
&nbsp;&nbsp;&nbsp; private LinkedList&lt;Object&gt; myList = new LinkedList&lt;Object&gt;();<br />
&nbsp;&nbsp;&nbsp; private int MAX = 10;<br />
&nbsp;&nbsp;&nbsp; private final Lock lock = new ReentrantLock();<br />
&nbsp;&nbsp;&nbsp; private final Condition full = lock.newCondition();<br />
&nbsp;&nbsp;&nbsp; private final Condition empty = lock.newCondition();<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; public Sycn2()...{<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; public void start()...{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; new Producer().start();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; new Consumer().start();<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; public static void main(String[] args) throws Exception...{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Sycn2 s2 = new Sycn2();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; s2.start();<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; class Producer extends Thread...{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public void run()...{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while(true)...{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; lock.lock();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try...{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while(myList.size() == MAX)...{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("warning: it's full!");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; full.await();<br />
&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; Object o = new Object();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(myList.add(o))...{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("Producer: " + o);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; empty.signal();<br />
&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; }catch(InterruptedException ie)...{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("producer is interrupted!");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }finally...{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; lock.unlock();<br />
&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; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; class Consumer extends Thread...{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public void run()...{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while(true)...{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; lock.lock();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try...{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while(myList.size() == 0)...{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("warning: it's empty!");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; empty.await();<br />
&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; Object o = myList.removeLast();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("Consumer: " + o);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; full.signal();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }catch(InterruptedException ie)...{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("consumer is interrupted!");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }finally...{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; lock.unlock();<br />
&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; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; <br />
}<br />
3.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 阻塞队列方法BlockingQueue<br />
BlockingQueue也是JDK5.0的一部分，它是一个已经在内部实现了同步的队列，实现方式采用的是我们的第2种await()/signal()方法。它可以在生成对象时指定容量大小。<br />
它用于阻塞操作的是put()和take()方法。<br />
put()方法类似于我们上面的生产者线程，容量最大时，自动阻塞。<br />
take()方法类似于我们上面的消费者线程，容量为0时，自动阻塞。<br />
下面是一个例子代码：<br />
import java.util.concurrent.*;</p>
<p>public class Sycn3...{<br />
&nbsp;&nbsp;&nbsp; private LinkedBlockingQueue&lt;Object&gt; queue = new LinkedBlockingQueue&lt;Object&gt;(10);<br />
&nbsp;&nbsp;&nbsp; private int MAX = 10;<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; public Sycn3()...{<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; public void start()...{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; new Producer().start();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; new Consumer().start();<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; public static void main(String[] args) throws Exception...{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Sycn3 s3 = new Sycn3();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; s3.start();<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; class Producer extends Thread...{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public void run()...{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while(true)...{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //synchronized(this){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try...{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(queue.size() == MAX)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("warning: it's full!");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Object o = new Object();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; queue.put(o);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("Producer: " + o);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }catch(InterruptedException e)...{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("producer is interrupted!");<br />
&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; //}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; class Consumer extends Thread...{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public void run()...{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while(true)...{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //synchronized(this){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try...{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(queue.size() == 0)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("warning: it's empty!");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Object o = queue.take();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("Consumer: " + o);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }catch(InterruptedException e)...{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("producer is interrupted!");<br />
&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; //}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; <br />
}<br />
你发现这个例子中的问题了吗？<br />
如果没有，我建议你运行一下这段代码，仔细观察它的输出，是不是有下面这个样子的？为什么会这样呢？<br />
&#8230;<br />
warning: it's full!<br />
Producer: java.lang.object@4526e2a<br />
&#8230;<br />
你可能会说这是因为put()和System.out.println()之间没有同步造成的，我也这样认为，我也这样认为，但是你把run()中的synchronized前面的注释去掉，重新编译运行，有改观吗？没有。为什么？<br />
这是因为，当缓冲区已满，生产者在put()操作时，put()内部调用了await()方法，放弃了线程的执行，然后消费者线程执行，调用take()方法，take()内部调用了signal()方法，通知生产者线程可以执行，致使在消费者的println()还没运行的情况下生产者的println()先被执行，所以有了上面的输出。run()中的synchronized其实并没有起什么作用。<br />
对于BlockingQueue大家可以放心使用，这可不是它的问题，只是在它和别的对象之间的同步有问题。<br />
对于这种多重嵌套同步的问题，以后再谈吧，欢迎大家讨论啊！<br />
4.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 管道方法PipedInputStream/PipedOutputStream<br />
这个类位于java.io包中，是解决同步问题的最简单的办法，一个线程将数据写入管道，另一个线程从管道读取数据，这样便构成了一种生产者/消费者的缓冲区编程模式。<br />
下面是一个例子代码，在这个代码我没有使用Object对象，而是简单的读写字节值，这是因为PipedInputStream/PipedOutputStream不允许传输对象，这是JAVA本身的一个bug,具体的大家可以看sun的解释：http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4131126<br />
import java.io.*;</p>
<p>public class Sycn4...{<br />
&nbsp;&nbsp;&nbsp; private PipedOutputStream pos;<br />
&nbsp;&nbsp;&nbsp; private PipedInputStream pis;<br />
&nbsp;&nbsp;&nbsp; //private ObjectOutputStream oos;<br />
&nbsp;&nbsp;&nbsp; //private ObjectInputStream ois;<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; public Sycn4()...{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try...{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pos = new PipedOutputStream();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pis = new PipedInputStream(pos);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //oos = new ObjectOutputStream(pos);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //ois = new ObjectInputStream(pis);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }catch(IOException e)...{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println(e);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; public void start()...{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; new Producer().start();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; new Consumer().start();<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; public static void main(String[] args) throws Exception...{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Sycn4 s4 = new Sycn4();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; s4.start();<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; class Producer extends Thread...{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public void run() ...{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try...{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while(true)...{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int b = (int) (Math.random() * 255);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("Producer: a byte, the value is " + b);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pos.write(b);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pos.flush();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //Object o = new MyObject();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //oos.writeObject(o);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //oos.flush();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //System.out.println("Producer: " + o);<br />
&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; }catch(Exception e)...{<br />
&nbsp;&nbsp;&nbsp;&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; e.printStackTrace();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }finally...{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try...{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pos.close();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pis.close();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //oos.close();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //ois.close();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }catch(IOException e)...{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; class Consumer extends Thread...{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public void run()...{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try...{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while(true)...{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int b = pis.read();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("Consumer: a byte, the value is " + String.valueOf(b));<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //Object o = ois.readObject();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //if(o != null)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //System.out.println("Consumer: " + o);<br />
&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; }catch(Exception e)...{<br />
&nbsp;&nbsp;&nbsp;&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; e.printStackTrace();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }finally...{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try...{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pos.close();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pis.close();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //oos.close();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //ois.close();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }catch(IOException e)...{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; //class MyObject implements Serializable {<br />
&nbsp;&nbsp;&nbsp; //}<br />
}</p>
<p>出处：<a href="http://blog.csdn.net/JaunLee/archive/2008/02/01/2077291.aspx">http://blog.csdn.net/JaunLee/archive/2008/02/01/2077291.aspx</a></p>
<img src ="http://www.blogjava.net/tbest/aggbug/321107.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/tbest/" target="_blank">liujg</a> 2010-05-16 19:03 <a href="http://www.blogjava.net/tbest/articles/321107.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>&lt;转&gt;绝对路径相对路径</title><link>http://www.blogjava.net/tbest/articles/317902.html</link><dc:creator>liujg</dc:creator><author>liujg</author><pubDate>Fri, 09 Apr 2010 16:04:00 GMT</pubDate><guid>http://www.blogjava.net/tbest/articles/317902.html</guid><wfw:comment>http://www.blogjava.net/tbest/comments/317902.html</wfw:comment><comments>http://www.blogjava.net/tbest/articles/317902.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/tbest/comments/commentRss/317902.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/tbest/services/trackbacks/317902.html</trackback:ping><description><![CDATA[1.基本概念的理解 <br />
<br />
　　绝对路径：绝对路径就是你的主页上的文件或目录在硬盘上真正的路径，(URL和物理路径)例如： <br />
C:\xyz\test.txt 代表了test.txt文件的绝对路径。http://www.sun.com/index.htm也代表了一个 <br />
URL绝对路径。 <br />
<br />
　　相对路径：相对与某个基准目录的路径。包含Web的相对路径（HTML中的相对目录），例如：在 <br />
Servlet中，"/"代表Web应用的跟目录。和物理路径的相对表示。例如："./" 代表当前目录, <br />
"../"代表上级目录。这种类似的表示，也是属于相对路径。 <br />
<br />
另外关于URI，URL,URN等内容，请参考RFC相关文档标准。 <br />
<br />
RFC 2396: Uniform Resource Identifiers (URI): Generic Syntax, <br />
(http://www.ietf.org/rfc/rfc2396.txt) <br />
<br />
<br />
2.关于JSP/Servlet中的相对路径和绝对路径。 <br />
<br />
2.1服务器端的地址 <br />
<br />
　　 服务器端的相对地址指的是相对于你的web应用的地址，这个地址是在服务器端解析的 <br />
（不同于html和javascript中的相对地址，他们是由客户端浏览器解析的）也就是说这时候 <br />
在jsp和servlet中的相对地址应该是相对于你的web应用，即相对于http://192.168.0.1/webapp/的。 <br />
<br />
　　其用到的地方有： <br />
forward：servlet中的request.getRequestDispatcher(address);这个address是 <br />
在服务器端解析的，所以，你要forward到a.jsp应该这么写： <br />
request.getRequestDispatcher(&#8220;/user/a.jsp&#8221;)这个/相对于当前的web应用webapp， <br />
其绝对地址就是：http://192.168.0.1/webapp/user/a.jsp。 <br />
sendRedirect：在jsp中&lt;%response.sendRedirect("/rtccp/user/a.jsp");%&gt; <br />
<br />
2.22、客户端的地址 <br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 所有的html页面中的相对地址都是相对于服务器根目录(http://192.168.0.1/)的， <br />
而不是(跟目录下的该Web应用的目录)http://192.168.0.1/webapp/的。 <br />
Html中的form表单的action属性的地址应该是相对于服务器根目录(http://192.168.0.1/)的， <br />
所以，如果提交到a.jsp为：action＝"/webapp/user/a.jsp"或action="&lt;%=request.getContextPath()%&gt;"/user/a.jsp； <br />
　　提交到servlet为actiom＝"/webapp/handleservlet"&nbsp; <br />
　　Javascript也是在客户端解析的，所以其相对路径和form表单一样。 <br />
<br />
<br />
　　因此，一般情况下，在JSP/HTML页面等引用的CSS,Javascript.Action等属性前面最好都加上 <br />
&lt;%=request.getContextPath()%&gt;,以确保所引用的文件都属于Web应用中的目录。 <br />
另外，应该尽量避免使用类似".","./","../../"等类似的相对该文件位置的相对路径，这样 <br />
当文件移动时，很容易出问题。 <br />
<br />
<br />
3. JSP/Servlet中获得当前应用的相对路径和绝对路径 <br />
3.1 JSP中获得当前应用的相对路径和绝对路径 <br />
根目录所对应的绝对路径:request.getRequestURI() <br />
文件的绝对路径&nbsp;&nbsp;&nbsp; 　:application.getRealPath(request.getRequestURI()); <br />
当前web应用的绝对路径 :application.getRealPath("/"); <br />
取得请求文件的上层目录:new File(application.getRealPath(request.getRequestURI())).getParent() <br />
<br />
3.2 Servlet中获得当前应用的相对路径和绝对路径 <br />
根目录所对应的绝对路径:request.getServletPath(); <br />
文件的绝对路径&nbsp;&nbsp;&nbsp; :request.getSession().getServletContext().getRealPath <br />
(request.getRequestURI())&nbsp;&nbsp; <br />
当前web应用的绝对路径 :servletConfig.getServletContext().getRealPath("/"); <br />
&nbsp;&nbsp;&nbsp;&nbsp; (ServletContext对象获得几种方式： <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; javax.servlet.http.HttpSession.getServletContext() <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; javax.servlet.jsp.PageContext.getServletContext() <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; javax.servlet.ServletConfig.getServletContext() <br />
&nbsp;&nbsp;&nbsp;&nbsp; ) <br />
<br />
4.java 的Class中获得相对路径，绝对路径的方法 <br />
4.1单独的Java类中获得绝对路径 <br />
　　根据java.io.File的Doc文挡，可知: <br />
默认情况下new File("/")代表的目录为：System.getProperty("user.dir")。 <br />
一下程序获得执行类的当前路径 <br />
package org.cheng.file; <br />
import java.io.File; <br />
<br />
public class FileTest { <br />
&nbsp;&nbsp;&nbsp; public static void main(String[] args) throws Exception {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
<br />
&nbsp; System.out.println(Thread.currentThread().getContextClassLoader().getResource(""));&nbsp;&nbsp;&nbsp;&nbsp; <br />
<br />
&nbsp; System.out.println(FileTest.class.getClassLoader().getResource(""));&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
<br />
　　System.out.println(ClassLoader.getSystemResource(""));&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp; System.out.println(FileTest.class.getResource(""));&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp; System.out.println(FileTest.class.getResource("/")); //Class文件所在路径&nbsp; <br />
&nbsp; System.out.println(new File("/").getAbsolutePath());&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp; System.out.println(System.getProperty("user.dir"));&nbsp;&nbsp;&nbsp; <br />
} <br />
} <br />
<br />
4.2服务器中的Java类获得当前路径（来自网络） <br />
(1).Weblogic <br />
<br />
WebApplication的系统文件根目录是你的weblogic安装所在根目录。 <br />
例如：如果你的weblogic安装在c:\bea\weblogic700..... <br />
那么，你的文件根路径就是c:\. <br />
所以，有两种方式能够让你访问你的服务器端的文件： <br />
a.使用绝对路径： <br />
比如将你的参数文件放在c:\yourconfig\yourconf.properties， <br />
直接使用 new FileInputStream("yourconfig/yourconf.properties"); <br />
b.使用相对路径： <br />
相对路径的根目录就是你的webapplication的根路径，即WEB-INF的上一级目录，将你的参数文件放 <br />
<br />
在yourwebapp\yourconfig\yourconf.properties， <br />
这样使用： <br />
new FileInputStream("./yourconfig/yourconf.properties"); <br />
这两种方式均可，自己选择。 <br />
<br />
(2).Tomcat <br />
<br />
在类中输出System.getProperty("user.dir");显示的是%Tomcat_Home%/bin <br />
<br />
(3).Resin <br />
<br />
不是你的JSP放的相对路径,是JSP引擎执行这个JSP编译成SERVLET <br />
的路径为根.比如用新建文件法测试File f = new File("a.htm"); <br />
这个a.htm在resin的安装目录下 <br />
<br />
(4).如何读相对路径哪？ <br />
<br />
在Java文件中getResource或getResourceAsStream均可 <br />
<br />
例：getClass().getResourceAsStream(filePath);//filePath可以是"/filename",这里的/代表web <br />
<br />
发布根路径下WEB-INF/classes <br />
<br />
默认使用该方法的路径是：WEB-INF/classes。已经在Tomcat中测试。 <br />
<br />
5.读取文件时的相对路径，避免硬编码和绝对路径的使用。（来自网络） <br />
5.1 采用Spring的DI机制获得文件，避免硬编码。 <br />
&nbsp;&nbsp; 参考下面的连接内容： <br />
&nbsp;&nbsp; http://www.javajia.net/viewtopic.php?p=90213&amp; <br />
5.2 配置文件的读取 <br />
参考下面的连接内容： <br />
http://dev.csdn.net/develop/article/39/39681.shtm <br />
5.3 通过虚拟路径或相对路径读取一个xml文件，避免硬编码 <br />
参考下面的连接内容： <br />
http://club.gamvan.com/club/clubPage.jsp?iPage=1&amp;tID=10708&amp;ccID=8 <br />
<br />
6.Java中文件的常用操作（复制，移动，删除，创建等）（来自网络） <br />
常用 java File 操作类 <br />
http://www.easydone.cn/014/200604022353065155.htm <br />
<br />
Java文件操作大全（JSP中） <br />
http://www.pconline.com.cn/pcedu/empolder/gj/java/0502/559401.html <br />
<br />
java文件操作详解（Java中文网） <br />
http://www.51cto.com/html/2005/1108/10947.htm <br />
<br />
JAVA 如何创建\删除\修改\复制目录及文件 <br />
http://www.gamvan.com/developer/java/2005/2/264.html <br />
<br />
总结： <br />
通过上面内容的使用，可以解决在Web应用服务器端，移动文件，查找文件，复制 <br />
删除文件等操作，同时对服务器的相对地址，绝对地址概念更加清晰。 <br />
建议参考URI,的RFC标准文挡。同时对Java.io.File. Java.net.URI.等内容了解透彻 <br />
对其他方面的理解可以更加深入和透彻。 <br />
================================================================================== <br />
<br />
参考资料: <br />
java/docs/ <br />
<br />
java.io.File <br />
java.io.InputStream <br />
java.io.OutputStream <br />
java.io.FileInputStream <br />
java.io.FileReader; <br />
java.io.FileOutputStream <br />
java.io.FileWriter; <br />
java.net.URI <br />
java.net.URL <br />
<br />
<br />
绝对路径与相对路径祥解 <br />
http://www.webjx.com/htmldata/2005-02-26/1109430310.html <br />
<br />
[『J道习练』]JSP和Servlet中的绝对路径和相对路径 <br />
http://w3china.org/blog/more.asp?name=pcthomas&amp;id=9122&amp;commentid=12376 <br />
<br />
JSP,Servlet,Class获得当前应用的相对路径和绝对路径 <br />
http://cy.lzu.edu.cn/cy/club/clubPage.jsp?ccStyle=0&amp;tID=886&amp;ccID=77 <br />
<br />
如何获得当前文件路径 <br />
http://www.matrix.org.cn/resource/article/44/44113_java.html <br />
<br />
通过Spring注入机制，取得文件 <br />
http://www.javajia.net/viewtopic.php?p=90213&amp; <br />
<br />
配置文件的读取 <br />
http://dev.csdn.net/develop/article/39/39681.shtm <br />
<br />
读取配置文件,通过虚拟路径或相对路径读取一个xml文件，避免硬编码！ <br />
http://club.gamvan.com/club/clubPage.jsp?iPage=1&amp;tID=10708&amp;ccID=8 <br />
<br />
常用 java File 操作类 <br />
http://www.easydone.cn/014/200604022353065155.htm <br />
<br />
Java文件操作大全 <br />
http://www.pconline.com.cn/pcedu/empolder/gj/java/0502/559401.html <br />
<br />
Java文件操作详解 <br />
http://www.51cto.com/html/2005/1108/10947.htm <br />
原文地址：<a href="http://www.blogjava.net/meil/archive/2006/10/10/73908.html" target="_blank">http://www.blogjava.net/meil/archive/2006/10/10/73908.html</a> 
<img src ="http://www.blogjava.net/tbest/aggbug/317902.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/tbest/" target="_blank">liujg</a> 2010-04-10 00:04 <a href="http://www.blogjava.net/tbest/articles/317902.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JVM内存模型(转)</title><link>http://www.blogjava.net/tbest/articles/288762.html</link><dc:creator>liujg</dc:creator><author>liujg</author><pubDate>Tue, 28 Jul 2009 08:14:00 GMT</pubDate><guid>http://www.blogjava.net/tbest/articles/288762.html</guid><wfw:comment>http://www.blogjava.net/tbest/comments/288762.html</wfw:comment><comments>http://www.blogjava.net/tbest/articles/288762.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/tbest/comments/commentRss/288762.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/tbest/services/trackbacks/288762.html</trackback:ping><description><![CDATA[<table>
    <tbody>
        <tr>
            <td>
            <p>原文地址:http://tech.e800.com.cn/articles/2009/79/1247104593971_1.html<br />
            JVM内存由 Perm 和 Heap 组成. 其中<br />
            Heap = {Old + NEW = { Eden , from, to } }<br />
            JVM内存模型中分两大块，一块是 NEW Generation, 另一块是Old Generation. 在New Generation中，有一个叫Eden的空间，主要是用来存放新生的对象，还有两个Survivor Spaces（from,to）, 它们用来存放每次垃圾回收后存活下来的对象。在Old Generation中，主要存放应用程序中生命周期长的内存对象，还有个Permanent Generation，主要用来放JVM自己的反射对象，比如类对象和方法对象等。</p>
            <p>垃圾回收描述：</p>
            <p>在New Generation块中，垃圾回收一般用Copying的算法，速度快。每次GC的时候，存活下来的对象首先由Eden拷贝到某个Survivor Space, 当Survivor Space空间满了后, 剩下的live对象就被直接拷贝到Old Generation中去。因此，每次GC后，Eden内存块会被清空。在Old Generation块中，垃圾回收一般用mark-compact的算法，速度慢些，但减少内存要求.<br />
            垃圾回收分多级，0级为全部(Full)的垃圾回收，会回收OLD段中的垃圾；1级或以上为部分垃圾回收，只会回收NEW中的垃圾，内存溢出通常发生于OLD段或Perm段垃圾回收后，仍然无内存空间容纳新的Java对象的情况。</p>
            <p>当一个URL被访问时，内存申请过程如下：<br />
            A. JVM会试图为相关Java对象在Eden中初始化一块内存区域<br />
            B. 当Eden空间足够时，内存申请结束。否则到下一步<br />
            C. JVM试图释放在Eden中所有不活跃的对象（这属于1或更高级的垃圾回收）, 释放后若Eden空间仍然不足以放入新对象，则试图将部分Eden中活跃对象放入Survivor区<br />
            D. Survivor区被用来作为Eden及OLD的中间交换区域，当OLD区空间足够时，Survivor区的对象会被移到Old区，否则会被保留在Survivor区<br />
            E. 当OLD区空间不够时，JVM会在OLD区进行完全的垃圾收集（0级）<br />
            F. 完全垃圾收集后，若Survivor及OLD区仍然无法存放从Eden复制过来的部分对象，导致JVM无法在Eden区为新对象创建内存区域，则出现&#8221;out of memory错误&#8221;</p>
            <p>JVM调优建议:</p>
            <p>ms/mx：定义YOUNG+OLD段的总尺寸，ms为JVM启动时YOUNG+OLD的内存大小；mx为最大可占用的YOUNG+OLD内存大小。在用户生产环境上一般将这两个值设为相同，以减少运行期间系统在内存申请上所花的开销。<br />
            NewSize/MaxNewSize：定义YOUNG段的尺寸，NewSize为JVM启动时YOUNG的内存大小；MaxNewSize为最大可占用的YOUNG内存大小。在用户生产环境上一般将这两个值设为相同，以减少运行期间系统在内存申请上所花的开销。<br />
            PermSize/MaxPermSize：定义Perm段的尺寸，PermSize为JVM启动时Perm的内存大小；MaxPermSize为最大可占用的Perm内存大小。在用户生产环境上一般将这两个值设为相同，以减少运行期间系统在内存申请上所花的开销。<br />
            SurvivorRatio：设置Survivor空间和Eden空间的比例</p>
            <p>内存溢出的可能性</p>
            <p>1. OLD段溢出<br />
            这种内存溢出是最常见的情况之一，产生的原因可能是：<br />
            1) 设置的内存参数过小(ms/mx, NewSize/MaxNewSize)<br />
            2) 程序问题<br />
            单个程序持续进行消耗内存的处理，如循环几千次的字符串处理，对字符串处理应建议使用StringBuffer。此时不会报内存溢出错，却会使系统持续垃圾收集，无法处理其它请求，相关问题程序可通过Thread Dump获取（见系统问题诊断一章）单个程序所申请内存过大，有的程序会申请几十乃至几百兆内存，此时JVM也会因无法申请到资源而出现内存溢出，对此首先要找到相关功能，然后交予程序员修改，要找到相关程序，必须在Apache日志中寻找。<br />
            当Java对象使用完毕后，其所引用的对象却没有销毁，使得JVM认为他还是活跃的对象而不进行回收，这样累计占用了大量内存而无法释放。由于目前市面上还没有对系统影响小的内存分析工具，故此时只能和程序员一起定位。</p>
            <p>2. Perm段溢出<br />
            通常由于Perm段装载了大量的Servlet类而导致溢出，目前的解决办法：<br />
            1) 将PermSize扩大，一般256M能够满足要求<br />
            2) 若别无选择，则只能将servlet的路径加到CLASSPATH中，但一般不建议这么处理</p>
            <p>3. C Heap溢出<br />
            系统对C Heap没有限制，故C Heap发生问题时，Java进程所占内存会持续增长，直到占用所有可用系统内存</p>
            <p>其他：</p>
            <p>JVM有2个GC线程。第一个线程负责回收Heap的Young区。第二个线程在Heap不足时，遍历Heap，将Young 区升级为Older区。Older区的大小等于-Xmx减去-Xmn，不能将-Xms的值设的过大，因为第二个线程被迫运行会降低JVM的性能。<br />
            为什么一些程序频繁发生GC？有如下原因：<br />
            l 程序内调用了System.gc()或Runtime.gc()。<br />
            l 一些中间件软件调用自己的GC方法，此时需要设置参数禁止这些GC。<br />
            l Java的Heap太小，一般默认的Heap值都很小。<br />
            l 频繁实例化对象，Release对象。此时尽量保存并重用对象，例如使用StringBuffer()和String()。<br />
            如果你发现每次GC后，Heap的剩余空间会是总空间的50%，这表示你的Heap处于健康状态。许多Server端的Java程序每次GC后最好能有65%的剩余空间。<br />
            经验之谈：<br />
            1．Server端JVM最好将-Xms和-Xmx设为相同值。为了优化GC，最好让-Xmn值约等于-Xmx的1/3[2]。<br />
            2．一个GUI程序最好是每10到20秒间运行一次GC，每次在半秒之内完成[2]。<br />
            注意：<br />
            1．增加Heap的大小虽然会降低GC的频率，但也增加了每次GC的时间。并且GC运行时，所有的用户线程将暂停，也就是GC期间，Java应用程序不做任何工作。<br />
            2．Heap大小并不决定进程的内存使用量。进程的内存使用量要大于-Xmx定义的值，因为Java为其他任务分配内存，例如每个线程的Stack等。<br />
            2．Stack的设定<br />
            每个线程都有他自己的Stack。</p>
            <p>-Xss<br />
            <br />
            每个线程的Stack大小<br />
            Stack的大小限制着线程的数量。如果Stack过大就好导致内存溢漏。-Xss参数决定Stack大小，例如-Xss1024K。如果Stack太小，也会导致Stack溢漏。<br />
            3．硬件环境<br />
            硬件环境也影响GC的效率，例如机器的种类，内存，swap空间，和CPU的数量。<br />
            如果你的程序需要频繁创建很多transient对象，会导致JVM频繁GC。这种情况你可以增加机器的内存，来减少Swap空间的使用[2]。<br />
            4．4种GC<br />
            第一种为单线程GC，也是默认的GC。，该GC适用于单CPU机器。<br />
            第二种为Throughput GC，是多线程的GC，适用于多CPU，使用大量线程的程序。第二种GC与第一种GC相似，不同在于GC在收集Young区是多线程的，但在Old区和第一种一样，仍然采用单线程。-XX:+UseParallelGC参数启动该GC。<br />
            第三种为Concurrent Low Pause GC，类似于第一种，适用于多CPU，并要求缩短因GC造成程序停滞的时间。这种GC可以在Old区的回收同时，运行应用程序。-XX:+UseConcMarkSweepGC参数启动该GC。</p>
            <p>第四种为Incremental Low Pause GC，适用于要求缩短因GC造成程序停滞的时间。这种GC可以在Young区回收的同时，回收一部分Old区对象。-Xincgc参数启动该GC。</p>
            </td>
        </tr>
    </tbody>
</table>
<img src ="http://www.blogjava.net/tbest/aggbug/288762.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/tbest/" target="_blank">liujg</a> 2009-07-28 16:14 <a href="http://www.blogjava.net/tbest/articles/288762.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>转：用Java Socket开发小型服务器，支持上千个并发（上）</title><link>http://www.blogjava.net/tbest/articles/249721.html</link><dc:creator>liujg</dc:creator><author>liujg</author><pubDate>Sun, 04 Jan 2009 04:55:00 GMT</pubDate><guid>http://www.blogjava.net/tbest/articles/249721.html</guid><wfw:comment>http://www.blogjava.net/tbest/comments/249721.html</wfw:comment><comments>http://www.blogjava.net/tbest/articles/249721.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/tbest/comments/commentRss/249721.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/tbest/services/trackbacks/249721.html</trackback:ping><description><![CDATA[<div class="date">&nbsp;</div>
<table style="table-layout: fixed">
    <tbody>
        <tr>
            <td>
            <div class="cnt" id="blog_text">Java Socket<br />
            套接字（socket）为两台计算机之间的通信提供了一种机制，在James Gosling注意到Java 语言之前，套接字就早已赫赫有名。该语言只是让您不必了解底层操作系统的细节就能有效地使用套接字。<br />
            1 客户机/服务器模型<br />
            在饭店里，菜单上各种具有异国情调的食品映入你的眼帘，于是你要了一份pizza。几分钟后，你用力咀嚼浇着融化的乳酪和其他你喜欢的配料的热pizza。你不知道，也不想知道：侍者从那里弄来了pizza，在制作过程中加进了什么，以及配料是如何获得的。<br />
            上例中包含的实体有：美味的pizza、接受你定餐的侍者、制作pizza的厨房，当然还有你。你是定pizza的顾客或客户。制作pizza的过程对于你而言是被封装的。你的请求在厨房中被处理，pizza制作完成后，由侍者端给你。<br />
            你所看到的就是一个客户机/服务器模型。客户机向服务器发送一个请求或命令。服务器处理客户机的请求。客户机和服务器之间的通讯是客户机/服务器模型中的一个重要组成部分，通常通过网络进行。<br />
            客户机/服务器模型是一个应用程序开发框架，该框架是为了将数据的表示与其内部的处理和存储分离开来而设计的。客户机请求服务，服务器为这些请求服务。请求通过网络从客户机传递到服务器。服务器所进行的处理对客户机而言是隐藏的。一个服务器可以为多台客户机服务。<br />
            多台客户机访问服务器<br />
            服务器和客户机不一定是硬件组件。它们可以是工作啊同一机器或不同机器上的程序。、<br />
            考虑一个航空定票系统中的数据输入程序：数据----乘客名、航班号、飞行日期、目的地等可以被输入到前端----客户机的应用程序中。一旦数据输入之后，客户机将数据发送到后端----服务器端。服务器处理数据并在数据库中保存数据。客户机/服务器模型的重要性在于所有的数据都存放在同一地点。客户机从不同的地方访问同一数据源，服务器对所有的输入数据应用同样的检验规则。<br />
            万维网为&#8216;为什么要将数据的表示与其存储、处理分离开来&#8217;提供了一个很好的例子。在Web上，你无需控制最终用户用来访问你数据的平台和软件。你可以考虑编写出适用与每一种潜在的目标平台的应用程序。<br />
            &#8216;客户机/服务器应用程序的服务器部分&#8217;管理通过多个客户机访问服务器的、多个用户共享的资源。表明&#8216;客户机/服务器程序的服务器部分&#8217;强大功能的最好例子应该是Web服务器，它通过Internet将HTML页传递给不同的Web用户。<br />
            Java编程语言中最基本的特点是在Java中创建的程序的代码的可移植性。因为具有其他语言所不具备的代码可移植性，Java允许用户只要编写一次应用程序，就可以在任何客户机系统上发布它，并可以让客户机系统解释该程序。这意味着：你只要写一次代码，就能使其在任何平台上运行。<br />
            <br />
            2 协议<br />
            当你同朋友交谈时，你们遵循一些暗含的规则（或协议）。例如：你们俩不能同时开始说话，或连续不间断地说话。如果你们这样作的话，谁也不能理解对方所说的东西。当你说话时，你的朋友倾听，反之亦然。你们以双方都能理解的语言和速度进行对话。<br />
            当计算机之间进行通讯的时候，也需要遵循一定的规则。数据以包的形式从一台机器发送到另一台。这些规则管理数据打包、数据传输速度和重新 数据将其恢复成原始形式。这些规则被称为网络协议。网络协议是通过网络进行通讯的系统所遵循的一系列规则和惯例。连网软件通常实现有高低层次之分的多层协议。网络协议的例子有：TCP/IP、UDP、Apple Talk和NetBEUI。<br />
            Java提供了一个丰富的、支持网络的类库，这些类使得应用程序能方便地访问网络资源。Java提供了两种通讯工具。它们是：使用用户报文协议（UDP）的报文和使用传输控制协议/因特网协议（TCP/IP）的Sockets（套接字）。<br />
            数据报包是一个字节数组从一个程序（发送程序）传送到另一个（接受程序）。由于数据报遵守UDP，不保证发出的数据包必须到达目的地。数据报并不是可信赖的。因此，仅当传送少量数据时才使用，而且发送者和接受者之间的距离间隔不大，假如是网络交通高峰，或接受程序正处理来自其他程序的多个请求，就有机会出现数据报包的丢失。<br />
            Sockets套接字用TCP来进行通讯。套接字模型同其他模型相比，优越性在于其不受客户请求来自何处的影响。只要客户机遵循TCP/IP协议，服务器就会对它的请求提供服务。这意味着客户机可以是任何类型的计算机。客户机不再局限为UNIX、Windows、DOS或Macintosh平台，因此，网上所有遵循TCP/IP协议的计算机可以通过套接字互相通讯。<br />
            <br />
            3 Sockets套接字<br />
            3.1 Sockets概况<br />
            在客户机/服务器应用程序中，服务器提供象处理数据库查询或修改数据库中的数据之类的服务。发生在客户机和服务器之间的通讯必须是可靠的，同时数据在客户机上的次序应该和服务器发送出来的次序相同。<br />
            什么是套接字？ <br />
            既然我们已经知道套接字扮演的角色，那么剩下的问题是：什么是套接字？Bruce Eckel 在他的《Java 编程思想》一书中这样描述套接字：套接字是一种软件抽象，用于表达两台机器之间的连接&#8220;终端&#8221;。对于一个给定的连接，每台机器上都有一个套接字，您也可以想象它们之间有一条虚拟的&#8220;电缆&#8221;，&#8220;电缆&#8221;的每一端都插入到套接字中。当然，机器之间的物理硬件和电缆连接都是完全未知的。抽象的全部目的是使我们无须知道不必知道的细节。 <br />
            简言之，一台机器上的套接字与另一台机器上的套接字交谈就创建一条通信通道。程序员可以用该通道来在两台机器之间发送数据。当您发送数据时，TCP/IP 协议栈的每一层都会添加适当的报头信息来包装数据。这些报头帮助协议栈把您的数据送到目的地。好消息是 Java 语言通过"流"为您的代码提供数据，从而隐藏了所有这些细节，这也是为什么它们有时候被叫做流套接字（streaming socket）的原因。<br />
            把套接字想成两端电话上的听筒，我和您通过专用通道在我们的电话听筒上讲话和聆听。直到我们决定挂断电话，对话才会结束（除非我们在使用蜂窝电话）。而且我们各自的电话线路都占线，直到我们挂断电话。<br />
            如果想在没有更高级机制如 ORB（以及 CORBA、RMI、IIOP 等等）开销的情况下进行两台计算机之间的通信，那么套接字就适合您。套接字的低级细节相当棘手。幸运的是，Java 平台给了您一些虽然简单但却强大的更高级抽象，使您可以容易地创建和使用套接字。<br />
            传输控制协议（TCP）提供了一条可靠的、点对点的通讯通道，客户机/服务器应用程序可以用该通道互相通讯。要通过TCP进行通讯，客户机和服务器程序建立连接并绑定套接字。套接字用于处理通过网络连接的应用程序之间的通讯。客户机和服务器之间更深入的通讯通过套接字完成。<br />
            Java被设计成一种连网语言。它通过将连接功能封装到套接字类里而使得网络编程更加容易。套接字类即Socket类（它创建一个客户套接字）和ServerSocket类（它创建一个服务器套接字）。套接字类大致介绍如下：<br />
            l&nbsp;&nbsp;&nbsp;&nbsp; Socket是基类，它支持TCP协议。TCP是一个可靠的流网络连接协议。Socket类提供了流输入/输出的方法，使得从套接字中读出数据和往套接字中写数据都很容易。该类对于编写因特网上的通讯程序而言是必不可少的。<br />
            l&nbsp;&nbsp;&nbsp;&nbsp; ServerSocket是一个因特网服务程序用来监听客户请求的类。ServerSocket实际上并不执行服务；而是创建了一个Socket对象来代表客户机。通讯由创建的对象来完成。<br />
            3.2 IP地址和端口<br />
            因特网服务器可以被认为是一组套接字类，它们提供了一般称为服务的附加功能。服务的例子有：电子邮件、远程登录的Telnet、和通过网络传输文件的文件传输协议（FTP）。每种服务都与一个端口相联系。端口是一个数值地址，通过它来处理服务请求（就象请求Web页一样）。<br />
            TCP协议需要两个数据项：IP地址和端口号。因此，当键入<a href="http://www.jinnuo.com/">http://www.jinnuo.com</a>时，你是如何进入金诺的主页呢？<br />
            因特网协议（IP）提供每一项网络设备。这些设备都带有一个称为IP地址的逻辑地址。由因特网协议提供的IP地址具有特定的形式。每个IP地址都是32位的数值，表示4个范围在0到255之间的8位数值金诺已经注册了它的名字，分配给<a href="http://www.jinnuo.com/">http://www.jinnuo.com</a>的IP地址为192.168.0.110。<br />
            注意：域名服务或DNS服务是将<a href="http://www.jinnuo.com/">http://www.jinnuo.com</a>翻译成192.168.0.110的服务。这使你可以键入<a href="http://www.jinnuo.com/">http://www.jinnuo.com</a>而不必记住IP地址。想象一下，怎么可能记住所有需要访问的站点的IP地址！有趣的是一个网络名可以映射到许多IP地址。对于经常访问的站点可能需要这一功能，因为这些站点容纳大量的信息，并需要多个IP地址来提供业务服务。例如：192.168.0.110的实际的内部名称为<a href="http://www.jinnuo.com/">http://www.jinnuo.com</a>。DNS可以将分配给jinnuo Ltd.的一系列IP地址翻译成<a href="http://www.jinnuo.com/">http://www.jinnuo.com</a>。<br />
            如果没有指明端口号，则使用服务文件中服务器的端口。每种协议有一个缺省的端口号，在端口号未指明时使用该缺省端口号。<br />
            端口号&nbsp;&nbsp;&nbsp;&nbsp; 应用<br />
            21&nbsp;&nbsp;&nbsp;&nbsp; FTP.传输文件<br />
            23&nbsp;&nbsp;&nbsp;&nbsp; Telnet.提供远程登录<br />
            25&nbsp;&nbsp;&nbsp;&nbsp; SMTP.传递邮件信息<br />
            67&nbsp;&nbsp;&nbsp;&nbsp; BOOTP.在启动时提供配置情况<br />
            80&nbsp;&nbsp;&nbsp;&nbsp; HTTP.传输Web页<br />
            109&nbsp;&nbsp;&nbsp;&nbsp; POP.使用户能访问远程系统中的邮箱<br />
            让我们再来看一下URL：<a href="http://www.jinnuo.com/">http://www.jinnuo.com</a><br />
            URL的第一部分（http）意味着你正在使用超文本传输协议（HTTP），该协议处理Web文档。如果没有指明文件，大多数的Web服务器会取一个叫index.html文件。因此，IP地址和端口既可以通过明确指出URL各部分来决定，也可以由缺省值决定。<br />
            4 创建Socket客户<br />
            我们将在本部分讨论的示例将阐明在 Java 代码中如何使用 Socket 和 ServerSocket。客户机用 Socket 连接到服务器。服务器用 ServerSocket 在端口 1001 侦听。客户机请求服务器 C: 驱动器上的文件内容。<br />
            创建 RemoteFileClient 类<br />
            import java.io.*;<br />
            import java.net.*;<br />
            public class RemoteFileClient {<br />
            &nbsp;&nbsp;&nbsp;&nbsp; protected BufferedReader socketReader;<br />
            &nbsp;&nbsp;&nbsp;&nbsp; protected PrintWriter socketWriter;<br />
            &nbsp;&nbsp;&nbsp;&nbsp; protected String hostIp;<br />
            &nbsp;&nbsp;&nbsp;&nbsp; protected int hostPort;<br />
            &nbsp;&nbsp;&nbsp;&nbsp; //构造方法<br />
            &nbsp;&nbsp;&nbsp;&nbsp; public RemoteFileClient(String hostIp, int hostPort) {<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.hostIp = hostIp;<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.hostPort=hostPort; <br />
            &nbsp;&nbsp;&nbsp;&nbsp; }<br />
            &nbsp;&nbsp;&nbsp;&nbsp; //向服务器请求文件的内容<br />
            &nbsp;&nbsp;&nbsp;&nbsp; public String getFile(String fileNameToGet) {<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; StringBuffer fileLines = new StringBuffer();<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try {<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; socketWriter.println(fileNameToGet);&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; socketWriter.flush();<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String line = null;<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while((line=socketReader.readLine())!=null)<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fileLines.append(line+"\n");<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; catch(IOException e) {<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("Error reading from file: "+fileNameToGet);<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return fileLines.toString();<br />
            &nbsp;&nbsp;&nbsp;&nbsp; }<br />
            &nbsp;&nbsp;&nbsp;&nbsp; //连接到远程服务器<br />
            &nbsp;&nbsp;&nbsp;&nbsp; public void setUpConnection() {<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try {<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Socket client = new Socket(hostIp,hostPort);<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; socketReader = new BufferedReader(new InputStreamReader(client.getInputStream()));<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; socketWriter = new PrintWriter(client.getOutputStream());<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; catch(UnknownHostException e) {<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("Error1 setting up socket connection: unknown host at "+hostIp+":"+hostPort);<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; catch(IOException e) {<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("Error2 setting up socket connection: "+e);<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
            &nbsp;&nbsp;&nbsp;&nbsp; }<br />
            &nbsp;&nbsp;&nbsp;&nbsp; //断开远程服务器<br />
            &nbsp;&nbsp;&nbsp;&nbsp; public void tearDownConnection() {<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try {<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; socketWriter.close(); <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; socketReader.close();<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }catch(IOException e) {&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; System.out.println("Error tearing down socket connection: "+e);<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
            &nbsp;&nbsp;&nbsp;&nbsp; }<br />
            &nbsp;&nbsp;&nbsp;&nbsp; public static void main(String args[]) {<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; RemoteFileClient remoteFileClient = new RemoteFileClient("127.0.0.1",1001);<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; remoteFileClient.setUpConnection();<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; StringBuffer fileContents = new StringBuffer();<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fileContents.append(remoteFileClient.getFile("RemoteFileServer.java"));&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //remoteFileClient.tearDownConnection();<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println(fileContents);<br />
            &nbsp;&nbsp;&nbsp;&nbsp; }<br />
            }<br />
            首先我们导入 java.net 和 java.io。java.net 包为您提供您需要的套接字工具。java.io 包为您提供对流进行读写的工具，这是您与 TCP 套接字通信的唯一途径。<br />
            我们给我们的类实例变量以支持对套接字流的读写和存储我们将连接到的远程主机的详细信息。<br />
            我们类的构造器有两个参数：远程主机的IP地址和端口号各一个，而且构造器将它们赋给实例变量。<br />
            我们的类有一个 main() 方法和三个其它方法。稍后我们将探究这些方法的细节。现在您只需知道 setUpConnection() 将连接到远程服务器，getFile() 将向远程服务器请求 fileNameToGet 的内容以及 tearDownConnection() 将从远程服务器上断开。<br />
            实现 main()<br />
            这里我们实现 main() 方法，它将创建 RemoteFileClient 并用它来获取远程文件的内容，然后打印结果。main() 方法用主机的 IP 地址和端口号实例化一个新 RemoteFileClient（客户机）。然后，我们告诉客户机建立一个到主机的连接。接着，我们告诉客户机获取主机上一个指定文件的内容。最后，我们告诉客户机断开它到主机的连接。我们把文件内容打印到控制台，只是为了证明一切都是按计划进行的。<br />
            建立连接<br />
            这里我们实现 setUpConnection() 方法，它将创建我们的 Socket 并让我们访问该套接字的流：<br />
            &nbsp;&nbsp;&nbsp;&nbsp; public void setUpConnection() {<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try {<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Socket client = new Socket(hostIp,hostPort);<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; socketReader = new BufferedReader(new InputStreamReader(client.getInputStream()));<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; socketWriter = new PrintWriter(client.getOutputStream());<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; catch(UnknownHostException e) {<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("Error1 setting up socket connection: unknown host at "+hostIp+":"+hostPort);<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; catch(IOException e) {<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("Error2 setting up socket connection: "+e);<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
            &nbsp;&nbsp;&nbsp;&nbsp; }<br />
            setUpConnection() 方法用主机的 IP 地址和端口号创建一个 Socket：<br />
            Socket client = new Socket(hostIp, hostPort);<br />
            我们把 Socket 的 InputStream 包装进 BufferedReader 以使我们能够读取流的行。然后，我们把 Socket 的 OutputStream 包装进 PrintWriter 以使我们能够发送文件请求到服务器：<br />
            socketReader = new BufferedReader(new InputStreamReader(client.getInputStream()));socketWriter = new PrintWriter(client.getOutputStream());<br />
            请记住我们的客户机和服务器只是来回传送字节。客户机和服务器都必须知道另一方即将发送的是什么以使它们能够作出适当的响应。在这个案例中，服务器知道我们将发送一条有效的文件路径。<br />
            当您实例化一个 Socket 时，将抛出 UnknownHostException。这里我们不特别处理它，但我们打印一些信息到控制台以告诉我们发生了什么错误。同样地，当我们试图获取 Socket 的 InputStream 或 OutputStream 时，如果抛出了一个一般 IOException，我们也打印一些信息到控制台。<br />
            与主机交谈<br />
            这里我们实现 getFile() 方法，它将告诉服务器我们想要什么文件并在服务器传回其内容时接收该内容。<br />
            &nbsp;&nbsp;&nbsp;&nbsp; public String getFile(String fileNameToGet) {<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; StringBuffer fileLines = new StringBuffer();<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try {<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; socketWriter.println(fileNameToGet);&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; socketWriter.flush();<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String line = null;<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while((line=socketReader.readLine())!=null)<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fileLines.append(line+"\n");<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; catch(IOException e) {<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("Error reading from file: "+fileNameToGet);<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return fileLines.toString();<br />
            &nbsp;&nbsp;&nbsp;&nbsp; }<br />
            对getFile()方法的调用要求一个有效的文件路径String。它首先创建名为fileLines的 StringBuffer，fileLines 用于存储我们读自服务器上的文件的每一行。<br />
            StringBuffer fileLines = new StringBuffer();<br />
            在 try{}catch{} 块中，我们用 PrintWriter 把请求发送到主机，PrintWriter 是我们在创建连接期间建立的。<br />
            &nbsp;&nbsp;&nbsp;&nbsp; socketWriter.println(fileNameToGet);&nbsp;&nbsp;&nbsp;&nbsp; socketWriter.flush();<br />
            请注意这里我们是 flush() 该 PrintWriter，而不是关闭它。这迫使数据被发送到服务器而不关闭 Socket。<br />
            一旦我们已经写到 Socket，我们就希望有一些响应。我们不得不在 Socket 的 InputStream 上等待它，我们通过在 while 循环中调用 BufferedReader 上的 readLine() 来达到这个目的。我们把每一个返回行附加到 fileLines StringBuffer（带有一个换行符以保护行）：<br />
            &nbsp;&nbsp;&nbsp;&nbsp; String line = null;&nbsp;&nbsp;&nbsp;&nbsp; while((line=socketReader.readLine())!=null)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fileLines.append(line+"\n");<br />
            断开连接<br />
            这里我们实现 tearDownConnection() 方法，它将在我们使用完毕连接后负责&#8220;清除&#8221;。tearDownConnection()方法只是分别关闭我们在Socket的InputStream和OutputStream上创建的 BufferedReader和PrintWriter。这样做会关闭我们从Socket获取的底层流，所以我们必须捕捉可能的 IOException。<br />
            总结一下客户机<br />
            我们的类研究完了。在我们继续往前讨论服务器端的情况之前，让我们回顾一下创建和使用 Socket 的步骤：<br />
            1.&nbsp;&nbsp;&nbsp;&nbsp; 用您想连接的机器的 IP 地址和端口实例化 Socket（如有问题则抛出 Exception）。<br />
            2.&nbsp;&nbsp;&nbsp;&nbsp; 获取 Socket 上的流以进行读写。<br />
            3.&nbsp;&nbsp;&nbsp;&nbsp; 把流包装进 BufferedReader/PrintWriter 的实例，如果这样做能使事情更简单的话。<br />
            4.&nbsp;&nbsp;&nbsp;&nbsp; 对 Socket 进行读写。<br />
            5.&nbsp;&nbsp;&nbsp;&nbsp; 关闭打开的流。 <br />
            5 创建服务器Socket<br />
            创建 RemoteFileServer 类<br />
            import java.io.*;<br />
            import java.net.*;<br />
            public class RemoteFileServer {&nbsp;&nbsp;&nbsp;&nbsp;<br />
            &nbsp;&nbsp;&nbsp;&nbsp; int listenPort;<br />
            &nbsp;&nbsp;&nbsp;&nbsp; public RemoteFileServer(int listenPort) {<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.listenPort=listenPort;<br />
            &nbsp;&nbsp;&nbsp;&nbsp; }<br />
            &nbsp;&nbsp;&nbsp;&nbsp; //允许客户机连接到服务器,等待客户机请求&nbsp;&nbsp;&nbsp;&nbsp;<br />
            &nbsp;&nbsp;&nbsp;&nbsp; public void acceptConnections() {<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try {<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ServerSocket server = new ServerSocket(listenPort);<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Socket incomingConnection = null;<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while(true) {<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; incomingConnection = server.accept();<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; handleConnection(incomingConnection);<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; catch(BindException e) {<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("Unable to bind to port "+listenPort);<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; catch(IOException e) {<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("Unable to instantiate a ServerSocket on port: "+listenPort);&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 />
            &nbsp;&nbsp;&nbsp;&nbsp; //与客户机Socket交互以将客户机所请求的文件的内容发送到客户机<br />
            &nbsp;&nbsp;&nbsp;&nbsp; public void handleConnection(Socket incomingConnection) {<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try {<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; OutputStream outputToSocket = incomingConnection.getOutputStream(); <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; InputStream inputFromSocket = incomingConnection.getInputStream();<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; BufferedReader streamReader = new BufferedReader(new InputStreamReader(inputFromSocket));<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FileReader fileReader = new FileReader(new File(streamReader.readLine()));<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; BufferedReader bufferedFileReader = new BufferedReader(fileReader); <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PrintWriter streamWriter = new PrintWriter(incomingConnection.getOutputStream());<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String line = null;<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while((line=bufferedFileReader.readLine())!=null){<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; streamWriter.println(line);<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; fileReader.close();<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; streamWriter.close();<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; streamReader.close();<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; catch(Exception e) {<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("Error handling a client: "+e);<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; e.printStackTrace(); <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
            &nbsp;&nbsp;&nbsp;&nbsp; }<br />
            &nbsp;&nbsp;&nbsp;&nbsp; public static void main(String args[]) {<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; RemoteFileServer server = new RemoteFileServer(1001);<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; server.acceptConnections();<br />
            &nbsp;&nbsp;&nbsp;&nbsp; }<br />
            }<br />
            跟客户机中一样，我们首先导入java.net的java.io。接着，我们给我们的类一个实例变量以保存端口，我们从该端口侦听进入的连接。缺省情况下，端口是1001。<br />
            我们的类有一个main()方法和两个其它方法。稍后我们将探究这些方法的细节。现在您只需知道acceptConnections()将允许客户机连接到服务器以及handleConnection()与客户机Socket交互以将您所请求的文件的内容发送到客户机。<br />
            实现 main()<br />
            这里我们实现main()方法，它将创建RemoteFileServer并告诉它接受连接：服务器端的main()方法中，我们实例化一个新RemoteFileServer，它将在侦听端口（1001）上侦听进入的连接请求。然后我们调用acceptConnections()来告诉该server进行侦听。<br />
            接受连接<br />
            这里我们实现 acceptConnections() 方法，它将创建一个 ServerSocket 并等待连接请求：<br />
            &nbsp;&nbsp;&nbsp;&nbsp; public void acceptConnections() {<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try {<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ServerSocket server = new ServerSocket(listenPort);<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Socket incomingConnection = null;<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while(true) {<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; incomingConnection = server.accept();<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; handleConnection(incomingConnection);<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; catch(BindException e) {<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("Unable to bind to port "+listenPort);<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; catch(IOException e) {<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("Unable to instantiate a ServerSocket on port: "+listenPort);&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 />
            acceptConnections()用欲侦听的端口号来创建ServerSocket。然后我们通过调用该ServerSocket的accept()来告诉它开始侦听。accept()方法将造成阻塞直到来了一个连接请求。此时，accept()返回一个新的Socket，这个Socket绑定到服务器上一个随机指定的端口，返回的Socket被传递给handleConnection()。请注意我们在一个无限循环中处理对连接的接受。这里不支持任何关机。<br />
            无论何时如果您创建了一个无法绑定到指定端口（可能是因为别的什么控制了该端口）的 ServerSocket，Java代码都将抛出一个错误。所以这里我们必须捕捉可能的BindException。就跟在客户机端上时一样，我们必须捕捉IOException，当我们试图在ServerSocket上接受连接时，它就会被抛出。请注意，您可以通过用毫秒数调用setSoTimeout()来为accept()调用设置超时，以避免实际长时间的等待。调用setSoTimeout()将使accept()经过指定占用时间后抛出IOException。<br />
            处理连接<br />
            这里我们实现handleConnection()方法，它将用连接的流来接收输入和写输出：<br />
            &nbsp;&nbsp;&nbsp;&nbsp; public void handleConnection(Socket incomingConnection) {<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try {<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; OutputStream outputToSocket = incomingConnection.getOutputStream(); <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; InputStream inputFromSocket = incomingConnection.getInputStream();<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; BufferedReader streamReader = new BufferedReader(new InputStreamReader(inputFromSocket));<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FileReader fileReader = new FileReader(new File(streamReader.readLine()));<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; BufferedReader bufferedFileReader = new BufferedReader(fileReader); <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PrintWriter streamWriter = new PrintWriter(incomingConnection.getOutputStream());<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String line = null;<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while((line=bufferedFileReader.readLine())!=null){<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; streamWriter.println(line);<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; fileReader.close();<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; streamWriter.close();<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; streamReader.close();<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; catch(Exception e) {<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("Error handling a client: "+e);<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; e.printStackTrace(); <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
            &nbsp;&nbsp;&nbsp;&nbsp; }<br />
            跟在客户机中一样，我们用getOutputStream()和getInputStream()来获取与我们刚创建的Socket相关联的流。跟在客户机端一样，我们把InputStream包装进BufferedReader，把OutputStream包装进PrintWriter。在服务器端上，我们需要添加一些代码，用来读取目标文件和把内容逐行发送到客户机。这里是重要的代码：<br />
            &nbsp;&nbsp;&nbsp;&nbsp; FileReader fileReader = new FileReader(new File(streamReader.readLine()));&nbsp;&nbsp;&nbsp;&nbsp; BufferedReader bufferedFileReader = new BufferedReader(fileReader);&nbsp;&nbsp;&nbsp;&nbsp; String line = null;&nbsp;&nbsp;&nbsp;&nbsp; while((line=bufferedFileReader.readLine())!=null) {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; streamWriter.println(line);&nbsp;&nbsp;&nbsp;&nbsp; }<br />
            这些代码值得详细解释。让我们一点一点来看：<br />
            &nbsp;&nbsp;&nbsp;&nbsp; FileReader fileReader = new FileReader(new File(streamReader.readLine()));<br />
            首先，我们使用Socket 的InputStream的BufferedReader。我们应该获取一条有效的文件路径，所以我们用该路径名构造一个新File。我们创建一个新FileReader来处理读文件的操作。<br />
            &nbsp;&nbsp;&nbsp;&nbsp; BufferedReader bufferedFileReader = new BufferedReader(fileReader);<br />
            这里我们把FileReader包装进BufferedReader以使我们能够逐行地读该文件。<br />
            接着，我们调用BufferedReader的readLine()。这个调用将造成阻塞直到有字节到来。我们获取一些字节之后就把它们放到本地的line变量中，然后再写出到客户机上。完成读写操作之后，我们就关闭打开的流。<br />
            请注意我们在完成从Socket的读操作之后关闭streamWriter和streamReader。您或许会问我们为什么不在读取文件名之后立刻关闭streamReader。原因是当您这样做时，您的客户机将不会获取任何数据。如果您在关闭streamWriter之前关闭streamReader，则您可以往Socket写任何东西，但却没有任何数据能通过通道（通道被关闭了）。<br />
            总结一下服务器<br />
            在我们接着讨论另一个更实际的示例之前，让我们回顾一下创建和使用ServerSocket的步骤：<br />
            1.&nbsp;&nbsp;&nbsp;&nbsp; 用一个您想让它侦听传入客户机连接的端口来实例化一个ServerSocket（如有问题则抛出 Exception）。<br />
            2.&nbsp;&nbsp;&nbsp;&nbsp; 调用ServerSocket的accept()以在等待连接期间造成阻塞。<br />
            3.&nbsp;&nbsp;&nbsp;&nbsp; 获取位于该底层Socket的流以进行读写操作。<br />
            4.&nbsp;&nbsp;&nbsp;&nbsp; 按使事情简单化的原则包装流。<br />
            5.&nbsp;&nbsp;&nbsp;&nbsp; 对Socket进行读写。<br />
            6.&nbsp;&nbsp;&nbsp;&nbsp; 关闭打开的流（并请记住，永远不要在关闭Writer之前关闭Reader）。</div>
            </td>
        </tr>
    </tbody>
</table>
<img src ="http://www.blogjava.net/tbest/aggbug/249721.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/tbest/" target="_blank">liujg</a> 2009-01-04 12:55 <a href="http://www.blogjava.net/tbest/articles/249721.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>snmp4j</title><link>http://www.blogjava.net/tbest/articles/240403.html</link><dc:creator>liujg</dc:creator><author>liujg</author><pubDate>Thu, 13 Nov 2008 14:35:00 GMT</pubDate><guid>http://www.blogjava.net/tbest/articles/240403.html</guid><wfw:comment>http://www.blogjava.net/tbest/comments/240403.html</wfw:comment><comments>http://www.blogjava.net/tbest/articles/240403.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/tbest/comments/commentRss/240403.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/tbest/services/trackbacks/240403.html</trackback:ping><description><![CDATA[<p>Provides classes and interfaces for creating, sending, and receiving SNMP messages. </p>
<p>The <code><font face="新宋体">org.snmp4j</font></code> classes are capable of creating, sending, and receiving SNMPv1/v2c/v3 messages. A SNMP message is composed of its message header and its PDU payload. This package contains three main groups of classes and interfaces:
<ul>
    <li>Classes for SNMP message and target creation
    <li>Classes for SNMP message sending (command generation)
    <li>Classes for SNMP message dispatching (command responding) </li>
</ul>
<p>The following UML package diagram illustrates the dependencies between the packages of the core SNMP4J API. Users of the API normally only need to use the <code><font face="新宋体">org.snmp4j</font></code> and the <code><font face="新宋体">org.snmp4j.smi</font></code> packages directly. </p>
<p><img src="http://blog.chinaunix.net/photo/10921_070202125539.gif"  alt="" /></p>
<p>&nbsp;</p>
<p>The following UML class diagram shows the most important classes of the org.snmp4j package and their relationships (relationships to other packages are not shown):. </p>
<p><img src="http://blog.chinaunix.net/photo/10921_070202125549.gif"  alt="" /></p>
<h2>SNMP Messages and Targets</h2>
<p>To exchange a SNMP message with a remote system, that system has to be identified, retransmission, and timeout policy information about the message exchange has to be specified. A remote system is specified with SNMP4J by creating a <code><font face="新宋体">Target</font></code> instance appropriate for the SNMP protocol to be used. </p>
<p>
<ul>
    <li>For SNMPv1 and SNMPv2c the <code><font face="新宋体">CommunityTarget</font></code> has to be used which provides community information in addition to the address, retransmission, and timeout policy information defined by the <code><font face="新宋体">Target</font></code> interface.
    <li>For SNMPv3 the <code><font face="新宋体">UserTarget</font></code> has to be used instead. It extends the <code><font face="新宋体">SecureTarget</font></code> abstract class and provides the following User Based Security Model (USM) user information: security name, security level, security model (i.e. USM), and authoritative engine ID. </li>
</ul>
<p>A SNMP message consists of the message's payload, the SNMP Protocol Data Unit (PDU) and a message header. Simplified said, in SNMP4J the message header information is represented by <code><font face="新宋体">Target</font></code> instances and the PDU is represented by one of the following classes:
<ul>
    <li><code><font face="新宋体">PDUv1</font></code> (SNMPv1)
    <li><code><font face="新宋体">PDU</font></code> (SNMPv2c)
    <li><code><font face="新宋体">ScopedPDU</font></code> (SNMPv3) </li>
</ul>
Thus, in order to be able to send a SNMP message with SNMP4J, a <code><font face="新宋体">PDU</font></code> instance and a <code><font face="新宋体">Target</font></code> instance have to be created.
<h4>PDU Examples (PDU 使用的例子)</h4>
<ul>
    <li>SNMPv1/v2c GETNEXT PDU
    <pre>import org.snmp4j.PDU;
    import org.snmp4j.smi.*;
    ...
    PDU pdu = new PDU();
    pdu.add(new VariableBinding(new OID("1.3.6.1.2.1.1.1"))); // sysDescr
    pdu.add(new VariableBinding(new OID("1.3.6.1.2.1.2.1"))); // ifNumber
    pdu.setType(PDU.GETNEXT);
    ...
    </pre>
    <li>SNMPv3 GETBULK PDU
    <pre>import org.snmp4j.ScopedPDU;
    import org.snmp4j.smi.*;
    ...
    ScopedPDU pdu = new ScopedPDU();
    pdu.add(new VariableBinding(new OID("1.3.6.1.2.1.2.1"))); // ifNumber
    pdu.add(new VariableBinding(new OID("1.3.6.1.2.1.2.2.1.10"))); // ifInOctets
    pdu.add(new VariableBinding(new OID("1.3.6.1.2.1.2.2.1.16"))); // ifOutOctets
    pdu.setType(PDU.GETBULK);
    pdu.setMaxRepetitions(50);
    // Get ifNumber only once
    pdu.setNonRepeaters(1);
    // set context non-default context (default context does not need to be set)
    pdu.setContextName(new OctetString("subSystemContextA"));
    // set non-default context engine ID (to use targets authoritative engine ID
    // use an empty (size == 0) octet string)
    pdu.setContextEngineID(OctetString.fromHexString("80:00:13:70:c0:a8:01:0d"));
    ...
    </pre>
    <li>SNMPv1 TRAP PDU ()
    <pre>import org.snmp4j.PDUv1;
    ...
    PDUv1 pdu = new PDUv1();
    pdu.setType(PDU.V1TRAP);
    pdu.setGenericTrap(PDUv1.COLDSTART);
    ...
    </pre>
    <li>SNMPv2c/SNMPv3 INFORM PDU
    <pre>import org.snmp4j.ScopedPDU;
    ...
    ScopedPDU pdu = new ScopedPDU();
    pdu.setType(PDU.INFORM);
    // sysUpTime
    long sysUpTime = (System.currentTimeMillis() - startTime) / 10;
    pdu.add(new VariableBinding(SnmpConstants.sysUpTime, new TimeTicks(sysUpTime)));
    pdu.add(new VariableBinding(SnmpConstants.snmpTrapOID, SnmpConstants.linkDown));
    // payload
    pdu.add(new VariableBinding(new OID("1.3.6.1.2.1.2.2.1.1"+downIndex),
    new Integer32(downIndex)));
    ...
    </pre>
    </li>
</ul>
<h4>Target Examples (对象例子)</h4>
<ul>
    <li>Community Target
    <pre>CommunityTarget target = new CommunityTarget();
    target.setCommunity(new OctetString("public"));
    target.setAddress(targetAddress);
    target.setVersion(SnmpConstants.version1);
    </pre>
    <li>User Target
    <pre>UserTarget target = new UserTarget();
    target.setAddress(targetAddress);
    target.setRetries(1);
    // set timeout to 500 milliseconds -&gt; 2*500ms = 1s total timeout
    target.setTimeout(500);
    target.setVersion(SnmpConstants.version3);
    target.setSecurityLevel(SecurityLevel.AUTH_PRIV);
    target.setSecurityName(new OctetString("MD5DES"));
    </pre>
    </li>
</ul>
<h2>Sending SNMP messages</h2>
<p>SNMP message are sent with SNMP4J by using a instance of the SNMP <code><font face="新宋体">Session</font></code> interface. The default implementation of this interface is the <code><font face="新宋体">Snmp</font></code> class. </p>
<p>To setup a <code><font face="新宋体">Snmp</font></code> instance it is sufficient to call its constructor with a <code><font face="新宋体">TransportMapping</font></code> instance. The transport mapping is used by the SNMP session to send (and receive) SNMP message to a remote systems by using a transport protocol, for example the User Datagram Protocol (UDP). </p>
<p>A SNMP4J <code><font face="新宋体">Snmp</font></code> instance supports SNMP v1, v2c, and v3 by default. By sub-classing <code><font face="新宋体">Snmp</font></code> other combinations of those SNMP protocol versions can be supported. </p>
<p>With SNMP4J, SNMP messages can be sent <em>synchronously</em> (blocking) and <em>asynchronously</em> (non-blocking). The <code><font face="新宋体">Snmp</font></code> class does not use an internal thread to process responses on asynchronous and synchronous requests. Nevertheless it uses the receiver threads of the transport mappings to process responses. </p>
<p>Asynchronous responses are returned by calling a callback method on an object instance that implements the <code><font face="新宋体">ResponseListener</font></code> interface. The callback is carried out on behalf of the transport mapping thread that received the response packet from the wire. Thus, if the called method blocks, the delivery of synchronous and asynchronous messages received on the listen port of that transport mapping will be also blocked. Other transport mapping will not be affected. Blocking can be avoided by either using synchronous messages only or by decoupling the processing within the callback method. </p>
<h4>Example for Sending a Synchronous Message (发送同步消息)</h4>
<pre>import org.snmp4j.*;
...
Snmp snmp = new Snmp(new DefaultUdpTransportMapping());
...
ResponseEvent response = snmp.send(requestPDU, target);
if (response.getResponse() == null) {
// request timed out
...
}
else {
System.out.println("Received response from: "+
response.getPeerAddress());
// dump response PDU
System.out.println(response.getResponse().toString());
}
</pre>
<h4>Example for Sending an Asynchronous Message (发送异步消息)</h4>
<pre>import org.snmp4j.*;
import org.snmp4j.event.*;
...
Snmp snmp = new Snmp(new DefaultUdpTransportMapping());
...
ResponseListener listener = new ResponseListener() {
public void onResponse(ResponseEvent event) {
PDU response = event.getResponse();
PDU request = event.getRequest();
if (response == null) {
System.out.println("Request "+request+" timed out");
}
else {
System.out.println("Received response "+response+" on request "+
request);
}
};
snmp.sendPDU(request, target, null, listener);
...
</pre>
<h2>Receiving SNMP messages(接收SNMP信息)</h2>
<p>SNMP4J receives SNMP messages through the listen port of transport mappings. In order to be able to receive responses or requests, that port needs to be set into listen mode. This has to be done by calling the <code><font face="新宋体">listen()</font></code> method of the <code><font face="新宋体">TransportMapping</font></code> instance to start the transport mappings internal listen thread. The internal thread is stopped and the listen port is closed by calling the <code><font face="新宋体">close()</font></code> method on the <code><font face="新宋体">TransportMapping</font></code> instance or the associated <code><font face="新宋体">Snmp</font></code> instance. </p>
<p>The transport mapping just receives the SNMP mesage as a stream of bytes and forwards the message to associated <code><font face="新宋体">MessageDispatcher</font></code> instances. By default, SNMP4J uses one instance of the <code><font face="新宋体">MessageDispatcherImpl</font></code> class for decoding and dispatching incoming messages. That instance is created and used internally by the <code><font face="新宋体">Snmp</font></code> class. </p>
<p>The <code><font face="新宋体">Snmp</font></code> class processes responses to outstanding requests and forwards PDUs of other SNMP messages to registered <code><font face="新宋体">CommandResponder</font></code> listener instances. To receive SNMP messages it is thus sufficient to
<ol>
    <li>Create a <code><font face="新宋体">TransportMapping</font></code> and initialize its listen port by calling <code><font face="新宋体">TransportMapping.listen()</font></code>.
    <li>Create a <code><font face="新宋体">Snmp</font></code> instance with the above <code><font face="新宋体">TransportMapping</font></code>.
    <li>Instantiate a class that implements the <code><font face="新宋体">CommandResponder</font></code> interface and register it with the <code><font face="新宋体">Snmp</font></code> instance by calling <code><font face="新宋体">Snmp.addCommandResponder(CommandResponder)</font></code>. </li>
</ol>
<p>When a unhandled SNMP message (thus a SNMP message where no corresponding outstanding request exists) is received, then the <code><font face="新宋体">processPdu(CommandResponderEvent)</font></code> method of the <code><font face="新宋体">CommandResponder</font></code> will be called with the decoded PDU and additional information about the received SNMP message provided by the message processing model that has decoded the SNMP message. </p>
<h4>Example for Receiving SNMP Messages (接收SNMP消息的例子)</h4>
<pre>import org.snmp4j.*;
import org.snmp4j.smi.*;
import org.snmp4j.mp.SnmpConstants;
...
TransportMapping transport =
new DefaultUdpTransportMapping(new UdpAddress("0.0.0.0/161"));
Snmp snmp = new Snmp(transport);
if (version == SnmpConstants.version3) {
byte[] localEngineID =
((MPv3)snmp.getMessageProcessingModel(MessageProcessingModel.MPv3)).createLocalEngineID();
USM usm = new USM(SecurityProtocols.getInstance(),
new OctetString(localEngineID), 0);
SecurityModels.getInstance().addSecurityModel(usm);
snmp.setLocalEngine(localEngineID, 0, 0);
// Add the configured user to the USM
...
}
snmp.addCommandResponder(this);
transport.listen();
...
public synchronized void processPdu(CommandResponderEvent e) {
PDU command = e.getPdu();
if (command != null) {
...
}
}</pre>
<pre>以下是 org.snmp4j.smi 包下的说明:</pre>
<pre>Provides classes for the representation of SMIv1/v2 data types (which also includes some basic ASN.1 primitive data types).
<p>The <code><font face="新宋体">org.snmp4j.smi</font></code> classes are capable of BER encoding and decoding themself to/from a byte stream. In addition, the SMI data type classes provide convenient functions for manipulating their content. </p>
<p>The <code><font face="新宋体">VariantVariable</font></code> is a special class that can be used in command responder applications to intercept access to a SMI value.</p>
<h4>Variable Binding Examples </h4>
<pre>import org.snmp4j.smi.*;
...
VariableBinding vb = new VariableBinding(new OID("1.3.6.1.2.1.1.4.0"));
vb.setValue(new OctetString("SNMP4J Text"));
...
vb = new VariableBinding();
vb.setOid(new OID(new int[] { 1,3,6,1,2,1,1,2,0 }));
...
vb = new VariableBinding(vb.getOid(), new IpAddress("255.255.255.255"));
...
vb = new VariableBinding(vb.getOid(), new Gauge32(2^32-1));
int syntax = vb.getSyntax();
if (syntax != SMIConstants.SYNTAX_GAUGE32) {
// never reached
}
else {
long value = ((UnsignedInteger32)vb.getValue()).getValue();
System.out.println(vb.getOid() + " = " + value);
// prints: 1.3.6.1.2.1.1.2.0 = 4294967295
}
...
</pre>
<p>The following UML class diagram shows the most important classes of the <code><font face="新宋体">org.snmp4j.smi</font></code> package and their relationships (relationships to other packages are not shown): </p>
<p><a href="http://www.snmp4j.org/doc/org/snmp4j/smi/doc-files/org_snmp4j_smi.gif" target="_blank"><font color="#0000ff">UML类图</font></a></p>
</pre>
<pre>以下是 org.snmp.asn1 包中的说明</pre>
<pre>Provides classes and interfaces for the mapping between Abstract Syntax Notation One (ASN.1) formatted values and their transfer syntax according to the Basic Encoding Rules (BER).
<p>The <code><font face="新宋体">org.snmp4j.asn1</font></code> classes are capable of serializing of ASN.1 formatted values into a byte stream and deserializing the same from a byte stream. There are three groups of classes/interfaces in this package:
<ul>
    <li>The <code><font face="新宋体">BER</font></code> class implements the BER serialization and deserialization by providing static methods for encoding/decoding of primitive ASN.1 and Structure of Management Information (SMI) data types.
    <li>The <code><font face="新宋体">BERSerializable</font></code> interface provides a common interface for all objects that are (de)serializable according to the Basic Encoding Rules (BER).
    <li>The <code><font face="新宋体">BERInputStream</font></code> and the <code><font face="新宋体">BEROutputStream</font></code> provide optimized implementations for the serialization and deserialization of the <code><font face="新宋体">InputStream</font></code> and <code><font face="新宋体">OutputStream</font></code> abstract classes. </li>
</ul>
<p>&nbsp;</p>
<p>The following UML class diagram shows the most important classes of the <code><font face="新宋体">org.snmp4j.asn1</font></code> package and their relationships (relationships to other packages are not shown): </p>
<img src="file:///C:/Documents%20and%20Settings/Admin/Local%20Settings/Temp/Rar$EX23.172/snmp4j/src/org/snmp4j/asn1/doc-files/org_snmp4j_asn1.gif" name="UML Class Diagram org.snmp4j.asn1"  alt="" /> </pre>
<pre>以下是 org.snmp4j.mp 包中的说明</pre>
<pre>Provides classes and interfaces for the SNMP message processing.
<p>The <code><font face="新宋体">org.snmp4j.mp</font></code> classes provide services to process SNMP messages. The services provided are defined in the <code><font face="新宋体">MessageProcessingModel</font></code> interface and include the following:
<ul>
    <li>Prepare data elements from an incoming SNMP message as described in RFC3412 &#167;7.2.
    <li>Prepare a response message as defined in RFC3412 &#167;7.1.
    <li>Prepare an outgoing message as defined in RFC3412 &#167;7.1. </li>
</ul>
<p>&nbsp;</p>
<p>This interface is implemented by the message processing model classes for the SNMP versions 1, v2c, and v3: <code><font face="新宋体">MPv1</font></code>, <code><font face="新宋体">MPv2c</font></code>, and <code><font face="新宋体">MPv3</font></code>. </p>
The <code><font face="新宋体">MessageDispatcherImpl</font></code> chooses which message processing model it uses to process an outgoing or incoming SNMP message based on the SNMP version of the message. The SNMP version is either extracted from the message header (incoming message) or from the <code><font face="新宋体">Target</font></code> instance associated with the outgoing PDU (ougoing message).
<p>To be able to match requests and responses SNMP uses request IDs. Since request IDs are created by the command generator, the request IDs are unique within such a command generator only. SNMP4J therefore has to abstract from request IDs and uses <code><font face="新宋体">PduHandle</font></code> instances instead. </p>
<p>If a <code><font face="新宋体">PDU</font></code> is processed for sending by the SNMP4J <code><font face="新宋体">MessageDispatcherImpl</font></code> and the PDU's request ID is set to 0, then a SNMP4J application wide unique ID is generated and set as request ID of the supplied PDU. In any case, the PDU's request ID will be used as transaction ID of the outgoing message. The transaction ID identifies a messages <code><font face="新宋体">PduHandle</font></code>. </p>
<p>If a <code><font face="新宋体">PDU</font></code> is received by the SNMP4J <code><font face="新宋体">MessageDispatcherImpl</font></code> a unique transaction ID is generated so that command responders as well as the message processing model can match requests and responses. </p>
<p>The following UML class diagram shows the most important classes of the <code><font face="新宋体">org.snmp4j.mp</font></code> package and their relationships (relationships to other packages are not shown): </p>
<img src="file:///C:/Documents%20and%20Settings/Admin/Local%20Settings/Temp/Rar$EX36.469/snmp4j/src/org/snmp4j/mp/doc-files/org_snmp4j_mp.gif" name="UML Class Diagram org.snmp4j.mp"  alt="" /> </pre>
<pre>以下是 org.snmp4j.transport 包中的说明</pre>
<pre>Provides transport protocol mappings for SNMP.
<p>The <code><font face="新宋体">org.snmp4j.transport</font></code> classes are capable of sending and receiving byte messages to and from a network using transport mapping specific transport protocol. All SNMP4J transport mappings have to implement the <code><font face="新宋体">org.snmp4j.TransportMapping</font></code> interface. SNMP4J supports two transport mappings for the transport protocols UDP and TCP: </p>
<ul>
    <li>The UDP transport mapping is the default SNMP transport mapping. It is implemented by the <code><font face="新宋体">DefaultUdpTransportMapping</font></code> class.
    <li>The TCP transport mapping is implemented by the <code><font face="新宋体">DefaultTcpTransportMapping</font></code> using the <code><font face="新宋体">java.nio</font></code> package. </li>
</ul>
<p>Additional transport mappings can be easily added. It is sufficient to implement the <code><font face="新宋体">org.snmp4j.TransportMapping</font></code> interface and add an instance of that class to the <code><font face="新宋体">Snmp</font></code> (or <code><font face="新宋体">MessageDispatcher</font></code>) object. To be able to lookup a transport mapping by an <code><font face="新宋体">Address</font></code> class via the <code><font face="新宋体">TransportMappings</font></code> (as <code><font face="新宋体">Snmp</font></code> does for notification listeners), a transport mapping has to be registered in a transport mapping registration file. The default file is <code><font face="新宋体">transports.properties</font></code> in the <code><font face="新宋体">org.snmp4j.transport</font></code> package. To use a different file, set the system property <code><font face="新宋体">org.snmp4j.transportMappings</font></code>. </p>
<p>Connection-oriented transport mappings like TCP should implement the <code><font face="新宋体">ConnectionOrientedTransportMapping</font></code> interface to support <code><font face="新宋体">MessageLengthDecoder</font></code> and <code><font face="新宋体">TransportStateListener</font></code>.</p>
<p>The following UML class diagram shows the classes of the <code><font face="新宋体">org.snmp4j.transport</font></code> package and their relationships (relationships to other packages are not shown): </p>
<img alt="UML Class Diagram org.snmp4j.transport" src="file:///C:/Documents%20and%20Settings/Admin/Local%20Settings/Temp/Rar$EX49.297/snmp4j/src/org/snmp4j/transport/doc-files/org_snmp4j_transport.gif" name="UML Class Diagram org.snmp4j.transport" /> </pre>
<pre>以下是 org.snmp4j.util 包中的说明</pre>
<pre>Contains table retrieval utilities and multi-threading support classes as well as miscellaneous utility classes.
<p>The <code><font face="新宋体">org.snmp4j.util</font></code> contains the following groups of classes: </p>
<ul>
    <li>Classes for SNMP table retrieval. The class <code><font face="新宋体">TableUtils</font></code> can be used to asynchronously retrieve table data effeciently row by row.
    <li>Classes for support of multi-threaded message dispatching. The class <code><font face="新宋体">MultiThreadedMessageDispatcher</font></code> implements the <code><font face="新宋体">MessageDispatcher</font></code> interface and uses the <code><font face="新宋体">MessageDispatcherImpl</font></code> class to dispatch incoming message using the threads of a <code><font face="新宋体">ThreadPool</font></code>. </li>
</ul>
<p>The following UML class diagram shows the classes of the <code><font face="新宋体">org.snmp4j.util</font></code> package and their relationships (relationships to other packages are not shown): </p>
<img src="file:///C:/Documents%20and%20Settings/Admin/Local%20Settings/Temp/Rar$EX54.625/snmp4j/src/org/snmp4j/util/doc-files/org_snmp4j_util.gif" name="UML Class Diagram org.snmp4j.transport"  alt="" /> </pre>
<img src ="http://www.blogjava.net/tbest/aggbug/240403.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/tbest/" target="_blank">liujg</a> 2008-11-13 22:35 <a href="http://www.blogjava.net/tbest/articles/240403.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Serializable 相关（http://www.lupaworld.com/25070/viewspace_16379.html）</title><link>http://www.blogjava.net/tbest/articles/212171.html</link><dc:creator>liujg</dc:creator><author>liujg</author><pubDate>Wed, 02 Jul 2008 09:39:00 GMT</pubDate><guid>http://www.blogjava.net/tbest/articles/212171.html</guid><wfw:comment>http://www.blogjava.net/tbest/comments/212171.html</wfw:comment><comments>http://www.blogjava.net/tbest/articles/212171.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/tbest/comments/commentRss/212171.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/tbest/services/trackbacks/212171.html</trackback:ping><description><![CDATA[<p>类通过实现 java.io.Serializable 接口以启用其序列化功能。未实现此接口的类将无法使其任何状态序列化或反序列化。可序列化类的所有子类型本身都是可序列化的。序列化接口没有方法或字段，仅用于标识可序列化的语义.<br />
Java的"对象序列化"能让你将一个实现了Serializable接口的对象转换成一组byte，这样日后要用这个对象时候，你就能把这些byte数据恢复出来，并据此重新构建那个对象了。<br />
要想序列化对象，你必须先创建一个OutputStream，然后把它嵌进ObjectOutputStream。这时，你就能用writeObject( )方法把对象写入OutputStream了。<br />
writeObject 方法负责写入特定类的对象的状态，以便相应的 readObject 方法可以还原它。通过调用 out.defaultWriteObject 可以调用保存 Object 的字段的默认机制。该方法本身不需要涉及属于其超类或子类的状态。状态是通过使用 writeObject 方法或使用 DataOutput 支持的用于基本数据类型的方法将各个字段写入 ObjectOutputStream 来保存的。<br />
http://www.lupaworld.com/25070/viewspace_16379.html</p>
<img src ="http://www.blogjava.net/tbest/aggbug/212171.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/tbest/" target="_blank">liujg</a> 2008-07-02 17:39 <a href="http://www.blogjava.net/tbest/articles/212171.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>关于forward和redirect的区别（转载）</title><link>http://www.blogjava.net/tbest/articles/212168.html</link><dc:creator>liujg</dc:creator><author>liujg</author><pubDate>Wed, 02 Jul 2008 09:19:00 GMT</pubDate><guid>http://www.blogjava.net/tbest/articles/212168.html</guid><wfw:comment>http://www.blogjava.net/tbest/comments/212168.html</wfw:comment><comments>http://www.blogjava.net/tbest/articles/212168.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/tbest/comments/commentRss/212168.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/tbest/services/trackbacks/212168.html</trackback:ping><description><![CDATA[<font style="color: rgb(0,1,2)" color="#226ddd" size="2">forward是服务器请求资源，服务器直接访问目标地址的URL，把那个URL的响应内容读取过来，然后把这些内容再发给浏览器，浏览器根本不知道服务器发送的内容是从哪儿来的，所以它的地址栏中还是原来的地址。还有，转发是在web应用程序之内进行的，可以访问web应用程序所设定的内部目录，像是WEB-INF目录，只能在Web应用程序中进行，不能指定至其它的Web应用程序的地址。<br />
<span style="display: none">Tsj:J\vn,CR*|C0</span>redirect就是服务端根据逻辑,发送一个状态码,告诉浏览器重新去请求那个地址，一般来说浏览器会用刚才请求的所有参数重新请求，所以session,request参数都可以获取。web应用程序会要求客户端浏览器重新发出请求地址，客户端会重新连接至所指定的地址，因此浏览器的地址会出现重新导向的信息，重新导向后的请求由浏览器发出，所以不能访问Web应用程序中的隐藏目录，像是WEB-INF，重新是由浏览器重新要求一个网页，可以指定至<a onclick="javascript:tagshow(event, '%C6%E4%CB%FB');" href="javascript:;" target="_self"><u><strong>其他</strong></u></a>的Web应用程序地址。</font><font style="color: rgb(0,1,2)" size="2"><span style="display: none">LUPA开源社区%ZY-m!N?+M v2D+H R%[</span><br />
<span style="display: none">LUPA开源社区Lz-x9O(p;[ S</span><br />
<br />
<span style="display: none">'M"O$M.Iw,T;K`0</span>RequestDispatcher.forward()方法和HttpServletResponse.sendRedirect()方法的区别是：前者仅是容器中控制权的转向，在客户端浏览器地址栏中不会显示出转向后的地址，他是不会改变Request的值，如果你需要在下一个页面中能从中获取新的信息的话，你可以Request.setAttribute()来放置一些标志，这样从下一个页面中获取；后者则是完全的跳转，浏览器将会得到跳转的地址，并重新发送请求链接。这样，从浏览器的地址栏中可以看到跳转后的链接地址。所以，前者更加高效，在前者可以满足需要时，尽量使用Request Dispatcher.forward()方法，并且，这样也有助于隐藏实际的链接。在有些情况下，比如，需要跳转到一个其它服务器上的资源，则必须使用 HttpServletResponse.sendRequest()方法。<span style="display: none">LUPA开源社区;Xh~OI</span><br />
<br />
<span style="display: none">Thi5~X0</span></font><font style="color: rgb(0,1,2)" size="2">1、forward与include共亨Request范围内的对象,而redirect则不行，即：如果一个javabean被声明为request范围的话，则被forward到的资源也可以访问这个javabean,而redriect则不行。<br />
<span style="display: none">Y7u(H9?&amp;F8b0</span>2、forward与include基本上都是转发到context内部的资源，而redirect可以重定向到外部的资源,如： req.sendRedriect("http://www.mocuai.com");<span style="display: none">LUPA开源社区C {4_jC^+N</span><br />
</font>
<div style="color: rgb(0,1,2)"></div>
<br />
<img src ="http://www.blogjava.net/tbest/aggbug/212168.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/tbest/" target="_blank">liujg</a> 2008-07-02 17:19 <a href="http://www.blogjava.net/tbest/articles/212168.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>