﻿<?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/jiangmin/category/14714.html</link><description>：“最重要的是忠实于自己，忠实于你爱的人，还有要努力工作。我指的是不能想明天，只有今天拼命工作，不停的练习，不停的奋斗。我指的是开发你的智力，让它达到最高的水平，尽自己最大的力量去做得最好，在你职业的领域里，要比任何活着的人都懂得多。你还得学会运用一切条件，抓住每一分机会：手头的一本书，可以跳舞的一块地板，或者可以游泳的一池水，只要是你的，都要加以利用。”</description><language>zh-cn</language><lastBuildDate>Wed, 26 Aug 2009 20:29:33 GMT</lastBuildDate><pubDate>Wed, 26 Aug 2009 20:29:33 GMT</pubDate><ttl>60</ttl><item><title>hibernate 经验谈</title><link>http://www.blogjava.net/jiangmin/articles/292025.html</link><dc:creator>JiangMin</dc:creator><author>JiangMin</author><pubDate>Thu, 20 Aug 2009 15:51:00 GMT</pubDate><guid>http://www.blogjava.net/jiangmin/articles/292025.html</guid><wfw:comment>http://www.blogjava.net/jiangmin/comments/292025.html</wfw:comment><comments>http://www.blogjava.net/jiangmin/articles/292025.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jiangmin/comments/commentRss/292025.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jiangmin/services/trackbacks/292025.html</trackback:ping><description><![CDATA[Hibernate不是盏省油的灯，也不是想像的射来射去很简单的事。有很多细节处理不好会让你很不舒服的，这方面最突出的表现在两方面：一是事务管理，是JTA事务还是JDBC事务？幸亏有了Spring和J2EE容器；二是胡乱映射，模型关系建立不合理或者错误导致，或者是映射策略和技术不过关导致。这样的最终结果是抛出一堆HibernateException，摸不着头脑。下面是我实践中的一些总结作为备忘录写出来。参考的是最新的Hibernate 3.2.6GA API文档，还吸收了Hibernate牛人（夏新）写的书和翻译中文开发手册的精华。 <br />
<br />
1、Configuration/SessionFactory/Session <br />
&nbsp;&nbsp; Configuration实例代表了一个应用程序中Java类型 到SQL数据库映射的完整集合. Configuration被用来构建一个(不可变的 (immutable))SessionFactory. <br />
&nbsp;&nbsp; SessionFactory是线程安全的，创建代价很高。 <br />
&nbsp;&nbsp;&nbsp; Session是非线程安全的，轻量级的。一个Session对应一个JDBC连接， <br />
&nbsp;&nbsp;&nbsp; Session的connection()会获取Session与之对应的数据库连接Connection对象。 <br />
&nbsp;&nbsp;&nbsp; Session的功能就是操作对象的，这些对象和数据库表有映射关系。 <br />
&nbsp;&nbsp;&nbsp; Session操作的对象是有状态的，分三类： <br />
&nbsp;&nbsp;&nbsp; 自由状态（transient）: 未持久化，未与任何Session相关联，数据库表中没有对应的记录。 <br />
&nbsp;&nbsp;&nbsp; 持久化状态（persistent）: 与一个Session相关联，对应数据库表中一条记录。 <br />
&nbsp;&nbsp;&nbsp; 游离状态（detached）: 已经进行过持久化，但当前未与任何Session相关联，数据库表中曾经有一条记录，现在还有没有就不知道了。 <br />
<br />
&nbsp;&nbsp;&nbsp; 游离状态的实例可以通过调用save()、persist()或者saveOrUpdate()方法进行持久化。持久化实例可以通过调用 delete()变成游离状态。通过get()或load()方法得到的实例都是持久化状态的。游离状态的实例可以通过调用 update()、0saveOrUpdate()、lock()或者replicate()进行持久化。游离或者自由状态下的实例可以通过调用merge()方法成为一个新的持久化实例。 <br />
<br />
2、Session的save()/persist()/update()/saveOrUpdate()/merge()/delete()方法 <br />
&nbsp;&nbsp;&nbsp; save()方法将指定对象保存，插入表中一条数据； <br />
&nbsp;&nbsp;&nbsp; persist()方法将指定对象保存，插入表中一条数据，我还没发现它和save方法有什么特别之处。 <br />
&nbsp;&nbsp;&nbsp; replicate()方法完全使用给定对象各个属性的值（包括标识id）来持久化给定的游离状态（Transient）的实体，很暴力啊，其中还需要指定存储模式（有四种保存策略供选择）。 <br />
&nbsp;&nbsp;&nbsp; update()方法将指定对象更新，更新表中一条数据； <br />
&nbsp;&nbsp;&nbsp; saveOrUpdate()方法接收一个实体对象，根据实体对象的id判断是否已经存在进行保存或更新操作，这样保存和更新方法就统一了； <br />
&nbsp;&nbsp;&nbsp; merge()方法将给定的对象的状态复制到具有相同标识的持久化对象上。 <br />
&nbsp;&nbsp;&nbsp; delete()方法将指定对象删除，删除表中一条数据； <br />
<br />
&nbsp;&nbsp;&nbsp; 特别注意：为了使用saveOrUpdate()方法，在由定义映射文件时，通过设定&lt;id&gt;标签的unsaved-value="null"来判断执行什么操作： 当id属性等于unsaved-value的值（在此为null）时，则认为还没有保存，应该执行保存操作，否则执行更新操作。这样设定之后，可以使用saveOrUpdate()方法来统一保存和更新的方法。 <br />
<br />
&nbsp;&nbsp;&nbsp; &lt;id name="id" column="id" type="java.lang.Integer" unsaved-value="null"&gt; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;generator class="native"/&gt; <br />
&nbsp;&nbsp;&nbsp; &lt;/id&gt; <br />
<br />
unsaved-value可以设定的值有四个： <br />
&nbsp;&nbsp;&nbsp; any：总是储存 <br />
&nbsp;&nbsp;&nbsp; none：总是更新 <br />
&nbsp;&nbsp;&nbsp; null：id为null时储存（预设） <br />
&nbsp;&nbsp;&nbsp; valid：id为null或是指定值时储存 <br />
<br />
3、Session的get()/load()方法 <br />
&nbsp;&nbsp;&nbsp; get()方法会总是查询实体对象，不存在时候返回null； <br />
&nbsp;&nbsp;&nbsp; load()方法也是获取一个实体对象，不存在时候抛空指针异常。 <br />
<br />
4、Session的clear()/evict()方法 <br />
&nbsp;&nbsp;&nbsp; clear()方法清除Session级别缓存中的所有实体（包括各种状态）对象，目的是释放内存。 <br />
&nbsp;&nbsp;&nbsp; evict()方法清除Session级别缓存中的指定的实体（包括各种状态）对象。 <br />
&nbsp;&nbsp;&nbsp; 当然，Session关闭后，这些缓存也就不存在了，会等待JVM回收。 <br />
<br />
5、Session的flush()方法 <br />
&nbsp;&nbsp;&nbsp; flush()强制持久化Session缓存中的实体对象。一般还会调用clear()或evict()，目的是赶紧保存，释放宝贵内存资源。 <br />
<br />
6、Session的commit()/rollback()方法 <br />
&nbsp;&nbsp;&nbsp; commit()方法用于提交Session上的事务，否则工作单元不会对数据库产生影响。如果执行出现异常（也就是commit()失败了），则之前的操作取消，执行rollback()可撤消之前的操作。 <br />
<br />
7、Session的close()/isOpen()/isConnected()/reconnect()方法 <br />
&nbsp;&nbsp;&nbsp; close()方法关闭Session所对应数据库连接，与其相关联的对象生命周期结束。 <br />
&nbsp;&nbsp;&nbsp; isOpen()方法检查Session是否仍然打开，如果Session已经断开，则可以使用reconnect(Connection connection)来重新让Session关联一个JDBC连接。 <br />
&nbsp;&nbsp;&nbsp; isConnected()方法检查当前Session是否处于连接状态。 <br />
<br />
8、Criteria、DetchedCriteria和Query接口 <br />
&nbsp;&nbsp;&nbsp; Criteria和Query的实例都是和Session绑定的，其生命周期跟随着Session结束而结束。 <br />
&nbsp;&nbsp;&nbsp; DetchedCriteria实例相当于一个SQL模板，目的是为了复用。其中的getExecutableCriteria(session)方法接收一个Session对象，并与之绑定，返回一个Criteria对象。 <br />
<br />
9、Hibernate类的initialize()方法 <br />
&nbsp;&nbsp;&nbsp; initialize()方法强制Hibernate立即加载指定实体所关联的对象和集合。Hibernate类中还有其他几个很有用但不适很常用的方法。 <br />
<br />
10、映射文件中的lazy属性 <br />
&nbsp;&nbsp;&nbsp; 在Hibernate3中，class元素的lazy属性默认是true，如果不需要，则需要显示指定为lazy="false"，否则，操作load返回的对象会抛异常。另外Hibernate3中还可以为实体属性指定lazy属性。 <br />
<br />
11、JDBC事务和JTA事务 <br />
&nbsp;&nbsp;&nbsp; Hibernate本身没有事务管理功能，它依赖于JDBC或JTA的事务管理功能，在Hibernate配置文件中，如果不显式指定Transaction的工厂类别属性hibernate.transaction.factory_class的配置，则默认为JDBC事务： <br />
&nbsp;&nbsp;&nbsp; &lt;property name="hibernate.transaction.factory_class"&gt;org.hibernate.transaction.JDBCTransactionFactory&lt;/property&gt;。 <br />
&nbsp;&nbsp;&nbsp; 在通过SessionFactory获取到Session后，与Session相关联的JDBC Connection实例就被设定为false。 <br />
<br />
&nbsp;&nbsp;&nbsp; 特别注意：如果数据库不支持事务，比如MySQL的MyISAM引擎的表就不支持事务，声明事务也不会起作用。要使MySQL5的表支持事务，则可以指定表的引擎类型为InnoDB。如果是学习或者研究，目前最好还是使用PostgreSQL 8.3或DB2、Oracle。 <br />
JDBC事务总是和一个数据库连接（或一个Session）相关联的。 <br />
&nbsp;&nbsp;&nbsp; JTA事务则可以跨越多个数据连接（或多个Session），这些连接还可以是不同数据库的连接，JTA事务一般由容器进行管理。编程只要在多个操作单元的开始和结束定义JTA事务的边界即可。 <br />
<br />
&nbsp;&nbsp;&nbsp; 特别注意：如果使用了JTA事务，则不能再用在JDBC式的事务来管理每个Session的操作，否则会出错。为了程序的的通用性，一般来说，都是使用JTA事务来构建应用，这使用任何环境。当然，也可以使用事务代理为每个JDBC的操作方法加入事务控制。这样也为程序以后移植到JTA容器事务上带来很大方便。其实现在可以使用Spring的事务管理，与Hibernate结合的非常完美。 
<img src ="http://www.blogjava.net/jiangmin/aggbug/292025.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jiangmin/" target="_blank">JiangMin</a> 2009-08-20 23:51 <a href="http://www.blogjava.net/jiangmin/articles/292025.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JBPM 流程定义工具</title><link>http://www.blogjava.net/jiangmin/articles/JBPM-JPDL-FLEX-workflow.html</link><dc:creator>JiangMin</dc:creator><author>JiangMin</author><pubDate>Wed, 10 Jun 2009 08:07:00 GMT</pubDate><guid>http://www.blogjava.net/jiangmin/articles/JBPM-JPDL-FLEX-workflow.html</guid><wfw:comment>http://www.blogjava.net/jiangmin/comments/281174.html</wfw:comment><comments>http://www.blogjava.net/jiangmin/articles/JBPM-JPDL-FLEX-workflow.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jiangmin/comments/commentRss/281174.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jiangmin/services/trackbacks/281174.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;最近使用Flex做了一个流程定义工具，实现在web上画流程图，并输出对应的符合JPDL的XML文本。<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<img height="569" alt="" src="http://www.blogjava.net/images/blogjava_net/jiangmin/WFD-JBPM.jpg" width="800" border="0" /><br />
<br />
<br />
<br />
<img alt="" src="http://www.blogjava.net/images/blogjava_net/jiangmin/WFD-JPDL.jpg" border="0" />
<img src ="http://www.blogjava.net/jiangmin/aggbug/281174.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jiangmin/" target="_blank">JiangMin</a> 2009-06-10 16:07 <a href="http://www.blogjava.net/jiangmin/articles/JBPM-JPDL-FLEX-workflow.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>基于GWT-EXT Hibernate的工作流引擎</title><link>http://www.blogjava.net/jiangmin/articles/GWT-EXTHibernateworkflow.html</link><dc:creator>JiangMin</dc:creator><author>JiangMin</author><pubDate>Wed, 15 Apr 2009 08:49:00 GMT</pubDate><guid>http://www.blogjava.net/jiangmin/articles/GWT-EXTHibernateworkflow.html</guid><wfw:comment>http://www.blogjava.net/jiangmin/comments/265792.html</wfw:comment><comments>http://www.blogjava.net/jiangmin/articles/GWT-EXTHibernateworkflow.html#Feedback</comments><slash:comments>7</slash:comments><wfw:commentRss>http://www.blogjava.net/jiangmin/comments/commentRss/265792.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jiangmin/services/trackbacks/265792.html</trackback:ping><description><![CDATA[<p><br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;以下是本人开发的基于GWT-EXT&nbsp;和Hibernate的工作流系统。拿出来秀一下！<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</p>
<p><img height="737" alt="" src="http://www.blogjava.net/images/blogjava_net/jiangmin/login.jpg" width="1024" border="0" /><br />
<br />
<img height="737" alt="" src="http://www.blogjava.net/images/blogjava_net/jiangmin/hp.jpg" width="1024" border="0" /><br />
<img height="737" alt="" src="http://www.blogjava.net/images/blogjava_net/jiangmin/gm.jpg" width="1024" border="0" /></p>
<p><img height="737" alt="" src="http://www.blogjava.net/images/blogjava_net/jiangmin/myinfo.jpg" width="1024" border="0" /><br />
<img height="737" alt="" src="http://www.blogjava.net/images/blogjava_net/jiangmin/pc.jpg" width="1024" border="0" /><br />
<img height="737" alt="" src="http://www.blogjava.net/images/blogjava_net/jiangmin/Action.jpg" width="1024" border="0" /><br />
<img height="737" alt="" src="http://www.blogjava.net/images/blogjava_net/jiangmin/wfp.jpg" width="1024" border="0" /><br />
<img height="737" alt="" src="http://www.blogjava.net/images/blogjava_net/jiangmin/inc.jpg" width="1024" border="0" /><br />
</p>
<img src ="http://www.blogjava.net/jiangmin/aggbug/265792.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jiangmin/" target="_blank">JiangMin</a> 2009-04-15 16:49 <a href="http://www.blogjava.net/jiangmin/articles/GWT-EXTHibernateworkflow.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Apache Axis初级教程---安装、应用  </title><link>http://www.blogjava.net/jiangmin/articles/187596.html</link><dc:creator>JiangMin</dc:creator><author>JiangMin</author><pubDate>Thu, 20 Mar 2008 16:37:00 GMT</pubDate><guid>http://www.blogjava.net/jiangmin/articles/187596.html</guid><wfw:comment>http://www.blogjava.net/jiangmin/comments/187596.html</wfw:comment><comments>http://www.blogjava.net/jiangmin/articles/187596.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jiangmin/comments/commentRss/187596.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jiangmin/services/trackbacks/187596.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 本文讲述了Apache Axis的安装及简单应用，作为Apache Axis的一个入门教程。虽然现在Apache Web Service项目已经推出了Apache Axis2，Axis2相对Axis是一个很大的更新，关于Apache Axis2的介绍，请参考http://ws.apache.org/axis2，目前的版本是1.3。既然已经有了Apache Axis2这个更加优秀的Web Servi...&nbsp;&nbsp;<a href='http://www.blogjava.net/jiangmin/articles/187596.html'>阅读全文</a><img src ="http://www.blogjava.net/jiangmin/aggbug/187596.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jiangmin/" target="_blank">JiangMin</a> 2008-03-21 00:37 <a href="http://www.blogjava.net/jiangmin/articles/187596.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JAVA处理日期（Date）时间（Time）以及相关类的介绍</title><link>http://www.blogjava.net/jiangmin/articles/183681.html</link><dc:creator>JiangMin</dc:creator><author>JiangMin</author><pubDate>Tue, 04 Mar 2008 05:39:00 GMT</pubDate><guid>http://www.blogjava.net/jiangmin/articles/183681.html</guid><wfw:comment>http://www.blogjava.net/jiangmin/comments/183681.html</wfw:comment><comments>http://www.blogjava.net/jiangmin/articles/183681.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jiangmin/comments/commentRss/183681.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jiangmin/services/trackbacks/183681.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: JAVA处理日期时间常用方法： &lt;!--[if !supportLists]--&gt;1.&nbsp;&nbsp;&nbsp; &lt;!--[endif]--&gt;java.util.Calendar Calendar 类是一个抽象类，它为特定瞬间与一组诸如 YEAR、MONTH、DAY_OF_MONTH、HOUR 等 日历字段之间的转换提供了一些方法，并为操作日历字段（例如获...&nbsp;&nbsp;<a href='http://www.blogjava.net/jiangmin/articles/183681.html'>阅读全文</a><img src ="http://www.blogjava.net/jiangmin/aggbug/183681.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jiangmin/" target="_blank">JiangMin</a> 2008-03-04 13:39 <a href="http://www.blogjava.net/jiangmin/articles/183681.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>(原)一个remedy java api 实现操纵ARS数据的通用类(包括附件上传与下载)</title><link>http://www.blogjava.net/jiangmin/articles/124862.html</link><dc:creator>JiangMin</dc:creator><author>JiangMin</author><pubDate>Sun, 17 Jun 2007 17:01:00 GMT</pubDate><guid>http://www.blogjava.net/jiangmin/articles/124862.html</guid><wfw:comment>http://www.blogjava.net/jiangmin/comments/124862.html</wfw:comment><comments>http://www.blogjava.net/jiangmin/articles/124862.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/jiangmin/comments/commentRss/124862.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jiangmin/services/trackbacks/124862.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 负责控制ARS的类：package&nbsp;remedy.api;import&nbsp;java.io.File;import&nbsp;java.io.IOException;import&nbsp;java.io.InputStream;import&nbsp;java.util.HashMap;import&nbsp;java.util.Iterator;import&nbsp;ja...&nbsp;&nbsp;<a href='http://www.blogjava.net/jiangmin/articles/124862.html'>阅读全文</a><img src ="http://www.blogjava.net/jiangmin/aggbug/124862.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jiangmin/" target="_blank">JiangMin</a> 2007-06-18 01:01 <a href="http://www.blogjava.net/jiangmin/articles/124862.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>dom4j学习-创建xml文档,修改xml和递归输出xml</title><link>http://www.blogjava.net/jiangmin/articles/122016.html</link><dc:creator>JiangMin</dc:creator><author>JiangMin</author><pubDate>Mon, 04 Jun 2007 15:55:00 GMT</pubDate><guid>http://www.blogjava.net/jiangmin/articles/122016.html</guid><wfw:comment>http://www.blogjava.net/jiangmin/comments/122016.html</wfw:comment><comments>http://www.blogjava.net/jiangmin/articles/122016.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jiangmin/comments/commentRss/122016.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jiangmin/services/trackbacks/122016.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: dom4j的官方地址：http://www.dom4j.org/下载dom4j开发包：http://sourceforge.net/project/showfiles.php?group_id=16035下载完dom4j之后，在dom4j的docs/cookbook.html里有详细的入门手册，而在src/samples里面则是一些样例,详细介绍了怎样进行入门介绍dom4j的一个最...&nbsp;&nbsp;<a href='http://www.blogjava.net/jiangmin/articles/122016.html'>阅读全文</a><img src ="http://www.blogjava.net/jiangmin/aggbug/122016.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jiangmin/" target="_blank">JiangMin</a> 2007-06-04 23:55 <a href="http://www.blogjava.net/jiangmin/articles/122016.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>用JTidy转换html为xml</title><link>http://www.blogjava.net/jiangmin/articles/122015.html</link><dc:creator>JiangMin</dc:creator><author>JiangMin</author><pubDate>Mon, 04 Jun 2007 15:48:00 GMT</pubDate><guid>http://www.blogjava.net/jiangmin/articles/122015.html</guid><wfw:comment>http://www.blogjava.net/jiangmin/comments/122015.html</wfw:comment><comments>http://www.blogjava.net/jiangmin/articles/122015.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jiangmin/comments/commentRss/122015.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jiangmin/services/trackbacks/122015.html</trackback:ping><description><![CDATA[最近要从网页中提取信息，想先把html转换成标准的xml格式，然后方便使用dom4j进行后续的分析，试用了不少现成的类库，JTidy、NekoHTML、HTML Parser、Jericho，最后还是使用了JTidy。
<p>　　只是r8 snapshot还只是一个nightly builds，前面的r7版更已经是4年前的事了，这个项目就这样荒废了？可能是参与的人太少又或者是觉得已经成熟？</p>
<p>　　JTidy提供了一个语法检查器和标签补偿器，能够对各种乱七八糟的html进行修复，使之符合xhtml标准。</p>
<p>　　r8 snapshot相对于r7改变了一些参数的设置方法，特别是在字符编码处理上，用setInputEncoding和setOutputEncoding方法来确定输入和输出文件的字符编码，可以使用任何有效的Java编码名称，这就比以前的强多了。</p>
<p>　　总体上解析的结果还不错，只是有些地方还需要对生成文件进行手工调整，或者自己再编一段代码处理一下，已经不是大问题了。</p>
<p>　　<strong>一些常用的参数设置：</strong></p>
<p>setAltText(java.lang.String altText) <br>加上默认的alt属性值<br>setBreakBeforeBR(boolean breakBeforeBR) <br>在换行&lt;br /&gt;之前加一空行<br>setCharEncoding(int charencoding) <br>已废弃<br>setConfigurationFromFile(java.lang.String filename) <br>从文件中读取配置信息<br>setConfigurationFromProps(java.util.Properties props) <br>从properties中读取配置信息<br>setErrfile(java.lang.String errfile) <br>错误输出文件<br>setFixBackslash(boolean fixBackslash) <br>URL中用/取代\<br>setForceOutput(boolean forceOutput) <br>不管生成的xml是否有错，强制输出。<br>setHideComments(boolean hideComments) <br>结果中不生成注释<br>setInputEncoding(java.lang.String encoding) <br>输入编码<br>setLogicalEmphasis(boolean logicalEmphasis) <br>用em替代i，strong替代b<br>setMessageListener(TidyMessageListener listener) <br>加入一个TidyMessageListener监听器<br>setOnlyErrors(boolean onlyErrors) <br>只输出错误文件<br>setOutputEncoding(java.lang.String encoding) <br>输出编码<br>setPrintBodyOnly(boolean bodyOnly) <br>只输出body中的部分<br>setRepeatedAttributes(int repeatedAttributes) <br>重复属性的处理<br>setSpaces(int spaces) <br>每行前的空格数，就是缩进格式<br>setTidyMark(boolean tidyMark) <br>是否生成tidy标记<br>setTrimEmptyElements(boolean trimEmpty) <br>不输出空元素<br>setUpperCaseAttrs(boolean upperCaseAttrs) <br>属性变大写<br>setUpperCaseTags(boolean upperCaseTags) <br>标记变大写<br>setWraplen(int wraplen) <br>多长换行<br>setXHTML(boolean xhtml) <br>输出xhtml<br>setXmlOut(boolean xmlOut) <br>输出xml<br>setXmlPi(boolean xmlPi) <br>文件头输出xml标记<br>setXmlSpace(boolean xmlSpace) <br>加入xml名字空间属性</p>
<p>使用方法极为easy，定义输入输出流，用tidy.parse()转换就行了：</p>
<p>BufferedInputStream in;</p>
<p>FileOutputStream out;</p>
<p>Tidy tidy = new Tidy();</p>
<p>tidy.setConfigurationFromFile(configFileName);//配置文件，写入上面的设置参数</p>
<p>try {</p>
<p>in = new BufferedInputStream(new FileInputStream(srcFileName));</p>
<p>out = new FileOutputStream(outFileName);</p>
<p>tidy.parse(in, out);</p>
<p>} catch (IOException e) {</p>
<p>System.out.println(e);</p>
<p>}</p>
<img src ="http://www.blogjava.net/jiangmin/aggbug/122015.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jiangmin/" target="_blank">JiangMin</a> 2007-06-04 23:48 <a href="http://www.blogjava.net/jiangmin/articles/122015.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>LDAP技术报告(转)</title><link>http://www.blogjava.net/jiangmin/articles/116592.html</link><dc:creator>JiangMin</dc:creator><author>JiangMin</author><pubDate>Thu, 10 May 2007 13:04:00 GMT</pubDate><guid>http://www.blogjava.net/jiangmin/articles/116592.html</guid><wfw:comment>http://www.blogjava.net/jiangmin/comments/116592.html</wfw:comment><comments>http://www.blogjava.net/jiangmin/articles/116592.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jiangmin/comments/commentRss/116592.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jiangmin/services/trackbacks/116592.html</trackback:ping><description><![CDATA[<p>LDAP技术报告<br>&nbsp; 一、目录和目录服务<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; LDAP(Lightweight Directory Access Protocol)轻型目录访问协议是目录访问协议的一种。因此下面首先介绍什么是目录和目录服务。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 目录是一个以一定规则排列的对象的属性集合，是一个存储着关于对象各种属性的特殊数据库，这些属性可以供访问和管理对象时使用，类似电话簿和图书馆卡片分类系统。这里，我们所谈的目录服务是指网络目录服务。目录服务是指一个存储着用于访问、管理或配置网络资源信息的特殊数据库（also called data repository），它把网络环境中的各种资源都作为目录信息，在目录树结构中分层存储，对这些信息可以存储、访问、管理并使用。网络中的这些资源包括用户、各个应用系统、硬件设备、网络设备、数据、信息等。目录服务是为有效的集成管理网络目录中的信息提供服务，是支持网络系统的重要底层基础技术之一。<br>目录服务将分布式系统中的用户、资源和组成分布式系统的其它对象统一的组织起来，提供一个单一的逻辑视图，允许用户和应用透明地访问网络上的资源。一个由目录服务支持的网络系统是一个集成的、网络化的、统一的系统，而不是各个独立功能部分的简单聚合。在目录服务系统中对象可以根据名字或功能、属性访问，而不是根据机器地址、文件服务器名字和mail地址等访问。在目录服务的基础上开发的应用，易于使用、功能增强和易于管理，目录信息的共享为应用的开发提供了方便。下一代分布式网络的信息模型和模式是一种基于目录的，当我们进入网络时，是登录到一个基于目录的网络中，而不是登录到某个机器上。<br>目录服务可以存储信息种类：<br>用户帐户信息（登入名、口令、权限）<br>用户个人信息（电话号码、地址、雇员ID号）<br>外围设备配置信息（打印机、调制借调器、传真）<br>应用程序配置信息<br>安全信息<br>网络基础设施配置信息（路由器、代理服务器、INTERNET访问设置）<br>人们可以想得到的，网络目录中都可以存储<br>这些信息集中在一个标准数据库中，就可以有多种不同的使用方法。其中，最普通的是供系统管理员用于网络访问控制和网络资源访问控制。目录将成为对许多网络活动进行集中控制的地方。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 控制的例子：<br>用户登入进入一个网络，系统进行认证和权限判定；<br>用户进入网络后，访问网络中的资源，系统向目录服务查询该用户是否具有使用该资源的权限，并返回所请求资源的物理地址。<br>个人用户可以使用目录服务存储个人设置信息，并可以对其所有环境进行集中存储和控制。<br>随着目录服务技术的成熟，人们可以使用该技术通过一些网络设备监视和控制网络传输情况。</p>
<p>&nbsp;&nbsp;&nbsp; 目录服务的基本功能：<br>资源信息的目录式表示、分布存储、资源定位和查找、用户的统一认证、系统资源的统一授权、系统资源信息的共享、系统资源的单点统一管理、安全传输的保证、资源的统一监控等。<br>目录服务的主要优点：<br>网络管理工作大大减轻，包括管理网络上的各个应用；<br>网络的集中管理点；<br>访问用户信息的集中控制点；<br>存储在其它条件下很难处理的管理信息<br>系统资源信息的利用率高、管理的可扩展性好<br>简单地说，目录的发展经历了书面目录（电话目录、医士列表）——基于计算机的目录（PIM，不易共享、必须访问到响应的软件和计算机）——网络目录（公共的、共享的、统一的）。<br>传统的目录是计算机或网络基础结目录的一个构件，它向其它应用程序提供服务，但没有提供集成管理的机制，网络上的计算和服务需要一种公共的、分布式的目录，能够跨平台地对应用程序和用户提供集中、统一的服务。目录服务将使网络上的系统资源管理朝着单一的、全网络的目标发展，并能够让用户、管理员以更容易的方式来管理网络环境。目录服务作为一种工具来减少大型网络的管理负担，提供了集中的单点管理和适应复杂环境所必须的灵活性，减轻了非目录服务系统中存在的冗余管理。<br>通过网络资源逻辑接口，目录服务（ADS）减少了人们为了利用网络功能而必须对网络掌握的程度。也就是说，普通用户只需要很少的网络知识，就可以通过复杂网络访问和使用资源。用户不需要再了解资源的物理分布，访问本地打印机的方法和访问远程网络资源的方法相同。目录服务（ADS）提供了逻辑表示与资源的网络上的物理位置的连接，从用户的角度看，这可能是转移到基于目录的网络操作系统具有的最大优点。）<br>目录服务和数据库的区别：<br>读多于写<br>一般不支持事务处理<br>信息访问方式不同（一个是SQL、一个是LDAP的API）<br>目录中的信息一般不要求严格的一致性<br>传统的数据库是平面的，无法表示资源之间及资源使用控制的复杂逻辑关系而远远不能满足当前资源信息管理的各种要求。<br>目录服务与DNS系统的相同之处和不同之处<br>相同之处：<br>分布存储<br>树型层次结构<br>容错<br>不同之处：<br>DNS的功能和目录服务不同，DNS功能单一，本质上是将主机名解析成IP地址。目录服务是可以为多个应用提供网络资源的信息存储和管理，具有广泛的应用特性；<br>DNS是以一系列文本文件为基础，是一种纯文本式的数据库，无法进行扩展，适应其它功能的要求；<br>与分布式文件系统的相同在于采用了准树型层次结构，具有一定的授权功能，区别在于：<br>目录服务表示资源的各种属性信息，可为各种应用提供服务，文件不能表示；<br>目录服务有很强的逻辑表示和分类，文件的组织逻辑性单一，主要按存储位置；<br>文件系统的认证功能较差<br>独立性强<br>目录服务的应用举例<br>C4ISR系统：由多个大的子系统构成，管理问题更为复杂和严重<br>新的应用：电子商务（IBM）、操作系统（WINDOWS2000）<br>网络的监控管理<br>会议系统和PIM<br>搜索功能<br>太多的应用——基于目录的应用<br>原有应用的资源管理的重新开发<br>二、&nbsp; LDAP协议的特点<br>X.500协议是为了便于建立全局、分布式的目录信息而设计的一套协议。它是一种C---S（Client—Server）结构的应用协议，支持用户通过网络访问和维护资源信息，另外还具有几个突出的特点：<br>支持分布式的目录信息维护，所以每一个运行X.500的服务器都只需负责自己所管辖的资源信息，只需在本地就可完成信息的更新；<br>提供强大查询能力，可以让用户随心所欲的设计查询方式；<br>全局的信息标示，通过这种标示可以唯一的定位信息位置，获取内容；<br>结构化的信息模式，支持开发者的本地扩展；<br>遵循统一的标准，所以可以通过标准的方式访问任何一个X.500服务器，获取信息；<br>X.500协议中包含了这诸多的强大功能，可以说在很大的程度上满足了用户和开发者的要求，但是在用户和开发制的使用过程中却逐渐暴露出其许多的不足之处，阻碍了它的应用和推广，主要集中在使用方式和性能开销上这两个方面，由于X.500是在OSI协议栈上实现的，虽然X.500提供了强大的信息查询功能，但是协议所要求的访问格式却十分复杂，往往难以掌握；其次在运行X.500服务器时对系统的开销要求较高。为了兼顾保留协议的优点和克服这些不尽人意的地方，推出了由X.500目录服务协议延伸发展而来的轻型目录访问协议（Lightweight Drectory Access Protocol，简称LDAP）。LDAP协议继承了X.500的90%左右的功能，同时兼容所有使用X.500协议建立的服务端数据库，避免了重复开发的浪费；在运行开销上却只是X.500的10%。正是由于LDAP具有巨大的优越性，它从一开始仅仅是作为X.500客户层的另一种实现方式，到现在在许多应用中完全替代了X.500协议，成为一个完整实用的应用开发协议。<br>LDAP在以下四个方面对X.500进行了简化：<br>传输 ：&nbsp;&nbsp; LDAP直接运行在TCP上，避免了OSI多层通信的高层开销；<br>功能：&nbsp;&nbsp;&nbsp; LDAP简化了X.500的功能，抛弃了较少用到的功能和冗余的操作；<br>数据表示：X.500的数据表示结构复杂，LDAP采用简单的字符串对数据进行表示；<br>编码：&nbsp;&nbsp;&nbsp; LDAP用于网络传输的编码规则比 X.500的编码规则更加简单。<br>总到来说，基于LDAP的目录服务有以下特点。<br>目的是存储网络资源的信息<br>结构化的信息框架(面向对象的信息存储方法)，采用树型层次式结构表示<br>在系统中的单点集中（不指物理位置）管理资源，可实现单一登入点<br>读多于写<br>基于TCP 协议<br>Client/Server逻辑结构<br>标准的访问协议LDAP<br>强大的搜索功能，允许用户组织复杂的查询要求 <br>维护的分散性(信息可分布存储,具有集中式数据库无可比拟的优越性) <br>可全球唯一的命名<br>动态添加和修改信息<br>容错功能<br>自动更新和维护存储的信息<br>方便的备份和恢复功能<br>安全访问和信息传输的安全<br>易对资源进行授权管理<br>三、&nbsp; LDAP协议的内容<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; LDAP定义了四种基本模型：<br>信息模型说明了LDAP目录中可以存储哪些信息；<br>命名模型说明了如何组织和引用LDAP目录中的信息；<br>功能模型说明了LDAP目录中的信息处理，特别是如何访问和更新信息；<br>安全模型说明如何保护LDAP目录中的信息不受非授权访问和修改。<br>信息模型<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; LDAP的信息模型是以模式（Schema）为基础的，以项目（Entry）为核心的。模式由若干项目组成，项目是描述客观实体的基本单位，项目（如图3）由描述客观实体具体信息的一组属性（Attribute）构成。属性（如图3）只能有一种类型（Type），可以有一个或多个值（Value）。属性的类型具体说明属性值可以存储哪些信息，以及这些信息的行为特性。例如，属性cn的类型是caseIgnoreString，它意味着属性值是按照词典排序的字符串，并且在比较时忽略大小写，如BEIJING和Beijing是相同的；属性tele的类型是telephoneNumber，它具有caseIgnoreString的全部特性，另外在比较时忽略空格和破折号，如0731-4573670和07314573670是相同的。每个项目都有一个属性objectClass，用于说明项目的类型，以及项目中的必选属性和可选属性。属性objectClass的取值可以是一个或多个，其中必须有一个用于说明项目的基本结构的结构对象类（Structural object class），结构对象类不能轻易改变；除此之外，还可以有若干个对项目结构进行辅助说明的辅助对象类（Auxiliary object class），在访问控制允许的范围内可以新增或删除辅助对象类。</p>
<p>命名模型<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在LDAP目录中，项目是按照树形结构组织的，根据项目在树形结构中的位置对项目进行命名，这样的命名通常称为标识（Distinguished name），简称DN。DN由若干元素构成，每个元素称为相对标识（Relative distinguished name），简称RDN。RDN由项目的一个或多个属性构成。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; LDAP的命名模型（如图4）与我们熟悉的文件系统有很多相似之处，RDN与文件系统中的文件名很相似，DN与文件的绝对路径名很相似。另外，与文件系统一样，兄弟项目（即，具有相同父项目的子项目）必然具有不同的RDN。LDAP的命名模型与文件系统之间的区别主要有：<br>在LDAP目录中，位于叶节点和非叶节点的项目都拥有各自的属性；在文件系统中，只有位于叶节点的文件拥有较丰富的内容，而位于非叶节点的目录的内容相对简单。<br>在LDAP目录中，DN中各元素的排序是从叶到根；在文件系统中，文件绝对路径名中各元素的排序是从根到叶。<br>在LDAP目录中，DN中各元素之间的分隔符是&#8220;，&#8221;；在文件系统中，文件绝对路径名中各元素之间的分隔符是&#8220;/&#8221;或&#8220;\&#8221;。<br>在LDAP目录中，允许超越树形结构的别名项目（Alias entry），它指向其它项目。</p>
<p>功能模型<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; LDAP的功能模型涉及以下三个方面：<br>询问（Interrogation）<br>LDAP在信息询问方面主要定义了查找（Search）和比较（Compare）两个操作。在查找操作中，根据选取标准在指定范围内选择项目，这个选取标准通常称作查找过滤器（Search filter），并且可以规定一组需要返回的属性。另外，还可以规定查找结果的大小和客户端等待结果的时间。比较操作主要是判断指定项目是否包含指定属性（包括类型和值）。<br>更新（Update）<br>LDAP在信息更新方面定义了新增（Add）、删除（Delete）、修改（Modify）和修改RDN（Modify RDN）等四个操作。新增操作主要是在LDAP目录中插入一个新的项目。删除操作主要是从LDAP目录中删除已有项目。修改操作主要是修改已有项目的属性，具体地说，可以增加、删除、修改属性或属性值。修改RDN操作主要是修改项目的名字。<br>身份验证（Authentication）<br>LDAP在身份验证方面定义了连接（Bind）、断接（Unbind）和作废（Abandon）等三个操作。连接操作主要是客户端向服务器提供身份信息，包括DN和口令，以便于服务器验证客户端的身份，身份验证成功即建立客户端与服务器之间的会话（session）。断接操作主要是结束客户端与服务器的会话。作废操作主要是中止正在执行的操作。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 安全模型<br>如何控制从网络上来的各种访问请求，防止非授权的访问发生？这对于一个系统而言，也是十分重要的，因为许多的用户信息（如密码、费用）以及许多系统的配置数据等都属于敏感信息，它们不希望被随便一个普通的使用者访问，而只允许管理员拥有查询和修改的权限。LDAP的安全模型是以客户端的身份信息为基础的。客户端的身份信息通过连接操作提供给服务器，服务器根据身份信息对客户端提出的访问请求进行控制。在LDAP中存在一个被称为访问控制列表（Access Control List，以下简称ACL）的文件，控制各类访问请求具有的权限。ACL文件中的控制方式具有极大的弹性：即可以在大范围上控制某一类资源可以被某类甚至某个用户访问，还可以具体到资源类中的任何一个属性。其授权的种类有读、搜索、比较、写这几种，可以单独，也可以组合使用。一般的格式是<br>access to &#8220;cn=*,ou=nudt,o=cs,c=cn&#8221; <br>by&nbsp;&nbsp;&nbsp; &#8220;cn=tom,ou=nudt,o=cs,c=cn&#8221;&nbsp;&nbsp; write<br>上面的控制设置就赋予了Tom对NUDT部门下的所有资源信息写的权利，当然也就有了读等这些权利了。详细的定制和完善ACL文件，可以使目录服务系统提供较好的安全性。此外，开发者还可以根据安全程度的需要，在LDAP中集成其它的安全工具，如KERBOUS, SSL等应用广泛的安全技术，适用不同层次用户的需要。</p>
<p>四、 LDAP如何工作以及如何开发LDAP的应用<br>LDAP是以服务器—客户端方式工作的，目录服务将数据库软件的逻辑结构分为前端（客户端）和后端（服务端和仓库）（图1）&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </p>
<p><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 客户端是直接面对一般开发者和用户的；服务端是用于接收和解释客户请求，然后以客户的身份完成请求，并将完成结果返回给用户；仓库则是真正存储信息的地方。在LDAP中，服务端和仓库之间的连接采用了ODBC机制，所以可以使用任何支持和具有ODBC驱动程序的数据库软件，简单的可以是Linux系统中自带的GDBM或Alpha中的NDBM等数据库管理系统；也可以选用在功能和性能上更优越的Oracle和Sybase等系统，这样，可以提高系统的可移植性。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 现在已经有了许多基于LDAP协议开发出的资源管理系统和工具，如Openldap、NDS（Novell Directory Service）和ADS（Active Directory Service）等。它们已经逐渐的被使用在了各个需要目录服务的领域，并且应用的趋势在增强。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Openldap是Michigan大学发布的免费软件，实现了LDAP v2的功能，并部分支持LDAP v3。它提供原代码，可以在大多数的Unix和Linux系统中安装。开发者能够直接利用它所附带的一些SHELL工具开发简单的应用，这些SHELL包括了查询（ldapsearch）、修改（ldapmodify）、删除（ldapdelete）、增加（ldapadd）等，关于他们的使用方法可以参照帮助文件；也可以调用它提供的程序接口（API）来开发应用，接口包括了查询（ldap_search）、修改（ldap_modify）、增加（ldap_add）、删除（ldap_delete）等。从模版的定制到资源信息的组织和输入都可以按照用户的要求进行，开发出满足你要求的应用软件。<br>我们以openldap1.2.7为例，进一步说明LDAP的工作方式。也就是如何使用openldap1.2.7来建立一个基于LDAP应用开发。Openldap1.2.7的后台数据库选用gdbm 1.8.0，Openldap实现了与gdbm的接口ldbm。SLAPD是Openldap实现的独立的LDAP服务的守护进程，SLURPD是Openldap实现的独立的LDAP更新和复制的守护进程。gdbm 是GNU发布的免费dbm，使用哈希排序的数据库例程集，与标准的UNIX下的dbm例程一样工作。gdbm有比Berkeley dbm更快的快速排序，并且它是可重入的。<br>进行开发前，先要安装gdbm和openldap。<br>得到gdbm1.8.0.tar，tar xvf gdbm1.8.0.tar<br>cd ./gdbm<br>./configure<br>make<br>make install<br>然后安装openldap：<br>tar xvf openldap.tar<br>cd ./ldap<br>./configure - - with-ldbm-api=gdbm，使ldap服务进程在后端使用gdbm数据库<br>make depend<br>make<br>make install<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 接下来，进行基于LDAP协议的应用开发，大致分为四个步骤，这四个步骤同时也分别对应了建立协议中四种基本模型的过程：信息模型、命名模型、功能模型和安全模型。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 首先是建立信息模型，既计划需要管理的资源范围，在LDAP中所建立的信息以&#8220;实体&#8221;（entry）为单位，数据库的框架被称为&#8220;模版&#8221;（schema），每个实体的属性范围都会在模版中说明。模版的内容可以根据你的需要随意定制，可以将具有类似属性范围的信息归为一类，对于一类实体的说明采用了基于面向对象的机制，将模版中的每一个信息框架称为一个类&#8220;class&#8221;，而可以用这个类定义出你需要的事例，也就是一个个信息实体。<br>例如在模版文件中写入这样内容：<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; objectclass&nbsp; person<br>{<br>requires<br>account,<br>userpassword<br>allows<br>sex,<br>&#8230;&#8230;<br>}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 其中requires所包含的属性是每一个登记的用户都必须填写的属性范围，而allows所包含的则是可有可无的内容，这也给信息的存储控制增添了许多灵活性；其中，象系统管理员这种资源可以与一般用户合并，只是需要在属性中加入&#8220;类型&#8221;这样的属性用以区分是用户还是，为了安全，也可以将管理员单独设置为一类资源，在他的属性范围中包括帐号名、密码、管辖的范围（机器等设备的标示）、和联系方式等。对于其它的资源则根据实际情况分别设计，最后生成一个完整的模版文件。在openldap中，模版文件包括编辑yourname.oc.conf（定义信息对象类的文件）和yourname.at.conf（定义对象类中属性的文件）。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 对照上面的信息模型所建立的信息库还仅仅是一个个零散的资源记录，为了表现出它们之间的逻辑联系，需要完成LDAP中的命名模型。在平面式数据库中定位信息记录是通过每一条记录前面的标号或通过某些域的关键字匹配来完成的，实现过程大多是通过轮询，这在提高处理性能上就造成了许多障碍。LDAP中采用了更加合理的树形存储方式，将资源信息记录分别放置在树的根到叶的位置上，这种方式总是从不同的方面表现出了信息记录之间的某种从属的逻辑关系。<br>&nbsp;&nbsp;&nbsp; 对于每一个信息实体的定位使用全球唯一的命名方式既&#8220;可区分的名字&#8221;（DN：Distinguished Name），信息间的逻辑关系同时从DN中得到体现。可以参照Internet中的域名来理解DN的表示方法，如果你将所管理的信息按照地域进行分类，那么DN中就回包含你的分类标准，如从国家，到地区，在具体到某个部门中的人或者机器等等，格式是&#8220;cn=&nbsp; ，ou=&nbsp; ，o=&nbsp; ，c=&nbsp; &#8221;。（其中的cn、ou、o、c都是一些标示关键字，分别表示用户名字、部门、地区和国家）这样当用户需要寻找某人的一些信息（如电话号码、Email地址等），如果知道他的工作地址，那么可以查找这个单位中所有符合条件的人员信息，如果查找的条件较具体，那么可以直接找到这个人的信息实体，即使是给的查找条件比较模糊，也可以找出单位中所有符合条件的人员信息，然后由用户从中挑选出需要的，信息的逻辑结构见（图2）<br>&nbsp; cn&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 中国<br>&nbsp;<br>&nbsp; o&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 长沙&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 上海&nbsp;&nbsp;&nbsp;&nbsp; 北京<br>&nbsp;<br>&nbsp; ou&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 国防科大&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 市政府<br>&nbsp;<br>&nbsp;cn&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 张三&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 李四<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 当然，分类方式完全可以按照你的需要进行选择，将所有的信息组织在数据库中。建立了信息模版之后，就可以开始生成数据库本身了。添加数据库信息可以是先写一个LDIF（Ldap Data Information Format）格式的文档，（每个ldif文件对应一个数据库，在LDAP中可以有多个数据库，）这种格式是与模版是对应的，将一个个信息实体罗列在文件中，然后使用SHELL工具&#8220;ldif2ldbm&#8221;将其转换为当前使用的数据库软件的格式，并且在启动服务端时告诉这些数据库文件的存储路径；<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;如何真正的访问LDAP信息库中的记录则是在其功能模型中定义的内容，在应用开发中即开发一个LDAP的客户端和该客户端如何访问LDAP服务器。Openldap提供的仅仅是一系列的shell命令和API,我们要依靠这些底层调用来建立一个完整的用户访问和显示环境。如果不进行这方面的开发，可以使用普通的浏览器或者直接通过shell命令来操作，不过这种操作方式需要对LDAP的环境，配置情况，存储内容都有相当详细的了解，还要记住LDAP中复杂而又繁琐命令格式。普通用户根本不可能掌握。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 一个完整的访问过程包括四个步骤：初始化、绑定服务器、访问资源信息和断开连接。其中初始化是分配一个操作句柄；绑定服务器是向服务端提供自己的身份标示（含用户名和密码等）；访问资源信息则是提出自己的访问请求（如查询和更新，他们分别有对应的标准API），等待并获取访问结果；断开连接是在所有的访问工作完成之后断开与服务端的连接，释放占用的资源。LDAP是简化了X.500中的许多操作，它在访问资源的方式中主要提供与&#8220;读&#8221;和&#8220;写&#8221;相关的操作手段。与&#8220;读&#8221;相关的有查找（search）和比较（compare），在查找时可以通过设置不同的&#8220;过滤器&#8221;（filter）达到获得自己需要的结果，过滤器中的内容可以涉及到任何相关属性的名称及取值范围等，并且支持与、或、非等关系表达式；&#8220;比较&#8221;则是将特定记录中某属性的值取出与自己的设定进行关系比较。与&#8220;写&#8221;相关的操作有增加、删除、修改和更名。增加是在信息库中增加新的信息记录，当然不能有相同唯一标示的记录存在；删除是将被认定为无用的信息记录从库中删除；修改是对于库中资源信息的某些属性值进行修改；更名则是更替唯一标示中最后一部分的内容，往往使用在仅仅这个资源的名称有了改变的情况下。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 如何防止资源信息的非授权访问和处理数据备份以及恢复是在安全模型中解决的问题。我们在下一章进行详细说明。<br>在处理好以上四个方面后 ，我们就可以启动LDAP服务了，在openldap中，启动服务器端的SLAPD（LDAP服务器进程），就可以响应用户的访问了。<br>&nbsp;LDAP中的访问控制<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; LDAP通过安全控制列表ACL（Access Control List）可以对信息库中的所有资源进行访问控制，甚至可以具体到一个资源记录中的某个属性。在openldap中，是在slapd.conf中定义的。Slapd.conf是LDAP最主要的配置文件，它说明了LDAP中使用的模板文件、日志文件、数据库位置、系统管理员帐号、系统管理员口令和各种安全机制等，其中主要是定义用户访问权限和建立LDAP的主从和主备关系。<br>对于用户访问权限，举例说明，我们可以将用户信件信息只授权给收件人，那么当该用户在绑定服务器并提供正确的帐号名和密码之后可以访问所有寄给他的信件，而其他用户试图超越自身的权限，获取其他用户的信件信息时会被立即拒绝。可以这样来描述权限的设置：<br>access to dn=&#8221;.*, User=Tom, o=XY, c=A&#8221;&nbsp;&nbsp; by&nbsp; dn=&#8221;User=Tom, o=XY, c=A&#8221;。<br>通过这条限制就将信件的访问权限完全的赋给了信件的收取者。同样，设备的访问权限是授予了相应的设备管理员，而用户这类资源则只能由系统管理员来控制。<br>对于用户密码这个属性，可以这样定义。<br>access to dn=".*,grp=general,ou=nudt,o=cs,c=cn" attr=userpassword<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; by self&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; write<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; by *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; none</p>
<p>在slapd.conf中还可以定义referral配置，它的值应是另一个LDAP服务器或多个LDAP服务器的 URL，当用户进行查询时，没在本地找到，就会去referral指定的其它LDAP服务器进行查找。openldap直接在服务器上实现了referral，而是返回给客户referral地址，如图1。①向server发出请求；需要指向其它server时，②返回referral地址；③客户需重新向referral地址发出请求；④返回结果。为了网格用户的方便，需要屏蔽掉信息所在地址即referral，实现Chaining，即在服务器上自动支持referral，如图2。①向server发出请求；需要指向其它server时，②自动指向referral地址；③自动向referral地址发出请求；④返回结果。</p>
<p>图1<br>图2<br>有了referral的功能，我们就可以把网络内的LDAP服务器都建立这样一种联系，使得用户不必记住每个LDAP服务器都存储些什么内容以及它们的地址，只要记住离自己最近的LDAP服务器就可以了，如果用户要操作的内容不在该服务器上，会自动地寻找直到找到正确的服务器，得到正确的内容为止。<br>六、LDAP的主从备份功能<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 安全机制中一个重要的内容就是备份和恢复，在LDAP中提供了主从备份服务器的机制，它方便和经济地实现了备份和恢复的功能。下面介绍主从服务器的配置方法和运行过程。<br>主服务器为了表明当前所运行服务进程的身份，必须在其配置文件（slapd.conf）中注明，并且还标明所有从（备份）服务进程的地址（IP或域名）；从（备份）服务进程中需要标明它所面对的主服务进程的地址（IP或域名）。<br>主服务进程配置文件：<br># Just show the necessary portion for replicate， &#8216;389&#8217; is the port number<br>replica&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; host=172.26.20.98：389<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; binddn=&#8220;adm=replica99，ou=nudt，o=cs，c=cn&#8221;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bindmethod=simple&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; credentials=passwd<br># The second slave server<br>replica&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; host=172.26.20.97：389<br>&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; 。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 。<br>（注）：<br>binddn是主server向该从server发出操作命令时使用的身份。<br>&nbsp;&nbsp;&nbsp; Bindmethod是标明使用的身份验证的方法，可以是&#8220;用户名+密码&#8221;也可以是kerberos方法。<br>&nbsp;&nbsp;&nbsp; Credentials分别为密码和认证书</p>
<p>从server配置文件：<br># Just show the necessary portion for replicate，98 is the IP of the master server<br>referral&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ldap：//172.26.20.98<br>updatedn&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8220;adm=replica99，ou=nudt，o=cs，c=cn&#8221;<br># Give updatedn the right to write the Directory Tree<br>access&nbsp; to &#8220;.*，o=cs，c=cn&#8221;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; by &#8220;cn=replica99，ou=nudt，o=cs，c=cn&#8221;&nbsp; write</p>
<p>（注）：<br>referral：是当在本地无法提供信息数据时，提供下一个服务器的地址，可以通过再一次查询获取数据。<br>在备份服务进程的配置文件中，不必使用referral，因为它不真正的提供索引服务。<br>启动顺序<br>将主服务进程上的数据库文件拷贝给各个从（备份）服务进程，达到最初的一致。<br>启动主服务进程上的slapd进程<br>启动从服务进程上的slapd进程<br>启动主服务进程上的slurpd进程<br>slurpd是可以定时把主服务器上的修改进行备份，依据是由写操作产生的日志，如果由于网络的原因导致了备份失败，slurpd会自动进行重试，直到备份成功。<br>日志<br>设置在主服务进程r服务器上，需要修改配置文件：<br># For log of the LDAP server ，you can set the file name you like<br>replogfile&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /home/ldap/nhpce.replog<br>实际此文件只是给slurpd进程使用，作为一个广播操作命令的中转站，真正的日志文件在/var/tmp下,文件名称为slurpd.replog。<br>一个主服务器的从服务器个数是没有限制的，通过以上设置，可以产生了一个由主服务器进程和一个或几个从服务进程组成的服务机群，主守护进程作为整个服务机群的核心，其始终维持系统信息的一致性，因为除了查询以外的请求都首先由它操作自己的信息库，然后再将该操作广播给各个从服务器，同步更新各自的信息库。而对于查询请求，由于不会造成信息内容的改变，所以可以由各个从服务器完成，这样的方式特别适用于象目录服务这样查询请求远远多于修改等请求的应用。</p>
<p>下面是一个主服务器和多个从服务器组成的服务机群处理访问的步骤：<br>客户向服务机群发出请求（客户使用的可能是IP或域名），此请求可以被一个前端的域名服务器转给一个从服务进程。<br>从服务进程将除了搜索以外的请求发向主服务进程。<br>主服务进程根据请求成功完成相应操作之后，将操作广播给所有的从服务进程。<br>从服务进程r此时完成主服务进程要求的操作。<br>从服务进程将操作结果返回给客户。<br><br>图3<br>这样的服务器机群，每个从服务器都有一个主服务器信息的完全备份，当出现主服务器因为各种原因无法提供服务或无法恢复其信息数据时，则可将备份服务器上的数据信息转移到主服务器上，继续提供服务；或者直接将备份服务器的配置文件进行修改，从新启动服务进程，将其身份变为主服务进程。而且这些处理都十分方便。如果在平时就做好准备，那么可以在极短的时间内恢复服务。<br>实际上，不但一个主服务器可以对应多个从服务器，而且一个从服务器可以从多个主服务器上备份信息，形成一个主备的服务机群。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 采用主备关系服务机群的系统逻辑视图如下：&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </p>
<p>&nbsp;</p>
<p>图4<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在上图中，设置了两个主服务信息库，它们平时可以是各不相干的角色，管理各自的域内事务，而后面的两个备份信息库则为了提高使用效率，同时作为了两个主服务信息库的备份库。对于上面两种方式的实现，其配置文件的写法大体相同。<br>不仅如此，多个LDAP服务器之间可以互为主从关系，即每个服务器都把自己管理部分定义为主服务信息库，而其他所有的LDAP服务器把与之相应的信息库定义为该主信息库的从信息库。这样，实际上每个LDAP服务器的地位是平等的，存储的信息则包括了全局的信息。每个单位只有对本单位的LDAP服务器上本单位的信息具有写和修改的权限。而修改的同时各个单位的LDAP服务器上的相应的信息就都修改了，每个单位的用户都可以在本地的LDAP上访问全局的信息，而且基本上能保证是最新的信息，这种方式有响应时间短，资源利用率高，抗毁能力强的优点。充分地发挥了分布式系统特点。缺点是每一次写操作都要广播到每个LDAP服务器，增加了网络的负担。但因为目录服务的特点是读操作远远大于写操作，实际上对网络负载影响不大。具体逻辑关系见下图。<br>图5<br>在配置上需要在每个LDAP服务器上建立相应的slapd.conf文件，在配置文件中声明自那部分是主服务器并定义每个从服务器的位置和权限。自己作为从服务器从那些LDAP服务器中以什么身份取得那些信息。下面举例说明。在国家高性能计算环境中基于LDAP的目录服务采用了这种组织形式，它的LDAP的配置文件如下，本地服务器是国防科大。<br>下面是slapd.conf简化了的写法。</p>
<p>#NHPCE Slapd Configure File<br>include&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /etc/openldap/slapd.oc.conf<br>include&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /etc/openldap/slapd.at.conf<br>schemacheck&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; on<br>pidfile&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /var/run/slapd.pid<br>argsfile&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /var/run/slapd.args<br>access to attr=userpassword<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; by self&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; read<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; by dn="cn=Manager_nudt,grp=GENERAL,ou=NUDT,o=CS,c=CN"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; read<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; by *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; none&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </p>
<p>#ldbm definition for the NUDT master database<br>database&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ldbm<br>suffix&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "ou=NUDT,o=CS,c=CN"<br>directory&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /etc/openldap/database/nudt_db<br>rootdn&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "cn=Manager_nudt,grp=GENERAL,ou=NUDT,o=CS,c=CN"<br>replogfile&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /etc/openldap/database/nudt_db/slapd.replog<br>replica&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; host=159.226.39.173:389<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; binddn="cn=Replicator_nudt,grp=GENERAL,ou=NUDT,o=CS,c=CN"<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bindmethod=simple<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; credentials=secret<br>replica&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; host=159.226.39.144:389<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; binddn="cn=Replicator_nudt,grp=GENERAL,ou=NUDT,o=CS,c=CN"<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bindmethod=simple<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; credentials=secret<br>index&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; default&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; none<br>defaultaccess&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; read<br>access to dn=".*,grp=general,ou=nudt,o=cs,c=cn"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; attr=userpassword<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; by self&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; write<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; by *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; none<br>access to dn=".*,grp=general,ou=nudt,o=cs,c=cn"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; attrs=email,telephone,description<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; by self&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; write<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; by *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; read&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>access to dn="cn=Manager_nudt,grp=GENERAL,ou=NUDT,o=CS,c=CN" <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; by *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; none<br>access to dn="cn=Replicator_nudt,grp=GENERAL,ou=NUDT,o=CS,c=CN"<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; by self&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; write <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; by *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; none<br>lastmod&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; on</p>
<p>#ldbm definition for the NUDT slave database<br>database&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ldbm<br>suffix&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "ou=CAS,o=BJ,c=CN"<br>directory&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /etc/openldap/database/cas_db<br>rootdn&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "cn=Replicator_cas,grp=GENERAL,ou=CAS,o=BJ,c=CN"<br>updatedn&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "cn=Replicator_cas,grp=GENERAL,ou=CAS,o=BJ,c=CN"<br>index&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; default&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; none<br>defaultaccess&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; read&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;<br>#ldbm definition for the JNICT slave database<br>database&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ldbm<br>suffix&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "ou=JNICT,o=WX,c=CN"<br>directory&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /etc/openldap/database/jnict_db<br>rootdn&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "cn=Replicator_jnict,grp=GENERAL,ou=JNICT,o=WX,c=CN"<br>updatedn&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "cn=Replicator_jnict,grp=GENERAL,ou=JNICT,o=WX,c=CN"<br>index&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; default&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; none<br>defaultaccess&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; read&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>七、 LDAP的应用前景<br>目录服务系统将在越来越多的网络应用系统中使用，特别是一些大型的网络应用（一些大型网站也会需要）当中，这也是各个大公司为什么要将此作为网络基础软件来看待。<br>集中单点管理、分布容错和单一登入点（包括合理的认证服务）的功能是具有巨大的诱人优势。<br>使用LDAP可以开发大的应用软件项目，比如可以应用在C4ISR中，当然会还有其它应用。<br>小的项目也会需要目录服务的的支持，目录服务是一个在逻辑上集中存储资源信息的特殊数据库，许多数据库开发都可以用LDAP替代，而且LDAP更易于开发，更灵活。<br>目录服务系统将从现行的V2、V3继续发展，具有目录服务功能的网络DEN（发布、发现和获取）即将出现，不经对网络上的高层资源进行集中管理，而且对网络基础设备的集中管理，例如：具有目录路由器。一句话：就是DEN将网络服务和网络设备的管理更好地继承到普通管理技术中。</p>
<img src ="http://www.blogjava.net/jiangmin/aggbug/116592.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jiangmin/" target="_blank">JiangMin</a> 2007-05-10 21:04 <a href="http://www.blogjava.net/jiangmin/articles/116592.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>LDAP操作之java篇（2）</title><link>http://www.blogjava.net/jiangmin/articles/116589.html</link><dc:creator>JiangMin</dc:creator><author>JiangMin</author><pubDate>Thu, 10 May 2007 13:01:00 GMT</pubDate><guid>http://www.blogjava.net/jiangmin/articles/116589.html</guid><wfw:comment>http://www.blogjava.net/jiangmin/comments/116589.html</wfw:comment><comments>http://www.blogjava.net/jiangmin/articles/116589.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jiangmin/comments/commentRss/116589.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jiangmin/services/trackbacks/116589.html</trackback:ping><description><![CDATA[<span>续接上一篇我们将举例来讲解对节点的操作</span><span>(</span><span>也就是</span><span>entry)</span><span>，包括查询、增加、修改、删除节点。</span>
<p>&lt;!--[if !supportLists]--&gt;<span><span><img height=11 alt=* src="file:///C:/DOCUME~1/kkkk/LOCALS~1/Temp/msohtml1/01/clip_image001.gif" width=11><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span>&lt;!--[endif]--&gt;<span>增加节点</span></p>
<p><span>/**</span></p>
<p><span>*entry </span><span>：包含新增节点的所有信息</span></p>
<p><span>/*</span></p>
<p><span>public boolean addInformation(Entry entry)</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>try </span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>Attributes attrs = new BasicAttributes();</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>Enumeration attrEnum = entry.keys();</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>while (attrEnum.hasMoreElements()) </span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>String type = (String) attrEnum.nextElement();</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>Attribute oneAttr = new BasicAttribute(type);</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>Vector vals = (Vector) entry.get(type);</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>Enumeration valEnum = vals.elements();</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>while (valEnum.hasMoreElements()) </span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>oneAttr.add((String) valEnum.nextElement());</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>attrs.put(oneAttr);</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>dc.createSubcontext(entry.getDN(), attrs);</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>return true;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>} catch (Exception ne) {</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>//System.err.println("Error: " + ne.getMessage());</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>ne.printStackTrace();</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>return false;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span>举一个构造</span><span>entry</span><span>的例子：</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>Entry en<span>&nbsp;&nbsp;&nbsp; </span>= new Entry();</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>String enDN = "cn=dsafa,dc=gsmd,dc=com";</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>Vector employeeName = new Vector();</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>Vector objectClass = new Vector();</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>Vector mailAddress = new Vector();</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>Vector mobilePhone = new Vector();</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>en.setDN(enDN);</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>employeeName.add("liufu");</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>en.put("employeeName",employeeName);</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>objectClass.add("cssisMail");</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>en.put("objectClass",objectClass);</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>mailAddress.add("dsfsa");</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>en.put("mailAddress",mailAddress);</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>mobilePhone.add("1234");</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>en.put("mobilePhone",mobilePhone);</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></p>
<p>&lt;!--[if !supportLists]--&gt;<span><span><img height=11 alt=* src="file:///C:/DOCUME~1/kkkk/LOCALS~1/Temp/msohtml1/01/clip_image001.gif" width=11><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span>&lt;!--[endif]--&gt;<span>修改节点的信息</span></p>
<p><span>每个节点相当于一个实体，每个实体有很多属性，当然我们要改的就是某些或某个属性的值。</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>/**</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>*dn </span><span>：节点的位置</span> <span>如：</span><span>ou = kk, dc = china ,dc=com</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>/*</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>public boolean modifyInformation(String dn)</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>try {</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>ModificationItem[] mods = new ModificationItem[2];</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>Attribute mobilePhone = new BasicAttribute("mobilePhone",</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>"12315");</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>Attribute employeeName = new BasicAttribute("employeeName","Smith");</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>mods[0] = new ModificationItem(DirContext.ADD_ATTRIBUTE,</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>mobilePhone);</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>mods[1] = new ModificationItem(DirContext.REPLACE_ATTRIBUTE,</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>employeeName);</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>dc.modifyAttributes(dn,mods);</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>return true;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>} catch (NamingException ne) {</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>System.err.println("Error: " + ne.getMessage());</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>return false;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></p>
<p>&lt;!--[if !supportLists]--&gt;<span><span><img height=11 alt=* src="file:///C:/DOCUME~1/kkkk/LOCALS~1/Temp/msohtml1/01/clip_image001.gif" width=11><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span>&lt;!--[endif]--&gt;<span>删除指定的节点</span></p>
<p><span>这个简单没啥好说的把：）</span></p>
<p><span>public boolean deleteInformation(String dn)</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>try {</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>dc.destroySubcontext("cn=asdf,ou=mail,dc=gsmd,dc=com");</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>return true;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>} catch (NamingException ne) {</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>System.err.println("Error: " + ne.getMessage());</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>return false;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</span></p>
<p>&nbsp;</p>
<p>&lt;!--[if !supportLists]--&gt;<span><span><img height=11 alt=* src="file:///C:/DOCUME~1/kkkk/LOCALS~1/Temp/msohtml1/01/clip_image001.gif" width=11><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span>&lt;!--[endif]--&gt;<span>修改节点的名字（</span><span>dn</span><span>）</span></p>
<p><span>这个好像只能修改叶子节点的，有没有人找到可以修改非叶子节点</span><span>dn</span><span>的方法，</span><span><a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#37;&#69;&#53;&#37;&#57;&#49;&#37;&#56;&#65;&#37;&#69;&#56;&#37;&#65;&#70;&#37;&#56;&#57;&#37;&#69;&#54;&#37;&#56;&#56;&#37;&#57;&#49;&#112;&#111;&#114;&#99;&#117;&#112;&#105;&#110;&#101;&#50;&#48;&#48;&#52;&#64;&#49;&#50;&#54;&#46;&#99;&#111;&#109;"><span><span>告诉<span>我</span></span></span>porcupine2004@126.com</a></span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>public boolean renameEntry(String oldDN,String newDN)</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>try {</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>dc.rename(oldDN,newDN);</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>return true;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>} catch (NamingException ne) {</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>System.err.println("Error: " + ne.getMessage());</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>return false;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</span></p>
<p><span>这两篇文章就</span><span>LDAP</span><span>的一些操作进行了简单的讲解，</span><span>ldap</span><span>远远不止这些，偶还是一只小小菜鸟，不断在学习中，我会留下偶学习的痕迹的，希望能与各位大大交流，有啥问题也可以一起探讨.</span></p>
<img src ="http://www.blogjava.net/jiangmin/aggbug/116589.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jiangmin/" target="_blank">JiangMin</a> 2007-05-10 21:01 <a href="http://www.blogjava.net/jiangmin/articles/116589.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>LDAP操作之java篇（1）</title><link>http://www.blogjava.net/jiangmin/articles/116588.html</link><dc:creator>JiangMin</dc:creator><author>JiangMin</author><pubDate>Thu, 10 May 2007 13:00:00 GMT</pubDate><guid>http://www.blogjava.net/jiangmin/articles/116588.html</guid><wfw:comment>http://www.blogjava.net/jiangmin/comments/116588.html</wfw:comment><comments>http://www.blogjava.net/jiangmin/articles/116588.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jiangmin/comments/commentRss/116588.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jiangmin/services/trackbacks/116588.html</trackback:ping><description><![CDATA[<span>本文将分成</span><span>4</span><span>部分对</span><span>LDAP</span><span>操作进行讲解，每一部分都附带小例子</span><span>(</span><span>主要是参考</span><span>MANNING - LDAP Programming, Management and Intergration</span><span>一书，自己做了一些修改并通过验证</span><span>)</span><span>。阅读本文要有一定的</span><span>LDAP</span><span>知识，其实如果你自己配过</span><span>LDAP</span><span>服务器以后再来看这篇文章应该没什么难度</span><span>(</span><span>参见上一篇文章《在</span><span>windows</span><span>上配置</span><span>openldap</span><span>》</span><span>)</span>
<p>&lt;!--[if !supportLists]--&gt;<span><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span>&lt;!--[endif]--&gt;<span>连接</span><span>LDAP</span><span>服务器</span></p>
<p><span>String dn; //</span><span>包括连接</span><span>LDAP</span><span>服务器的用户及要操作的根节点</span></p>
<p><span>DirContext dc; //</span><span>相当于这个树的一个映像</span></p>
<p><span>Properties env = new Properties();</span></p>
<p><span>env.put(DirContext.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.ldap.LdapCtxFactory");</span></p>
<p><span>env.put(DirContext.PROVIDER_URL, "ldap://" + host + ":" + port);</span></p>
<p><span>if (dn != null) {</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>env.put(DirContext.SECURITY_PRINCIPAL, dn);</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>env.put(DirContext.SECURITY_CREDENTIALS, password);</span></p>
<p><span>}</span></p>
<p><span>dc = new InitialDirContext(env);</span></p>
<p>&nbsp;</p>
<p><span>dn</span><span>举例</span><span>: dn=&#8221; cn=Manager,dc=kkk,dc=com&#8221;,password</span><span>就是这个</span><span>dn</span><span>对应的密码。</span><span>Host</span><span>是</span><span>LDAP</span><span>服务器的主机地址，</span><span>port</span><span>是端口</span><span>(openLDAP</span><span>默认开放的是</span><span>389)</span></p>
<p>&nbsp;</p>
<p>&lt;!--[if !supportLists]--&gt;<span><span><img height=11 alt=* src="file:///C:/DOCUME~1/kkkk/LOCALS~1/Temp/msohtml1/01/clip_image001.gif" width=11><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span>&lt;!--[endif]--&gt;<span>查询这棵树的所有节点</span></p>
<p><span>有点类似</span><span>sql</span><span>里边的</span><span>select * from tableName;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; </span>/**</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; * @param base </span><span>：根节点</span><span>(</span><span>在这里是</span><span>&#8221;dc=kkk,dc=com&#8221;)</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; * @param scope </span><span>：搜索范围</span></p>
<p><span>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; * @param filter </span><span>：指定子节点</span><span>(</span><span>格式为</span><span>&#8221;(objectclass=*)&#8221;,*</span><span>是指全部，你也可以指定某一特定类型的树节点</span><span>)</span></p>
<p><span>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; * @param attributes </span><span>：属性集合</span><span>(</span><span>格式为</span><span>{&#8220;*&#8221;}</span><span>如果要指定搜索某一指定的属性列，就把</span><span>*</span><span>改成响应的属性列名称就行了</span><span>)</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; </span>* @return result </span><span>：</span><span>result</span><span>里边存的就是查询的结果集合</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; </span>*/</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; </span>public Vector searchInformation(String base, String scope, String filter,</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; String[] attributes)</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; </span>{</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; </span>Vector results = new Vector();</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; SearchControls sc = new SearchControls();</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (scope.equals("base")) {</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; sc.setSearchScope(SearchControls.OBJECT_SCOPE);</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; } else if (scope.equals("one")) {</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; sc.setSearchScope(SearchControls.ONELEVEL_SCOPE);</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; } else {</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; </span>sc.setSearchScope(SearchControls.SUBTREE_SCOPE);</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; </span>// Reduce data provided by the LDAP server by listing</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; </span>// only those attributes we want to return.</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (attributes.length &gt; 0) {</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; </span>sc.setReturningAttributes(attributes);</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; </span>}</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; </span>NamingEnumeration ne = null;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; try {</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; ne = dc.search(base, filter, sc);</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; </span>// Use the NamingEnumeration object to cycle through</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; </span>// the result set.</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; </span>while (ne.hasMore()) {</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; </span>Entry entry = new Entry();</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; </span>SearchResult sr = (SearchResult) ne.next();</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; String name = sr.getName();</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; </span>if (base != null &amp;&amp; !base.equals("")) {</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; entry.setDN(name + "," + base);</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; </span>} else {</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; entry.setDN(name);</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; </span>Attributes at = sr.getAttributes();</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; NamingEnumeration ane = at.getAll();</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; while (ane.hasMore()) {</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; </span>Attribute attr = (Attribute) ane.next();</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; String attrType = attr.getID();</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; </span>NamingEnumeration values = attr.getAll();</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; Vector vals = new Vector();</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; // Another NamingEnumeration object, this time</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; </span>// to iterate through attribute values.</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; </span>while (values.hasMore()) {</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; Object oneVal = values.nextElement();</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (oneVal instanceof String) {</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; </span>vals.addElement((String) oneVal);</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; </span>} else {</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; </span>vals.addElement(new String((byte[]) oneVal));</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; </span>}</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; entry.put(attrType, vals);</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; </span>results.addElement(entry);</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; </span>}</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; </span>// The search() method can throw a number of exceptions.</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; </span>// Here we just handle and print the exception.</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; </span>// In real life we might want to pass the exception along</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; </span>// to a piece of the software that might have a better</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; // context for correcting or presenting the problem.</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; </span>} catch (Exception nex) {</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; System.err.println("Error: " + nex.getMessage());</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; </span>nex.printStackTrace();</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; lc.close();</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; </span>}</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return results;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; </span>}</span></p>
<img src ="http://www.blogjava.net/jiangmin/aggbug/116588.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jiangmin/" target="_blank">JiangMin</a> 2007-05-10 21:00 <a href="http://www.blogjava.net/jiangmin/articles/116588.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java zip 中文问题（转）</title><link>http://www.blogjava.net/jiangmin/articles/111390.html</link><dc:creator>JiangMin</dc:creator><author>JiangMin</author><pubDate>Tue, 17 Apr 2007 12:54:00 GMT</pubDate><guid>http://www.blogjava.net/jiangmin/articles/111390.html</guid><wfw:comment>http://www.blogjava.net/jiangmin/comments/111390.html</wfw:comment><comments>http://www.blogjava.net/jiangmin/articles/111390.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jiangmin/comments/commentRss/111390.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jiangmin/services/trackbacks/111390.html</trackback:ping><description><![CDATA[个人说明 : java.util.zip.* 压缩解压文件包！不过这个包没解决中文文件名问题。以下是从网上找解决方案！ 自我感觉采用org.apache.tools.zip是比较好的解决方案。
<div>&nbsp;</div>
<div>压缩程序 ： 比较复杂，可以实现，递归程序！主要是压缩文件夹（要传文件名^_^）</div>
<div>解压程序 ： 比较简单！</div>
<div>&nbsp;</div>
<div>用ant解压包含中文文件名的压缩文件 <br>中文问题是java中的普遍性问题.今天下午遇到一个包含中文文件名的压缩文件解压问题.找了不少资料.现贴出解集.<br>在java.util.zip包也可以用来处理解压问题,不过对含有中文文件名的压缩包无能为力,这是因为ZipOutputStream压缩和解压ZIP文件对文件名都是以UTF-8编码方式来处理的,而我们用winzip压缩文件对文件名只会以ASCII编码方式来处理.所以会出现编码不一致的问题.<br>有两种解决方案:<br>第一种就是修改ZipOutputStream,参考修改如下:(这个我没有测试过)</div>
<div>// ZipEntry e = createZipEntry(getUTF8String(b, 0, len));<br>ZipEntry e=null;<br>try <br>{<br>&nbsp;&nbsp;&nbsp; if (this.encoding.toUpperCase().equals("UTF-8"))<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; e=createZipEntry(getUTF8String(b, 0, len));<br>&nbsp;&nbsp;&nbsp; else<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; e=createZipEntry(new String(b,0,len,this.encoding));<br>}catch(Exception byteE) {<br>&nbsp;&nbsp;&nbsp; e=createZipEntry(getUTF8String(b, 0, len));<br>}<br>再加一个<br>public ZipInputStream(InputStream in,String encoding) {<br>&nbsp;&nbsp;&nbsp; super(new PushbackInputStream(in,512),new Inflater(true),512);<br>&nbsp;&nbsp;&nbsp; usesDefaultInflater = true;<br>&nbsp;&nbsp;&nbsp; if(in == null) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; throw new NullPointerException("in is null");<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; this.encoding=encoding;<br>} <br>第二种方法就是用ant包,可以在官方网站http://ant.apache.org/bindownload.cgi下载,把ant.jar导入到类中.<br>参考用例如下:<br>public void unzip(String zipFileName,String outputDirectory) throws Exception{<br>try {<br>&nbsp;&nbsp;&nbsp; org.apache.tools.zip.ZipFile zipFile = new org.apache.tools.zip.ZipFile(zipFileName);<br>&nbsp;&nbsp;&nbsp; java.util.Enumeration e = zipFile.getEntries();</div>
<div>&nbsp;&nbsp;&nbsp; org.apache.tools.zip.ZipEntry zipEntry = null;</div>
<div>&nbsp;&nbsp;&nbsp; while (e.hasMoreElements()){<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; zipEntry = (org.apache.tools.zip.ZipEntry)e.nextElement();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("unziping "+zipEntry.getName());<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (zipEntry.isDirectory()){<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String name=zipEntry.getName();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; name=name.substring(0,name.length()-1);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("输出路径："+outputDirectory+File.separator+name);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; File f1=new File(outputDirectory+File.separator);<br>f1.mkdir();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; File f=new File(outputDirectory+File.separator+name);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; f.mkdir();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("创建目录："+outputDirectory+File.separator+name);</div>
<div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }else{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; File f=new File(outputDirectory+File.separator+zipEntry.getName());<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; f.createNewFile();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; InputStream in = zipFile.getInputStream(zipEntry);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FileOutputStream out=new FileOutputStream(f);<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; int c;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;byte[] by=new byte[1024];<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while((c=in.read(by)) != -1){<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; out.write(by,0,c);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;out.close();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; in.close();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; }</div>
<div>}<br>catch (Exception ex){</div>
<div>}<br>}</div>
<img src ="http://www.blogjava.net/jiangmin/aggbug/111390.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jiangmin/" target="_blank">JiangMin</a> 2007-04-17 20:54 <a href="http://www.blogjava.net/jiangmin/articles/111390.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>有关java远程读取文件的方法 </title><link>http://www.blogjava.net/jiangmin/articles/110563.html</link><dc:creator>JiangMin</dc:creator><author>JiangMin</author><pubDate>Fri, 13 Apr 2007 17:07:00 GMT</pubDate><guid>http://www.blogjava.net/jiangmin/articles/110563.html</guid><wfw:comment>http://www.blogjava.net/jiangmin/comments/110563.html</wfw:comment><comments>http://www.blogjava.net/jiangmin/articles/110563.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jiangmin/comments/commentRss/110563.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jiangmin/services/trackbacks/110563.html</trackback:ping><description><![CDATA[<span style="COLOR: #008080">&nbsp;1</span><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #0000ff">package</span><span style="COLOR: #000000">&nbsp;word;<br></span><span style="COLOR: #008080">&nbsp;2</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top><br></span><span style="COLOR: #008080">&nbsp;3</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000">&nbsp;java.io.FileOutputStream;<br></span><span style="COLOR: #008080">&nbsp;4</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000">&nbsp;java.io.InputStream;<br></span><span style="COLOR: #008080">&nbsp;5</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000">&nbsp;java.net.HttpURLConnection;<br></span><span style="COLOR: #008080">&nbsp;6</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top><br></span><span style="COLOR: #008080">&nbsp;7</span><span style="COLOR: #000000"><img id=Codehighlighter1_134_803_Open_Image onclick="this.style.display='none'; Codehighlighter1_134_803_Open_Text.style.display='none'; Codehighlighter1_134_803_Closed_Image.style.display='inline'; Codehighlighter1_134_803_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_134_803_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_134_803_Closed_Text.style.display='none'; Codehighlighter1_134_803_Open_Image.style.display='inline'; Codehighlighter1_134_803_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;FileRead&nbsp;</span><span id=Codehighlighter1_134_803_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"></span><span id=Codehighlighter1_134_803_Open_Text><span style="COLOR: #000000">{<br></span><span style="COLOR: #008080">&nbsp;8</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top><br></span><span style="COLOR: #008080">&nbsp;9</span><span style="COLOR: #000000"><img id=Codehighlighter1_176_801_Open_Image onclick="this.style.display='none'; Codehighlighter1_176_801_Open_Text.style.display='none'; Codehighlighter1_176_801_Closed_Image.style.display='inline'; Codehighlighter1_176_801_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_176_801_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_176_801_Closed_Text.style.display='none'; Codehighlighter1_176_801_Open_Image.style.display='inline'; Codehighlighter1_176_801_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedSubBlock.gif" align=top></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;main(String[]&nbsp;args)&nbsp;</span><span id=Codehighlighter1_176_801_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"></span><span id=Codehighlighter1_176_801_Open_Text><span style="COLOR: #000000">{<br></span><span style="COLOR: #008080">10</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;java.net.URL&nbsp;urlfile&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">null</span><span style="COLOR: #000000">;&nbsp;<br></span><span style="COLOR: #008080">11</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;HttpURLConnection&nbsp;httpUrl&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">null</span><span style="COLOR: #000000">;&nbsp;<br></span><span style="COLOR: #008080">12</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top><br></span><span style="COLOR: #008080">13</span><span style="COLOR: #000000"><img id=Codehighlighter1_251_771_Open_Image onclick="this.style.display='none'; Codehighlighter1_251_771_Open_Text.style.display='none'; Codehighlighter1_251_771_Closed_Image.style.display='inline'; Codehighlighter1_251_771_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_251_771_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_251_771_Closed_Text.style.display='none'; Codehighlighter1_251_771_Open_Image.style.display='inline'; Codehighlighter1_251_771_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">try</span><span style="COLOR: #000000">&nbsp;</span><span id=Codehighlighter1_251_771_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"></span><span id=Codehighlighter1_251_771_Open_Text><span style="COLOR: #000000">{<br></span><span style="COLOR: #008080">14</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top><br></span><span style="COLOR: #008080">15</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;连接指定的网络资源,获取网络输入流</span><span style="COLOR: #008000"><br></span><span style="COLOR: #008080">16</span><span style="COLOR: #008000"><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;urlfile&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;java.net.URL(<br></span><span style="COLOR: #008080">17</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">http://10.142.202.12/ftp/Y0131000000168/D0011000006537.jpg</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br></span><span style="COLOR: #008080">18</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;httpUrl&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;(HttpURLConnection)&nbsp;urlfile.openConnection();<br></span><span style="COLOR: #008080">19</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;httpUrl.connect();<br></span><span style="COLOR: #008080">20</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;bytesum&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br></span><span style="COLOR: #008080">21</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;byteread&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br></span><span style="COLOR: #008080">22</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;InputStream&nbsp;inStream&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;httpUrl.getInputStream();<br></span><span style="COLOR: #008080">23</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;FileOutputStream&nbsp;fs&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;FileOutputStream(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">c:/1.jpg</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br></span><span style="COLOR: #008080">24</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">byte</span><span style="COLOR: #000000">[]&nbsp;buffer&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">byte</span><span style="COLOR: #000000">[</span><span style="COLOR: #000000">1444</span><span style="COLOR: #000000">];<br></span><span style="COLOR: #008080">25</span><span style="COLOR: #000000"><img id=Codehighlighter1_697_762_Open_Image onclick="this.style.display='none'; Codehighlighter1_697_762_Open_Text.style.display='none'; Codehighlighter1_697_762_Closed_Image.style.display='inline'; Codehighlighter1_697_762_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_697_762_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_697_762_Closed_Text.style.display='none'; Codehighlighter1_697_762_Open_Image.style.display='inline'; Codehighlighter1_697_762_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">while</span><span style="COLOR: #000000">&nbsp;((byteread&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;inStream.read(buffer))&nbsp;</span><span style="COLOR: #000000">!=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">)&nbsp;</span><span id=Codehighlighter1_697_762_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"></span><span id=Codehighlighter1_697_762_Open_Text><span style="COLOR: #000000">{<br></span><span style="COLOR: #008080">26</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;bytesum&nbsp;</span><span style="COLOR: #000000">+=</span><span style="COLOR: #000000">&nbsp;byteread;<br></span><span style="COLOR: #008080">27</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fs.write(buffer,&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">,&nbsp;byteread);<br></span><span style="COLOR: #008080">28</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;<br></span><span style="COLOR: #008080">29</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br></span><span style="COLOR: #008080">30</span><span style="COLOR: #000000"><img id=Codehighlighter1_793_798_Open_Image onclick="this.style.display='none'; Codehighlighter1_793_798_Open_Text.style.display='none'; Codehighlighter1_793_798_Closed_Image.style.display='inline'; Codehighlighter1_793_798_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_793_798_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_793_798_Closed_Text.style.display='none'; Codehighlighter1_793_798_Open_Image.style.display='inline'; Codehighlighter1_793_798_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">catch</span><span style="COLOR: #000000">&nbsp;(Exception&nbsp;e)&nbsp;</span><span id=Codehighlighter1_793_798_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"></span><span id=Codehighlighter1_793_798_Open_Text><span style="COLOR: #000000">{<br></span><span style="COLOR: #008080">31</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top><br></span><span style="COLOR: #008080">32</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000">&nbsp;<br></span><span style="COLOR: #008080">33</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">34</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">35</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top></span>
<img src ="http://www.blogjava.net/jiangmin/aggbug/110563.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jiangmin/" target="_blank">JiangMin</a> 2007-04-14 01:07 <a href="http://www.blogjava.net/jiangmin/articles/110563.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Tomcat+DB2的数据库连接池配置</title><link>http://www.blogjava.net/jiangmin/articles/110560.html</link><dc:creator>JiangMin</dc:creator><author>JiangMin</author><pubDate>Fri, 13 Apr 2007 17:01:00 GMT</pubDate><guid>http://www.blogjava.net/jiangmin/articles/110560.html</guid><wfw:comment>http://www.blogjava.net/jiangmin/comments/110560.html</wfw:comment><comments>http://www.blogjava.net/jiangmin/articles/110560.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jiangmin/comments/commentRss/110560.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jiangmin/services/trackbacks/110560.html</trackback:ping><description><![CDATA[<div class=blogtext id=blogtext__fks_nCANEH7d3w7qRprayqZmMA==>网上找到使用TOMCAT配置DB2的资料很少，很多人挂&#8220;羊头&#8220;卖&#8220;狗肉&#8221;，这是老大花了一定的时间研究之后才搞定的，所以发出来避免大家走弯路，虽然是转载，希望能发到首页，避免大家走弯路<br>转自老大的blog,顺便打打广告<a href="http://163hbfang.blog.163.com/blog/static/2448133200621134590/"><font color=#bbbb99 size=2>http://163hbfang.blog.163.com/blog/static/2448133200621134590/</font></a>
<p>上面还是有很多有技术价值的东西，不过因为在163所以很少人光顾，帮他打广告^_^<br>1、操作系统Windows2000（经测试，在Linux不需操作第6点)<br>2、Tomcat版本：Apache Tomcat/5.0.16<br>3、JDK版本：j2sdk1.4.1_03<br>4、DB2版本：使用db2inst1用户输入db2level命令得到：DB2 v8.1.0.96，修订包为"10"<br>5、在安装DB2的机器上/opt/IBM/db2/V8.1/java目录下拷贝db2java.zip、db2jcc.jar到$CATALINA_HOME/common/lib下，并重命名db2java.zip为db2java.jar<br>6、把db2java.jar加classpath<br>&nbsp;&nbsp; .;C:\j2sdk1.4.1_03\lib\dt.jar;D:\tomcat5\common\lib\db2jcc.jar;D:\tomcat5\common\lib\db2java.jar;<br>7、手工配置zjdii.xml，不要在$CATALINA_HOME/conf/server.xml修改任何信息；在$CATALINA_HOME/conf/localhost下修改或新建zjdii.xml</p>
<p>&lt;Context displayName="ZJDII" docBase="zjdii" path="/zjdii"&gt;<br>&nbsp; &lt;Logger className="org.apache.catalina.logger.FileLogger" prefix="localhost_zjdii_log." suffix=".txt" timestamp="true"/&gt;<br>&nbsp; &lt;Resource auth="Container" name="jdbc/zjdii" type="javax.sql.DataSource"/&gt;<br>&nbsp; &lt;ResourceParams name="jdbc/zjdii"&gt;<br>&nbsp;&nbsp;&nbsp; &lt;parameter&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;name&gt;factory&lt;/name&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;value&gt;org.apache.commons.dbcp.BasicDataSourceFactory&lt;/value&gt;<br>&nbsp;&nbsp;&nbsp; &lt;/parameter&gt;<br>&nbsp;&nbsp;&nbsp; &lt;parameter&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;name&gt;url&lt;/name&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;value&gt;jdbc:db2://192.168.200.113:6789/zjdii&lt;/value&gt;<br>&nbsp;&nbsp;&nbsp; &lt;/parameter&gt;<br>&nbsp;&nbsp;&nbsp; &lt;parameter&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;name&gt;password&lt;/name&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;value&gt;yourpasswd&lt;/value&gt;<br>&nbsp;&nbsp;&nbsp; &lt;/parameter&gt;<br>&nbsp;&nbsp;&nbsp; &lt;parameter&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;name&gt;maxWait&lt;/name&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;value&gt;1000&lt;/value&gt;<br>&nbsp;&nbsp;&nbsp; &lt;/parameter&gt;<br>&nbsp;&nbsp;&nbsp; &lt;parameter&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;name&gt;maxActive&lt;/name&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;value&gt;10&lt;/value&gt;<br>&nbsp;&nbsp;&nbsp; &lt;/parameter&gt;<br>&nbsp;&nbsp;&nbsp; &lt;parameter&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;name&gt;driverClassName&lt;/name&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;value&gt;COM.ibm.db2.jdbc.net.DB2Driver&lt;/value&gt;<br>&nbsp;&nbsp;&nbsp; &lt;/parameter&gt;<br>&nbsp;&nbsp;&nbsp; &lt;parameter&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;name&gt;username&lt;/name&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;value&gt;yourusername&lt;/value&gt;<br>&nbsp;&nbsp;&nbsp; &lt;/parameter&gt;<br>&nbsp;&nbsp;&nbsp; &lt;parameter&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;name&gt;maxIdle&lt;/name&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;value&gt;30&lt;/value&gt;<br>&nbsp;&nbsp;&nbsp; &lt;/parameter&gt;<br>&nbsp; &lt;/ResourceParams&gt;<br>&lt;/Context&gt;<br><br>常见错误信息及解决方案：</p>
<p>org.apache.commons.dbcp.SQLNestedException: Cannot load JDBC driver class 'COM.i<br>bm.db2.jdbc.net.DB2Driver', cause:<br>java.lang.ClassNotFoundException: COM.ibm.db2.jdbc.net.DB2Driver<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at org.apache.catalina.loader.StandardClassLoader.loadClass(StandardClas<br>sLoader.java:891)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at org.apache.catalina.loader.StandardClassLoader.loadClass(StandardClas<br>sLoader.java:756)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:315)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at java.lang.Class.forName0(Native Method)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at java.lang.Class.forName(Class.java:140)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at org.apache.commons.dbcp.BasicDataSource.createDataSource(BasicDataSou<br>rce.java:730)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at org.apache.commons.dbcp.BasicDataSource.getConnection(BasicDataSource<br>.java:518)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at com.zjdii.db.DataBase.getConnection(Database.java:44)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at com.zjdii.db.DBFactory.getPreparedStatement(DBFactory.java:86)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at org.apache.jsp.test.clob.clob_jsp._jspService(clob_jsp.java:50)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:133)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at javax.servlet.http.HttpServlet.service(HttpServlet.java:856)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper<br>.java:311)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:3<br>01)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:248)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at javax.servlet.http.HttpServlet.service(HttpServlet.java:856)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(Appl<br>icationFilterChain.java:284)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationF<br>ilterChain.java:204)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperV<br>alve.java:256)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValv<br>eContext.java:151)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.jav<br>a:564)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at org.apache.catalina.core.StandardContextValve.invokeInternal(Standard<br>ContextValve.java:245)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at org.apache.catalina.core.StandardContextValve.invoke(StandardContextV<br>alve.java:199)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValv<br>eContext.java:151)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.jav<br>a:564)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.j<br>ava:195)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValv<br>eContext.java:151)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.j<br>ava:164)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValv<br>eContext.java:149)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.jav<br>a:564)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineVal<br>ve.java:156)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValv<br>eContext.java:151)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.jav<br>a:564)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:972)</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at org.apache.coyote.tomcat5.CoyoteAdapter.service(CoyoteAdapter.java:21<br>1)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java<br>:805)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.proce<br>ssConnection(Http11Protocol.java:696)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at org.apache.tomcat.util.net.TcpWorkerThread.runIt(PoolTcpEndpoint.java<br>:605)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadP<br>ool.java:677)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at java.lang.Thread.run(Thread.java:536)<br>java.lang.NullPointerException</p>
<p><br>解决方案：<br>把D:\tomcat5\webapps\common\lib\db2java.jar;加入classpath里</p>
<p>&nbsp;</p>
<p>javax.servlet.ServletException: com/ibm/db2/jcc/SQLJPackage<br>&nbsp;org.apache.jasper.runtime.PageContextImpl.doHandlePageException(PageContextImpl.java:867)<br>&nbsp;org.apache.jasper.runtime.PageContextImpl.handlePageException(PageContextImpl.java:800)<br>&nbsp;org.apache.jsp.test.clob.clob_jsp._jspService(clob_jsp.java:82)<br>&nbsp;org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:133)<br>&nbsp;javax.servlet.http.HttpServlet.service(HttpServlet.java:856)<br>&nbsp;org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:311)<br>&nbsp;org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:301)<br>&nbsp;org.apache.jasper.servlet.JspServlet.service(JspServlet.java:248)<br>&nbsp;javax.servlet.http.HttpServlet.service(HttpServlet.java:856)</p>
<p><br>root cause </p>
<p>java.lang.NoClassDefFoundError: com/ibm/db2/jcc/SQLJPackage<br>&nbsp;COM.ibm.db2.jdbc.net.DB2Connection.prepareStatement(DB2Connection.java:627)<br>&nbsp;org.apache.commons.dbcp.DelegatingConnection.prepareStatement(DelegatingConnection.java:216)<br>&nbsp;org.apache.commons.dbcp.PoolingDataSource$PoolGuardConnectionWrapper.prepareStatement(PoolingDataSource.java:323)<br>&nbsp;com.zjdii.db.DBFactory.getPreparedStatement(DBFactory.java:167)<br>&nbsp;org.apache.jsp.test.clob.clob_jsp._jspService(clob_jsp.java:50)<br>&nbsp;org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:133)<br>&nbsp;javax.servlet.http.HttpServlet.service(HttpServlet.java:856)<br>&nbsp;org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:311)<br>&nbsp;org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:301)<br>&nbsp;org.apache.jasper.servlet.JspServlet.service(JspServlet.java:248)<br>&nbsp;javax.servlet.http.HttpServlet.service(HttpServlet.java:856)</p>
<p><br>note The full stack trace of the root cause is available in the Tomcat logs.</p>
<p>解决方案：<br>把D:\tomcat5\webapps\common\lib\db2jcc.jar;加入classpath里</p>
</div>
<img src ="http://www.blogjava.net/jiangmin/aggbug/110560.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jiangmin/" target="_blank">JiangMin</a> 2007-04-14 01:01 <a href="http://www.blogjava.net/jiangmin/articles/110560.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>利用commons-fileupload组件上传文件至服务器和数据库</title><link>http://www.blogjava.net/jiangmin/articles/101800.html</link><dc:creator>JiangMin</dc:creator><author>JiangMin</author><pubDate>Sun, 04 Mar 2007 16:31:00 GMT</pubDate><guid>http://www.blogjava.net/jiangmin/articles/101800.html</guid><wfw:comment>http://www.blogjava.net/jiangmin/comments/101800.html</wfw:comment><comments>http://www.blogjava.net/jiangmin/articles/101800.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jiangmin/comments/commentRss/101800.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jiangmin/services/trackbacks/101800.html</trackback:ping><description><![CDATA[
		<span id="ArticleContent1_ArticleContent1_lblContent"> 
<p>common-fileupload是jakarta项目组开发的一个功能很强大的上传文件组件</p><p>下面先介绍上传文件到服务器（多文件上传）：</p><p>import javax.servlet.*;<br />import javax.servlet.http.*;<br />import java.io.*;<br />import java.util.*;<br />import java.util.regex.*;<br />import org.apache.commons.fileupload.*;<br /></p><p>public class upload extends HttpServlet {<br />  private static final String CONTENT_TYPE = "text/html; charset=GB2312";<br />  //Process the HTTP Post request<br />  public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {<br />    response.setContentType(CONTENT_TYPE);<br />    PrintWriter out=response.getWriter();<br />    try {<br />    DiskFileUpload fu = new DiskFileUpload();<br /> // 设置允许用户上传文件大小,单位:字节，这里设为2m<br /> fu.setSizeMax(2*1024*1024);<br /> // 设置最多只允许在内存中存储的数据,单位:字节<br /> fu.setSizeThreshold(4096);<br /> // 设置一旦文件大小超过getSizeThreshold()的值时数据存放在硬盘的目录<br /> fu.setRepositoryPath("c:\\windows\\temp");<br /> //开始读取上传信息<br /> List fileItems = fu.parseRequest(request);<br /> // 依次处理每个上传的文件<br />   Iterator iter = fileItems.iterator();</p><p>//正则匹配，过滤路径取文件名<br />   String regExp=".+\\\\(.+)$";</p><p>//过滤掉的文件类型<br />String[] errorType={".exe",".com",".cgi",".asp"};<br />   Pattern p = Pattern.compile(regExp);<br />      while (iter.hasNext()) {<br />       FileItem item = (FileItem)iter.next();<br />       //忽略其他不是文件域的所有表单信息<br />       if (!item.isFormField()) {<br />           String name = item.getName();<br />           long size = item.getSize();<br />           if((name==null||name.equals("")) &amp;&amp; size==0)<br />               continue;<br />        Matcher m = p.matcher(name);<br />       boolean result = m.find();<br />       if (result){<br />           for (int temp=0;temp&lt;errorType.length;temp++){<br />           if (m.group(1).endsWith(errorType[temp])){<br />                 throw new IOException(name+": wrong type");<br />           }<br />           }<br />           try{</p><p>//保存上传的文件到指定的目录</p><p>//在下文中上传文件至数据库时，将对这里改写<br />             item.write(new File("d:\\" + m.group(1)));</p><p>           out.print(name+"&amp;nbsp;&amp;nbsp;"+size+"&lt;br&gt;");<br />           }<br />           catch(Exception e){<br />             out.println(e);<br />           }</p><p>        }<br />       else<br />       {<br />         throw new IOException("fail to upload");<br />       }<br />       }<br />   }<br />}<br /> catch (IOException e){<br />   out.println(e);<br /> }<br /> catch (FileUploadException e){<br />      out.println(e);<br /> }<br /> <br />  }<br />}</p><p>下面是个html的上传页面：</p><p>&lt;h1&gt;文件上传演示&lt;/h1&gt;</p><p>&lt;form name="uploadform" method="POST" action="/upload" ENCTYPE="multipart/form-data"&gt;</p><p>        &lt;table border="1" width="450" cellpadding="4" cellspacing="2" bordercolor="#9BD7FF"&gt;</p><p>        &lt;tr&gt;&lt;td width="100%" colspan="2"&gt;</p><p>                        文件1：&lt;input name="x" size="40" type="file"&gt;</p><p>        &lt;/td&gt;&lt;/tr&gt;</p><p>        &lt;tr&gt;&lt;td width="100%" colspan="2"&gt;</p><p>                        文件2：&lt;input name="y" size="40" type="file"&gt;</p><p>        &lt;/td&gt;&lt;/tr&gt;</p><p>        &lt;tr&gt;&lt;td width="100%" colspan="2"&gt;</p><p>                        文件3：&lt;input name="z" size="40" type="file"&gt;</p><p>        &lt;/td&gt;&lt;/tr&gt;</p><p>        &lt;/table&gt;</p><p>        &lt;br/&gt;&lt;br/&gt;</p><p>        &lt;table&gt;</p><p>        &lt;tr&gt;&lt;td align="center"&gt;&lt;input name="upload" type="submit" value="开始上传"/&gt;&lt;/td&gt;&lt;/tr&gt;</p><p>       &lt;/table&gt;</p><p>&lt;/form&gt;</p><p>现在介绍上传文件到服务器，下面只写出相关代码：</p><p>以sql2000为例，表结构如下：</p><p>字段名：name    filecode</p><p>类型： varchar     image</p><p>数据库插入代码为：PreparedStatement pstmt=conn.prepareStatement("insert into test values(?,?)");</p><p>代码如下：</p><p>。。。。。。</p><p>           try{<br />             //item.write(new File("d:\\" + m.group(1)));//这段代码如果不去掉，将一同写入到服务器中</p><p>             int byteread=0;</p><p>             InputStream inStream=item.getInputStream();  //读取输入流，也就是上传的文件内容<br />             pstmt.setString(1,m.group(1));<br />             pstmt.setBinaryStream(2,inStream,(int)size);<br />             pstmt.executeUpdate();<br />             inStream.close();</p><p>             out.println(name+"&amp;nbsp;&amp;nbsp;"+size+"&lt;br&gt;");<br />           }</p><p>。。。。。。</p><p>这样就实现了上传文件至数据库<br /></p></span>
<img src ="http://www.blogjava.net/jiangmin/aggbug/101800.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jiangmin/" target="_blank">JiangMin</a> 2007-03-05 00:31 <a href="http://www.blogjava.net/jiangmin/articles/101800.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>基于Java Web的文件上传进度显示的一种解决方案</title><link>http://www.blogjava.net/jiangmin/articles/101799.html</link><dc:creator>JiangMin</dc:creator><author>JiangMin</author><pubDate>Sun, 04 Mar 2007 16:30:00 GMT</pubDate><guid>http://www.blogjava.net/jiangmin/articles/101799.html</guid><wfw:comment>http://www.blogjava.net/jiangmin/comments/101799.html</wfw:comment><comments>http://www.blogjava.net/jiangmin/articles/101799.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jiangmin/comments/commentRss/101799.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jiangmin/services/trackbacks/101799.html</trackback:ping><description><![CDATA[
		<span id="ArticleContent1_ArticleContent1_lblContent"> 
<p>在Web应用开发中，常常会遇到文件的上传下载模块，下载文件时无论IE还是常用的flashget等下载软件都提供了友好的下载进度显示，可以让用户很清晰的了解到下载的进度，特别是在进行大文件传输时，为用户提供了非常舒服的感觉...可以想像，一个几百M或者上G的文件传输过程没有进度显示，是一件多么让人无法忍受的事情。<br /><br />?然而在如今大多数的服务器上传组件中却没能提供文件上传进度的显示功能或相应开发接口，当进行大文件上传操作或低速网络上传时，长时间的无知状态常常使用户不知所措。<br /><br />?本文（及附上的相应组件）提供了一套基于Java Web的HTTP文件上传进度显示的解决方案，可以应用于jsp,servlet的web应用开发中，它由apache的commons-fileupload-1.0组件扩展而来，没有改动任何原有组件代码，进度显示部分完全以一种扩展组件形式出现，你可以随时使用或不使用此显示组件，而无需对原有上传应用程序进行大规模的变动。<br /><br />ahxu-commons-fileuploadex-1.0在apache的commons-fileupload-1.0的基础上扩展了以下功能：<br /><br /><font color="#ff0000" size="2">1.增加了文件类型检测功能，可以设定上传文件的类型，不被允许上传的文件将不能上传；<br />2.增加了对非文件域表单上传的过滤功能，可以选择或不选择上传接收非文件域的表单内容；<br />3.增加了文件上传进度报告功能，动态报告上传文件的文件名、大小、速度、总时间、剩余时间等，并提供了基于此进度报告功能的一种解决方案；</font></p><font color="#ff0000" size="2"><p><br /></p></font><font color="#000000" size="5"><strong>安装（以tomcat-5.0.27为例）：</strong></font><br />1.下载apache的commons-fileupload-1.0组件<br />下载地址<a href="http://apache.linuxforum.net/dist/jakarta/commons/fileupload/binaries/commons-fileupload-1.0.zip">http://apache.linuxforum.net/dist/jakarta/commons/fileupload/binaries/commons-fileupload-1.0.zip</a><a href="http://jakarta.apache.org/commons/fileupload/"></a><br />2. 下载ahxu的ahxu-commons-fileuploadex-1.0组件<br />下载地址<a href="http://www.lizonghan.com/ahxu/ahxu-commons-fileuploadex-1.0.jar">http://www.lizonghan.com/ahxu/ahxu-commons-fileuploadex-1.0.jar<br /></a>3. 将此二个.jar文件放入一个已配置好的web应用的WEB-INF\lib目录下，例如：test\WEB-INF\lib<br /><font size="5"><strong>测试：</strong></font><br />1.下载应用测试代码upload-jsp.rar，下载地址<a href="http://www.lizonghan.com/ahxu/upload-jsp.rar">http://www.lizonghan.com/ahxu/upload-jsp.rar</a> ，解压放在此web应用的根目录，例如：test\<br />2.运行测试upload.jsp，要求IE5.0以上，例如：<a href="http://127.0.0.1/test/upload.jsp">http://127.0.0.1/test/upload.jsp</a><br />3.选择一个或二个大点儿的文件，最好几百M，然后上传，上传过程中会弹出一个进度对话框，如图<p align="center"><img alt="" hspace="0" src="http://dev.csdn.net/images/blog_csdn_net/ahxu/35401/o_progress1.jpg" align="baseline" border="0" /><br /><font size="2">图1 文件上传进度显示对话框</font></p><p align="left">4.文件上传完毕后将显示上传结果，进度对话框自动关闭。<br /><font color="#0000ff" size="2"><font color="#ff0000">注：以上过程在win2000+sp4+tomcat5.0.27+IE6.0测试通过，其它环境是否能正常运行，希望大家测试后将信息反馈给我，谢谢！</font></font></p><p align="left"><font size="5"><strong>有用的upload-jsp.rar：</strong></font></p><p align="left">upload-jsp.rar中包含的4个文件：upload.jsp、receive.jsp、progressbar.jsp、progressdetail.jsp</p><p><strong>1．upload.jsp——文件上传表单页面；</strong><br />此页面包含了文件上传的form表单，当然也可以是你的应用中任何你喜欢的有文件上传form表单的页面。此页面在submit时调用javascript函数uploadBegin()弹出进度显示对话框（显示progressbar.jsp）；你也可以根据需要自己定制，例如不用对话框，用iframe等。但form的onSubmit时要调用uploadBegin()，如： 
</p><table width="90%" bgcolor="#cccccc" border="0"><tbody><tr><td><p><font size="2">&lt;script language="javascript"&gt;<br />function uploadBegin(){<br /> theFeats = "height=200,width=320,location=no,menubar=no,resizable=no,scrollbars=no,status=no,toolbar=no";<br /> strAppVersion = navigator.appVersion;<br /> if (document.uploadForm.file1.value != "")<br /> {<br />     if (strAppVersion.indexOf('MSIE') != -1 &amp;&amp; strAppVersion.substr(strAppVersion.indexOf('MSIE')+5,1) &gt; 4)<br />     { <br />   winstyle = "dialogWidth=320px; dialogHeight:200px; center:yes";<br />   window.showModelessDialog(&lt;%="\""+response.encodeURL("progressbar.jsp")+"\""%&gt;,window,winstyle);<br />     }<br /> }<br />}<br />&lt;/script&gt;</font></p><p><font size="2">&lt;form action=&lt;%="\""+response.encodeURL("receive.jsp")+"\""%&gt; enctype="multipart/form-data" method="post" name="uploadForm" id="uploadForm" onsubmit="uploadBegin();"&gt;</font></p></td></tr></tbody></table><strong>2．receive.jsp——文件上传接收页，即服务器端接收上传数据并处理上传数据的页面，可以用servlet来代替；</strong><table width="90%" bgcolor="#cccccc" border="0"><tbody><tr><td><p><font size="2">&lt;%</font></p><p><font size="2">List fileItemList=null;<br />//DiskFileUpload fu = new DiskFileUpload();//初使化使用原有apache的upload<br />DiskFileUploadEx fu = new DiskFileUploadEx();//初使化ahxu扩展后的组件<br />fu.setSizeMax(1000*1024*1024);//原有apache的upload:设置允许上传的最大值<br />fu.setAllowFiles(".txt;.jpg;.rm");//ahxu扩展后：设置允许的上传文件类型</font></p><p><font size="2">try{<br /> <br /> //fileItemList=fu.parseRequest(request);//使用原有apache的upload:由request接收上传文件<br /> fileItemList=fu.parseRequestExSessionReport(request);//ahxu扩展后的:接收上传文件<br /> Iterator fileItemListIte=fileItemList.iterator();<br /> while(fileItemListIte.hasNext())<br /> {<br />  FileItem file=(FileItem)fileItemListIte.next();<br />  out.println(file.getName()+"&lt;br&gt;");<br />//此处进行文件处理</font><font size="2"><br /> }<br /> out.println("上传成功");<br />}catch (Exception e){<br /> out.println("上传失败&lt;br&gt;");<br /> out.println(e.getMessage());<br /> /*显示不被允许上传的文件列表，原有apache的upload无此部分 begin*/<br /> if(e instanceof DiskFileUploadEx.InvalidFileUploadException){<br />  out.println("&lt;p&gt;以下文件不被允许：&lt;/p&gt;");<br />  Iterator unAllowFileS=((DiskFileUploadEx.InvalidFileUploadException)e).getInvalidFileList().iterator();<br />  while(unAllowFileS.hasNext()){<br />   out.println((String)unAllowFileS.next()+"&lt;br&gt;");<br />  }<br /> /*显示不被允许上传的文件列表，原有apache的upload无此部分 end */<br /> }</font></p><p><font size="2">}<br />finally{<br />Thread.sleep(1000);<br />fu.clear(request);//ahxu扩展后的组件:接收上传文件后的清理工作，原有apache组件没有此过程<br />}<br />%&gt;</font></p></td></tr></tbody></table><strong>3．progressbar.jsp——文件上传进度显示页，如图1；<br /></strong>你也可以根据自己的需要定制自己样式的进度显示页面。<br /><strong>4．progressdetail.jsp——文件上传进度数据读取页，用来构造上传进度信息，供progressbar.jsp读取显示，无需修改</strong><p><font size="5"><strong>简单应用部署的总结：</strong></font><br />1．下载安装apache的commons-fileupload-1.0组件及ahxu-commons-fileuploadex-1.0组件；<br />2．编辑上传表单文件，注意要复制upload.jsp的uploadBegin()，以及form表单的onsubmit="uploadBegin();"<br />3．复制progressbar.jsp、progressdetail.jsp无需修改；<br />4．根据需要编辑receive.jsp页的内容。</p></span>
<img src ="http://www.blogjava.net/jiangmin/aggbug/101799.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jiangmin/" target="_blank">JiangMin</a> 2007-03-05 00:30 <a href="http://www.blogjava.net/jiangmin/articles/101799.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java中文问题详解(高手必读）</title><link>http://www.blogjava.net/jiangmin/articles/101798.html</link><dc:creator>JiangMin</dc:creator><author>JiangMin</author><pubDate>Sun, 04 Mar 2007 16:26:00 GMT</pubDate><guid>http://www.blogjava.net/jiangmin/articles/101798.html</guid><wfw:comment>http://www.blogjava.net/jiangmin/comments/101798.html</wfw:comment><comments>http://www.blogjava.net/jiangmin/articles/101798.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jiangmin/comments/commentRss/101798.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jiangmin/services/trackbacks/101798.html</trackback:ping><description><![CDATA[我来说一下tomcat如何实现JSP的你就明白了。<br />预备知识：<br />　1.字节和unicode<br />　　Java内核是unicode的，就连class文件也是，但是很多媒体，包括文件/流的保存方式<br />　　是使用字节流的。 因此Java要对这些字节流经行转化。char是unicode的，而byte是字节.<br />　　Java中byte/char互转的函数在sun.io的包中间有。其中ByteToCharConverter类是中调度，<br />　　可以用来告诉你，你用的Convertor。其中两个很常用的静态函数是<br />　　 public static ByteToCharConverter getDefault() ;<br />　　 public static ByteToCharConverter getConverter(String encoding);<br />　　如果你不指定converter，则系统会自动使用当前的Encoding,GB平台上用GBK,EN平台上用<br />　　8859_1<br />　　<br />　　我们来就一个简单的例子：<br />　　　　　"你"的gb码是：0xC4E3 ,unicode是0x4F60<br />　　　　　你用:<br />　　　　　--encoding="gb2312";<br />　　　　　--byte b[]={(byte)´\u00c4´,(byte)´\u00E3´};<br />　　　　　--convertor=ByteToCharConverter.getConverter(encoding);<br />　　　　　--char [] c=converter.convertAll(b);<br />　　　　　--for(int i=0;i&lt;c.length;c )<br />　　　　　--{<br />　　　　　-- System.out.println(Integer.toHexString(c[i]));<br />　　　　　--}<br />　　　　　--打印出来是0x4F60<br />　　　　　--但是如果使用8859_1的编码，打印出来是<br />　　　　　--0x00C4,0x00E3<br />　　　　　----例１<br />　　　　 反过来：<br />　　　　 --encoding="gb2312";<br />　　　　 　　　char c[]={´\u4F60´};<br />　　　　　　　 convertor=ByteToCharConverter.getConverter(encoding);<br />　　　　　--byte [] b=converter.convertAll(c);<br />　　　　　--for(int i=0;i&lt;b.length;c )<br />　　　　　--{<br />　　　　　-- System.out.println(Integer.toHexString(b[i]));<br />　　　　　--}<br />　　　　　　--打印出来是：0xC4,0xE3<br />　　　　　　----例２<br />　　　　　　--如果用8859_1就是0x3F，?号，表示无法转化　　　　　　--<br />　　　　　 很多中文问题就是从这两个最简单的类派生出来的。而却有很多类　　<br />　　不直接支持把Encoding输入，这给我们带来诸多不便。很多程序难得用encoding<br />　　了，直接用default的encoding，这就给我们移植带来了很多困难<br />　　--<br />　　2.UTF-8<br />　　--UTF-8是和Unicode一一对应的，其实现很简单<br />　　--<br />　　 -- 7位的Unicode: 0 _ _ _ _ _ _ _<br />　　--11位的Unicode: 1 1 0 _ _ _ _ _ 1 0 _ _ _ _ _ _<br />　　--16位的Unicode: 1 1 1 0 _ _ _ _ 1 0 _ _ _ _ _ _ 1 0 _ _ _ _ _ _<br />　　--21位的Unicode: 1 1 1 1 0 _ _ _ 1 0 _ _ _ _ _ _ 1 0 _ _ _ _ _ _ 1 0 _ _ _ _ _ _<br />　　--大多数情况是只使用到16位以下的Unicode:<br />　　--"你"的gb码是：0xC4E3 ,unicode是0x4F60<br />　　--我们还是用上面的例子<br />　　--　　--例１：0xC4E3的二进制：<br />　　--　　--　　　 1 1 0 0 0 1 0 0 1 1 1 0 0 0 1 1<br />　　--　　--　　　 由于只有两位我们按照两位的编码来排，但是我们发现这行不通，<br />　　--　　--　　　 因为第７位不是0因此，返回"?"<br />　　--　　--　　　 <br />　　--　　--例２：0x4F60的二进制：<br />　　--　　--　　　 0 1 0 0 1 1 1 1 0 1 1 0 0 0 0 0 <br />　　--　　--　　　 我们用UTF-8补齐，变成：<br />　　--　　--　　　 11100100 10111101 10100000<br />　　--　　--　　　 E4--BD-- A0<br />　　--　　--　　　 于是返回0xE4,0xBD,0xA0<br />　　--　　--<br />　　3.String和byte[]<br />　　--String其实核心是char[],然而要把byte转化成String，必须经过编码。<br />　　--String.length()其实就是char数组的长度，如果使用不同的编码，很可<br />　　--能会错分，造成散字和乱码。<br />　　--例：<br />　　----byte [] b={(byte)´\u00c4´,(byte)´\u00e3´};<br />　　----String str=new String(b,encoding);　　----<br />　　----如果encoding=8859_1，会有两个字，但是encoding=gb2312只有一个字　　----<br />　　--这个问题在处理分页是经常发生<br />　　4.Reader,Writer/InputStream,OutputStream<br />　　--Reader和Writer核心是char，InputStream和OutputStream核心是byte。<br />　　--但是Reader和Writer的主要目的是要把Char读/写InputStream/OutputStream<br />--一个reader的例子：<br />--文件test.txt只有一个"你"字，0xC4,0xE3--<br />--String encoding=;<br />--InputStreamReader reader=new InputStreamReader(<br />----new FileInputStream("text.txt"),encoding);<br />--char []c=new char[10];<br />--int length=reader.read(c);<br />--for(int i=0;i&lt;c.length;i )<br />----System.out.println(c[i]);<br />　　--如果encoding是gb2312，则只有一个字符，如果encoding=8859_1，则有两个字符<br />　　--------<br />--<br />--<br />　　<br />　　 ----<br />　2.我们要对Java的编译器有所了解：<br />　--javac -encoding<br />　 我们常常没有用到ENCODING这个参数。其实Encoding这个参数对于跨平台的操作是很重要的。<br />　 如果没有指定Encoding，则按照系统的默认Encoding,gb平台上是gb2312，英文平台上是ISO8859_1。　 <br />　--Java的编译器实际上是调用sun.tools.javac.Main的类，对文件进行编译，这个类　--<br />　有compile函数中间有一个encoding的变量,-encoding的参数其实直接传给encoding变量。<br />　编译器就是根据这个变量来读取java文件的，然后把用UTF-8形式编译成class文件。<br />　一个例子：<br />　--public void test()<br />　--{<br />　----String str="你";<br />　----FileWriter write=new FileWriter("test.txt");<br />　----write.write(str);<br />　----write.close();<br />　--}<br />　----例３<br />--如果用gb2312编译，你会找到E4 BD A0的字段<br />--<br />--如果用8859_1编译，<br />--00C4 00E3的二进制：<br />--00000000 11000100 00000000 11100011--<br />--因为每个字符都大于7位，因此用11位编码：<br />--11000001 10000100 11000011 10100011 <br />--C1-- 84--　C3--　 A3<br />--你会找到C1 84 C3 A3 --<br />　　　　<br />　　但是我们往往忽略掉这个参数，因此这样往往会有跨平台的问题：<br />　　--　　例３在中文平台上编译，生成ZhClass<br />　　--　　例３在英文平台上编译，输出EnClass<br />　　--1.　 ZhClass在中文平台上执行OK,但是在英文平台上不行<br />　　--2.　 EnClass在英文平台上执行OK,但是在中文平台上不行<br />　　原因：<br />　--1.在中文平台上编译后，其实str在运行态的char[]是0x4F60,　----<br />　--在中文平台上运行，FileWriter的缺省编码是gb2312,因此<br />　--CharToByteConverter会自动用调用gb2312的converter,把str转化<br />　--成byte输入到FileOutputStream中，于是0xC4,0xE3放进了文件。<br />　--但是如果是在英文平台下，CharToByteConverter的缺省值是8859_1,<br />　--FileWriter会自动调用8859_1去转化str,但是他无法解释，因此他会<br />　--输出"?"　----<br />　--2.　在英文平台上编译后，其实str在运行态的char[]是0x00C4 0x00E3,　----<br />　--在中文平台上运行，中文无法识别，因此会出现??<br />　--　　在英文平台上，0x00C4--&gt;0xC4,0x00E3-&gt;0xE3，因此0xC4,0xE3被放进了<br />　--文件<br />----<br />1.对于JSP正文的解释：<br />--Tomcat首先看一下你的叶面中有没有"&lt;%@page include的符号。有，则在相同<br />--地方设定response.setContentType(..);按照encoding的来读，没有他按照8859_1<br />--读取文件，然后用UTF-8写成.java文件，然后用sun.tools.Main去读取这个文件，<br />--（当然它使用UTF-8去读），然后编译成class文件<br />--setContentType改变的是out的属性，out变量缺省的encoding是8859_1<br /><br />2.对Parameter的解释<br />--很不幸Parameter只有ISO8859_1的解释，这个质料可以在servlet的实现代码中找到。<br /><br />3.对include的解释<br />格式的，但是很不幸，由于那个写"org.apache.jasper.compiler.Parser"的人<br />在数组JspUtil.ValidAttribute[]忘记加了一个参数：encoding,因此导致不支<br />持这种方式。你完全可以编译源代码，加上对encoding的支持<br /><br />总结：<br /><br />如果你在NT底下，最简单的方法就是欺骗java,不加任何Encoding变量：<br />&lt;html&gt;<br />你好&lt;%=request.getParameter("value")%&gt;<br />&lt;/html&gt;<br /><br />http://localhost/test/test.jsp?value=你<br /><br />结果:你好你<br /><br />但这种方法局限性较大，比如对上传的文章分段，这样的做法是死定的，最好的<br />解决方案是用这种方案：<br />&lt;%@ page contentType="text/html;charset=gb2312" %&gt;<br />&lt;html&gt;<br />你好&lt;%=new String(request.getParameter("value").getBytes("8859_1"),"gb2312")%&gt;<br />&lt;/html&gt;<br /><img src ="http://www.blogjava.net/jiangmin/aggbug/101798.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jiangmin/" target="_blank">JiangMin</a> 2007-03-05 00:26 <a href="http://www.blogjava.net/jiangmin/articles/101798.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>HotSpot JVM 垃圾收集原理</title><link>http://www.blogjava.net/jiangmin/articles/86145.html</link><dc:creator>JiangMin</dc:creator><author>JiangMin</author><pubDate>Thu, 07 Dec 2006 10:31:00 GMT</pubDate><guid>http://www.blogjava.net/jiangmin/articles/86145.html</guid><wfw:comment>http://www.blogjava.net/jiangmin/comments/86145.html</wfw:comment><comments>http://www.blogjava.net/jiangmin/articles/86145.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jiangmin/comments/commentRss/86145.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jiangmin/services/trackbacks/86145.html</trackback:ping><description><![CDATA[HotSpot JVM<span lang="EN-US" style="FONT-FAMILY: 华文楷体"></span><span style="FONT-FAMILY: 华文楷体">垃圾收集原理<span lang="EN-US"><?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /?><o:p></o:p></span></span><p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt"><b style="mso-bidi-font-weight: normal"><span style="FONT-SIZE: 14pt; FONT-FAMILY: 华文楷体">目的<span lang="EN-US">:<o:p></o:p></span></span></b></p><p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt"><span lang="EN-US"><span style="mso-spacerun: yes"><font face="Times New Roman" size="3">     </font></span></span><span style="FONT-SIZE: 12pt; FONT-FAMILY: 华文楷体">本文描述了<span lang="EN-US">Sun</span>公司的<span lang="EN-US">HotSpot Java</span>虚拟机的垃圾收集工作原理。以便为更多<span lang="EN-US">Java</span>爱好者在设计，开发以及部署时带来更多便利和益处。<span lang="EN-US"><o:p></o:p></span></span></p><p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt"><b style="mso-bidi-font-weight: normal"><span style="FONT-SIZE: 14pt; FONT-FAMILY: 华文楷体">摘要：<span lang="EN-US"><o:p></o:p></span></span></b></p><p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt"><font size="3"><span lang="EN-US"><font face="Times New Roman"><span style="mso-tab-count: 1">       </span><span style="mso-spacerun: yes">  </span></font></span><span lang="EN-US" style="FONT-SIZE: 12pt; FONT-FAMILY: 华文楷体">JVM</span></font><span style="FONT-SIZE: 12pt; FONT-FAMILY: 华文楷体">规范中要求任何实现<span lang="EN-US">JVM</span>的实现必须要提供一个能够回收未被使用内存的机制。这个机制就是垃圾回收（<span lang="EN-US">GC</span>－<span lang="EN-US">Garbage Collection</span>）。然而垃圾回收机制设计的好坏将直接影响依赖其运行的<span lang="EN-US">java</span>应用的性能（包括处理能力，响应时间等）。在接下来的章节中将详细介绍<span lang="EN-US">SUN</span>公司的<span lang="EN-US">Java</span>虚拟机（其正式名称是<span lang="EN-US">Sun HotSopt JVM</span>）中的垃圾回收机制。<span lang="EN-US"><o:p></o:p></span></span></p><h3 style="MARGIN: 13pt 0cm"><span style="FONT-SIZE: 14pt; LINE-HEIGHT: 173%; FONT-FAMILY: 华文楷体; mso-font-kerning: 22.0pt">分代垃圾回收<span lang="EN-US"><o:p></o:p></span></span></h3><p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt"><b style="mso-bidi-font-weight: normal"><span lang="EN-US" style="FONT-SIZE: 14pt"><span style="mso-tab-count: 1"><font face="Times New Roman">      </font></span></span></b><font size="3"><span lang="EN-US" style="mso-bidi-font-size: 10.5pt"><span style="mso-spacerun: yes"><font face="Times New Roman"> </font></span></span><span lang="EN-US" style="FONT-SIZE: 12pt; FONT-FAMILY: 华文楷体">HotSpot JVM</span></font><span style="FONT-SIZE: 12pt; FONT-FAMILY: 华文楷体">使用分代垃圾回收的方式。这种垃圾回收方式并不是<span lang="EN-US">HotSpot JVM</span>的首创，而是人们在实践中发现存在下面的两条规律并在很早的时候就提出来了。即<span lang="EN-US">:<o:p></o:p></span></span></p><p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span lang="EN-US" style="FONT-SIZE: 12pt; FONT-FAMILY: 华文楷体">1</span><span style="FONT-SIZE: 12pt; FONT-FAMILY: 华文楷体">）大多数对象在创建后很短的时间内就会没有任何对象再使用它了，即未被其它对象引用。<span lang="EN-US"><o:p></o:p></span></span></p><p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span lang="EN-US" style="FONT-SIZE: 12pt; FONT-FAMILY: 华文楷体">2</span><span style="FONT-SIZE: 12pt; FONT-FAMILY: 华文楷体">）大多数一直被使用的对象（老对象）很少引用新创建的对象。<span lang="EN-US"><o:p></o:p></span></span></p><p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span style="FONT-SIZE: 12pt; FONT-FAMILY: 华文楷体">对于<span lang="EN-US">Java</span>应用来说这两条规律始终是存在的，也有人根据这些规律称其为“弱分代”。因为将<span lang="EN-US">java</span>对象分为“年轻”对象和“老”对象时并没有一个非常明确的指标而是由<span lang="EN-US">JVM</span>规范的实现者控制的（当然<span lang="EN-US">JVM</span>也可以提供参数让具体的开发者设定）。在<span lang="EN-US">HotSpot JVM</span>中将分配到的内存堆（<span lang="EN-US">Heap</span>）分为两个物理区域，一个是“年轻”区，另一个是“老”区。在这里我将“年轻”的一代叫做“新生代”，而对应的将“老”的一代对象叫做“老生代”。<span lang="EN-US"><o:p></o:p></span></span></p><p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 42pt; TEXT-INDENT: -21pt; mso-list: l0 level1 lfo1; tab-stops: list 42.0pt"><span lang="EN-US" style="FONT-SIZE: 12pt; FONT-FAMILY: Wingdings; mso-fareast-font-family: Wingdings; mso-bidi-font-family: Wingdings"><span style="mso-list: Ignore">l<span style="FONT: 7pt 'Times New Roman'">        </span></span></span><span style="FONT-SIZE: 12pt; FONT-FAMILY: 华文楷体">新生代：绝大多数新创建的对象存放于此，这个区域一般来说比较小而且垃圾收集的频率也比较高。因为许多对象在创建后很快就会“死”去，在每次的“新生代”垃圾收集后能够“幸存”的对象非常的少。使用在“新生代”的这种垃圾收集叫做次要垃圾收集（<span lang="EN-US">Minor Collection</span>）。正是因为“新生代”的大小（较小，寻址时间很短）和其存放的对象的特点（寿命短，所以有很多垃圾，每次收集都能释放较大的内存空间）使得次要垃圾收集的效率非常高。见图<span lang="EN-US">1</span>。 <span lang="EN-US"><o:p></o:p></span></span></p><p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-ALIGN: center" align="center"><span lang="EN-US" style="mso-bidi-font-size: 10.5pt"><?xml:namespace prefix = v ns = "urn:schemas-microsoft-com:vml" /?><v:shapetype id="_x0000_t75" coordsize="21600,21600" o:spt="75" o:preferrelative="t" path="m@4@5l@4@11@9@11@9@5xe" filled="f" stroked="f"><v:stroke joinstyle="miter"></v:stroke><v:formulas><v:f eqn="if lineDrawn pixelLineWidth 0"></v:f><v:f eqn="sum @0 1 0"></v:f><v:f eqn="sum 0 0 @1"></v:f><v:f eqn="prod @2 1 2"></v:f><v:f eqn="prod @3 21600 pixelWidth"></v:f><v:f eqn="prod @3 21600 pixelHeight"></v:f><v:f eqn="sum @0 0 1"></v:f><v:f eqn="prod @6 1 2"></v:f><v:f eqn="prod @7 21600 pixelWidth"></v:f><v:f eqn="sum @8 21600 0"></v:f><v:f eqn="prod @7 21600 pixelHeight"></v:f><v:f eqn="sum @10 21600 0"></v:f></v:formulas><v:path o:extrusionok="f" gradientshapeok="t" o:connecttype="rect"></v:path><o:lock v:ext="edit" aspectratio="t"></o:lock></v:shapetype><o:p></o:p></span></p><span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><div align="center"><img src="http://www.cublog.cn/u/15296/upfile/060311222121.jpg" onload="javascript:if(this.width&gt;500)this.width=500;" border="0" /></div></span><p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-ALIGN: center" align="center"><span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"></span></p><p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-ALIGN: center" align="center"><span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"></span> </p><p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-ALIGN: center" align="center"><span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">图</span><span lang="EN-US" style="FONT-SIZE: 12pt"><font face="Times New Roman">1</font></span><span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">：分代垃圾回收</span><span lang="EN-US" style="FONT-SIZE: 12pt"><o:p></o:p></span></p><p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-ALIGN: center" align="center"><span lang="EN-US" style="FONT-SIZE: 12pt"><o:p><font face="Times New Roman"> </font></o:p></span></p><p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 42pt; TEXT-INDENT: -21pt; mso-list: l0 level1 lfo1; tab-stops: list 42.0pt"><span lang="EN-US" style="FONT-SIZE: 12pt; FONT-FAMILY: Wingdings; mso-fareast-font-family: Wingdings; mso-bidi-font-family: Wingdings"><span style="mso-list: Ignore">l<span style="FONT: 7pt 'Times New Roman'">        </span></span></span><span style="FONT-SIZE: 12pt; FONT-FAMILY: 华文楷体">老生代：在“新生代”中生存了较长时间的对象将被提升为“老”对象并转移到“老生代”区。这个区域一般要大一些而且增长的速度相对于“新生代”要慢一些，所以负责“老生代”垃圾收集的主垃圾收集（<span lang="EN-US">Major Collection</span>）的执行频率与次要垃圾收集比要低很多。主垃圾收集发生在“老生代”中的对象占用的存储空间达到一定的量值的时候。见图<span lang="EN-US">1</span>。<span lang="EN-US"><o:p></o:p></span></span></p><p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt"><span lang="EN-US" style="FONT-SIZE: 12pt; COLOR: red"><font face="Times New Roman">*</font></span><span style="FONT-SIZE: 12pt; COLOR: red; FONT-FAMILY: 华文楷体">为方便起见，在下面的章节中将用次收集来替代“次要垃圾收集”，用主收集替代“主要垃圾收集”</span><span style="FONT-SIZE: 12pt; COLOR: red; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">。</span><span lang="EN-US" style="FONT-SIZE: 12pt; COLOR: red; FONT-FAMILY: 华文楷体"><o:p></o:p></span></p><p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 33pt; mso-char-indent-count: 2.75"><span style="FONT-SIZE: 12pt; FONT-FAMILY: 华文楷体">为了使次收集的收集时间尽可能的短，<span lang="EN-US">HotSpot JVM</span>使用了一种叫做卡表（<span lang="EN-US">Card Table</span>）的机制见图<span lang="EN-US">2</span>，来避免在每次进行次收集的时候遍历整个“老生代”。</span></p><span style="FONT-SIZE: 12pt; FONT-FAMILY: 华文楷体"><span lang="EN-US" style="COLOR: red"><o:p><div align="center"><img src="http://www.cublog.cn/u/15296/upfile/060311222152.jpg" onload="javascript:if(this.width&gt;500)this.width=500;" border="0" /></div></o:p></span></span><p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: center" align="center"><span lang="EN-US" style="mso-bidi-font-size: 10.5pt"><o:p></o:p></span></p><p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: center" align="center"><font size="3"><span style="FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">图</span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt"><font face="Times New Roman">2</font></span><span style="FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">：</span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt"><font face="Times New Roman">HotSpot</font></span><span style="FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">中的卡表</span><span lang="EN-US" style="mso-bidi-font-size: 10.5pt"><o:p></o:p></span></font></p><p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt"><span lang="EN-US" style="mso-bidi-font-size: 10.5pt"><font size="3"><font face="Times New Roman"><span style="mso-tab-count: 1">       </span><span style="mso-spacerun: yes">  </span></font></font></span><span style="FONT-SIZE: 12pt; FONT-FAMILY: 华文楷体">卡表的机制是将“老生代”以<span lang="EN-US">512</span>字节为单位进行划分，划分得到的每个区域叫做一个卡。每个卡在卡表中有占用一个一个字节的标识。<span lang="EN-US">java</span>代码在执行的过程中<span lang="EN-US">JVM</span>一旦发现“老生代”的对象引用了或者释放了“新生代”中的对象，那么<span lang="EN-US">JVM</span>就要将与之对应的卡表中的状态置为相应的值。这样在次收集的时候只遍历被标记为“脏”的卡，以便知道哪些“新生代”的对象被引用中，是不可以进行回收的。<span lang="EN-US"><o:p></o:p></span></span></p><p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt"><span lang="EN-US" style="mso-bidi-font-size: 10.5pt"><font size="3"><font face="Times New Roman"><span style="mso-tab-count: 1">       </span><span style="mso-spacerun: yes">  </span></font></font></span><span style="FONT-SIZE: 12pt; FONT-FAMILY: 华文楷体">分代进行垃圾收集的好处是可以根据每个代的具体特点为其设定不同的垃圾收集算法。在新生代中往往使用速度较快的垃圾收集算法，因为次要收集的频率比较高。这种算法在内存的使用效率上没有优势，好在“新生代”的空间占整个<span lang="EN-US">JVM</span>内存堆比例较小，尚不能对性能构成大的问题。而内存使用效率高的算法往往用在“老生代”的垃圾收集上。因为“老生代”占据着<span lang="EN-US">JVM</span>堆的很大部分。虽然“老生代”中进行的主收集每次的收集时间相对于次收集要长好多，但是主收集在频率上要比次收集少很多，故对性能的影响也不大。正是这种新、“老生代”的相互补很好的平衡<span lang="EN-US">JVM</span>垃圾收集中的瓶颈。<span lang="EN-US"><o:p></o:p></span></span></p><h3 style="MARGIN: 13pt 0cm"><span style="FONT-SIZE: 14pt; LINE-HEIGHT: 173%; FONT-FAMILY: 华文楷体; mso-font-kerning: 22.0pt">新生代的组成<span lang="EN-US"><o:p></o:p></span></span></h3><p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt"><span lang="EN-US" style="FONT-SIZE: 12pt; FONT-FAMILY: 华文楷体"><span style="mso-tab-count: 1">       </span><span style="mso-spacerun: yes">  </span></span><span style="FONT-SIZE: 12pt; FONT-FAMILY: 华文楷体">“新生代”又<span lang="EN-US">3</span>个部分组成，见图<span lang="EN-US">3</span>。一个<span lang="EN-US">Eden</span>和两个生存区（</span><span lang="EN-US" style="FONT-SIZE: 12pt; FONT-FAMILY: 华文楷体; mso-bidi-font-family: Arial; mso-bidi-font-style: italic">Survivor Space</span><span style="FONT-SIZE: 12pt; FONT-FAMILY: 华文楷体">），</span></p><span style="FONT-SIZE: 12pt; FONT-FAMILY: 华文楷体"><span lang="EN-US"><o:p><div align="center"><img src="http://www.cublog.cn/u/15296/upfile/060311222214.jpg" onload="javascript:if(this.width&gt;500)this.width=500;" border="0" /></div></o:p></span></span><p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: center" align="center"><span lang="EN-US" style="mso-bidi-font-size: 10.5pt"><o:p></o:p></span></p><p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: center" align="center"><span style="FONT-SIZE: 12pt; FONT-FAMILY: 华文楷体">图<span lang="EN-US">3</span>：新生代组成<span lang="EN-US"><o:p></o:p></span></span></p><p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt"><span style="FONT-SIZE: 12pt; FONT-FAMILY: 华文楷体">其中：<span lang="EN-US"><o:p></o:p></span></span></p><p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 42pt; TEXT-INDENT: -21pt; mso-list: l0 level1 lfo1; tab-stops: list 42.0pt"><span lang="EN-US" style="FONT-SIZE: 12pt; FONT-FAMILY: Wingdings; mso-fareast-font-family: Wingdings; mso-bidi-font-family: Wingdings"><span style="mso-list: Ignore">l<span style="FONT: 7pt 'Times New Roman'">        </span></span></span><span lang="EN-US" style="FONT-SIZE: 12pt; FONT-FAMILY: 华文楷体">Eden</span><span style="FONT-SIZE: 12pt; FONT-FAMILY: 华文楷体">：绝大部分新创建的对象存放在此区域。为什么说绝大多数而不是所有的呢？原因是应用在创建一个非常大的对象的时候<span lang="EN-US">JVM</span>会直接将其分配在老生代而非新生代。在每次完成次收集的时候<span lang="EN-US">Eden</span>区域总是空的。<span lang="EN-US"><o:p></o:p></span></span></p><p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 42pt; TEXT-INDENT: -21pt; mso-list: l0 level1 lfo1; tab-stops: list 42.0pt"><span lang="EN-US" style="FONT-SIZE: 12pt; FONT-FAMILY: Wingdings; mso-fareast-font-family: Wingdings; mso-bidi-font-family: Wingdings"><span style="mso-list: Ignore">l<span style="FONT: 7pt 'Times New Roman'">        </span></span></span><span style="FONT-SIZE: 12pt; FONT-FAMILY: 华文楷体">存活区：顾名思义在垃圾收集过程中没有被当作垃圾收集的对象将放在次区域中。也就是说这个区域中的对象至少经历了一次次收集。存放存活区的对象在被“提升”到老生代前还有机会被收集。存活区有一对，他们中的一个始终保持为空，另一个用于存放存活下来的对象。<span lang="EN-US"><o:p></o:p></span></span></p><p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 42pt"><span lang="EN-US" style="FONT-SIZE: 12pt; FONT-FAMILY: 华文楷体"><span style="mso-spacerun: yes">  </span></span><span style="FONT-SIZE: 12pt; FONT-FAMILY: 华文楷体">图<span lang="EN-US">4</span>描述了次收集的收集过程，其中绿色部分是未被使用的对象<span lang="EN-US"><o:p></o:p></span></span></p><p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: center" align="center"><span lang="EN-US" style="FONT-SIZE: 12pt; FONT-FAMILY: 华文楷体"><o:p></o:p></span></p><p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: center" align="center"><span style="FONT-SIZE: 12pt; FONT-FAMILY: 华文楷体"><img src="http://www.cublog.cn/u/15296/upfile/060311222236.jpg" onload="javascript:if(this.width&gt;500)this.width=500;" border="0" /></span></p><p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: center" align="center"><span style="FONT-SIZE: 12pt; FONT-FAMILY: 华文楷体">图<span lang="EN-US">4</span>：一次次收集<span lang="EN-US"><o:p></o:p></span></span></p><p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt"><span style="FONT-SIZE: 12pt; FONT-FAMILY: 华文楷体">（即垃圾）。从图中可以看到在<span lang="EN-US">Eden</span>区的绿色部分将被收集而幸存下来的对象（白色部分）将被移到没有被使用的存活区<span lang="EN-US">2</span>。在存活区<span lang="EN-US">1</span>中的绿色部分是也是不被使用的对象，这些对象也将被收集。而位于存活区<span lang="EN-US">1</span>中的蓝色部分是尚被引用但是还不够“老”的这些对象也将移到到存活区<span lang="EN-US">2</span>。存活区<span lang="EN-US">1</span>中剩余的部分就是被引用且已经够“老”的对象，他们将被移到老生代区。<span lang="EN-US"><o:p></o:p></span></span></p><p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt"><span lang="EN-US" style="FONT-SIZE: 12pt; FONT-FAMILY: 华文楷体"><span style="mso-tab-count: 1">       </span><span style="mso-spacerun: yes">  </span></span><span style="FONT-SIZE: 12pt; FONT-FAMILY: 华文楷体">在完成了一次次收集后（见图<span lang="EN-US">5</span>），两个存活区就会交互角色。即存活区<span lang="EN-US">2</span>中将存放存活对象，存活区<span lang="EN-US">1</span>将不被使用。<span lang="EN-US">Eden</span>区将会变的空空如也。同时由于有新对象移到了老生代，老生代的空间将被更多的对象占据。<span lang="EN-US"><o:p></o:p></span></span></p><p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: center" align="center"><span lang="EN-US" style="FONT-SIZE: 12pt; FONT-FAMILY: 华文楷体"><o:p></o:p></span></p><span style="FONT-SIZE: 12pt; FONT-FAMILY: 华文楷体"><div align="center"><img src="http://www.cublog.cn/u/15296/upfile/060311222326.jpg" onload="javascript:if(this.width&gt;500)this.width=500;" border="0" /></div></span><p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: center" align="center"><span style="FONT-SIZE: 12pt; FONT-FAMILY: 华文楷体">图<span lang="EN-US">5</span>：完成一次次收集后<span lang="EN-US"><o:p></o:p></span></span></p><h3 style="MARGIN: 13pt 0cm"><span style="FONT-SIZE: 14pt; LINE-HEIGHT: 173%; FONT-FAMILY: 华文楷体; mso-font-kerning: 22.0pt">垃圾收集器<span lang="EN-US"><o:p></o:p></span></span></h3><p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt"><span lang="EN-US" style="FONT-SIZE: 12pt; FONT-FAMILY: 华文楷体"><span style="mso-tab-count: 1">       </span><span style="mso-spacerun: yes">  </span>Sun </span><span style="FONT-SIZE: 12pt; FONT-FAMILY: 华文楷体">的<span lang="EN-US">HotSpot JVM</span>提供了<span lang="EN-US">3</span>中不同的垃圾收集器。他们可以根据应用的实际情况有选择性的使用。下面将分别介绍。<span lang="EN-US"><o:p></o:p></span></span></p><p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 24pt"><b style="mso-bidi-font-weight: normal"><span style="FONT-SIZE: 12pt; FONT-FAMILY: 华文楷体">串行收集器：</span></b><span style="FONT-SIZE: 12pt; FONT-FAMILY: 华文楷体">又叫做“标记<span lang="EN-US">-</span>压缩”收集器。这种收集器在收集的时候要求<span lang="EN-US">JVM</span>停止执行应用。所以人们戏称这种收集模式为<span lang="EN-US">Stop-the-World(</span>停止一切<span lang="EN-US">)</span>模式。在完成收集后<span lang="EN-US">JVM</span>才继续执行应用（见图<span lang="EN-US">6</span>）。<span lang="EN-US"><o:p></o:p></span></span></p><p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 24pt; TEXT-ALIGN: center" align="center"><span lang="EN-US" style="FONT-SIZE: 12pt; FONT-FAMILY: 华文楷体"><o:p></o:p></span></p><span style="FONT-SIZE: 12pt; FONT-FAMILY: 华文楷体"><div align="center"><img src="http://www.cublog.cn/u/15296/upfile/060311222345.jpg" onload="javascript:if(this.width&gt;500)this.width=500;" border="0" /></div></span><p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 24pt; TEXT-ALIGN: center" align="center"><span style="FONT-SIZE: 12pt; FONT-FAMILY: 华文楷体">图<span lang="EN-US">6</span>：串行收集<span lang="EN-US"><o:p></o:p></span></span></p><p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 24pt"><span style="FONT-SIZE: 12pt; FONT-FAMILY: 华文楷体">串行收集器首先将“老生代”中的仍然存活的对象进行标记并将这些对象压缩到“老生代”空间的前端。这样“老生代”的后端将变成一个连续的空间，以便从“新生代”中足够老的对象顺利的“提升”到“老生代”中（见图<span lang="EN-US">7</span>，红色部分为垃圾对象）。对于大多数不要求有非常迅速响应（例如几秒钟）的场合，例如客户端程序，这种收集器还是能够胜任的。<span lang="EN-US"><o:p></o:p></span></span></p><p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 24pt; TEXT-ALIGN: center" align="center"><span lang="EN-US" style="FONT-SIZE: 12pt; FONT-FAMILY: 华文楷体"><o:p></o:p></span></p><span style="FONT-SIZE: 12pt; FONT-FAMILY: 华文楷体"><div align="center"><img src="http://www.cublog.cn/u/15296/upfile/060311222404.jpg" onload="javascript:if(this.width&gt;500)this.width=500;" border="0" /></div></span><p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 24pt; TEXT-ALIGN: center" align="center"><span style="FONT-SIZE: 12pt; FONT-FAMILY: 华文楷体">图<span lang="EN-US">7</span>：“老生代”的一次压缩<span lang="EN-US"><o:p></o:p></span></span></p><p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 24pt"><b style="mso-bidi-font-weight: normal"><span style="FONT-SIZE: 12pt; FONT-FAMILY: 华文楷体">并行收集器：</span></b><span style="FONT-SIZE: 12pt; FONT-FAMILY: 华文楷体">在目前实际的应用中多数的<span lang="EN-US">java</span>程序都运行在具有很大物理内存和多个<span lang="EN-US">CPU</span>的服务器上。在比较理想的情况下垃圾收集应该能够有效利用所有的<span lang="EN-US">CPU</span>，而不是只用其中的一个且其他的<span lang="EN-US">CPU</span>都处于空闲状态。为避免过多的垃圾收集以便提高系统的吞吐量（即处理能力），在服务器模式的环境下<span lang="EN-US">Sun</span>的<span lang="EN-US">HotSopt JVM</span>使用并行收集器进行垃圾回收。因为这种垃圾回收器的一个主要目标是提高吞吐量，所以也叫做吞吐量型的收集器。并行收集器的工作方式是在次收集（对应于“新生代”）中使用所有的<span lang="EN-US">CPU</span>进行并行收集，在主收集（对应于“老生代”）中采用串行收集器（见图<span lang="EN-US">8</span>）。虽然与串行收集器相比较主收集没有显著的改善（因为两者在“老生代”中都使用了相同的串行收集器），但是在次收集部分的效率得以大幅度的提高。进而提高的系统的吞吐量。<span lang="EN-US"><o:p></o:p></span></span></p><p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 24pt; TEXT-ALIGN: center" align="center"><b style="mso-bidi-font-weight: normal"><span lang="EN-US" style="FONT-SIZE: 12pt; FONT-FAMILY: 华文楷体"><o:p></o:p></span></b></p><span style="FONT-SIZE: 12pt; FONT-FAMILY: 华文楷体"><div align="center"><img src="http://www.cublog.cn/u/15296/upfile/060311222428.jpg" onload="javascript:if(this.width&gt;500)this.width=500;" border="0" /></div></span><p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 24pt; TEXT-ALIGN: center" align="center"><span style="FONT-SIZE: 12pt; FONT-FAMILY: 华文楷体">图<span lang="EN-US">8</span>：并行收集<span lang="EN-US"><o:p></o:p></span></span></p><p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 24pt"><b style="mso-bidi-font-weight: normal"><span style="FONT-SIZE: 12pt; FONT-FAMILY: 华文楷体">同步收集器（</span></b><b><i><span lang="EN-US" style="FONT-SIZE: 10pt; FONT-FAMILY: Arial">Mostly-Concurrent Collector</span></i></b><b><i><span style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体; mso-bidi-font-family: Arial; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial">）</span></i></b><b style="mso-bidi-font-weight: normal"><span style="FONT-SIZE: 12pt; FONT-FAMILY: 华文楷体">：</span></b><span style="FONT-SIZE: 12pt; FONT-FAMILY: 华文楷体">对于某些的应用程序来说响应速度要远比吞吐量重要。同时收集器就是为低延时而设计的一种收集器。在已经介绍的<span lang="EN-US">Stop-the-World</span>（停止一切）的收集模式中，当垃圾收集没有结束前对于外部的请求是不会进行响应的，直到收集完毕应用才会继续响应请求。这对于次搜集来说一般来说停顿时间不是很长（因为次收集往往需要很短的时间），但对于主收集来说，即使不是很频繁也会导致应用较长时间的停顿，尤其是在<span lang="EN-US">JVM</span>堆分配的比较大的时候就更明显了。为了解决这种情况<span lang="EN-US">Sun JVM</span>引入了同步收集器的方式。这种方式也叫做同步标记－清楚（<span lang="EN-US">CMS</span>）或者还可以叫做“低延迟”收集器。图<span lang="EN-US">9</span>展示了其工作原理。<span lang="EN-US"><o:p></o:p></span></span></p><p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 24pt; TEXT-ALIGN: center" align="center"><span lang="EN-US" style="FONT-SIZE: 12pt; FONT-FAMILY: 华文楷体"><o:p></o:p></span></p><p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 24pt; TEXT-ALIGN: center" align="center"><span style="FONT-SIZE: 12pt; FONT-FAMILY: 华文楷体"><img src="http://www.cublog.cn/u/15296/upfile/060311222445.jpg" onload="javascript:if(this.width&gt;500)this.width=500;" border="0" /></span></p><p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 24pt; TEXT-ALIGN: center" align="center"><span style="FONT-SIZE: 12pt; FONT-FAMILY: 华文楷体">图<span lang="EN-US">9</span>：同步收集器<span lang="EN-US"><o:p></o:p></span></span></p><p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 24pt"><span style="FONT-SIZE: 12pt; FONT-FAMILY: 华文楷体">同步收集器以一个短暂的停顿开始，在这个短暂的停顿中将对那些能够迅速确定不是垃圾的对象进行标记。紧接着将进入同步标记阶段，在这个阶段中同步收集器对被使用的对象进一步进行标记，而应用也同时运行。应用在运行的过程中可能改变了对某些对象的引用，这使得同步标记阶段中并不能保证所有的被引用对象进行了标记，也导致了必须需要进行的第三个阶段－“再标记”。在再标记阶段中将会使应用进入第二个暂停，利用这个暂停时间同步收集器将完成对所有对象的标记。可以看出在再标记的过程中使用了并行的方式，所以这部分标记的对象的数量要比在初始阶段中标记完成的多。在最后一个阶段同步收集器将会把前几个阶段中标记出来的“老生代”中的垃圾对象进行清除。但是不会将被引用的对象放在一个连续的空间中（见图<span lang="EN-US">10</span>，橙色为垃圾对象，绿色为收集后的空闲空间）。可以看出“老生代”中的可用空间并不是连续的，这个会导致将为提升到“老生代”的对象分配空间时需要工多的时间和资源。<span lang="EN-US"><o:p></o:p></span></span></p><p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 24pt; TEXT-ALIGN: center" align="center"><span lang="EN-US" style="FONT-SIZE: 12pt; FONT-FAMILY: 华文楷体"><o:p></o:p></span></p><span style="FONT-SIZE: 12pt; FONT-FAMILY: 华文楷体"><div align="center"><img src="http://www.cublog.cn/u/15296/upfile/060311222527.jpg" onload="javascript:if(this.width&gt;500)this.width=500;" border="0" /></div></span><p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 24pt; TEXT-ALIGN: center" align="center"><span style="FONT-SIZE: 12pt; FONT-FAMILY: 华文楷体">图<span lang="EN-US">10</span>：“老生代”中的同步清除<span lang="EN-US"><o:p></o:p></span></span></p><p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 24pt"><span style="FONT-SIZE: 12pt; FONT-FAMILY: 华文楷体">与串行收集器和并行收集器相比较同步收集器会有下面几个特点。<span lang="EN-US"><o:p></o:p></span></span></p><p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 48pt; mso-char-indent-count: 4.0"><span lang="EN-US" style="FONT-SIZE: 12pt; FONT-FAMILY: 华文楷体">1)</span><span style="FONT-SIZE: 12pt; FONT-FAMILY: 华文楷体">要求分配到的堆大；<span lang="EN-US"><o:p></o:p></span></span></p><p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 48pt; mso-char-indent-count: 4.0"><span lang="EN-US" style="FONT-SIZE: 12pt; FONT-FAMILY: 华文楷体">2</span><span style="FONT-SIZE: 12pt; FONT-FAMILY: 华文楷体">）对不连续空间的使用效率低；<span lang="EN-US"><o:p></o:p></span></span></p><p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 48pt; mso-char-indent-count: 4.0"><span lang="EN-US" style="FONT-SIZE: 12pt; FONT-FAMILY: 华文楷体">3</span><span style="FONT-SIZE: 12pt; FONT-FAMILY: 华文楷体">）在某些情况下能够显著缩短主收集使应用停顿的时间。<span lang="EN-US"><o:p></o:p></span></span></p><h3 style="MARGIN: 13pt 0cm"><span style="FONT-SIZE: 14pt; LINE-HEIGHT: 173%; FONT-FAMILY: 华文楷体; mso-font-kerning: 22.0pt">附录<span lang="EN-US">A</span>：参考文献<span lang="EN-US"><o:p></o:p></span></span></h3><p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 5.35pt; TEXT-INDENT: -5.35pt; mso-char-indent-count: -.5"><span style="text-fit: 110.55pt; mso-text-fit-id: -1555845632"><span lang="EN-US" style="FONT-SIZE: 12pt; FONT-FAMILY: 华文楷体; mso-font-kerning: 0pt; mso-font-width: 89%">JVM Specification</span></span><span style="text-fit: 110.55pt; mso-text-fit-id: -1555845632"><span style="FONT-SIZE: 12pt; FONT-FAMILY: 华文楷体; mso-font-kerning: 0pt; mso-font-width: 89%">第二版</span></span><span lang="EN-US" style="FONT-SIZE: 12pt; FONT-FAMILY: 华文楷体; mso-font-kerning: 0pt"><o:p></o:p></span></p><p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt"><span lang="EN-US" style="FONT-SIZE: 12pt; FONT-FAMILY: 华文楷体">http://java.sun.com/docs/books/vmspec/2nd-edition/html/VMSpecTOC.doc.html<o:p></o:p></span></p><img src ="http://www.blogjava.net/jiangmin/aggbug/86145.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jiangmin/" target="_blank">JiangMin</a> 2006-12-07 18:31 <a href="http://www.blogjava.net/jiangmin/articles/86145.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Hot Spot JVM5中的GC调优</title><link>http://www.blogjava.net/jiangmin/articles/86144.html</link><dc:creator>JiangMin</dc:creator><author>JiangMin</author><pubDate>Thu, 07 Dec 2006 10:29:00 GMT</pubDate><guid>http://www.blogjava.net/jiangmin/articles/86144.html</guid><wfw:comment>http://www.blogjava.net/jiangmin/comments/86144.html</wfw:comment><comments>http://www.blogjava.net/jiangmin/articles/86144.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jiangmin/comments/commentRss/86144.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jiangmin/services/trackbacks/86144.html</trackback:ping><description><![CDATA[
		<div class="title1">
				<strong>Hot Spot JVM5中的GC调优</strong>
		</div>
		<p>
				<strong>
						<br />
				</strong> </p>
		<p align="center">
				<strong>Written by Halatu Hubisi</strong>
		</p>
		<p>
				<br />
				<strong>引言<br /></strong>有JAVA开发经验的朋友们一定碰到过下面的这种情况,那就是自己所开发的应用运行了一段时间后其性能或者响应速度会有明显的降低.这是由多方面的原因造成的即有程序本身的优化问题,也有运行环境问题.此运行环境即包括硬件环境也包括软件环境.大多数人第一个能想到的解决方法是提升硬件的配置而忽略了程序本身的运行环境JVM也提供了比较多的调优选项.本文将重点描述利用JVM的一些选项对GC进行调优.</p>
		<p>
				<strong>约定:</strong>
				<br />1.读者应具备一定JAVA的知识. </p>
		<p>2.本文中的JVM选项均以SUN公司发布的HotSpot JVM 5为准（不过大多数的选项在JVM1.3,JVM1.4中也是可用的）. </p>
		<p>3.以JAVA_HOME下demo/jfc/SwingSet2/SwingSet2.jar为例进行说明. </p>
		<p>4.阅读本文需要一些关于GC的知识，可以到附录A中了解这些知识。 </p>
		<p>
				<strong>关键字:</strong>
				<br />JVM(java虚拟机),调优,GC(垃圾回收)</p>
		<p>
				<strong>JVM GC调优</strong>
				<br />为了能够将JVM GC的调优能够使用在具体的实践当中,下面将利用若干个例子来说明GC的调优.<br /><strong>例1：Heap size 设置</strong><br />JVM堆的设置是指java程序运行过程中JVM可以调配使用的内存空间的设置.JVM在启动的时候会自动设置Heap size的值，其初始空间(即-Xms)是物理内存的1/64，最大空间(-Xmx)是物理内存的1/4。可以利用JVM提供的-Xmn -Xms -Xmx等选项可进行设置。Heap size 的大小是Young Generation 和Tenured Generaion 之和。<br />当在JAVA_HOME下demo/jfc/SwingSet2/目录下执行下面的命令。<br />java -jar -Xmn4m -Xms16m -Xmx16m SwingSet2.jar<br />系统输出为：<br />Exception in thread "Image Fetcher 0" java.lang.OutOfMemoryError: Java heap space<br />Exception in thread "Image Fetcher 3" java.lang.OutOfMemoryError: Java heap space<br />Exception in thread "Image Fetcher 1" java.lang.OutOfMemoryError: Java heap space<br />Exception in thread "Image Fetcher 2" java.lang.OutOfMemoryError: Java heap space<br />除了这些异常信息外，还会发现程序的响应速度变慢了。这说明Heap size 设置偏小，GC占用了更多的时间，而应用分配到的执行时间较少。<br /><font color="#ff0000"><span class="style3">提示：在JVM中如果98％的时间是用于GC且可用的Heap size 不足2％的时候将抛出此异常信息。</span><br /></font>将上面的命令换成以下命令执行则应用能够正常使用，且未抛出任何异常。<br />java -jar -Xmn4m -Xms16m -Xmx32m SwingSet2.jar<br /><span class="style3"><font color="#ff0000">提示：Heap Size 最大不要超过可用物理内存的80％，一般的要将-Xms和-Xmx选项设置为相同，而-Xmn为1/4的-Xmx值。 </font></span></p>
		<p>
				<strong>例2：Young Generation（-Xmn）的设置</strong>
				<br />在本例中看一下Young Generation的设置不同将有什么现象发生。<br />假设将Young generation 的大小设置为4M ，即执行java -jar -verbose:gc -Xmn4m -Xms32m -Xmx32m -XX:+PrintGCDetails SwingSet2.jar，屏幕输出如下（节选）<br />[GC [DefNew: 3968K-&gt;64K(4032K), 0.0923407 secs] 3968K-&gt;2025K(32704K), 0.0931870 secs]<br />[GC [DefNew: 4021K-&gt;64K(4032K), 0.0356847 secs] 5983K-&gt;2347K(32704K), 0.0365441 secs]<br />[GC [DefNew: 3995K-&gt;39K(4032K), 0.0090603 secs] 6279K-&gt;2372K(32704K), 0.0093377 secs]<br />[GC [DefNew: 3992K-&gt;23K(4032K), 0.0057540 secs] 6325K-&gt;2356K(32704K), 0.0060290 secs]<br />[GC [DefNew: 3984K-&gt;27K(4032K), 0.0013058 secs] 6317K-&gt;2360K(32704K), 0.0015888 secs]<br />[GC [DefNew: 3981K-&gt;59K(4032K), 0.0023307 secs] 6315K-&gt;2422K(32704K), 0.0026091 secs]<br />将程序体制并将Young Generation的大小设置为8M，即执行java -jar -verbose:gc -Xmn8m -Xms32m -Xmx32m -XX:+PrintGCDetails SwingSet2.jar，屏幕输出如下（节选）<br />[GC [DefNew: 7808K-&gt;192K(8000K), 0.1016784 secs] 7808K-&gt;2357K(32576K), 0.1022834 secs]<br />[GC [DefNew: 8000K-&gt;70K(8000K), 0.0149659 secs] 10165K-&gt;2413K(32576K), 0.0152557 secs]<br />[GC [DefNew: 7853K-&gt;59K(8000K), 0.0069122 secs] 10196K-&gt;2403K(32576K), 0.0071843 secs]<br />[GC [DefNew: 7867K-&gt;171K(8000K), 0.0075745 secs] 10211K-&gt;2681K(32576K), 0.0078376 secs]<br />[GC [DefNew: 7970K-&gt;192K(8000K), 0.0201353 secs] 10480K-&gt;2923K(32576K), 0.0206867 secs]<br />[GC [DefNew: 7979K-&gt;30K(8000K), 0.1787079 secs] 10735K-&gt;4824K(32576K), 0.1790065 secs]<br />那么根据GC输出的信息（这里取第一行）做一下Minor收集的比较。可以看出两次的Minor收集分别在Young generation中找回3904K（3968K-&gt;64K）和7616K(7808K-&gt;192K)而对于整个jvm则找回1943K（3968K-&gt;2025）和5451K（7808K-&gt;2357K）。第一种情况下Minor收集了大约50％（1943/3904）的对象，而另外的50％的对象则被移到了tenured generation。在第二中情况下Minor收集了大约72％的对象，只有不到30％的对象被移到了Tenured Generation.这个例子说明此应用在的Young generation 设置为4m时显的偏小。<br /><span class="style3"><font color="#ff0000">提示：一般的Young Generation的大小是整个Heap size的1/4。Young generation的minor收集率应一般在70％以上。当然在实际的应用中需要根据具体情况进行调整。</font></span></p>
		<p>
				<strong>例3：Young Generation对应用响应的影响</strong>
				<br />还是使用-Xmn4m 和-Xmn8m进行比较，先执行下面的命令<br /></p>
		<p>java -jar -verbose:gc -Xmn4m -Xms32m -Xmx32m -XX:+PrintGCDetails -XX:+PrintGCApplicationConcurrentTime -XX:+PrintGCApplicationStoppedTime SwingSet2.jar<br />屏幕输出如下（节选）<br />Application time: 0.5114944 seconds<br />[GC [DefNew: 3968K-&gt;64K(4032K), 0.0823952 secs] 3968K-&gt;2023K(32704K), 0.0827626 secs]<br />Total time for which application threads were stopped: 0.0839428 seconds<br />Application time: 0.9871271 seconds<br />[GC [DefNew: 4020K-&gt;64K(4032K), 0.0412448 secs] 5979K-&gt;2374K(32704K), 0.0415248 secs]<br />Total time for which application threads were stopped: 0.0464380 seconds<br />Young Generation 的Minor收集占用的时间可以计算如下：应用线程被中断的总时常/（应用执行总时?L+应用线程被中断的总时常），那么在本例中垃圾收集占用的时?L约为系统的5％~14％。那么当垃圾收集占用的时间的比例越大的时候，系统的响应将越慢。<br /><span class="style3"><font color="#ff0000">提示：对于互联网应用系统的响应稍微慢一些，用户是可以接受的，但是对于GUI类型的应用响应速度慢将会给用户带来非常不好的体验。</font></span></p>
		<p>
				<strong>例4：如何决定Tenured Generation 的大小</strong>
				<br />分别以-Xmn8m -Xmx32m和-Xmn8m -Xmx64m进行对比，先执行<br />java -verbose:gc -Xmn8m -Xmx32m-XX:+PririntGCDetails -XX:+PrintGCTimeStamps java类，命令行将提示（只提取了Major收集）<br /></p>
		<p>111.042: [GC 111.042: [DefNew: 8128K-&gt;8128K(8128K), 0.0000505 secs]111.042: [Tenured: 18154K-&gt;2311K(24576K), 0.1290354 secs] 26282K-&gt;2311K(32704K), 0.1293306 secs]<br />122.463: [GC 122.463: [DefNew: 8128K-&gt;8128K(8128K), 0.0000560 secs]122.463: [Tenured: 18630K-&gt;2366K(24576K), 0.1322560 secs] 26758K-&gt;2366K(32704K), 0.1325284 secs]<br />133.896: [GC 133.897: [DefNew: 8128K-&gt;8128K(8128K), 0.0000443 secs]133.897: [Tenured: 18240K-&gt;2573K(24576K), 0.1340199 secs] 26368K-&gt;2573K(32704K), 0.1343218 secs]<br />144.112: [GC 144.112: [DefNew: 8128K-&gt;8128K(8128K), 0.0000544 secs]144.112: [Tenured: 16564K-&gt;2304K(24576K), 0.1246831 secs] 24692K-&gt;2304K(32704K), 0.1249602 secs]<br />再执行java -verbose:gc -Xmn8m -Xmx64m-XX:+PririntGCDetails -XX:+PrintGCTimeStamps java类，命令行将提示（只提取了Major收集）<br />90.597: [GC 90.597: [DefNew: 8128K-&gt;8128K(8128K), 0.0000542 secs]90.597: [Tenured: 49841K-&gt;5141K(57344K), 0.2129882 secs] 57969K-&gt;5141K(65472K), 0.2133274 secs]<br />120.899: [GC 120.899: [DefNew: 8128K-&gt;8128K(8128K), 0.0000550 secs]120.899: [Tenured: 50384K-&gt;2430K(57344K), 0.2216590 secs] 58512K-&gt;2430K(65472K), 0.2219384 secs]<br />153.968: [GC 153.968: [DefNew: 8128K-&gt;8128K(8128K), 0.0000511 secs]153.968: [Tenured: 51164K-&gt;2309K(57344K), 0.2193906 secs] 59292K-&gt;2309K(65472K), 0.2196372 secs]<br />可以看出在Heap size 为32m的时候系统等候时间约为0.13秒左右，而设置为64m的时候等候时间则增大到0.22秒左右了。但是在32m的时候系统的Major收集间隔为10秒左右，而Heap size 增加到64m的时候为30秒。那么应用在运行的时候是选择32m还是64m呢？如果应用是web类型（即要求有大的吞吐量）的应用则使用64m（即heapsize大一些）的比较好。对于要求实时响应要求较高的场合（例如GUI型的应用）则使用32m比较好一些。 <br /><span class="style3"><font color="#ff0000">注意：<br />1。因为在JVM5运行时已经对Heap-size进行了优化，所以在能确定java应用运行时不会超过默认的Heap size的情况下建议不要对这些值进行修改。<br />2。Heap size的 -Xms -Xmn 设置不要超出物理内存的大小。否则会提示“Error occurred during initialization of VM Could not reserve enough space for object heap”。</font></span></p>
		<p>
				<strong>例5:如何缩短minor收集的时间</strong>
				<br />下面比较一下采用-XX:+UseParNewGC选项和不采用它的时候的minor收集将有什么不同。先执行<br />java -jar -server -verbose:gc -Xmn8m -Xms32m -Xmx32m SwingSet2.jar <br />系统将输出如下信息（片段〕<br />[GC 7807K-&gt;2641K(32576K), 0.0676654 secs]<br />[GC 10436K-&gt;3108K(32576K), 0.0245328 secs]<br />[GC 10913K-&gt;3176K(32576K), 0.0072865 secs]<br />[GC 10905K-&gt;4097K(32576K), 0.0223928 secs]<br />之后再执行 java -jar -server -verbose:gc -XX:+UseParNewGC -Xmn8m -Xms32m -Xmx32m SwingSet2.jar<br />系统将输出如下信息（片段〕<br />[ParNew 7808K-&gt;2656K(32576K), 0.0447687 secs]<br />[ParNew 10441K-&gt;3143K(32576K), 0.0179422 secs]<br />[ParNew 10951K-&gt;3177K(32576K), 0.0031914 secs]<br />[ParNew 10985K-&gt;3867K(32576K), 0.0154991 secs]<br />很显然使用了-XX:+UseParNewGC选项的minor收集的时间要比不使用的时候优。 </p>
		<p>
				<strong>例6:如何缩短major收集的时间</strong>
				<br />下面比较一下采用-XX:+UseConcMarkSweepGC选项和不采用它的时候的major收集将有什么不同。先执行<br />java -jar -verbose:gc -XX:+UseConcMarkSweepGC -XX:+UseParNewGC -Xmn64m -Xms256m -Xmx256m SwingSet2.jar<br />系统将输出如下信息（片段〕<br />[Full GC 22972K-&gt;18690K(262080K), 0.2326676 secs]<br />[Full GC 18690K-&gt;18690K(262080K), 0.1701866 secs<br />之后再执行 java -jar -verbose:gc -XX:+UseParNewGC -Xmn64m -Xms256m -Xmx256m SwingSet2.jar<br />系统将输出如下信息（片段〕<br />[Full GC 56048K-&gt;18869K(260224K), 0.3104852 secs]<br /><span class="style3"><font color="#ff0000">提示：此选项在Heap Size 比较大而且Major收集时间较长的情况下使用更合适。</font></span></p>
		<p>
				<strong>例7:关于-server选项</strong> 在JVM中将运行中的类认定为server-class的时候使用此选项。SUN 的Hot Spot JVM5 如果判断到系统的配置满足如下条件则自动将运行的类认定为server-class，并且会自动设置jvm的选项（当没有手工设置这选项的时候〕而且HOTSPOT JVM5提供了自动调优的功能，他会根据JVM的运行情况进行调整。如果没有特别的需要是不需要太多的人工干预的。SUN形象的称这个机制为“人体工学”（Ergonomics〕。具体可以参考http://java.sun.com/docs/hotspot/gc5.0/ergo5.html<br />*.具有2个或更多个物理的处理器<br />*.具有2G或者更多的物理内存<br /><span class="style3"><font color="#ff0000">提示：此选项要放在所有选项的前面。例如：java -server 其他选项 java类 </font></span></p>
		<p>
				<strong>附录A:预备知识</strong>
				<br />
				<strong>．</strong>JVM中对象的划分及管理 </p>
		<p>JVM根据运行于其中的对象的生存时间大致的分为3种。并且将这3种不同的对象分别存放在JVM从系统分配到的不同的内存空间。这种对象存放空间的管理方式叫做Generation管理方式。<br />1。Young Generation：用于存放“早逝”对象（即瞬时对象）。例如：在创建对象时或者调用方法时使用的临时对象或局部变量。<br />2。Tenured Generation：用于存放“驻留”对象（即较长时间被引用的对象）。往往体现为一个大型程序中的全局对象或长时间被使用的对象。<br />3。Perm Generation：用于存放“永久”对象。这些对象管理着运行于JVM中的类和方法。</p>
		<p>
				<strong>．</strong>JVM选项的分类 </p>
		<p>JVM有这么几种选项供使用.<br />1.供-X选项使用的项目,又称为非标准选项，不同厂商的此类型选项是有所不同的。例如：IBM的JVM用的一些选项在Sun的JVM中就不一定能生效。这种选项的使用方式如下:<br />java -Xmn16m -Xms64m -Xmx64m java类名<br />2.供-XX选项使用的项目，这种类型的选项可能要求有对系统信息访问的权限。所以要慎用。这种选项的使用方式如下:<br />java -XX:MaxHeapFreeRatio=70 -XX:+PrintGCDetails java类名<br />3.java选项(即在命令行执行java后提示的选项).<br />java -server -verbose:gc -d64 java类名 </p>
		<p>
				<strong>．</strong>垃圾收集分类 </p>
		<p>在JVM中有两种垃圾方式，一种叫做Minor（次收集），另一种叫做Major（主收集）。其中Minor在Young Generation的空间被对象全部占用后执行，主要是对Young Generation中的对象进行垃圾收集。而Major是针对于整个Heap size的垃圾收集。其中Minor方式的收集经常发生，并且Minor收集所占用的系统时间小。Major方式的垃圾收集则是一种“昂贵”的垃圾收集方式，因为在Major要对整个Heap size进行垃圾收集,这会使得应用停顿的时间变得较长。</p>
		<p>
				<strong>．</strong>GC信息的格式 </p>
		<p>
		</p>
		<p>[GC [&lt;collector&gt;: &lt;starting occupancy1&gt; -&gt; &lt;ending occupancy1&gt;, &lt;pause time1&gt; secs] &lt;starting occupancy3&gt; -&gt; &lt;ending occupancy3&gt;, &lt;pause time3&gt; secs]<br />&lt;collector&gt; GC为minor收集过程中使用的垃圾收集器起的内部名称.<br />&lt;starting occupancy1&gt; young generation 在进行垃圾收集前被对象使用的存储空间.<br />&lt;ending occupancy1&gt; young generation 在进行垃圾收集后被对象使用的存储空间<br />&lt;pause time1&gt; minor收集使应用暂停的时间长短(秒) <br />&lt;starting occupancy3&gt; 整个堆(Heap Size)在进行垃圾收集前被对象使用的存储空间<br />&lt;ending occupancy3&gt; 整个堆(Heap Size)在进行垃圾收集后被对象使用的存储空间<br />&lt;pause time3&gt; 整个垃圾收集使应用暂停的时间长短(秒),包括major收集使应用暂停的时间(如果发生了major收集).<br /><strong>．</strong>GC信息的选项<br />-XX:+PrintGCDetails 显示GC的详细信息<br />-XX:+PrintGCApplicationConcurrentTime 打印应用执行的时间<br />-XX:+PrintGCApplicationStoppedTime 打印应用被暂停的时间<br /><span class="style3"><font color="#ff0000">提示:1.":"后的"+"号表示开启此选项,如果是"-"号那么表示关闭此选项。<br />     2.在不同的选项和不同的收集方式和类型下输出的格式会有所不同。 </font></span></p>
		<p>
				<strong>附录B：HotSpot JVM 选项</strong>
				<br />请参考<a href="http://java.sun.com/docs/hotspot/VMOptions.html"><font color="#0000ff">JavaTM HotSpot VM Options</font></a></p>
		<p>
				<strong>附录C：其他资源</strong>
				<br />
				<a href="http://java.sun.com/docs/hotspot/gc5.0/gc_tuning_5.html">
						<font color="#0000ff">http://java.sun.com/docs/hotspot/gc5.0/gc_tuning_5.html</font>
				</a>
				<br />
				<a href="http://java.sun.com/docs/hotspot/gc5.0/ergo5.html">
						<font color="#0000ff">http://java.sun.com/docs/hotspot/gc5.0/ergo5.html</font>
				</a>
				<br />
		</p>
<img src ="http://www.blogjava.net/jiangmin/aggbug/86144.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jiangmin/" target="_blank">JiangMin</a> 2006-12-07 18:29 <a href="http://www.blogjava.net/jiangmin/articles/86144.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>在jsp程序中使用com组件</title><link>http://www.blogjava.net/jiangmin/articles/85192.html</link><dc:creator>JiangMin</dc:creator><author>JiangMin</author><pubDate>Sun, 03 Dec 2006 08:23:00 GMT</pubDate><guid>http://www.blogjava.net/jiangmin/articles/85192.html</guid><wfw:comment>http://www.blogjava.net/jiangmin/comments/85192.html</wfw:comment><comments>http://www.blogjava.net/jiangmin/articles/85192.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jiangmin/comments/commentRss/85192.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jiangmin/services/trackbacks/85192.html</trackback:ping><description><![CDATA[在jsp程序中使用com组件的机会并不多，jsp也没有直接操作com的函数，但有的工作有时候还必须使用com组件来完成，下面就来说一下具体的操作方法。<br />　　在jsp中使用com组件有两种方法：一种是用javascript在客户端来控制（严格说这个应该是html的功能），如：<br /><br /><br /><table bordercolor="#55aaff" cellspacing="0" cellpadding="0" rules="none" width="500" align="center" bgcolor="#ddedfb" border="1"><tbody><tr><td width="10"><br /></td><td>　　&lt;OBJECT id="myCom" classid="clsid:9D8A2E2F-D38F-CDAC-D0C5-5B3FB2275442" codebase=".com/com.cab#version=1.9.9.0" &gt;<br />　　&lt;/OBJECT&gt;<br />　　&lt;script&gt;<br />　　function Hello() { <br />　　var result=  myCom.Hello(“李宗斌“); <br />　　return result;<br />　　}<br />　　&lt;/scipt&gt;</td></tr></tbody></table><br />　　结果返回：你好，李宗斌<br /><br />　　但是这种方法有个弊端就是只能在客户端操作，不能操作服务器端的东西。而且每个客户端都要安装这个组件才能运行。<br />　　第二种是直接用jsp通过Java-COM连接桥JACOB来操作服务器端的com组件。JACOB的下载地址是http://danadler.com/jacob/。运行的时候需要两个文件：jacob.jar和jacob.dll。<br />　　配置的方法是：把jacob.jar放到CLASSPATH里，把jacob.dll所在的路径加到path里。如d:\com<br /><br />　　使用的方法如下：<br /><br />　　1。先在服务器端注册com组件；<br />　　2。找到组件的名字（一般应该是知道的，不知道的话就到注册表中去找）；<br />　　3。程序示例：<br /><table bordercolor="#55aaff" cellspacing="0" cellpadding="0" rules="none" width="500" align="center" bgcolor="#ddedfb" border="1"><tbody><tr><td width="10"><br /></td><td>　　&lt;%@ page contentType="text/html; charset=gb2312" language="java" %&gt;<br />　　&lt;%@ page import="com.jacob.com.*" %&gt;<br />　　&lt;%@ page import="com.jacob.activeX.*" %&gt;<br />　　&lt;%<br />　　System.runFinalizersOnExit(true);<br />　　ActiveXComponent mf = new ActiveXComponent("MakerCom.MakerExt");//找到组件<br />　　Object  myCom = mf.getObject();//生成一个对象<br />　　String  result= Dispatch.call( myCom, "Hello", new Variant( "李宗斌") )  ;<br />　　/*调用组件的方法，myCom是组件的对象名，Hello是组件的函数，new Variant( "李宗斌") 是组件的参数变量，如果有多个可以在后边加上，方法一致*/<br />　　out.println(result);<br />　　%&gt; </td></tr></tbody></table><img src ="http://www.blogjava.net/jiangmin/aggbug/85192.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jiangmin/" target="_blank">JiangMin</a> 2006-12-03 16:23 <a href="http://www.blogjava.net/jiangmin/articles/85192.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ZIP操作加上图片水印合成``一步完成</title><link>http://www.blogjava.net/jiangmin/articles/81397.html</link><dc:creator>JiangMin</dc:creator><author>JiangMin</author><pubDate>Wed, 15 Nov 2006 14:49:00 GMT</pubDate><guid>http://www.blogjava.net/jiangmin/articles/81397.html</guid><wfw:comment>http://www.blogjava.net/jiangmin/comments/81397.html</wfw:comment><comments>http://www.blogjava.net/jiangmin/articles/81397.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/jiangmin/comments/commentRss/81397.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jiangmin/services/trackbacks/81397.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 这个类的功能是  解压ZIP包 把包里的图片放入一个文件夹, 然后把图片打上水印,在把打好水印的图片压缩成一个ZIP包来替换原来哪个ZIP包,具体请看代码!						  1								import				 java.awt.AlphaComposite;				  2																		import				 java.awt.Gra...&nbsp;&nbsp;<a href='http://www.blogjava.net/jiangmin/articles/81397.html'>阅读全文</a><img src ="http://www.blogjava.net/jiangmin/aggbug/81397.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jiangmin/" target="_blank">JiangMin</a> 2006-11-15 22:49 <a href="http://www.blogjava.net/jiangmin/articles/81397.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JavaMail API详解</title><link>http://www.blogjava.net/jiangmin/articles/79568.html</link><dc:creator>JiangMin</dc:creator><author>JiangMin</author><pubDate>Tue, 07 Nov 2006 04:30:00 GMT</pubDate><guid>http://www.blogjava.net/jiangmin/articles/79568.html</guid><wfw:comment>http://www.blogjava.net/jiangmin/comments/79568.html</wfw:comment><comments>http://www.blogjava.net/jiangmin/articles/79568.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jiangmin/comments/commentRss/79568.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jiangmin/services/trackbacks/79568.html</trackback:ping><description><![CDATA[
		<span style="COLOR: blue">一、JavaMail API简介</span>
		<br />JavaMail API是读取、撰写、发送电子信息的可选包。我们可用它来建立如Eudora、Foxmail、MS Outlook Express一般的邮件用户代理程序（Mail User Agent,简称MUA）。而不是像sendmail或者其它的邮件传输代理（Mail Transfer Agent，简称MTA）程序那样可以传送、递送、转发邮件。从另外一个角度来看，我们这些电子邮件用户日常用MUA程序来读写邮件，而MUA依赖着MTA处理邮件的递送。<br />在清楚了到MUA与MTA之间的关系后，让我们看看JavaMail API是如何提供信息访问功能的吧！JavaMail API被设计用于以不依赖协议的方式去发送和接收电子信息，这个API被分为两大部分：<br /><br />基本功能：如何以不依赖于协议的方式发送接收电子信息，这也是本文所要描述的，不过在下文中，大家将看到这只是一厢情愿而已。<br />第二个部分则是依赖特定协议的，比如SMTP、POP、IMAP、NNTP协议。在这部分的JavaMail API是为了和服务器通讯，并不在本文的内容中。<br /><br /><span style="COLOR: blue">二、相关协议一览</span><br />在我们步入JavaMail API之前，先看一下API所涉及的协议。以下便是大家日常所知、所乐于使用的4大信息传输协议：<br />SMTP<br />POP<br />IMAP<br />MIME<br />当然，上面的4个协议，并不是全部，还有NNTP和其它一些协议可用于传输信息，但是由于不常用到，所以本文便不提及了。理解这4个基本的协议有助于我们更好的使用JavaMail API。然而JavaMail API是被设计为与协议无关的，目前我们并不能克服这些协议的束缚。确切的说，如果我们使用的功能并不被我们选择的协议支持，那么JavaMail API并不可能如魔术师一样神奇的赋予我们这种能力。<br /><br /><span style="COLOR: blue">1．SMTP</span><br />简单邮件传输协议定义了递送邮件的机制。在下文中，我们将使用基于Java-Mail的程序与公司或者ISP的SMTP服务器进行通讯。这个SMTP服务器将邮件转发到接收者的SMTP服务器，直至最后被接收者通过POP或者IMAP协议获取。这并不需要SMTP服务器使用支持授权的邮件转发，但是却的确要注意SMTP服务器的正确设置（SMTP服务器的设置与JavaMail API无关）。<br /><br /><span style="COLOR: blue">2．POP</span><br />POP是一种邮局协议，目前为第3个版本，即众所周知的POP3。POP定义了一种用户如何获得邮件的机制。它规定了每个用户使用一个单独的邮箱。大多数人在使用POP时所熟悉的功能并非都被支持，例如查看邮箱中的新邮件数量。而这个功能是微软的Outlook内建的，那么就说明微软Outlook之类的邮件客户端软件是通过查询最近收到的邮件来计算新邮件的数量来实现前面所说的功能。因此在我们使用JavaMail API时需要注意，当需要获得如前面所讲的新邮件数量之类的信息时，我们不得不自己进行计算。<br /><br /><span style="COLOR: blue">3．IMAP</span><br />IMAP使用在接收信息的高级协议，目前版本为第4版，所以也被称为IMAP4。需要注意的是在使用IMAP时，邮件服务器必须支持该协议。从这个方面讲，我们并不能完全使用IMAP来替代POP，不能期待IMAP在任何地方都被支持。假如邮件服务器支持IMAP，那么我们的邮件程序将能够具有以下被IMAP所支持的特性：每个用户在服务器上可具有多个目录，这些目录能在多个用户之间共享。<br />其与POP相比高级之处显而易见，但是在尝试采取IMAP时，我们认识到它并不是十分完美的：由于IMAP需要从其它服务器上接收新信息，将这些信息递送给用户，维护每个用户的多个目录，这都为邮件服务器带来了高负载。并且IMAP与POP的一个不同之处是POP用户在接收邮件时将从邮件服务器上下载邮件，而IMAP允许用户直接访问邮件目录，所以在邮件服务器进行备份作业时，由于每个长期使用此邮件系统的用户所用的邮件目录会占有很大的空间，这将直接导致邮件服务器上磁盘空间暴涨。<br /><br /><span style="COLOR: blue">4．MIME</span><br />MIME并不是用于传送邮件的协议，它作为多用途邮件的扩展定义了邮件内容的格式：信息格式、附件格式等等。一些RFC标准都涉及了MIME：RFC 822, RFC 2045, RFC 2046, RFC 2047，有兴趣的Matrixer可以阅读一下。而作为JavaMail API的开发者，我们并不需关心这些格式定义，但是这些格式被用在了程序中。<br /><br /><span style="COLOR: blue">5．NNTP和其它的第三方协议</span><br />正因为JavaMail API在设计时考虑到与第三方协议实现提供商之间的分离，故我们可以很容易的添加一些第三方协议。SUN维护着一个第三方协议实现提供商的列表：<a href="http://java.sun.com/products/javamail/Third_Party.html" target="_new">http://java.sun.com/products/javamail/Third_Party.html</a>，通过此列表我们可以找到所需要的而又不被SUN提供支持的第三方协议：比如NNTP这个新闻组协议和S/MIME这个安全的MIME协议。<br /><br /><span style="COLOR: blue">三、安装</span><br /><span style="COLOR: blue">1．安装JavaMail</span><br />为了使用JavaMail API，需要从<a href="ttp://java.sun.com/products/javamail/downloads/index.html" target="_new">http://java.sun.com/products/javamail/downloads/index.html</a>下载文件名格式为javamail-[version].zip的文件（这个文件中包括了JavaMail实现），并将其中的mail.jar文件添加到CLASSPATH中。这个实现提供了对SMTP、IMAP4、POP3的支持。<br />注意：在安装JavaMail实现之后，我们将在demo目录中发现许多有趣的简单实例程序。<br />在安装了JavaMail之后,我们还需要安装JavaBeans Activation Framework，因为这个框架是JavaMail API所需要的。如果我们使用J2EE的话，那么我们并无需单独下载JavaMail，因为它存在于J2EE.jar中，只需将J2EE.jar加入到CLASSPATH即可。<br /><br /><span style="COLOR: blue">2．安装JavaBeans Activation Framework</span><br />从<a href="http://java.sun.com/products/javabeans/glasgow/jaf.html" target="_new">http://java.sun.com/products/javabeans/glasgow/jaf.html</a>下载JavaBeans Activation Framework，并将其添加到CLASSPATH中。此框架增加了对任何数据块的分类、以及对它们的处理的特性。这些特性是JavaMail API需要的。虽然听起来这些特性非常模糊，但是它对于我们的JavaMail API来说只是提供了基本的MIME类型支持。<br />到此为止，我们应当把mail.jar和activation.jar都添加到了CLASSPATH中。<br />当然如果从方便的角度讲，直接把这两个Jar文件复制到JRE目录的lib/ext目录中也可以。<br /><br /><span style="COLOR: blue">四、初次认识JavaMail API</span><br /><span style="COLOR: blue">1．了解我们的JavaMail环境</span><br /><span style="COLOR: green">A．纵览JavaMail核心类结构</span><br />打开JavaMail.jar文件，我们将发现在javax.mail的包下面存在着一些核心类：Session、Message、Address、Authenticator、Transport、Store、Folder。而且在javax.mail.internet包中还有一些常用的子类。<br /><span style="COLOR: green">B．Session</span><br />Session类定义了基本的邮件会话。就像Http会话那样，我们进行收发邮件的工作都是基于这个会话的。Session对象利用了java.util.Properties对象获得了邮件服务器、用户名、密码信息和整个应用程序都要使用到的共享信息。<br />Session类的构造方法是私有的，所以我们可以使用Session类提供的getDefaultInstance()这个静态工厂方法获得一个默认的Session对象：<br /><pre class="overflow"><br />Properties props = new Properties();<br />// fill props with any information<br />Session session = Session.getDefaultInstance(props, null);<br /></pre><br />或者使用getInstance()这个静态工厂方法获得自定义的Session: <br /><pre class="overflow"><br />Properties props = new Properties();<br />// fill props with any information<br />Session session = Session.getInstance(props, null);<br /></pre><br />从上面的两个例子中不难发现，getDefaultInstance()和getInstance()方法的第二个参数都是null，这是因为在上面的例子中并没有使用到邮件授权，下文中将对授权进行详细介绍。<br />从很多的实例看，在对mail server进行访问的过程中使用共享的Session是足够的，即使是工作在多个用户邮箱的模式下也不例外。<br /><br /><span style="COLOR: green">C．Message</span><br />当我们建立了Session对象后，便可以被发送的构造信息体了。在这里SUN提供了Message类型来帮助开发者完成这项工作。由于Message是一个抽象类，大多数情况下，我们使用javax.mail.internet.MimeMessage这个子类，该类是使用MIME类型、MIME信息头的邮箱信息。信息头只能使用US-ASCII字符，而非ASCII字符将通过编码转换为ASCII的方式使用。<br />为了建立一个MimeMessage对象，我们必须将Session对象作为MimeMessage构造方法的参数传入：<br /><pre class="overflow"><br />MimeMessage message = new MimeMessage(session);<br /></pre><br />注意：对于MimeMessage类来讲存在着多种构造方法，比如使用输入流作为参数的构造方法。<br /><br />在建立了MimeMessage对象后，我们需要设置它的各个part，对于MimeMessage类来说，这些part就是MimePart接口。最基本的设置信息内容的方法就是通过表示信息内容和米么类型的参数调用setContent()方法：<br /><pre class="overflow"><br />message.setContent("Hello", "text/plain");<br /></pre><br />然而，如果我们所使用的MimeMessage中信息内容是文本的话，我们便可以直接使用setText()方法来方便的设置文本内容。<br /><pre class="overflow"><br />message.setText("Hello");<br /></pre><br />前面所讲的两种方法，对于文本信息，后者更为合适。而对于其它的一些信息类型，比如HTML信息，则要使用前者。<br />别忘记了，使用setSubject()方法对邮件设置邮件主题：<br /><pre class="overflow"><br />message.setSubject("First");<br /></pre><br /><br /><span style="COLOR: green">D．Address</span><br />到这里，我们已经建立了Session和Message，下面将介绍如何使用邮件地址类：Address。像Message一样，Address类也是一个抽象类，所以我们将使用javax.mail.internet.InternetAddress这个子类。<br />通过传入代表邮件地址的字符串，我们可以建立一个邮件地址类：<br /><pre class="overflow"><br />Address address = new InternetAddress("president@whitehouse.gov"); <br /></pre><br />如果要在邮件地址后面增加名字的话，可以通过传递两个参数：代表邮件地址和名字的字符串来建立一个具有邮件地址和名字的邮件地址类：<br /><pre class="overflow"><br />Address address = new InternetAddress("president@whitehouse.gov", "George Bush"); <br /></pre><br />本文在这里所讲的邮件地址类是为了设置邮件信息的发信人和收信人而准备的，在建立了邮件地址类后，我们通过message的setFrom()和setReplyTo()两种方法设置邮件的发信人：<br /><pre class="overflow"><br />message.setFrom(address);<br />message.setReplyTo(address);<br /></pre><br />若在邮件中存在多个发信人地址，我们可用addForm()方法增加发信人：<br /><pre class="overflow"><br />Address address[] = ...;<br />message.addFrom(address);<br /></pre><br />为了设置收信人，我们使用addRecipient()方法增加收信人，此方法需要使用Message.RecipientType的常量来区分收信人的类型：<br /><pre class="overflow"><br />message.addRecipient(type, address)<br /></pre><br />下面是Message.RecipientType的三个常量:<br />Message.RecipientType.TO<br />Message.RecipientType.CC<br />Message.RecipientType.BCC<br />因此，如果我们要发送邮件给总统，并发用一个副本给第一夫人的话，下面的方法将被用到：<br /><pre class="overflow"><br />Address toAddress = new InternetAddress("vice.president@whitehouse.gov");<br />Address ccAddress = new InternetAddress("first.lady@whitehouse.gov");<br />message.addRecipient(Message.RecipientType.TO, toAddress);<br />message.addRecipient(Message.RecipientType.CC, ccAddress);<br /></pre><br />JavaMail API并没有提供检查邮件地址有效性的机制。当然我们可以自己完成这个功能：验证邮件地址的字符是否按照RFC822规定的格式书写或者通过DNS服务器上的MX记录验证等。<br /><br /><span style="COLOR: green">E．Authenticator</span><br />像java.net类那样，JavaMail API通过使用授权者类（Authenticator）以用户名、密码的方式访问那些受到保护的资源，在这里“资源”就是指邮件服务器。在javax.mail包中可以找到这个JavaMail的授权者类（Authenticator）。<br />在使用Authenticator这个抽象类时，我们必须采用继承该抽象类的方式，并且该继承类必须具有返回PasswordAuthentication对象（用于存储认证时要用到的用户名、密码）getPasswordAuthentication()方法。并且要在Session中进行注册，使Session能够了解在认证时该使用哪个类。<br />下面代码片断中的MyAuthenticator就是一个Authenticator的子类。<br /><pre class="overflow"><br />Properties props = new Properties();<br />// fill props with any information<br />Authenticator auth = new MyAuthenticator();<br />Session session = Session.getDefaultInstance(props, auth);<br /></pre><br /><br /><span style="COLOR: green">F．Transport</span><br />在发送信息时，Transport类将被用到。这个类实现了发送信息的协议（通称为SMTP），此类是一个抽象类，我们可以使用这个类的静态方法send()来发送消息：<br /><pre class="overflow"><br />Transport.send(message);<br /></pre><br />当然，方法是多样的。我们也可由Session获得相应协议对应的Transport实例。并通过传递用户名、密码、邮件服务器主机名等参数建立与邮件服务器的连接，并使用sendMessage()方法将信息发送，最后关闭连接：<br /><pre class="overflow"><br />message.saveChanges(); // implicit with send()<br />Transport transport = session.getTransport("smtp");<br />transport.connect(host, username, password);<br />transport.sendMessage(message, message.getAllRecipients());<br />transport.close();<br /></pre><br />评论：上面的方法是一个很好的方法，尤其是在我们在同一个邮件服务器上发送多个邮件时。因为这时我们将在连接邮件服务器后连续发送邮件，然后再关闭掉连接。send()这个基本的方法是在每次调用时进行与邮件服务器的连接的，对于在同一个邮件服务器上发送多个邮件来讲可谓低效的方式。<br />注意：如果需要在发送邮件过程中监控mail命令的话，可以在发送前设置debug标志：<br /><pre class="overflow"><br />session.setDebug(true)。<br /></pre><br /><br /><span style="COLOR: green">G．Store和Folder</span><br />接收邮件和发送邮件很类似都要用到Session。但是在获得Session后，我们需要从Session中获取特定类型的Store，然后连接到Store，这里的Store代表了存储邮件的邮件服务器。在连接Store的过程中，极有可能需要用到用户名、密码或者Authenticator。<br /><pre class="overflow"><br />// Store store = session.getStore("imap");<br />Store store = session.getStore("pop3");<br />store.connect(host, username, password);<br /></pre><br />在连接到Store后，一个Folder对象即目录对象将通过Store的getFolder()方法被返回，我们可从这个Folder中读取邮件信息：<br /><pre class="overflow"><br />Folder folder = store.getFolder("INBOX");<br />folder.open(Folder.READ_ONLY);<br />Message message[] = folder.getMessages();<br /></pre><br />上面的例子首先从Store中获得INBOX这个Folder（对于POP3协议只有一个名为INBOX的Folder有效），然后以只读（Folder.READ_ONLY）的方式打开Folder，最后调用Folder的getMessages()方法得到目录中所有Message的数组。<br /><br />注意：对于POP3协议只有一个名为INBOX的Folder有效，而对于IMAP协议，我们可以访问多个Folder（想想前面讲的IMAP协议）。而且SUN在设计Folder的getMessages()方法时采取了很智能的方式：首先接收新邮件列表，然后再需要的时候（比如读取邮件内容）才从邮件服务器读取邮件内容。<br />在读取邮件时，我们可以用Message类的getContent()方法接收邮件或是writeTo()方法将邮件保存，getContent()方法只接收邮件内容（不包含邮件头），而writeTo()方法将包括邮件头。<br /><pre class="overflow"><br />System.out.println(((MimeMessage)message).getContent());<br /></pre><br />在读取邮件内容后，别忘记了关闭Folder和Store。<br /><pre class="overflow"><br />folder.close(aBoolean);<br />store.close();<br /></pre><br />传递给Folder.close()方法的boolean 类型参数表示是否在删除操作邮件后更新Folder。 <br /><br /><span style="COLOR: green">H．继续向前进！</span><br />在讲解了以上的七个Java Mail核心类定义和理解了简单的代码片断后，下文将详细讲解怎样使用这些类实现JavaMail API所要完成的高级功能。<br /><br /><span style="COLOR: blue">五、使用JavaMail API</span><br />在明确了JavaMail API的核心部分如何工作后，本人将带领大家学习一些使用Java Mail API任务案例。<br /><span style="COLOR: blue">1．发送邮件</span><br />在获得了Session后，建立并填入邮件信息，然后发送它到邮件服务器。这便是使用Java Mail API发送邮件的过程，在发送邮件之前，我们需要设置SMTP服务器：通过设置Properties的mail.smtp.host属性。<br /><pre class="overflow"><br />String host = ...;<br />String from = ...;<br />String to = ...;<br /><br />// Get system properties<br />Properties props = System.getProperties();<br /><br />// Setup mail server<br />props.put("mail.smtp.host", host);<br /><br />// Get session<br />Session session = Session.getDefaultInstance(props, null);<br /><br />// Define message<br />MimeMessage message = new MimeMessage(session);<br />message.setFrom(new InternetAddress(from));<br />message.addRecipient(Message.RecipientType.TO, <br />  new InternetAddress(to));<br />message.setSubject("Hello JavaMail");<br />message.setText("Welcome to JavaMail");<br />// Send message<br />Transport.send(message);<br /></pre><br />由于建立邮件信息和发送邮件的过程中可能会抛出异常，所以我们需要将上面的代码放入到try-catch结构块中。<br /><br /><span style="COLOR: blue">2．接收邮件</span><br />为了在读取邮件，我们获得了session，并且连接到了邮箱的相应store，打开相应的Folder，然后得到我们想要的邮件，当然别忘记了在结束时关闭连接。<br /><pre class="overflow"><br />String host = ...;<br />String username = ...;<br />String password = ...;<br /><br />// Create empty properties<br />Properties props = new Properties();<br /><br />// Get session<br />Session session = Session.getDefaultInstance(props, null);<br /><br />// Get the store<br />Store store = session.getStore("pop3");<br />store.connect(host, username, password);<br /><br />// Get folder<br />Folder folder = store.getFolder("INBOX");<br />folder.open(Folder.READ_ONLY);<br /><br />// Get directory<br />Message message[] = folder.getMessages();<br /><br />for (int i=0, n=message.length; i&lt;n; i++) {<br />   System.out.println(i + ": " + message[i].getFrom()[0] <br />     + "\t" + message[i].getSubject());<br />}<br /><br />// Close connection <br />folder.close(false);<br />store.close();<br /></pre><br />上面的代码所作的是从邮箱中读取每个邮件，并且显示邮件的发信人地址和主题。从技术角度讲，这里存在着一个异常的可能：当发信人地址为空时，getFrom()[0]将抛出异常。<br /><br />下面的代码片断有效的说明了如何读取邮件内容，在显示每个邮件发信人和主题后，将出现用户提示从而得到用户是否读取该邮件的确认，如果输入YES的话，我们可用Message.writeTo(java.io.OutputStream os)方法将邮件内容输出到控制台上，关于Message.writeTo()的具体用法请看JavaMail API。<br /><pre class="overflow"><br />BufferedReader reader = new BufferedReader (<br />  new InputStreamReader(System.in));<br /><br />// Get directory<br />Message message[] = folder.getMessages();<br />for (int i=0, n=message.length; i&lt;n; i++) {<br />  System.out.println(i + ": " + message[i].getFrom()[0] <br />    + "\t" + message[i].getSubject());<br /><br />  System.out.println("Do you want to read message? " +<br />    "[YES to read/QUIT to end]");<br />  String line = reader.readLine();<br />  if ("YES".equals(line)) {<br />    message[i].writeTo(System.out);<br />  } else if ("QUIT".equals(line)) {<br />    break;<br />  }<br />}<br /></pre><br /><br /><span style="COLOR: blue">3．删除邮件和标志</span><br />设置与message相关的Flags是删除邮件的常用方法。这些Flags表示了一些系统定义和用户定义的不同状态。在Flags类的内部类Flag中预定义了一些标志：<br />Flags.Flag.ANSWERED<br />Flags.Flag.DELETED<br />Flags.Flag.DRAFT<br />Flags.Flag.FLAGGED<br />Flags.Flag.RECENT<br />Flags.Flag.SEEN<br />Flags.Flag.USER<br />但需要在使用时注意的：标志存在并非意味着这个标志被所有的邮件服务器所支持。例如，对于删除邮件的操作，POP协议不支持上面的任何一个。所以要确定哪些标志是被支持的——通过访问一个已经打开的Folder对象的getPermanetFlags()方法，它将返回当前被支持的Flags类对象。<br />删除邮件时，我们可以设置邮件的DELETED标志： <br /><pre class="overflow"><br />message.setFlag(Flags.Flag.DELETED, true);<br /></pre><br />但是首先要采用READ_WRITE的方式打开Folder：<br /><pre class="overflow"><br />folder.open(Folder.READ_WRITE);<br /></pre><br />在对邮件进行删除操作后关闭Folder时，需要传递一个true作为对删除邮件的擦除确认。<br /><pre class="overflow"><br />folder.close(true);<br /></pre><br />Folder类中另一种用于删除邮件的方法expunge()也同样可删除邮件，但是它并不为sun提供的POP3实现支持，而其它第三方提供的POP3实现支持或者并不支持这种方法。<br />另外，介绍一种检查某个标志是否被设置的方法：Message.isSet(Flags.Flag flag)方法，其中参数为被检查的标志。<br /><br /><span style="COLOR: blue">4．邮件认证</span><br />我们在前面已经学会了如何使用Authenticator类来代替直接使用用户名和密码这两字符串作为Session.getDefaultInstance()或者Session.getInstance()方法的参数。在前面的小试牛刀后，现在我们将了解到全面认识一下邮件认证。<br />我们在此取代了直接使用邮件服务器主机名、用户名、密码这三个字符串作为连接到POP3 Store的方式，使用存储了邮件服务器主机名信息的属性文件，并在获得Session时传入自定义的Authenticator实例：<br /><pre class="overflow"><br />// Setup properties<br />Properties props = System.getProperties();<br />props.put("mail.pop3.host", host);<br /><br />// Setup authentication, get session<br />Authenticator auth = new PopupAuthenticator();<br />Session session = Session.getDefaultInstance(props, auth);<br /><br />// Get the store<br />Store store = session.getStore("pop3");<br />store.connect();<br /></pre><br /><br />PopupAuthenticator类继承了抽象类Authenticator，并且通过重载Authenticator类的getPasswordAuthentication()方法返回PasswordAuthentication类对象。而getPasswordAuthentication()方法的参数param是以逗号分割的用户名、密码组成的字符串。<br /><pre class="overflow"><br />import javax.mail.*;<br />import java.util.*;<br /><br />public class PopupAuthenticator extends Authenticator {<br /><br />  public PasswordAuthentication getPasswordAuthentication(String param) {<br />    String username, password;<br /><br />    StringTokenizer st = new StringTokenizer(param, ",");<br />    username = st.nextToken();<br />    password = st.nextToken();<br /><br />    return new PasswordAuthentication(username, password);<br />  }<br /><br />}<br /></pre><br /><br /><span style="COLOR: blue">5．回复邮件</span><br />回复邮件的方法很简单：使用Message类的reply()方法，通过配置回复邮件的收件人地址和主题（如果没有提供主题的话，系统将默认将“Re：”作为邮件的主体），这里不需要设置任何的邮件内容，只要复制发信人或者reply-to到新的收件人。而reply()方法中的boolean参数表示是否将邮件回复给发送者（参数值为false），或是恢复给所有人（参数值为true）。<br />补充一下，reply-to地址需要在发信时使用setReplyTo()方法设置。<br /><pre class="overflow"><br />MimeMessage reply = (MimeMessage)message.reply(false);<br />reply.setFrom(new InternetAddress("president@whitehouse.gov"));<br />reply.setText("Thanks");<br />Transport.send(reply);<br /></pre><br /><br /><span style="COLOR: blue">6．转发邮件</span><br />转发邮件的过程不如前面的回复邮件那样简单，它将建立一个转发邮件，这并非一个方法就能做到。<br />每个邮件是由多个部分组成，每个部分称为一个邮件体部分，是一个BodyPart类对象，对于MIME类型邮件来讲就是MimeBodyPart类对象。这些邮件体包含在成为Multipart的容器中对于MIME类型邮件来讲就是MimeMultiPart类对象。在转发邮件时，我们建立一个文字邮件体部分和一个被转发的文字邮件体部分，然后将这两个邮件体放到一个Multipart中。说明一下，复制一个邮件内容到另一个邮件的方法是仅复制它的DataHandler（数据处理者）即可。这是由JavaBeans Activation Framework定义的一个类，它提供了对邮件内容的操作命令的访问、管理了邮件内容操作，是不同的数据源和数据格式之间的一致性接口。<br /><pre class="overflow"><br />// Create the message to forward<br />Message forward = new MimeMessage(session);<br /><br />// Fill in header<br />forward.setSubject("Fwd: " + message.getSubject());<br />forward.setFrom(new InternetAddress(from));<br />forward.addRecipient(Message.RecipientType.TO, <br />  new InternetAddress(to));<br /><br />// Create your new message part<br />BodyPart messageBodyPart = new MimeBodyPart();<br />messageBodyPart.setText(<br />  "Here you go with the original message:\n\n");<br /><br />// Create a multi-part to combine the parts<br />Multipart multipart = new MimeMultipart();<br />multipart.addBodyPart(messageBodyPart);<br /><br />// Create and fill part for the forwarded content<br />messageBodyPart = new MimeBodyPart();<br />messageBodyPart.setDataHandler(message.getDataHandler());<br /><br />// Add part to multi part<br />multipart.addBodyPart(messageBodyPart);<br /><br />// Associate multi-part with message<br />forward.setContent(multipart);<br /><br />// Send message<br />Transport.send(forward);<br /></pre><br /><br /><span style="COLOR: blue">7．使用附件</span><br />附件作为与邮件相关的资源经常以文本、表格、图片等格式出现，如流行的邮件客户端一样，我们可以用JavaMail API从邮件中获取附件或是发送带有附件的邮件。<br /><br /><span style="COLOR: green">A．发送带有附件的邮件</span><br />发送带有附件的邮件的过程有些类似转发邮件，我们需要建立一个完整邮件的各个邮件体部分，在第一个部分（即我们的邮件内容文字）后，增加一个具有DataHandler的附件而不是在转发邮件时那样复制第一个部分的DataHandler。<br /><br />如果我们将文件作为附件发送，那么要建立FileDataSource类型的对象作为附件数据源；如果从URL读取数据作为附件发送，那么将要建立URLDataSource类型的对象作为附件数据源。<br /><br />然后将这个数据源（FileDataSource或是URLDataSource）对象作为DataHandler类构造方法的参数传入，从而建立一个DataHandler对象作为数据源的DataHandler。<br /><br />接着将这个DataHandler设置为邮件体部分的DataHandler。这样就完成了邮件体与附件之间的关联工作，下面的工作就是BodyPart的setFileName()方法设置附件名为原文件名。<br /><br />最后将两个邮件体放入到Multipart中，设置邮件内容为这个容器Multipart，发送邮件。<br /><pre class="overflow"><br />// Define message<br />Message message = new MimeMessage(session);<br />message.setFrom(new InternetAddress(from));<br />message.addRecipient(Message.RecipientType.TO, <br />  new InternetAddress(to));<br />message.setSubject("Hello JavaMail Attachment");<br /><br />// Create the message part <br />BodyPart messageBodyPart = new MimeBodyPart();<br /><br />// Fill the message<br />messageBodyPart.setText("Pardon Ideas");<br /><br />Multipart multipart = new MimeMultipart();<br />multipart.addBodyPart(messageBodyPart);<br /><br />// Part two is attachment<br />messageBodyPart = new MimeBodyPart();<br />DataSource source = new FileDataSource(filename);<br />messageBodyPart.setDataHandler(new DataHandler(source));<br />messageBodyPart.setFileName(filename);<br />multipart.addBodyPart(messageBodyPart);<br /><br />// Put parts in message<br />message.setContent(multipart);<br /><br />// Send the message<br />Transport.send(message);<br /></pre><br />如果我们使用servlet实现发送带有附件的邮件，则必须上传附件给servlet，这时需要注意提交页面form中对编码类型的设置应为multipart/form-data。<br /><pre class="overflow"><br />&lt;FORM ENCTYPE="multipart/form-data" <br />    method=post action="/myservlet"&gt; <br />  &lt;INPUT TYPE="file" NAME="thefile"&gt;<br />  &lt;INPUT TYPE="submit" VALUE="Upload"&gt;<br />&lt;/FORM&gt;<br /></pre><br /><br /><span style="COLOR: green">B．读取邮件中的附件</span><br />读取邮件中的附件的过程要比发送它的过程复杂一点。因为带有附件的邮件是多部分组成的，我们必须处理每一个部分获得邮件的内容和附件。<br />但是如何辨别邮件信息内容和附件呢？Sun在Part类（BodyPart类实现的接口类）中提供了getDisposition()方法让开发者获得邮件体部分的部署类型，当该部分是附件时，其返回之将是Part.ATTACHMENT。但附件也可以没有部署类型的方式存在或者部署类型为Part.INLINE，无论部署类型为Part.ATTACHMENT还是Part.INLINE，我们都能把该邮件体部分导出保存。<br /><pre class="overflow"><br />Multipart mp = (Multipart)message.getContent();<br /><br />for (int i=0, n=multipart.getCount(); i&lt;n; i++) {<br />  Part part = multipart.getBodyPart(i));<br /><br />  String disposition = part.getDisposition();<br /><br />  if ((disposition != null) &amp;&amp; <br />      ((disposition.equals(Part.ATTACHMENT) || <br />       (disposition.equals(Part.INLINE))) {<br />    saveFile(part.getFileName(), part.getInputStream());<br />  }<br />}<br /></pre><br />下列代码中使用了saveFile方法是自定义的方法，它根据附件的文件名建立一个文件，如果本地磁盘上存在名为附件的文件，那么将在文件名后增加数字表示区别。然后从邮件体中读取数据写入到本地文件中（代码省略）。<br /><pre class="overflow"><br />// from saveFile()<br />File file = new File(filename);<br />for (int i=0; file.exists(); i++) {<br />  file = new File(filename+i);<br />}<br /></pre><br />以上是邮件体部分被正确设置的简单例子，如果邮件体部分的部署类型为null，那么我们通过获得邮件体部分的MIME类型来判断其类型作相应的处理，代码结构框架如下：<br /><pre class="overflow"><br />if (disposition == null) {<br />  // Check if plain<br />  MimeBodyPart mbp = (MimeBodyPart)part;<br />  if (mbp.isMimeType("text/plain")) {<br />    // Handle plain<br />  } else {<br />    // Special non-attachment cases here of <br />    // image/gif, text/html, ...<br />  }<br />...<br />}<br /></pre><br /><br /><span style="COLOR: blue">8．处理HTML邮件</span><br />前面的例子中发送的邮件都是以文本为内容的（除了附件），下面将介绍如何接收和发送基于HTML的邮件。<br /><span style="COLOR: green">A．发送HTML邮件</span><br />假如我们需要发送一个HTML文件作为邮件内容，并使邮件客户端在读取邮件时获取相关的图片或者文字的话，只要设置邮件内容为html代码，并设置内容类型为text/html即可：<br /><pre class="overflow"><br />String htmlText = "&lt;H1&gt;Hello&lt;/H1&gt;" + <br />  "&lt;img src=\"http://www.jguru.com/images/logo.gif\"&gt;";<br />message.setContent(htmlText, "text/html"));<br /></pre><br />请注意：这里的图片并不是在邮件中内嵌的，而是在URL中定义的。邮件接收者只有在线时才能看到。<br />在接收邮件时，如果我们使用JavaMail API接收邮件的话是无法实现以HTML方式显示邮件内容的。因为JavaMail API邮件内容视为二进制流。所以要显示HTML内容的邮件，我们必须使用JEditorPane或者第三方HTML展现组件。<br /><br />以下代码显示了如何使用JEditorPane显示邮件内容：<br /><pre class="overflow"><br />if (message.getContentType().equals("text/html")) {<br />  String content = (String)message.getContent();<br />  JFrame frame = new JFrame();<br />  JEditorPane text = new JEditorPane("text/html", content);<br />  text.setEditable(false);<br />  JScrollPane pane = new JScrollPane(text);<br />  frame.getContentPane().add(pane);<br />  frame.setSize(300, 300);<br />  frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);<br />  frame.show();<br />}<br /></pre><br /><br /><span style="COLOR: green">B．在邮件中包含图片</span><br />如果我们在邮件中使用HTML作为内容，那么最好将HTML中使用的图片作为邮件的一部分，这样无论是否在线都会正确的显示HTML中的图片。处理方法就是将HTML中用到的图片作为邮件附件并使用特殊的cid URL作为图片的引用，这个cid就是对图片附件的Content-ID头的引用。<br />处理内嵌图片就像向邮件中添加附件一样，不同之处在于我们必须通过设置图片附件所在的邮件体部分的header中Content-ID为一个随机字符串，并在HTML中img的src标记中设置为该字符串。这样就完成了图片附件与HTML的关联。<br /><pre class="overflow"><br />String file = ...;<br /><br />// Create the message<br />Message message = new MimeMessage(session);<br /><br />// Fill its headers<br />message.setSubject("Embedded Image");<br />message.setFrom(new InternetAddress(from));<br />message.addRecipient(Message.RecipientType.TO, <br />  new InternetAddress(to));<br /><br />// Create your new message part<br />BodyPart messageBodyPart = new MimeBodyPart();<br />String htmlText = "&lt;H1&gt;Hello&lt;/H1&gt;" + <br />  "&lt;img src=\"cid:memememe\"&gt;";<br />messageBodyPart.setContent(htmlText, "text/html");<br /><br />// Create a related multi-part to combine the parts<br />MimeMultipart multipart = new MimeMultipart("related");<br />multipart.addBodyPart(messageBodyPart);<br /><br />// Create part for the image<br />messageBodyPart = new MimeBodyPart();<br /><br />// Fetch the image and associate to part<br />DataSource fds = new FileDataSource(file);<br />messageBodyPart.setDataHandler(new DataHandler(fds));<br />messageBodyPart.setHeader("Content-ID","&lt;memememe&gt;");<br /><br />// Add part to multi-part<br />multipart.addBodyPart(messageBodyPart);<br /><br />// Associate multi-part with message<br />message.setContent(multipart);<br /></pre><br /><br /><span style="COLOR: blue">9．在邮件中搜索短语</span><br />JavaMail API提供了过滤器机制，它被用来建立搜索短语。这个短语由javax.mail.search包中的SearchTerm抽象类来定义，在定义后我们便可以使用Folder的Search()方法在Folder中查找邮件：<br /><pre class="overflow"><br />SearchTerm st = ...;<br />Message[] msgs = folder.search(st);<br /></pre><br />下面有22个不同的类（继承了SearchTerm类）供我们使用：<br />AND terms (class AndTerm)<br />OR terms (class OrTerm)<br />NOT terms (class NotTerm)<br />SENT DATE terms (class SentDateTerm)<br />CONTENT terms (class BodyTerm)<br />HEADER terms (FromTerm / FromStringTerm, RecipientTerm / RecipientStringTerm, SubjectTerm, etc.)<br />使用这些类定义的断语集合，我们可以构造一个逻辑表达式，并在Folder中进行搜索。下面是一个实例：在Folder中搜索邮件主题含有“ADV”字符串或者发信人地址为friend@public.com的邮件。<br /><pre class="overflow"><br />SearchTerm st = <br />  new OrTerm(<br />    new SubjectTerm("ADV:"), <br />    new FromStringTerm("friend@public.com"));<br />Message[] msgs = folder.search(st);<br /></pre><br /><br /><span style="COLOR: blue">六、参考资源</span><br /><a href="http://java.sun.com/products/javamail/index.jsp" target="_new">JavaMail API Home</a><br /><a href="http://java.sun.com/developer/onlineTraining/JavaMail/contents.html" target="_new">Sun’s JavaMail API基础</a><br /><a href="http://java.sun.com/products/javabeans/glasgow/jaf.html" target="_new">JavaBeans Activation Framework Home</a><br /><a href="http://mail.java.sun.com/archives/javamail-interest.html" target="_new">javamail-interest mailing list</a><br /><a href="http://java.sun.com/products/javamail/FAQ.html" target="_new">Sun's JavaMail FAQ</a><br /><a href="http://www.jguru.com/faq/JavaMail" target="_new">jGuru's JavaMail FAQ</a><br /><a href="http://java.sun.com/products/javamail/Third_Party.html" target="_new">Third Party Products List</a><br /><br /><span style="COLOR: blue">七、代码下载</span><br /><a href="http://java.sun.com/developer/onlineTraining/JavaMail/exercises.html" target="_new">http://java.sun.com/developer/onlineTraining/JavaMail/exercises.html</a><img src ="http://www.blogjava.net/jiangmin/aggbug/79568.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jiangmin/" target="_blank">JiangMin</a> 2006-11-07 12:30 <a href="http://www.blogjava.net/jiangmin/articles/79568.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Swing中弹出对话框的几种类</title><link>http://www.blogjava.net/jiangmin/articles/78525.html</link><dc:creator>JiangMin</dc:creator><author>JiangMin</author><pubDate>Wed, 01 Nov 2006 09:45:00 GMT</pubDate><guid>http://www.blogjava.net/jiangmin/articles/78525.html</guid><wfw:comment>http://www.blogjava.net/jiangmin/comments/78525.html</wfw:comment><comments>http://www.blogjava.net/jiangmin/articles/78525.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jiangmin/comments/commentRss/78525.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jiangmin/services/trackbacks/78525.html</trackback:ping><description><![CDATA[Swing中提供了JOptionPane类来实现类似Windows平台下的MessageBox的功能，同样在Java中也有，利用JOptionPane类中的各个static方法来生成各种标准的对话框，实现显示出信息、提出问题、警告、用户输入参数等功能。这些对话框都是模式对话框。
ConfirmDialog　---　确认对话框，提出问题，然后由用户自己来确认（按"Yes"或"No"按钮）
InputDialog　---　提示输入文本
MessageDialog　---　显示信息
OptionDialog　-－　组合其它三个对话框类型。
　　这四个对话框可以采用showXXXDialog()来显示，如showConfirmDialog()显示确认对话框、showInputDialog()显示输入文本对话框、showMessageDialog()显示信息对话框、showOptionDialog()显示选择性的对话框。它们所使用的参数说明如下：
① ParentComponent：指示对话框的父窗口对象，一般为当前窗口。也可以为null即采用缺省的Frame作为父窗口，此时对话框将设置在屏幕的正中。
② message：指示要在对话框内显示的描述性的文字
③ String title：标题条文字串。
④ Component：在对话框内要显示的组件（如按钮）
⑤ Icon：在对话框内要显示的图标
⑥ messageType：一般可以为如下的值ERROR_MESSAGE、INFORMATION_MESSAGE、WARNING_MESSAGE、QUESTION_MESSAGE、PLAIN_MESSAGE、
⑦ optionType：它决定在对话框的底部所要显示的按钮选项。一般可以为DEFAULT_OPTION、YES_NO_OPTION、YES_NO_CANCEL_OPTION、OK_CANCEL_OPTION。
使用实例：
（１）显示MessageDialog
JOptionPane.showMessageDialog(null, "在对话框内显示的描述性的文字", "标题条文字串", JOptionPane.ERROR_MESSAGE);
（２）显示ConfirmDialog
JOptionPane.showConfirmDialog(null, "choose one", "choose one", JOptionPane.YES_NO_OPTION);
（３）显示OptionDialog：该种对话框可以由用户自己来设置各个按钮的个数并返回用户点击各个按钮的序号（从0开始计数）
Object[] options = {"确定","取消","帮助"};
int response=JOptionPane.showOptionDialog(this, "这是个选项对话框，用户可以选择自己的按钮的个数", "选项对话框标题",JOptionPane.YES_OPTION, JOptionPane.QUESTION_MESSAGE, null, options, options[0]);
if(response==0)
{ this.setTitle("您按下了第OK按钮 ");
}
else if(response==1)
{ this.setTitle("您按下了第Cancel按钮 ");
}
else if(response==2)
{ this.setTitle("您按下了第Help按钮 ");
}
（４）显示InputDialog 以便让用户进行输入
String inputValue = JOptionPane.showInputDialog("Please input a value");
（５）显示InputDialog 以便让用户进行选择地输入
Object[] possibleValues = { "First", "Second", "Third" }; //用户的选择项目
Object selectedValue = JOptionPane.showInputDialog(null, "Choose one", "Input",JOptionPane.INFORMATION_MESSAGE, null, possibleValues, possibleValues[0]);
setTitle("您按下了"+(String)selectedValue+"项目");
<img src ="http://www.blogjava.net/jiangmin/aggbug/78525.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jiangmin/" target="_blank">JiangMin</a> 2006-11-01 17:45 <a href="http://www.blogjava.net/jiangmin/articles/78525.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>利用JAVA API写入remedy表单的方法</title><link>http://www.blogjava.net/jiangmin/articles/76139.html</link><dc:creator>JiangMin</dc:creator><author>JiangMin</author><pubDate>Thu, 19 Oct 2006 05:00:00 GMT</pubDate><guid>http://www.blogjava.net/jiangmin/articles/76139.html</guid><wfw:comment>http://www.blogjava.net/jiangmin/comments/76139.html</wfw:comment><comments>http://www.blogjava.net/jiangmin/articles/76139.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/jiangmin/comments/commentRss/76139.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jiangmin/services/trackbacks/76139.html</trackback:ping><description><![CDATA[又分享一个我的类,给刚做REMEDY的朋友提供帮助
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000">&nbsp;com.remedy.arsys.api.</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">;<br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000">&nbsp;java.util.</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">;<br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000">&nbsp;java.io.</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">;<br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top><br><img id=Codehighlighter1_93_2205_Open_Image onclick="this.style.display='none'; Codehighlighter1_93_2205_Open_Text.style.display='none'; Codehighlighter1_93_2205_Closed_Image.style.display='inline'; Codehighlighter1_93_2205_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_93_2205_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_93_2205_Closed_Text.style.display='none'; Codehighlighter1_93_2205_Open_Image.style.display='inline'; Codehighlighter1_93_2205_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;ARSWriter&nbsp;</span><span id=Codehighlighter1_93_2205_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"></span><span id=Codehighlighter1_93_2205_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000">&nbsp;String&nbsp;remedyServer;<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000">&nbsp;String&nbsp;remedyUserName;<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000">&nbsp;String&nbsp;remedyPassword;<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000">&nbsp;String&nbsp;remedyForm;<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000">&nbsp;ARServerUser&nbsp;serverUser&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">null</span><span style="COLOR: #000000">;<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;<br><img id=Codehighlighter1_332_859_Open_Image onclick="this.style.display='none'; Codehighlighter1_332_859_Open_Text.style.display='none'; Codehighlighter1_332_859_Closed_Image.style.display='inline'; Codehighlighter1_332_859_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_332_859_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_332_859_Closed_Text.style.display='none'; Codehighlighter1_332_859_Open_Image.style.display='inline'; Codehighlighter1_332_859_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;createARServerUser(String&nbsp;remedyform)&nbsp;</span><span id=Codehighlighter1_332_859_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"></span><span id=Codehighlighter1_332_859_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">.remedyForm</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">remedyform;<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;InputStream&nbsp;config&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">.getClass().getResourceAsStream(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">/ARSWriterConfig.properties</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Properties&nbsp;configp</span><span style="COLOR: #000000">=</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;Properties();<br><img id=Codehighlighter1_506_702_Open_Image onclick="this.style.display='none'; Codehighlighter1_506_702_Open_Text.style.display='none'; Codehighlighter1_506_702_Closed_Image.style.display='inline'; Codehighlighter1_506_702_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_506_702_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_506_702_Closed_Text.style.display='none'; Codehighlighter1_506_702_Open_Image.style.display='inline'; Codehighlighter1_506_702_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">try</span><span style="COLOR: #000000">&nbsp;</span><span id=Codehighlighter1_506_702_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"></span><span id=Codehighlighter1_506_702_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;configp.load(config);<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;remedyServer</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">configp.getProperty(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">remedyServer</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;remedyUserName</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">configp.getProperty(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">remedyUserName</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;remedyPassword</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">configp.getProperty(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">remedyPassword</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br><img id=Codehighlighter1_726_754_Open_Image onclick="this.style.display='none'; Codehighlighter1_726_754_Open_Text.style.display='none'; Codehighlighter1_726_754_Closed_Image.style.display='inline'; Codehighlighter1_726_754_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_726_754_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_726_754_Closed_Text.style.display='none'; Codehighlighter1_726_754_Open_Image.style.display='inline'; Codehighlighter1_726_754_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">catch</span><span style="COLOR: #000000">&nbsp;(IOException&nbsp;e)&nbsp;</span><span id=Codehighlighter1_726_754_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"></span><span id=Codehighlighter1_726_754_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e.printStackTrace();<br><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;serverUser&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;ARServerUser(remedyUserName,&nbsp;remedyPassword,&nbsp;</span><span style="COLOR: #000000">""</span><span style="COLOR: #000000">,<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;remedyServer);<br><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top><br><img id=Codehighlighter1_904_937_Open_Image onclick="this.style.display='none'; Codehighlighter1_904_937_Open_Text.style.display='none'; Codehighlighter1_904_937_Closed_Image.style.display='inline'; Codehighlighter1_904_937_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_904_937_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_904_937_Closed_Text.style.display='none'; Codehighlighter1_904_937_Open_Image.style.display='inline'; Codehighlighter1_904_937_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;ARServerUser&nbsp;getARServerUser()&nbsp;</span><span id=Codehighlighter1_904_937_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"></span><span id=Codehighlighter1_904_937_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;serverUser;<br><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top><br><img id=Codehighlighter1_992_1672_Open_Image onclick="this.style.display='none'; Codehighlighter1_992_1672_Open_Text.style.display='none'; Codehighlighter1_992_1672_Closed_Image.style.display='inline'; Codehighlighter1_992_1672_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_992_1672_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_992_1672_Closed_Text.style.display='none'; Codehighlighter1_992_1672_Open_Image.style.display='inline'; Codehighlighter1_992_1672_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;createEntry(EntryItem[]&nbsp;entryItems)&nbsp;</span><span id=Codehighlighter1_992_1672_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"></span><span id=Codehighlighter1_992_1672_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Entry&nbsp;entry&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">null</span><span style="COLOR: #000000">;<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top><br><img id=Codehighlighter1_1035_1490_Open_Image onclick="this.style.display='none'; Codehighlighter1_1035_1490_Open_Text.style.display='none'; Codehighlighter1_1035_1490_Closed_Image.style.display='inline'; Codehighlighter1_1035_1490_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_1035_1490_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_1035_1490_Closed_Text.style.display='none'; Codehighlighter1_1035_1490_Open_Image.style.display='inline'; Codehighlighter1_1035_1490_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">try</span><span style="COLOR: #000000">&nbsp;</span><span id=Codehighlighter1_1035_1490_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"></span><span id=Codehighlighter1_1035_1490_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;EntryFactory&nbsp;entryMan&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;EntryFactory.getFactory();<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;entry&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;(Entry)&nbsp;entryMan.newInstance();<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;entry.setContext(serverUser);<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;Get&nbsp;the&nbsp;schema&nbsp;name</span><span style="COLOR: #008000"><br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NameID&nbsp;name&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;NameID(</span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">.remedyForm);<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;entry.setSchemaID(name);<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;set&nbsp;the&nbsp;entry&nbsp;items<img src="http://www.blogjava.net/Images/dot.gif"></span><span style="COLOR: #008000"><br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;entry.setEntryItems(entryItems);<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;entry.create();<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;entryMan.releaseInstance(entry);<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top><br><img id=Codehighlighter1_1523_1597_Open_Image onclick="this.style.display='none'; Codehighlighter1_1523_1597_Open_Text.style.display='none'; Codehighlighter1_1523_1597_Closed_Image.style.display='inline'; Codehighlighter1_1523_1597_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_1523_1597_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_1523_1597_Closed_Text.style.display='none'; Codehighlighter1_1523_1597_Open_Image.style.display='inline'; Codehighlighter1_1523_1597_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">catch</span><span style="COLOR: #000000">&nbsp;(NullPointerException&nbsp;e)&nbsp;</span><span id=Codehighlighter1_1523_1597_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"></span><span id=Codehighlighter1_1523_1597_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Null&nbsp;Pointer&nbsp;exception<img src="http://www.blogjava.net/Images/dot.gif">\n</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br><img id=Codehighlighter1_1621_1666_Open_Image onclick="this.style.display='none'; Codehighlighter1_1621_1666_Open_Text.style.display='none'; Codehighlighter1_1621_1666_Closed_Image.style.display='inline'; Codehighlighter1_1621_1666_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_1621_1666_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_1621_1666_Closed_Text.style.display='none'; Codehighlighter1_1621_1666_Open_Image.style.display='inline'; Codehighlighter1_1621_1666_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">catch</span><span style="COLOR: #000000">&nbsp;(ARException&nbsp;e)&nbsp;</span><span id=Codehighlighter1_1621_1666_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"></span><span id=Codehighlighter1_1621_1666_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(e);<br><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top><br><img id=Codehighlighter1_1715_1722_Open_Image onclick="this.style.display='none'; Codehighlighter1_1715_1722_Open_Text.style.display='none'; Codehighlighter1_1715_1722_Closed_Image.style.display='inline'; Codehighlighter1_1715_1722_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_1715_1722_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_1715_1722_Closed_Text.style.display='none'; Codehighlighter1_1715_1722_Open_Image.style.display='inline'; Codehighlighter1_1715_1722_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;putData2BMC(String&nbsp;xml)&nbsp;</span><span id=Codehighlighter1_1715_1722_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"></span><span id=Codehighlighter1_1715_1722_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img id=Codehighlighter1_1760_2198_Open_Image onclick="this.style.display='none'; Codehighlighter1_1760_2198_Open_Text.style.display='none'; Codehighlighter1_1760_2198_Closed_Image.style.display='inline'; Codehighlighter1_1760_2198_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_1760_2198_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_1760_2198_Closed_Text.style.display='none'; Codehighlighter1_1760_2198_Open_Image.style.display='inline'; Codehighlighter1_1760_2198_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;sendtoARS(List&nbsp;list)</span><span id=Codehighlighter1_1760_2198_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"></span><span id=Codehighlighter1_1760_2198_Open_Text><span style="COLOR: #000000">{<br><img id=Codehighlighter1_1797_2186_Open_Image onclick="this.style.display='none'; Codehighlighter1_1797_2186_Open_Text.style.display='none'; Codehighlighter1_1797_2186_Closed_Image.style.display='inline'; Codehighlighter1_1797_2186_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_1797_2186_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_1797_2186_Closed_Text.style.display='none'; Codehighlighter1_1797_2186_Open_Image.style.display='inline'; Codehighlighter1_1797_2186_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">for</span><span style="COLOR: #000000">(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;i</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;i</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">list.size();i</span><span style="COLOR: #000000">++</span><span style="COLOR: #000000">)</span><span id=Codehighlighter1_1797_2186_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"></span><span id=Codehighlighter1_1797_2186_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Map&nbsp;map</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">(HashMap)list.get(i);<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;EntryItem[]&nbsp;entryItems&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;EntryItem[map.size()];<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Object[]&nbsp;keys</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;map.keySet().toArray();<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Object[]&nbsp;values</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">map.values().toArray();<br><img id=Codehighlighter1_2019_2143_Open_Image onclick="this.style.display='none'; Codehighlighter1_2019_2143_Open_Text.style.display='none'; Codehighlighter1_2019_2143_Closed_Image.style.display='inline'; Codehighlighter1_2019_2143_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_2019_2143_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_2019_2143_Closed_Text.style.display='none'; Codehighlighter1_2019_2143_Open_Image.style.display='inline'; Codehighlighter1_2019_2143_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">for</span><span style="COLOR: #000000">(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;j</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;j</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">map.size();j</span><span style="COLOR: #000000">++</span><span style="COLOR: #000000">)</span><span id=Codehighlighter1_2019_2143_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"></span><span id=Codehighlighter1_2019_2143_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;entryItems[j]&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;EntryItem(</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;FieldID(Integer.parseInt((String)keys[j])),&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;Value((String)values[j]));<br><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">.createEntry(entryItems);<br><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;<br><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span></div>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">ARSWriterConfig.properties<br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top>remedyServer&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">192.168</span><span style="COLOR: #000000">.</span><span style="COLOR: #000000">1.251</span><span style="COLOR: #000000"><br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top>remedyUserName&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">Demo<br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top>remedyPassword&nbsp;</span><span style="COLOR: #000000">=</span></div>
这里我用的是remedy 7.0的jar包,环境配置如下:arutil70.jar,arapi70.jar这两个jar包就是它的API,在将ARServer的根目录加入到path中，其中根目录中包含如下文件，如果你的你应用是用于WEB的那么把以下文件所在的目录加入到librarypath中也行.<br><img height=351 alt={A24A7A2C-2583-4BF0-9A13-293C6ED7D2DD}0.jpg src="http://www.blogjava.net/images/blogjava_net/jiangmin/{A24A7A2C-2583-4BF0-9A13-293C6ED7D2DD}0.jpg" width=585 border=0>这些文件和jar包可以从remedy服务器端得到. 
<img src ="http://www.blogjava.net/jiangmin/aggbug/76139.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jiangmin/" target="_blank">JiangMin</a> 2006-10-19 13:00 <a href="http://www.blogjava.net/jiangmin/articles/76139.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>利用Notes的JAVA api发送邮件(代码片段)</title><link>http://www.blogjava.net/jiangmin/articles/76137.html</link><dc:creator>JiangMin</dc:creator><author>JiangMin</author><pubDate>Thu, 19 Oct 2006 04:47:00 GMT</pubDate><guid>http://www.blogjava.net/jiangmin/articles/76137.html</guid><wfw:comment>http://www.blogjava.net/jiangmin/comments/76137.html</wfw:comment><comments>http://www.blogjava.net/jiangmin/articles/76137.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jiangmin/comments/commentRss/76137.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jiangmin/services/trackbacks/76137.html</trackback:ping><description><![CDATA[最近要编写一个利用Notes自动发送邮件的程序,研究一天终于OK了``在这里跟大家分享代码<br /><div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000"> lotus.domino.AgentBase;<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000"> lotus.domino.NotesException;<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000"> lotus.domino.NotesFactory;<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000"> lotus.domino.Session;<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /><br /><img id="Codehighlighter1_188_401_Open_Image" onclick="this.style.display='none'; Codehighlighter1_188_401_Open_Text.style.display='none'; Codehighlighter1_188_401_Closed_Image.style.display='inline'; Codehighlighter1_188_401_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="Codehighlighter1_188_401_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_188_401_Closed_Text.style.display='none'; Codehighlighter1_188_401_Open_Image.style.display='inline'; Codehighlighter1_188_401_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" align="top" /></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">abstract</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000"> EclipseAgentBase </span><span style="COLOR: #0000ff">extends</span><span style="COLOR: #000000"> AgentBase </span><span id="Codehighlighter1_188_401_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/images/dot.gif" /></span><span id="Codehighlighter1_188_401_Open_Text"><span style="COLOR: #000000">{<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" /><br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" /></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">abstract</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000"> sendMail(String text);<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" /><br /><img id="Codehighlighter1_264_399_Open_Image" onclick="this.style.display='none'; Codehighlighter1_264_399_Open_Text.style.display='none'; Codehighlighter1_264_399_Closed_Image.style.display='inline'; Codehighlighter1_264_399_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_264_399_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_264_399_Closed_Text.style.display='none'; Codehighlighter1_264_399_Open_Image.style.display='inline'; Codehighlighter1_264_399_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top" /></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000"> Session getSession() </span><span id="Codehighlighter1_264_399_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/images/dot.gif" /></span><span id="Codehighlighter1_264_399_Open_Text"><span style="COLOR: #000000">{<br /><img id="Codehighlighter1_270_309_Open_Image" onclick="this.style.display='none'; Codehighlighter1_270_309_Open_Text.style.display='none'; Codehighlighter1_270_309_Closed_Image.style.display='inline'; Codehighlighter1_270_309_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_270_309_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_270_309_Closed_Text.style.display='none'; Codehighlighter1_270_309_Open_Image.style.display='inline'; Codehighlighter1_270_309_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top" /></span><span style="COLOR: #0000ff">try</span><span style="COLOR: #000000"> </span><span id="Codehighlighter1_270_309_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/images/dot.gif" /></span><span id="Codehighlighter1_270_309_Open_Text"><span style="COLOR: #000000">{<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" /></span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000"> NotesFactory.createSession();<br /><img id="Codehighlighter1_336_397_Open_Image" onclick="this.style.display='none'; Codehighlighter1_336_397_Open_Text.style.display='none'; Codehighlighter1_336_397_Closed_Image.style.display='inline'; Codehighlighter1_336_397_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_336_397_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_336_397_Closed_Text.style.display='none'; Codehighlighter1_336_397_Open_Image.style.display='inline'; Codehighlighter1_336_397_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top" />}</span></span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">catch</span><span style="COLOR: #000000"> (NotesException e) </span><span id="Codehighlighter1_336_397_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/images/dot.gif" /></span><span id="Codehighlighter1_336_397_Open_Text"><span style="COLOR: #000000">{<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" /></span><span style="COLOR: #0000ff">throw</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000"> RuntimeException(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Unable to create session</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">, e);<br /><img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />}</span></span><span style="COLOR: #000000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />}</span></span><span style="COLOR: #000000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />}</span></span><span style="COLOR: #000000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /><br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span></div><div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000"> java.io.IOException;<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000"> java.io.InputStream;<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000"> java.util.Properties;<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /><br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000"> lotus.domino.NotesThread;<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000"> lotus.domino.Session;<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000"> lotus.domino.</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">; <br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /><br /><img id="Codehighlighter1_219_1307_Open_Image" onclick="this.style.display='none'; Codehighlighter1_219_1307_Open_Text.style.display='none'; Codehighlighter1_219_1307_Closed_Image.style.display='inline'; Codehighlighter1_219_1307_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="Codehighlighter1_219_1307_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_219_1307_Closed_Text.style.display='none'; Codehighlighter1_219_1307_Open_Image.style.display='inline'; Codehighlighter1_219_1307_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" align="top" /></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000"> MyAgent </span><span style="COLOR: #0000ff">extends</span><span style="COLOR: #000000"> EclipseAgentBase </span><span id="Codehighlighter1_219_1307_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/images/dot.gif" /></span><span id="Codehighlighter1_219_1307_Open_Text"><span style="COLOR: #000000">{<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" /><br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" /></span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000"> String sendname;<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" /></span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000"> String servername;<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" /></span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000"> String filepatch;<br /><img id="Codehighlighter1_316_811_Open_Image" onclick="this.style.display='none'; Codehighlighter1_316_811_Open_Text.style.display='none'; Codehighlighter1_316_811_Closed_Image.style.display='inline'; Codehighlighter1_316_811_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_316_811_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_316_811_Closed_Text.style.display='none'; Codehighlighter1_316_811_Open_Image.style.display='inline'; Codehighlighter1_316_811_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top" /></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000"> MyAgent()</span><span id="Codehighlighter1_316_811_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/images/dot.gif" /></span><span id="Codehighlighter1_316_811_Open_Text"><span style="COLOR: #000000">{<br /><img id="Codehighlighter1_326_754_Open_Image" onclick="this.style.display='none'; Codehighlighter1_326_754_Open_Text.style.display='none'; Codehighlighter1_326_754_Closed_Image.style.display='inline'; Codehighlighter1_326_754_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_326_754_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_326_754_Closed_Text.style.display='none'; Codehighlighter1_326_754_Open_Image.style.display='inline'; Codehighlighter1_326_754_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top" />    </span><span style="COLOR: #0000ff">try</span><span style="COLOR: #000000"> </span><span id="Codehighlighter1_326_754_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/images/dot.gif" /></span><span id="Codehighlighter1_326_754_Open_Text"><span style="COLOR: #000000">{<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />        InputStream in </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">.getClass().getResourceAsStream(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">/MailSystem.properties</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />        Properties props </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000"> Properties();<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />         props.load(in);<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />         </span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">.sendname</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">props.getProperty(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">sendname</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />         </span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">.servername</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">props.getProperty(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">servername</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />         </span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">.filepatch</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">props.getProperty(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">filepatch</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />         </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">System.out.println(sendname);<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />         </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">System.out.println(servername);<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />         </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">System.out.println(filepatch);</span><span style="COLOR: #008000"><br /><img id="Codehighlighter1_778_807_Open_Image" onclick="this.style.display='none'; Codehighlighter1_778_807_Open_Text.style.display='none'; Codehighlighter1_778_807_Closed_Image.style.display='inline'; Codehighlighter1_778_807_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_778_807_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_778_807_Closed_Text.style.display='none'; Codehighlighter1_778_807_Open_Image.style.display='inline'; Codehighlighter1_778_807_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top" /></span><span style="COLOR: #000000">    }</span></span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">catch</span><span style="COLOR: #000000"> (IOException e) </span><span id="Codehighlighter1_778_807_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/images/dot.gif" /></span><span id="Codehighlighter1_778_807_Open_Text"><span style="COLOR: #000000">{<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />        <br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />        e.printStackTrace();<br /><img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />    }</span></span><span style="COLOR: #000000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />    <br /><img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />}</span></span><span style="COLOR: #000000"><br /><img id="Codehighlighter1_847_1303_Open_Image" onclick="this.style.display='none'; Codehighlighter1_847_1303_Open_Text.style.display='none'; Codehighlighter1_847_1303_Closed_Image.style.display='inline'; Codehighlighter1_847_1303_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_847_1303_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_847_1303_Closed_Text.style.display='none'; Codehighlighter1_847_1303_Open_Image.style.display='inline'; Codehighlighter1_847_1303_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top" /></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000"> sendMail(String text) </span><span id="Codehighlighter1_847_1303_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/images/dot.gif" /></span><span id="Codehighlighter1_847_1303_Open_Text"><span style="COLOR: #000000">{<br /><img id="Codehighlighter1_853_1251_Open_Image" onclick="this.style.display='none'; Codehighlighter1_853_1251_Open_Text.style.display='none'; Codehighlighter1_853_1251_Closed_Image.style.display='inline'; Codehighlighter1_853_1251_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_853_1251_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_853_1251_Closed_Text.style.display='none'; Codehighlighter1_853_1251_Open_Image.style.display='inline'; Codehighlighter1_853_1251_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top" /></span><span style="COLOR: #0000ff">try</span><span style="COLOR: #000000"> </span><span id="Codehighlighter1_853_1251_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/images/dot.gif" /></span><span id="Codehighlighter1_853_1251_Open_Text"><span style="COLOR: #000000">{<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />    Session session </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">.getSession();<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />    System.out.println(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Username: </span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">+</span><span style="COLOR: #000000"> session.getUserName());<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />    Database   db</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">session.getDatabase(servername,filepatch,</span><span style="COLOR: #0000ff">true</span><span style="COLOR: #000000">);<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />    Document   domMail</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">db.createDocument();   <br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />    domMail.appendItemValue(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Form</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Memo</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);   <br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />    RichTextItem   body</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">domMail.createRichTextItem(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">body</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">); <br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" /><br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />    body.appendText(text);   <br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" /><br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />    domMail.send(sendname);   <br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />    System.out.println(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">done</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);   <br /><img id="Codehighlighter1_1273_1300_Open_Image" onclick="this.style.display='none'; Codehighlighter1_1273_1300_Open_Text.style.display='none'; Codehighlighter1_1273_1300_Closed_Image.style.display='inline'; Codehighlighter1_1273_1300_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_1273_1300_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_1273_1300_Closed_Text.style.display='none'; Codehighlighter1_1273_1300_Open_Image.style.display='inline'; Codehighlighter1_1273_1300_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top" />    }</span></span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">catch</span><span style="COLOR: #000000"> (Exception e) </span><span id="Codehighlighter1_1273_1300_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/images/dot.gif" /></span><span id="Codehighlighter1_1273_1300_Open_Text"><span style="COLOR: #000000">{<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />        e.printStackTrace();<br /><img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />        }</span></span><span style="COLOR: #000000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />    }</span></span><span style="COLOR: #000000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" /><br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" /><br /><img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />}</span></span></div><br /><p> </p><div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /><span style="COLOR: #000000">MailSystem.properties<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /><br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />sendname</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">jiangmin.java@gmail.com<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />servername</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">Dominosrv</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">MVS<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />filepatch</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">mail</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">jiangmin.nsf</span></div><p><br />这两个类就是完整的代码,调用sendMail()就可以发送邮件了,光有代码是不能发送的,现在我们来说说环境的搭建,首先要安装Lotus Notes客护端(我这个程序不是运行在本地的,也就是说它不和Lotus Notes服务器在一起的,我们需要远程访问),然后我们需要两个JAR包Notes.jar和NCSO.jar,把D:\lotus\notes加到patch路径下(也就是Notes的根目录),最后就是配置Notes客户端了,配置好了,一切OK```如果你关掉Notes客户端,那么该程序需要你输入密码,要想不用输入密码那么你就得一直看着客户端了(没办法).</p><img src ="http://www.blogjava.net/jiangmin/aggbug/76137.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jiangmin/" target="_blank">JiangMin</a> 2006-10-19 12:47 <a href="http://www.blogjava.net/jiangmin/articles/76137.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>DocumentBuilder的parse(InputStream is)为什么不能直接用Socket的getInputStream()来构造Document对象</title><link>http://www.blogjava.net/jiangmin/articles/75384.html</link><dc:creator>JiangMin</dc:creator><author>JiangMin</author><pubDate>Mon, 16 Oct 2006 04:06:00 GMT</pubDate><guid>http://www.blogjava.net/jiangmin/articles/75384.html</guid><wfw:comment>http://www.blogjava.net/jiangmin/comments/75384.html</wfw:comment><comments>http://www.blogjava.net/jiangmin/articles/75384.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jiangmin/comments/commentRss/75384.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jiangmin/services/trackbacks/75384.html</trackback:ping><description><![CDATA[因为最近在负责一个中银的接口小项目,要求用Socket来传输XML,遇到一个这样的问题,Server端个Client发送一个String="&lt;?xml version='1.0' encoding='GB2312'?&gt;&lt;Login ServerName='sdfs' IsSuccess='0' Result='sdf' AlarmLevel='sdf' /&gt;";类似上面格式的字符串,然后在Client解析为Document对象然后就出现了parse(getInputStream())这句话,运行后报错:Socket is close.然后查看parse()和getInputStream()的原码,都没有明显的说明其原因.其实真正的原因在与Socket的getInputStream()返回的是一个没有结束标志的InputStream,相信大家原来都用过Socket来传递过字符串```大家的代码中肯定有一个readLine()的方法,看到这里应该明白几分道理了吧```这里Socket关闭的原因就是构造Document的时候接受了一个无限长度的InputStream,所以Socket避免网络堵塞将其关闭.<br />如觉得解释欠妥请一起讨论<img src ="http://www.blogjava.net/jiangmin/aggbug/75384.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jiangmin/" target="_blank">JiangMin</a> 2006-10-16 12:06 <a href="http://www.blogjava.net/jiangmin/articles/75384.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>浅出Java Socket 编程</title><link>http://www.blogjava.net/jiangmin/articles/74396.html</link><dc:creator>JiangMin</dc:creator><author>JiangMin</author><pubDate>Tue, 10 Oct 2006 15:35:00 GMT</pubDate><guid>http://www.blogjava.net/jiangmin/articles/74396.html</guid><wfw:comment>http://www.blogjava.net/jiangmin/comments/74396.html</wfw:comment><comments>http://www.blogjava.net/jiangmin/articles/74396.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jiangmin/comments/commentRss/74396.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jiangmin/services/trackbacks/74396.html</trackback:ping><description><![CDATA[
		<div class="ContentFont" id="NewaspContentLabel" style="PADDING-RIGHT: 10px; DISPLAY: block; PADDING-LEFT: 10px; PADDING-BOTTOM: 0px; PADDING-TOP: 0px">
				<font id="font_word" style="FONT-SIZE: 14px; FONT-FAMILY: 宋体, Verdana, Arial, Helvetica, sans-serif">出于多种目的要写这篇文章,简单的说是因为最近的工作和Java 的Socket相关.所以工作之余就有了写点东西的想法.同样我不希望把文章写的太复杂,因此浅出自己的一点心得.<br />事实上<a class="wordstyle" href="http://www.newasp.cn/" target="_blank">网络</a>编程简单的理解就是两台计算机相互通讯数据而已.对于程序员而言,去掌握一种编程接口并使用一种编程模型相对就会显得简单的多了.Java SDK提供一些相对简单的Api来完成这些工作.Socket就是其中之一.对于Java而言.这些Api存在与java.net 这个包里面.因此只要导入这个包就可以准备<a class="wordstyle" href="http://www.newasp.cn/" target="_blank">网络</a>编程了.<br /><a class="wordstyle" href="http://www.newasp.cn/" target="_blank">网络</a>编程的基本模型就是客户机到服务器模型.简单的说就是两个进程之间相互通讯,然后其中一个必须提供一个固定的位置,而另一个则只需要知道这个固定的位置.并去建立两者之间的联系..然后完成数据的通讯就可以了.这里提供固定位置的通常称为服务器,而建立联系的通常叫做客户端.基于这个简单的模型,就可以进入<a class="wordstyle" href="http://www.newasp.cn/" target="_blank">网络</a>编程啦.<br />Java对这个模型的支持有很多种Api.而这里我只想介绍有关Socket的编程接口.对于Java而言已经简化了Socket的编程接口.首先我们来讨论有关提供固定位置的服务方是如何建立的.Java提供了ServerSocket来对其进行支持.事实上当你创建该类的一个实力对象并提供一个端口资源你就建立了一个固定位置可以让其他计算机来访问你.ServerSocket server=new  ServerSocket(6789);这里稍微要注意的是端口的分配必须是唯一的.因为端口是为了唯一标识每台计算机唯一服务的.另外端口号是从0~65535之间的,前1024个端口已经被Tcp/Ip 作为保留端口,因此你所分配的端口只能是1024个之后的.好了.我们有了固定位置.现在所需要的就是一根连接线了.该连接线由客户方首先提出要求.因此Java同样提供了一个Socket对象来对其进行支持.只要客户方创建一个Socket的实例对象进行支持就可以了.Socket client<br />=new Socket(InetAddress.getLocalHost(),5678);客户机必须知道有关服务器的IP地址.对于着一点Java也提供了一个相关的类InetAddress 该对象的实例必须通过它的静态方法来提供.它的静态方法主要提供了得到本机IP 和通过名字或IP直接得到InetAddress的方法.<br />好了.上面的方法基本可以建立一条连线让两台计算机相互交流了.可是数据是如何传输的呢?事实上I/O操作总是和<a class="wordstyle" href="http://www.newasp.cn/" target="_blank">网络</a>编程息息相关的.因为底层的<a class="wordstyle" href="http://www.newasp.cn/" target="_blank">网络</a>是继续数据的.除非远程调用,处理问题的核心在执行上.否则数据的交互还是依赖于I\O操作的.所以你也必须导入java.io这个包.java的IO操作也不复杂.它提供了针对于字节流和Unicode的读者和写者,然后也提供了一个缓冲用于数据的读写.<br />  BufferedReader in=new BufferedReader(new InputStreamReader(server.getInputStream()));<br />  PrintWriter out=new PrintWriter(server.getOutputStream()); 
<p>上面两句就是建立缓冲并把原始的字节流转变为Unicode可以操作.而原始的字节流来源于Socket的两个方法.getInputStream()和getOutputStream()方.分别用来得到输入和输出.那么现在有了基本的模型和基本的操作工具.我们可以做一个简单的Socket例程了.<br />服务方:<br />import java.io.*;<br />import java.net.*;</p><p>public class MyServer {<br /> public static void main(String[] args) throws IOException{<br />  ServerSocket server=new ServerSocket(5678);<br />  Socket client=server.accept();<br />BufferedReader in=new BufferedReader(new InputStreamReader(client.getInputStream()));<br />PrintWriter out=new PrintWriter(client.getOutputStream());<br />while(true){<br /> String str=in.readLine();<br />System.out.println(str);<br /> out.println("has receive....");<br /> out.flush();<br /> if(str.equals("end"))<br /> break;<br />}<br />client.close();<br /> } <br />}</p><p>这个程序的主要目的在于服务器不断接收客户机所写入的信息只到.客户机发送"End"字符串就退出程序.并且服务器也会做出"Receive"为回应.告知客户机已接收到消息.</p><p>客户机代码:<br />import java.net.*;<br />import java.io.*;</p><p>public class Client{<br /> static Socket server;<br /> <br /> public static void main(String[] args)throws Exception{<br />  server=new Socket(InetAddress.getLocalHost(),5678);<br />  BufferedReader in=new BufferedReader(new InputStreamReader(server.getInputStream()));<br />  PrintWriter out=new PrintWriter(server.getOutputStream());<br />  BufferedReader wt=new BufferedReader(new InputStreamReader(System.in));<br />  <br />  while(true){<br />   String str=wt.readLine();<br />   out.println(str);<br />   out.flush();<br />   if(str.equals("end")){<br />    break;<br />   }<br />   System.out.println(in.readLine());<br />  }<br />  server.close();<br /> }<br />}</p><p>客户机代码则是接受客户键盘输入,并把该信息输出,然后输出"End"用来做退出标识.</p><p>这个程序只是简单的两台计算机之间的通讯.如果是多个客户同时访问一个服务器呢?你可以试着再运行一个客户端,结果是会抛出异常的.那么多个客户端如何实现呢?</p><p>其实,简单的分析一下,就可以看出客户和服务通讯的主要通道就是Socket本身.而服务器通过accept方法就是同意和客户建立通讯.这样当客户建立Socket的同时.服务器也会使用这一根连线来先后通讯.那么既然如此只要我们存在多条连线就可以了.那么我们的程序可以变为如下:</p><p>服务器:</p><p>import java.io.*;<br />import java.net.*;</p><p>public class MyServer {<br /> public static void main(String[] args) throws IOException{<br />  ServerSocket server=new ServerSocket(5678);<br />while(true){<br />  Socket client=server.accept();<br />BufferedReader in=new BufferedReader(new InputStreamReader(client.getInputStream()));<br />PrintWriter out=new PrintWriter(client.getOutputStream());<br />while(true){<br /> String str=in.readLine();<br />System.out.println(str);<br /> out.println("has receive....");<br /> out.flush();<br /> if(str.equals("end"))<br /> break;<br />}<br />client.close();<br />}<br /> } <br />}</p><p>这里仅仅只是加了一个外层的While循环.这个循环的目的就是当一个客户进来就为它分配一个Socket直到这个客户完成一次和服务器的交互,这里也就是接受到客户的"End"消息.那么现在就实现了多客户之间的交互了.但是.问题又来了.这样做虽然解决了多客户,可是是排队执行的.也就是说当一个客户和服务器完成一次通讯之后下一个客户才可以进来和服务器交互.无法做到同时服务.那么要如何才能同时达到既能相互之间交流又能同时交流呢?很显然这是一个并行执行的问题了.所以线程是最好的解决方案.<br />那么下面的问题是如何使用线程.首先要做的事情是创建线程并使得其可以和<a class="wordstyle" href="http://www.newasp.cn/" target="_blank">网络</a>连线取得联系.然后由线程来执行刚才的操作.要创建线程要么直接继承Thread要么实现Runnable接口,要建立和Socket的联系只要传递引用就可以了.而要执行线程就必须重写run方法.而run方法所做的事情.就是刚才单线程版本main所做的事情.因此我们的程序变成了这样:<br />import java.net.*;<br />import java.io.*;</p><p>public class MultiUser extends Thread{<br /> private Socket client;<br /> <br /> public MultiUser(Socket c){<br />  this.client=c;<br /> }<br /> <br /> public void run(){<br />  try{   <br />   BufferedReader in=new BufferedReader(new InputStreamReader(client.getInputStream()));<br />   PrintWriter out=new PrintWriter(client.getOutputStream());<br />    //Mutil User but can't parallel<br />    while(true){<br />     String str=in.readLine();<br />     System.out.println(str);<br />     out.println("has receive....");<br />     out.flush();<br />     if(str.equals("end"))<br />      break;<br />    }<br />   client.close();  <br />   }catch(IOException ex){<br />   }finally{<br />    <br />   }<br /> }<br /> <br /> public static void main(String[] args)throws IOException{<br />  ServerSocket server=new ServerSocket(5678);<br />  while(true){<br />   //transfer location change Single User or Multi User<br />   MultiUser mu=new MultiUser(server.accept());<br />   mu.start();<br />  }<br /> }<br />}</p><p>我的类直接从Thread类继承了下来.并且通过构造函数传递引用和客户Socket建立了联系.这样每个线程就有了.一个通讯管道.同样我们可以填写run方法.把之前的操作交给线程来完成.这样多客户并行的Socket就建立起来了.</p><p>我的文章写完了.虽然我的文章到这里就结束了.可是要和Java的Socket相关的操作还有很多.各位大侠继续努力吧....</p></font>
		</div>
<img src ="http://www.blogjava.net/jiangmin/aggbug/74396.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jiangmin/" target="_blank">JiangMin</a> 2006-10-10 23:35 <a href="http://www.blogjava.net/jiangmin/articles/74396.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>DOM例子</title><link>http://www.blogjava.net/jiangmin/articles/74231.html</link><dc:creator>JiangMin</dc:creator><author>JiangMin</author><pubDate>Tue, 10 Oct 2006 02:25:00 GMT</pubDate><guid>http://www.blogjava.net/jiangmin/articles/74231.html</guid><wfw:comment>http://www.blogjava.net/jiangmin/comments/74231.html</wfw:comment><comments>http://www.blogjava.net/jiangmin/articles/74231.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jiangmin/comments/commentRss/74231.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jiangmin/services/trackbacks/74231.html</trackback:ping><description><![CDATA[XML作为全球通用的结构化语言，越来越受人们青睐，各种开发平台（比如Microsoft Studio系列、Oracle系列、Inprise Borland系列等）也都把支持XML开发作为宣传口号之一 。由于笔者所从事的电子政务开发较早的引入了XML,所以尝到了许多甜头，在许多项目中利用XML数据交换信息，省去了许多麻烦事，不用制定繁锁的数据格式，利用XML数据易于表达，也利于一线开发者跟踪调试。 <br />笔者先前也曾发表过相关的文章，比如《简析Delphi中的XML编程》一文，有兴趣的读者可以到Google网（http://www.google.com）去搜索一下，有很多媒体转载。今天笔者想探讨的是关于JAVA中的XML编程，希望对正在或想要学习XML编程的新老读者有所帮助。 <br />在XML应用中，最常用也最实用的莫过于XML文件的读写，所以笔者通过一个简单的XML文件读写来作简要分析。可以在任何文本编辑器中先建立如下结构的XML文件，类似于HTML结构，但XML语义比较严格，起始标记必须配对，比如"〈学生花名册〉"与"〈／学生花名册〉"对应，空格多少可不必在意，但一般都以缩格形式书写，便于阅读。把此文件命名为Input.xml，可以在任何支持XML的浏览器中打开测试一下，如果输入正确，在浏览中可以看到此文件的树形表示结构。如果您还对XML结构感到比较陌生，建议先看看《简析Delphi中的XML编程》一文中关于XML文件的说明。 <br />Input.xml <br /><table cellspacing="1" cellpadding="3" width="&quot;90%&quot;" align="center" border="0"><tbody><tr><td><b>代码:</b></td></tr><tr><td class="code"><br />&lt;?xml version="1.0" encoding="GB2312"?&gt; <br />&lt;学生花名册&gt; <br />&lt;学生 性别 = "男"&gt; <br />&lt;姓名&gt;李华&lt;/姓名&gt; <br />&lt;年龄&gt;14&lt;/年龄&gt; <br />&lt;电话&gt;6287555&lt;/电话&gt; <br />&lt;/学生&gt; <br />&lt;学生 性别 = "男"&gt; <br />&lt;姓名&gt;张三&lt;/姓名&gt; <br />&lt;年龄&gt;16&lt;/年龄&gt; <br />&lt;电话&gt;8273425&lt;/电话&gt; <br />&lt;/学生&gt; <br />&lt;/学生花名册&gt; <br /></td></tr></tbody></table><br />准备工作做完后，接着就开始写实质性的JAVA代码了。为保存从XML文件读入的信息，需要先建一个简单的Bean来保存学生信息，命名为StudentBean，代码如下所示： <br />StudentBean.java <br /><table cellspacing="1" cellpadding="3" width="&quot;90%&quot;" align="center" border="0"><tbody><tr><td><b>代码:</b></td></tr><tr><td class="code"><br />public class StudentBean { <br />private String sex; //学生性别 <br />private String name; //学生姓名 <br />private int age; //学生年龄 <br />private String phone; //电话号码 <br /><br />public void setSex(String s) { <br />sex = s; <br />} <br />public void setName(String s) { <br />name = s; <br />} <br />public void setAge(int a) { <br />age = a; <br />} <br />public void setPhone(String s) { <br />phone = s; <br />} <br />public String getSex() { <br />return sex; <br />} <br />public String getName() { <br />return name; <br />} <br />public int getAge() { <br />return age; <br />} <br />public String getPhone() { <br />return phone; <br />} <br />} <br /></td></tr></tbody></table><br />之后写XML的测试类， <br />TESTXml.java <br /><table cellspacing="1" cellpadding="3" width="&quot;90%&quot;" align="center" border="0"><tbody><tr><td><b>代码:</b></td></tr><tr><td class="code"><br /><br />import java.io.*; //Java基础包，包含各种IO操作 <br />import java.util.*; //Java基础包，包含各种标准数据结构操作 <br />import javax.xml.parsers.*; //XML解析器接口 <br />import org.w3c.dom.*; //XML的DOM实现 <br />import org.apache.crimson.tree.XmlDocument; //写XML文件要用到 <br /><br />public class XMLTest { <br />      Vector student_Vector; <br />      XMLTest() { <br /><br />      } <br /><br />//为了保存多个学生信息，还得借助一个集合类(并不是单纯意义上的集合，JAVA中的集合是集合框架的概念，包含向量、列表、哈希表等），这里采用Vector向量类。定义在XMLTest测试类中，命名为student_Vector。然后定义两个方法readXMLFile和writeXMLFile，实现读写操作。代码如下： <br />      private void readXMLFile(String inFile) throws Exception { <br />//为解析XML作准备，创建DocumentBuilderFactory实例,指定DocumentBuilder <br />            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); <br />            DocumentBuilder db = null; <br />            try { <br />                  db = dbf.newDocumentBuilder(); <br />            } <br />            catch (ParserConfigurationException pce) { <br />                  System.err.println(pce); //出异常时输出异常信息，然后退出，下同 <br />                  System.exit(1); <br />            } <br /><br />            Document doc = null; <br />            try { <br />                  doc = db.parse(inFile); <br />            } <br />            catch (DOMException dom) { <br />                  System.err.println(dom.getMessage()); <br />                  System.exit(1); <br />            } <br />            catch (IOException ioe) { <br />                  System.err.println(ioe); <br />                  System.exit(1); <br />            } <br />//下面是解析XML的全过程，比较简单，先取根元素"学生花名册" <br />            Element root = doc.getDocumentElement(); <br />//取"学生"元素列表 <br />            NodeList students = root.getElementsByTagName("学生"); <br />            for (int i = 0; i &lt; students.getLength(); i++) { <br />//依次取每个"学生"元素 <br />                  Element student = (Element) students.item(i); <br />//创建一个学生的Bean实例 <br />                  StudentBean studentBean = new StudentBean(); <br />//取学生的性别属性 <br />                  studentBean.setSex(student.getAttribute("性别")); <br />//取"姓名"元素，下面类同 <br />                  NodeList names = student.getElementsByTagName("姓名"); <br />                  if (names.getLength() == 1) { <br />                        Element e = (Element) names.item(0); <br />                        Text t = (Text) e.getFirstChild(); <br />                        studentBean.setName(t.getNodeValue()); <br />                  } <br /><br />                  NodeList ages = student.getElementsByTagName("年龄"); <br />                  if (ages.getLength() == 1) { <br />                        Element e = (Element) ages.item(0); <br />                        Text t = (Text) e.getFirstChild(); <br />                        studentBean.setAge(Integer.parseInt(t.getNodeValue())); <br />                  } <br /><br />                  NodeList phones = student.getElementsByTagName("电话"); <br />                  if (phones.getLength() == 1) { <br />                        Element e = (Element) phones.item(0); <br />                        Text t = (Text) e.getFirstChild(); <br />                        studentBean.setPhone(t.getNodeValue()); <br />                  } <br /><br />                  student_Vector.add(studentBean); <br />            } <br />      } <br /><br />      private void writeXMLFile(String outFile) throws Exception { <br />//为解析XML作准备，创建DocumentBuilderFactory实例,指定DocumentBuilder <br />            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); <br />            DocumentBuilder db = null; <br />            try { <br />                  db = dbf.newDocumentBuilder(); <br />            } <br />            catch (ParserConfigurationException pce) { <br />                  System.err.println(pce); <br />                  System.exit(1); <br />            } <br /><br />            Document doc = null; <br />            doc = db.newDocument(); <br /><br />//下面是建立XML文档内容的过程，先建立根元素"学生花名册" <br />            Element root = doc.createElement("学生花名册"); <br />//根元素添加上文档 <br />            doc.appendChild(root); <br /><br />//取学生信息的Bean列表 <br />            for (int i = 0; i &lt; student_Vector.size(); i++) { <br />//依次取每个学生的信息 <br />                  StudentBean studentBean = (StudentBean) student_Vector.get(i); <br />//建立"学生"元素，添加到根元素 <br />                  Element student = doc.createElement("学生"); <br />                  student.setAttribute("性别", studentBean.getSex()); <br />                  root.appendChild(student); <br />//建立"姓名"元素，添加到学生下面，下同 <br />                  Element name = doc.createElement("姓名"); <br />                  student.appendChild(name); <br />                  Text tName = doc.createTextNode(studentBean.getName()); <br />                  name.appendChild(tName); <br /><br />                  Element age = doc.createElement("年龄"); <br />                  student.appendChild(age); <br />                  Text tAge = doc.createTextNode(String.valueOf(studentBean. <br />                              getAge())); <br />                  age.appendChild(tAge); <br /><br />                  Element phone = doc.createElement("电话"); <br />                  student.appendChild(phone); <br />                  Text tPhone = doc.createTextNode(studentBean.getPhone()); <br />                  phone.appendChild(tPhone); <br />            } <br />//把XML文档输出到指定的文件 <br />            FileOutputStream outStream = new FileOutputStream(outFile); <br />            OutputStreamWriter outWriter = new OutputStreamWriter(outStream); <br />            ( (XmlDocument) doc).write(outWriter, "GB2312"); <br />            outWriter.close(); <br />            outStream.close(); <br />      } <br /><br />//最后加入测试主函数，如下： <br />      public static void main(String[] args) throws Exception { <br />//建立测试实例 <br />            XMLTest xmlTest = new XMLTest(); <br />//初始化向量列表 <br />            xmlTest.student_Vector = new Vector(); <br /><br />            System.out.println("开始读Input.xml文件"); <br />            xmlTest.readXMLFile("Input.xml"); <br /><br />            System.out.println("读入完毕,开始写Output.xml文件"); <br />            xmlTest.writeXMLFile("Output.xml"); <br />            System.out.println("写入完成"); <br />            System.in.read(); <br />      } <br />} </td></tr></tbody></table><br />了，保存好StudentBean和XMLTest，把Input.xml保存到工作目录下。如果您输入很仔细，没敲错字母的话，可以看到"写入完成"了，去瞧瞧Output.xml文件和Input.xml文件是不是一样吧。如果您在调试过程中发现有什么问题，欢迎通过E-Mail：nbDeveloper@hotmail.com与笔者取得联系。 [/code]<img src ="http://www.blogjava.net/jiangmin/aggbug/74231.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jiangmin/" target="_blank">JiangMin</a> 2006-10-10 10:25 <a href="http://www.blogjava.net/jiangmin/articles/74231.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JAVA中的静态方法和非静态方法的继承覆盖问题</title><link>http://www.blogjava.net/jiangmin/articles/69386.html</link><dc:creator>JiangMin</dc:creator><author>JiangMin</author><pubDate>Wed, 13 Sep 2006 07:20:00 GMT</pubDate><guid>http://www.blogjava.net/jiangmin/articles/69386.html</guid><wfw:comment>http://www.blogjava.net/jiangmin/comments/69386.html</wfw:comment><comments>http://www.blogjava.net/jiangmin/articles/69386.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.blogjava.net/jiangmin/comments/commentRss/69386.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jiangmin/services/trackbacks/69386.html</trackback:ping><description><![CDATA[首先看一个JAVA文件:Test.java<br /><br /><div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: rgb(0, 0, 255);">class</span><span style="color: rgb(0, 0, 0);"> A{<br />    </span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">static</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);"> testP(){<br />       System.out.println(</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">A</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">);<br />       }<br />    </span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);"> testM(){<br />       System.out.println(</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">X</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">);<br />       }<br />}<br /><br /></span><span style="color: rgb(0, 0, 255);">class</span><span style="color: rgb(0, 0, 0);"> B </span><span style="color: rgb(0, 0, 255);">extends</span><span style="color: rgb(0, 0, 0);"> A{<br />    </span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">static</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);"> testP(){<br />       System.out.println(</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">B</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">);<br />       }<br />    </span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);"> testM(){<br />       System.out.println(</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">Y</span><span style="color: rgb(0, 0, 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);"> </span><span style="color: rgb(0, 0, 255);">class</span><span style="color: rgb(0, 0, 0);"> Test{<br />    </span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">static</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);"> main(String[] args){<br />       A a</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);"> A();<br />       B b</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);"> B();<br />       a.testP();</span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">结果是 A</span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);">       b.testP();</span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">结果是 B</span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);">       a.testM();</span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">结果是 X</span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);">       b.testM();</span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">结果是 Y</span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);">       a</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">b;<br />       a.testP();</span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">结果是  A</span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);">       b.testP();</span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">结果是  B</span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);">       a.testM();</span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">结果是  Y</span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);">       b.testM();</span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">结果是  Y</span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);">       }<br />}</span></div>大家可以看到结果，但是为什么会这个样子呢？下面我就试着来解释一下这个问题：<br />    大家都知道非静态方法的继承覆盖的原则，即向上转型时从他的实例中可而已看出来，但是静态方法却不是像非静态方法那样工作，虽然静态方法可以被继承但是为什么不能覆盖呢？<br />    原因是这样的，静态方法跟其他非静态方法不一样的区别在于静态方法不用NEW一个实例就可以调用的，即它的调用是根据他的类型来判断的，所以我总结一句话就是：静态方法的继承和覆盖是跟着引用类型的，而非静态方法是跟着实例本身的。<br />    这里只给出我个人观点，希望大家来评论评论！<br /><img src ="http://www.blogjava.net/jiangmin/aggbug/69386.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jiangmin/" target="_blank">JiangMin</a> 2006-09-13 15:20 <a href="http://www.blogjava.net/jiangmin/articles/69386.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java理论与实践: 用动态代理进行修饰</title><link>http://www.blogjava.net/jiangmin/articles/68949.html</link><dc:creator>JiangMin</dc:creator><author>JiangMin</author><pubDate>Mon, 11 Sep 2006 06:07:00 GMT</pubDate><guid>http://www.blogjava.net/jiangmin/articles/68949.html</guid><wfw:comment>http://www.blogjava.net/jiangmin/comments/68949.html</wfw:comment><comments>http://www.blogjava.net/jiangmin/articles/68949.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jiangmin/comments/commentRss/68949.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jiangmin/services/trackbacks/68949.html</trackback:ping><description><![CDATA[动态代理为实现许多常见设计模式（包括 Facade、Bridge、Interceptor、Decorator、Proxy（包括远程和虚拟代理）和 Adapter 模式）提供了替代的动态机制。虽然这些模式不使用动态代理，只用普通的类就能够实现，但是在许多情况下，动态代理方式更方便、更紧凑，可以清除许多手写或生成的类。<br />　　<br />　　<b>Proxy 模式</b><br />　　<br />　　Proxy 模式中要创建“stub”或“surrogate”对象，它们的目的是接受请求并把请求转发到实际执行工作的其他对象。远程方法调用（RMI）利用 Proxy 模式，使得在其他 JVM 中执行的对象就像本地对象一样；<a href="http://www.cooledu.cn/"><font color="#000000">企业</font></a><font color="#000000"></font><a href="http://www.cooledu.cn/"><font color="#000000">Java</font></a>Beans （EJB）利用 Proxy 模式添加远程调用、<a href="http://www.cooledu.cn/"><font color="#000000">安全</font></a>性和事务分界；而 JAX-RPC Web 服务则用 Proxy 模式让远程服务表现得像本地对象一样。在每一种情况中，潜在的远程对象的行为是由接口定义的，而接口本质上接受多种实现。调用者（在大多数情况下）不能区分出它们只是持有一个对 stub 而不是实际对象的引用，因为二者实现了相同的接口；stub 的工作是查找实际的对象、封送参数、把参数发送给实际对象、解除封送返回值、把返回值返回给调用者。代理可以用来提供远程控制（就像在 RMI、EJB 和 JAX-RPC 中那样），用安全性策略包装对象（EJB）、为昂贵的对象（EJB 实体 Bean）提供惰性装入，或者添加检测工具（例如日志记录）。<br />　　<br />　　在 5.0 以前的 JDK 中，RMI stub（以及它对等的 skeleton）是在编译时由 RMI 编译器（rmic）生成的类，RMI 编译器是 JDK 工具集的一部分。对于每个远程接口，都会生成一个 stub（代理）类，它代表远程对象，还生成一个 skeleton 对象，它在远程 JVM 中做与 stub 相反的工作 —— 解除封送参数并调用实际的对象。类似地，用于 Web 服务的 JAX-RPC 工具也为远程 Web 服务生成代理类，从而使远程 Web 服务看起来就像本地对象一样。<br />　　<br />　　不管 stub 类是以源代码还是以字节码生成的，代码生成仍然会向编译过程添加一些额外步骤，而且因为命名相似的类的泛滥，会带来意义模糊的可能性。另一方面，动态代理机制支持在编译时没有生成 stub 类的情况下，在运行时创建代理对象。在 JDK 5.0 及以后版本中，RMI 工具使用动态代理代替了生成的 stub，结果 RMI 变得更容易使用。许多 J2EE 容器也使用动态代理来实现 EJB。EJB 技术严重地依靠使用拦截（interception）来实现安全性和事务分界；动态代理为接口上调用的所有方法提供了集中的控制流程路径。<br />　　<br />　　<b>动态代理机制</b><br />　　<br />　　动态代理机制的核心是 InvocationHandler 接口，如清单 1 所示。调用句柄的工作是代表动态代理实际执行所请求的方法调用。传递给调用句柄一个 Method 对象（从 java.lang.reflect 包），参数列表则传递给方法；在最简单的情况下，可能仅仅是调用反射性的方法 Method.invoke() 并返回结果。<br />　　<br />　　清单 1. InvocationHandler 接口<br />　　<br />　　public interface InvocationHandler {<br />　　Object invoke(Object proxy, Method method, Object[] args)<br />　　throws Throwable;<br />　　}<br />　　<br />　　每个代理都有一个与之关联的调用句柄，只要代理的方法被调用时就会调用该句柄。根据通用的设计原则：接口定义类型、类定义实现，代理对象可以实现一个或多个接口，但是不能实现类。因为代理类没有可以访问的名称，它们不能有构造函数，所以它们必须由工厂创建。清单 2 显示了动态代理的最简单的可能实现，它实现 Set 接口并把所有 Set 方法（以及所有 Object 方法）分派给封装的 Set 实例。<br />　　<br />　　清单 2. 包装 Set 的简单的动态代理<br />　　<br />　　public class SetProxyFactory {<br />　　<br />　　public static Set getSetProxy(final Set s) {<br />　　return (Set) Proxy.newProxyInstance<br />　　(s.getClass().getClassLoader(),<br />　　new Class[] { Set.class },<br />　　new InvocationHandler() {<br />　　public Object invoke(Object proxy, Method method,<br />　　Object[] args) throws Throwable {<br />　　return method.invoke(s, args);<br />　　}<br />　　});<br />　　}<br />　　}<br />　　<br />　　SetProxyFactory 类包含一个静态工厂方法 getSetProxy()，它返回一个实现了 Set 的动态代理。代理对象实际实现 Set —— 调用者无法区分（除非通过反射）返回的对象是动态代理。SetProxyFactory 返回的代理只做一件事，把方法分派给传递给工厂方法的 Set 实例。虽然反射代码通常比较难读，但是这里的内容很少，跟上控制流程并不难 —— 只要某个方法在 Set 代理上被调用，它就被分派给调用句柄，调用句柄只是反射地调用底层包装的对象上的目标方法。当然，绝对什么都不做的代理可能有点傻，是不是呢？<br />　　<br />　　<b>什么都不做的适配器</b><br />　　<br />　　对于像 SetProxyFactory 这样什么都不做的包装器来说，实际有个很好的应用 —— 可以用它安全地把对象引用的范围缩小到特定接口（或接口集）上，方式是，调用者不能提升引用的类型，使得可以更安全地把对象引用传递给不受信任的代码（例如插件或回调）。清单 3 包含一组类定义，实现了典型的回调场景。从中会看到动态代理可以更方便地替代通常用手工（或用 IDE 提供的代码生成向导）实现的 Adapter 模式。<br />　　<br />　　清单 3. 典型的回调场景<br />　　<br />　　public interface ServiceCallback {<br />　　public void doCallback();<br />　　}<br />　　<br />　　public interface Service {<br />　　public void serviceMethod(ServiceCallback callback);<br />　　}<br />　　<br />　　public class ServiceConsumer implements ServiceCallback {<br />　　private Service service;<br />　　<br />　　...<br />　　public void someMethod() {<br />　　...<br />　　service.serviceMethod(this);<br />　　}<br />　　}<br />　　<br />　　ServiceConsumer 类实现了 ServiceCallback（这通常是支持回调的一个方便途径）并把 this 引用传递给 serviceMethod() 作为回调引用。这种方法的问题是没有机制可以阻止 Service 实现把 ServiceCallback 提升为 ServiceConsumer，并调用 ServiceConsumer 不希望 Service 调用的方法。有时对这个风险并不关心 —— 但有时却关心。如果关心，那么可以把回调对象作为内部类，或者编写一个什么都不做的适配器类（请参阅清单 4 中的 ServiceCallbackAdapter）并用 ServiceCallbackAdapter 包装 ServiceConsumer。ServiceCallbackAdapter 防止 Service 把 ServiceCallback 提升为 ServiceConsumer。<br />　　<br />　　清单 4. 用于安全地把对象限制在一个接口上以便不被恶意代码不能的适配器类<br />　　<br />　　public class ServiceCallbackAdapter implements ServiceCallback {<br />　　private final ServiceCallback cb;<br />　　<br />　　public ServiceCallbackAdapter(ServiceCallback cb) {<br />　　this.cb = cb;<br />　　}<br />　　<br />　　public void doCallback() {<br />　　cb.doCallback();<br />　　}<br />　　}<br />　　<br />　　编写 ServiceCallbackAdapter 这样的适配器类简单却乏味。必须为包装的接口中的每个方法编写重定向类。在 ServiceCallback 的示例中，只有一个需要实现的方法，但是某些接口，例如 Collections 或 JDBC 接口，则包含许多方法。现代的 IDE 提供了“Delegate Methods”向导，降低了编写适配器类的工作量，但是仍然必须为每个想要包装的接口编写一个适配器类，而且对于只包含生成的代码的类，也有一些让人不满意的地方。看起来应当有一种方式可以更紧凑地表示“什么也不做的限制适配器模式”。<br />　　<br />　　<b>通用适配器类</b><br />　　<br />　　清单 2 中的 SetProxyFactory 类当然比用于 Set 的等价的适配器类更紧凑，但是它仍然只适用于一个接口：Set。但是通过使用泛型，可以容易地创建通用的代理工厂，由它为任何接口做同样的工作，如清单 5 所示。它几乎与 SetProxyFactory 相同，但是可以适用于任何接口。现在再也不用编写限制适配器类了！如果想创建代理对象安全地把对象限制在接口 T，只要调用 getProxy(T.class,object) 就可以了，不需要一堆适配器类的额外累赘。<br />　　<br />　　清单 5. 通用的限制适配器工厂类<br />　　<br />　　public class GenericProxyFactory {<br />　　<br />　　public static&lt;T&gt; T getProxy(Class&lt;T&gt; intf,<br />　　final T obj) {<br />　　return (T)<br />　　Proxy.newProxyInstance(obj.getClass().getClassLoader(),<br />　　new Class[] { intf },<br />　　new InvocationHandler() {<br />　　public Object invoke(Object proxy, Method method,<br />　　Object[] args) throws Throwable {<br />　　return method.invoke(obj, args);<br />　　}<br />　　});<br />　　}<br />　　}<br /><br /><p></p><strong>动态代理作为 Decorator<br /></strong>　　<br />　　当然，动态代理工具能做的，远不仅仅是把对象类型限制在特定接口上。从 清单 2 和 清单 5 中简单的限制适配器到 Decorator 模式，是一个小的飞跃，在 Decorator 模式中，代理用额外的功能（例如<a href="http://www.cooledu.cn/">安全</a>检测或日志记录）包装调用。清单 6 显示了一个日志 InvocationHandler，它在调用目标对象上的方法之外，还写入一条日志信息，显示被调用的方法、传递的参数，以及返回值。除了反射性的 invoke() 调用之外，这里的全部代码只是生成调试信息的一部分 —— 还不是太多。代理工厂方法的代码几乎与 GenericProxyFactory 相同，区别在于它使用的是 LoggingInvocationHandler 而不是匿名的调用句柄。<br />　　<br />　　清单 6. 基于代理的 Decorator，为每个方法调用生成调试日志<br />　　<br />　　private static class LoggingInvocationHandler&lt;T&gt;<br />　　implements InvocationHandler {<br />　　final T underlying;<br />　　<br />　　public LoggingHandler(T underlying) {<br />　　this.underlying = underlying;<br />　　}<br />　　<br />　　public Object invoke(Object proxy, Method method,<br />　　Object[] args) throws Throwable {<br />　　StringBuffer sb = new StringBuffer();<br />　　sb.append(method.getName()); sb.append("(");<br />　　for (int i=0; args != null &amp;&amp; i&lt;args.length; i ) {<br />　　if (i != 0)<br />　　sb.append(", ");<br />　　sb.append(args[i]);<br />　　}<br />　　sb.append(")");<br />　　Object ret = method.invoke(underlying, args);<br />　　if (ret != null) {<br />　　sb.append(" -&gt; "); sb.append(ret);<br />　　}<br />　　System.out.println(sb);<br />　　return ret;<br />　　}<br />　　}<br />　　<br />　　如果用日志代理包装 HashSet，并执行下面这个简单的测试程序：<br />　　<br />　　Set s = newLoggingProxy(Set.class, new HashSet());<br />　　s.add("three");<br />　　if (!s.contains("four"))<br />　　s.add("four");<br />　　System.out.println(s);<br />　　<br />　　会得到以下输出：<br />　　<br />　　add(three) -&gt; true<br />　　contains(four) -&gt; false<br />　　add(four) -&gt; true<br />　　toString() -&gt; [four, three]<br />　　[four, three]<br />　　<br />　　这种方式是给对象添加调试包装器的一种好的而且容易的方式。它当然比生成代理类并手工创建大量 println() 语句容易得多（也更通用）。我进一步改进了这一方法；不必无条件地生成调试输出，相反，代理可以查询动态配置存储（从配置文件初始化，可以由 JMX MBean 动态修改），确定是否需要生成调试语句，甚至可能在逐个类或逐个实例的基础上进行。<br />　　<br />　　在这一点上，我认为读者中的 AOP 爱好者们几乎要跳出来说“这正是 AOP 擅长的啊！”是的，但是解决问题的方法不止一种 —— 仅仅因为某项技术能解决某个问题，并不意味着它就是最好的解决方案。在任何情况下，动态代理方式都有完全在“纯 <a href="http://www.cooledu.cn/">Java</a>”范围内工作的优势，不是每个公司都用（或应当用） AOP 的。<br />　　<br />　　<b>动态代理作为适配器</b><br />　　<br />　　代理也可以用作真正的适配器，提供了对象的一个视图，导出与底层对象实现的接口不同的接口。调用句柄不需要把每个方法调用都分派给相同的底层对象；它可以<a href="http://www.cooledu.cn/">检查</a>名称，并把不同的方法分派给不同的对象。例如，假设有一组表示持久实体（Person、Company 和 PurchaseOrder） 的 JavaBean 接口，指定了属性的 getter 和 setter，而且正在编写一个持久层，把数据库记录映射到实现这些接口的对象上。现在不用为每个接口编写或生成类，可以只用一个 JavaBean 风格的通用代理类，把属性保存在 Map 中。<br />　　<br />　　清单 7 显示的动态代理检查被调用方法的名称，并通过查询或修改属性图直接实现 getter 和 setter 方法。现在，这一个代理类就能实现多个 JavaBean 风格接口的对象。<br />　　<br />　　清单 7. 用于把 getter 和 setter 分派给 Map 的动态代理类<br />　　<br />　　public class JavaBeanProxyFactory {<br />　　private static class JavaBeanProxy implements InvocationHandler {<br />　　Map&lt;String, Object&gt; properties = new HashMap&lt;String,<br />　　Object&gt;();<br />　　<br />　　public JavaBeanProxy(Map&lt;String, Object&gt; properties) {<br />　　this.properties.putAll(properties);<br />　　}<br />　　<br />　　public Object invoke(Object proxy, Method method,<br />　　Object[] args)<br />　　throws Throwable {<br />　　String meth = method.getName();<br />　　if (meth.startsWith("get")) {<br />　　String prop = meth.substring(3);<br />　　Object o = properties.get(prop);<br />　　if (o != null &amp;&amp; !method.getReturnType().isInstance(o))<br />　　throw new ClassCastException(o.getClass().getName() <br />　　" is not a " method.getReturnType().getName());<br />　　return o;<br />　　}<br />　　else if (meth.startsWith("set")) {<br />　　// Dispatch setters similarly<br />　　}<br />　　else if (meth.startsWith("is")) {<br />　　// Alternate version of get for boolean properties<br />　　}<br />　　else {<br />　　// Can dispatch non get/set/is methods as desired<br />　　}<br />　　}<br />　　}<br />　　<br />　　public static&lt;T&gt; T getProxy(Class&lt;T&gt; intf,<br />　　Map&lt;String, Object&gt; values) {<br />　　return (T) Proxy.newProxyInstance<br />　　(JavaBeanProxyFactory.class.getClassLoader(),<br />　　new Class[] { intf }, new JavaBeanProxy(values));<br />　　}<br />　　}<br />　　<br />　　虽然因为反射在 Object 上工作会有潜在的类型安全性上的损失，但是，JavaBeanProxyFactory 中的 getter 处理会进行一些必要的额外的类型检测，就像我在这里用 isInstance() 对 getter 进行的检测一样。<br />　　<br />　　<b>性能成本</b><br />　　<br />　　正如已经看到的，动态代理拥有简化大量代码的潜力 —— 不仅能替代许多生成的代码，而且一个代理类还能代替多个手写的类或生成的代码。什么是成本呢？ 因为反射地分派方法而不是采用内置的虚方法分派，可能有一些性能上的成本。在早期的 JDK 中，反射的性能很差（就像早期 JDK 中几乎其他每件事的性能一样），但是在近 10 年，反射已经变得快多了。<br />　　<br />　　不必进入基准测试构造的主题，我编写了一个简单的、不太科学的测试程序，它循环地把数据填充到 Set，随机地对 Set进行插入、查询和删除元素。我用三个 Set 实现运行它：一个未经修饰的 HashSet，一个手写的、只是把所有方法转发到底层的 HashSet 的 Set 适配器，还有一个基于代理的、也只是把所有方法转发到底层 HashSet 的 Set 适配器。每次循环迭代都生成若干随机数，并执行一个或多个 Set 操作。手写的适配器比起原始的 HashSet 只产生很少百分比的性能负荷（大概是因为 JVM 级有效的内联缓冲和硬件级的分支预测）；代理适配器则明显比原始 HashSet 慢，但是开销要少于两个量级。<br />　　<br />　　我从这个试验得出的结论是：对于大多数情况，代理方式即使对轻量级方法也执行得足够好，而随着被代理的操作变得越来越重量级（例如远程方法调用，或者使用序列化、执行 IO 或者从数据库检索数据的方法），代理开销就会有效地接近于 0。当然也存在一些代理方式的性能开销无法接受的情况，但是这些通常只是少数情况。<br />　　<br />　　<b>结束语</b><br />　　<br />　　动态代理是强大而未充分利用的工具，可以用于实现许多设计模式，包括 Proxy、Decorator 和 Adapter。这些模式基于代理的实现容易编写，更难出错，并且具备更好的通用性；在许多情况下，一个动态代理类可以充当所有接口的 Decorator 或 Proxy，这样就不用每个接口都编写一个静态类。除了最关注性能的应用程序之外，动态代理方式可能比手写或机器生成 stub 的方式更可取。<br /><br /><p></p>动态代理为实现许多常见设计模式（包括 Facade、Bridge、Interceptor、Decorator、Proxy（包括远程和虚拟代理）和 Adapter 模式）提供了替代的动态机制。虽然这些模式不使用动态代理，只用普通的类就能够实现，但是在许多情况下，动态代理方式更方便、更紧凑，可以清除许多手写或生成的类。<br />　　<br />　　<b>Proxy 模式</b><br />　　<br />　　Proxy 模式中要创建“stub”或“surrogate”对象，它们的目的是接受请求并把请求转发到实际执行工作的其他对象。远程方法调用（RMI）利用 Proxy 模式，使得在其他 JVM 中执行的对象就像本地对象一样；<a href="http://www.cooledu.cn/">企业</a><a href="http://www.cooledu.cn/">Java</a>Beans （EJB）利用 Proxy 模式添加远程调用、<a href="http://www.cooledu.cn/">安全</a>性和事务分界；而 JAX-RPC Web 服务则用 Proxy 模式让远程服务表现得像本地对象一样。在每一种情况中，潜在的远程对象的行为是由接口定义的，而接口本质上接受多种实现。调用者（在大多数情况下）不能区分出它们只是持有一个对 stub 而不是实际对象的引用，因为二者实现了相同的接口；stub 的工作是查找实际的对象、封送参数、把参数发送给实际对象、解除封送返回值、把返回值返回给调用者。代理可以用来提供远程控制（就像在 RMI、EJB 和 JAX-RPC 中那样），用安全性策略包装对象（EJB）、为昂贵的对象（EJB 实体 Bean）提供惰性装入，或者添加检测工具（例如日志记录）。<br />　　<br />　　在 5.0 以前的 JDK 中，RMI stub（以及它对等的 skeleton）是在编译时由 RMI 编译器（rmic）生成的类，RMI 编译器是 JDK 工具集的一部分。对于每个远程接口，都会生成一个 stub（代理）类，它代表远程对象，还生成一个 skeleton 对象，它在远程 JVM 中做与 stub 相反的工作 —— 解除封送参数并调用实际的对象。类似地，用于 Web 服务的 JAX-RPC 工具也为远程 Web 服务生成代理类，从而使远程 Web 服务看起来就像本地对象一样。<br />　　<br />　　不管 stub 类是以源代码还是以字节码生成的，代码生成仍然会向编译过程添加一些额外步骤，而且因为命名相似的类的泛滥，会带来意义模糊的可能性。另一方面，动态代理机制支持在编译时没有生成 stub 类的情况下，在运行时创建代理对象。在 JDK 5.0 及以后版本中，RMI 工具使用动态代理代替了生成的 stub，结果 RMI 变得更容易使用。许多 J2EE 容器也使用动态代理来实现 EJB。EJB 技术严重地依靠使用拦截（interception）来实现安全性和事务分界；动态代理为接口上调用的所有方法提供了集中的控制流程路径。<br />　　<br />　　<b>动态代理机制</b><br />　　<br />　　动态代理机制的核心是 InvocationHandler 接口，如清单 1 所示。调用句柄的工作是代表动态代理实际执行所请求的方法调用。传递给调用句柄一个 Method 对象（从 java.lang.reflect 包），参数列表则传递给方法；在最简单的情况下，可能仅仅是调用反射性的方法 Method.invoke() 并返回结果。<br />　　<br />　　清单 1. InvocationHandler 接口<br />　　<br />　　public interface InvocationHandler {<br />　　Object invoke(Object proxy, Method method, Object[] args)<br />　　throws Throwable;<br />　　}<br />　　<br />　　每个代理都有一个与之关联的调用句柄，只要代理的方法被调用时就会调用该句柄。根据通用的设计原则：接口定义类型、类定义实现，代理对象可以实现一个或多个接口，但是不能实现类。因为代理类没有可以访问的名称，它们不能有构造函数，所以它们必须由工厂创建。清单 2 显示了动态代理的最简单的可能实现，它实现 Set 接口并把所有 Set 方法（以及所有 Object 方法）分派给封装的 Set 实例。<br />　　<br />　　清单 2. 包装 Set 的简单的动态代理<br />　　<br />　　public class SetProxyFactory {<br />　　<br />　　public static Set getSetProxy(final Set s) {<br />　　return (Set) Proxy.newProxyInstance<br />　　(s.getClass().getClassLoader(),<br />　　new Class[] { Set.class },<br />　　new InvocationHandler() {<br />　　public Object invoke(Object proxy, Method method,<br />　　Object[] args) throws Throwable {<br />　　return method.invoke(s, args);<br />　　}<br />　　});<br />　　}<br />　　}<br />　　<br />　　SetProxyFactory 类包含一个静态工厂方法 getSetProxy()，它返回一个实现了 Set 的动态代理。代理对象实际实现 Set —— 调用者无法区分（除非通过反射）返回的对象是动态代理。SetProxyFactory 返回的代理只做一件事，把方法分派给传递给工厂方法的 Set 实例。虽然反射代码通常比较难读，但是这里的内容很少，跟上控制流程并不难 —— 只要某个方法在 Set 代理上被调用，它就被分派给调用句柄，调用句柄只是反射地调用底层包装的对象上的目标方法。当然，绝对什么都不做的代理可能有点傻，是不是呢？<br />　　<br />　　<b>什么都不做的适配器</b><br />　　<br />　　对于像 SetProxyFactory 这样什么都不做的包装器来说，实际有个很好的应用 —— 可以用它安全地把对象引用的范围缩小到特定接口（或接口集）上，方式是，调用者不能提升引用的类型，使得可以更安全地把对象引用传递给不受信任的代码（例如插件或回调）。清单 3 包含一组类定义，实现了典型的回调场景。从中会看到动态代理可以更方便地替代通常用手工（或用 IDE 提供的代码生成向导）实现的 Adapter 模式。<br />　　<br />　　清单 3. 典型的回调场景<br />　　<br />　　public interface ServiceCallback {<br />　　public void doCallback();<br />　　}<br />　　<br />　　public interface Service {<br />　　public void serviceMethod(ServiceCallback callback);<br />　　}<br />　　<br />　　public class ServiceConsumer implements ServiceCallback {<br />　　private Service service;<br />　　<br />　　...<br />　　public void someMethod() {<br />　　...<br />　　service.serviceMethod(this);<br />　　}<br />　　}<br />　　<br />　　ServiceConsumer 类实现了 ServiceCallback（这通常是支持回调的一个方便途径）并把 this 引用传递给 serviceMethod() 作为回调引用。这种方法的问题是没有机制可以阻止 Service 实现把 ServiceCallback 提升为 ServiceConsumer，并调用 ServiceConsumer 不希望 Service 调用的方法。有时对这个风险并不关心 —— 但有时却关心。如果关心，那么可以把回调对象作为内部类，或者编写一个什么都不做的适配器类（请参阅清单 4 中的 ServiceCallbackAdapter）并用 ServiceCallbackAdapter 包装 ServiceConsumer。ServiceCallbackAdapter 防止 Service 把 ServiceCallback 提升为 ServiceConsumer。<br />　　<br />　　清单 4. 用于安全地把对象限制在一个接口上以便不被恶意代码不能的适配器类<br />　　<br />　　public class ServiceCallbackAdapter implements ServiceCallback {<br />　　private final ServiceCallback cb;<br />　　<br />　　public ServiceCallbackAdapter(ServiceCallback cb) {<br />　　this.cb = cb;<br />　　}<br />　　<br />　　public void doCallback() {<br />　　cb.doCallback();<br />　　}<br />　　}<br />　　<br />　　编写 ServiceCallbackAdapter 这样的适配器类简单却乏味。必须为包装的接口中的每个方法编写重定向类。在 ServiceCallback 的示例中，只有一个需要实现的方法，但是某些接口，例如 Collections 或 JDBC 接口，则包含许多方法。现代的 IDE 提供了“Delegate Methods”向导，降低了编写适配器类的工作量，但是仍然必须为每个想要包装的接口编写一个适配器类，而且对于只包含生成的代码的类，也有一些让人不满意的地方。看起来应当有一种方式可以更紧凑地表示“什么也不做的限制适配器模式”。<br />　　<br />　　<b>通用适配器类</b><br />　　<br />　　清单 2 中的 SetProxyFactory 类当然比用于 Set 的等价的适配器类更紧凑，但是它仍然只适用于一个接口：Set。但是通过使用泛型，可以容易地创建通用的代理工厂，由它为任何接口做同样的工作，如清单 5 所示。它几乎与 SetProxyFactory 相同，但是可以适用于任何接口。现在再也不用编写限制适配器类了！如果想创建代理对象安全地把对象限制在接口 T，只要调用 getProxy(T.class,object) 就可以了，不需要一堆适配器类的额外累赘。<br />　　<br />　　清单 5. 通用的限制适配器工厂类<br />　　<br />　　public class GenericProxyFactory {<br />　　<br />　　public static&lt;T&gt; T getProxy(Class&lt;T&gt; intf,<br />　　final T obj) {<br />　　return (T)<br />　　Proxy.newProxyInstance(obj.getClass().getClassLoader(),<br />　　new Class[] { intf },<br />　　new InvocationHandler() {<br />　　public Object invoke(Object proxy, Method method,<br />　　Object[] args) throws Throwable {<br />　　return method.invoke(obj, args);<br />　　}<br />　　});<br />　　}<br />　　}<br /><img src ="http://www.blogjava.net/jiangmin/aggbug/68949.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jiangmin/" target="_blank">JiangMin</a> 2006-09-11 14:07 <a href="http://www.blogjava.net/jiangmin/articles/68949.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>