﻿<?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 node-文章分类-项目问题解决</title><link>http://www.blogjava.net/luoqx/category/3050.html</link><description /><language>zh-cn</language><lastBuildDate>Thu, 01 Mar 2007 02:44:24 GMT</lastBuildDate><pubDate>Thu, 01 Mar 2007 02:44:24 GMT</pubDate><ttl>60</ttl><item><title>关于使用utf8编码实现全球化的几点困惑（请大家帮忙想想办法）</title><link>http://www.blogjava.net/luoqx/articles/35704.html</link><dc:creator>publisher luo</dc:creator><author>publisher luo</author><pubDate>Thu, 16 Mar 2006 11:44:00 GMT</pubDate><guid>http://www.blogjava.net/luoqx/articles/35704.html</guid><wfw:comment>http://www.blogjava.net/luoqx/comments/35704.html</wfw:comment><comments>http://www.blogjava.net/luoqx/articles/35704.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/luoqx/comments/commentRss/35704.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/luoqx/services/trackbacks/35704.html</trackback:ping><description><![CDATA[
		<p>某日一时兴起将我们的内容管理发布系统改成uft-8格式（即将所有页面encode变为utf8，mysql字符集也变成uft-8）来支持能够建立各种语言的网站（产品现在可以免费下载，网址为：<a href="http://sourceforge.net/projects/nodepublisher">http://sourceforge.net/projects/nodepublisher</a>）。但是在修改程序过程中发现了一个问题，那就是在客户端页面提交过来的请求的编码格式在服务器端无法获知。如果提交页面的&lt;head&gt;里面如果包含&lt;meta http-equiv="Content-Type" content="text/html; charset=utf-8"&gt;，汉字部分则以utf8编码提交，如果没有的话则以gbk编码提交，而服务器端接受到的request无法判别编码格式，取到的头信息只有一些zh类似的说明,所以无法正确的将其转换成正确的编码格式。 <br />另一需要注意的是不能将取到的参数从ISO8859转换成中文系统默认的字符集GBK,然后再转换成utf8，这样的话如果出现奇数汉字的话会导致部分汉字乱码，原因在于汉字在GBK编码中为2个byte，而在utf8编码则为3个byte，如果是偶数个汉字，从ISO8859（tomcat默认得到的request都是ISO8859编码）转换成GBK，然后再转换成ISO8859到还无妨，但是奇数个，最后一个byte不知道会怎么转换成GBK的，然后再转回到utf8时最后那个字符就会成为乱码，我想可能是跟String类里面的拆分char的方法有关，不知道谁有更加明确的分析和解释。<br />再一数据库方面使用mysql5，设置成utf8初始化数据脚本汉字转换成uft8，一切正常。后来无意将数据库转换成GBK编码，竟然程序运行也正常，后来经过测试将mysql设置成gbk，然后执行初始化sql脚本，汉字编码格式为GBK，程序运行依然正常。不明白其中的原由。</p>
<img src ="http://www.blogjava.net/luoqx/aggbug/35704.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/luoqx/" target="_blank">publisher luo</a> 2006-03-16 19:44 <a href="http://www.blogjava.net/luoqx/articles/35704.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>spring本地事务与JTA事务实现解析</title><link>http://www.blogjava.net/luoqx/articles/16451.html</link><dc:creator>publisher luo</dc:creator><author>publisher luo</author><pubDate>Sat, 22 Oct 2005 14:57:00 GMT</pubDate><guid>http://www.blogjava.net/luoqx/articles/16451.html</guid><wfw:comment>http://www.blogjava.net/luoqx/comments/16451.html</wfw:comment><comments>http://www.blogjava.net/luoqx/articles/16451.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/luoqx/comments/commentRss/16451.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/luoqx/services/trackbacks/16451.html</trackback:ping><description><![CDATA[<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;大家都知道spring支持两种事务，一种是本地连接事务（使用DataSourceTransactionManager），一种是JTA事务（使用JtaTransactionManager）。并且支持声明式事务和编程式事务两种方式。采用声明式事务使用AOP方式的TransactionProxyFactoryBean代理工厂类。<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;JTA事务实现相对较好理解，在执行实际类的符合模式的方法时，代理类通过<SPAN style="FONT-FAMILY: 宋体">在连接点前后插入预处理过程（开始事务）和后处理过程（commit或rollbak）即可。因为JTA事务支持两阶段提交所以在代码中启动多少个连接（不同的connection）都能保证事务最终提交或者回滚。可是本地连接事务是如何实现的呢？因为必须后面的dao层必须使用的同一个连接才能保证事务正常提交和回滚，在业务逻辑层可以调用dao层的多个类的多个方法，每个方法如果显式的将connection做为参数传入到还可以，但是这样connection就要出现调用的在业务逻辑层，而且dao的每个方法还要有个connection参数比较难看，而且开发人员要关注事务，这样就没有达到开发人员只要关注业务逻辑即可的要求。</SPAN>&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;web应用，各个类都要在多线程环境下运行，所以每个方法要保证线程安全，这样，不在dao方法中加参数而是在dao类中加入connection属性也就不可取了，怎么办？查看一下<FONT face=宋体>JdbcTemplate类，在执行每个方法需要数据库连接时都使用了DataSourceUtils.getConnection(getDataSource())方法？难道每回都从数据源里面取一条连接？不可能，这样事务肯定没法实现，可是怎么能保证取的是一条连接呢？对了是不是采用本地线程呀（TreadLocal），因为一段事务都是在一个线程中完成，所以只要在事务开始的时候将connection存放在本地线程中，然后事务过程中从本地线程中取出connection，直到事务结束即可。不错，这样只需要在每个dao方法的取数据库连接的方法中有个事务状态的判断即可。不错看看spring是不是这样实现的？果然如此，DataSourceUtils.getConnection（DataSource）方法调用doGetConnection()方法，方法内容如下：<BR>public static Connection doGetConnection(DataSource dataSource) throws SQLException {<BR>&nbsp;&nbsp;Assert.notNull(dataSource, "No DataSource specified");</FONT></P>
<P><FONT face=宋体>&nbsp;&nbsp;ConnectionHolder conHolder = (ConnectionHolder) TransactionSynchronizationManager.getResource(dataSource);<BR>&nbsp;&nbsp;if (conHolder != null) {<BR>&nbsp;&nbsp;&nbsp;conHolder.requested();<BR>&nbsp;&nbsp;&nbsp;return conHolder.getConnection();<BR>&nbsp;&nbsp;}</FONT></P>
<P><FONT face=宋体>&nbsp;&nbsp;logger.debug("Fetching JDBC Connection from DataSource");<BR>&nbsp;&nbsp;Connection con = dataSource.getConnection();</FONT></P>
<P><FONT face=宋体>&nbsp;&nbsp;if (TransactionSynchronizationManager.isSynchronizationActive()) {<BR>&nbsp;&nbsp;&nbsp;logger.debug("Registering transaction synchronization for JDBC Connection");<BR>&nbsp;&nbsp;&nbsp;// Use same Connection for further JDBC actions within the transaction.<BR>&nbsp;&nbsp;&nbsp;// Thread-bound object will get removed by synchronization at transaction completion.<BR>&nbsp;&nbsp;&nbsp;conHolder = new ConnectionHolder(con);<BR>&nbsp;&nbsp;&nbsp;conHolder.setSynchronizedWithTransaction(true);<BR>&nbsp;&nbsp;&nbsp;conHolder.requested();<BR>&nbsp;&nbsp;&nbsp;TransactionSynchronizationManager.registerSynchronization(<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;new ConnectionSynchronization(conHolder, dataSource));<BR>&nbsp;&nbsp;&nbsp;TransactionSynchronizationManager.bindResource(dataSource, conHolder);<BR>&nbsp;&nbsp;}</FONT></P>
<P><FONT face=宋体>&nbsp;&nbsp;return con;<BR>&nbsp;}<BR>conHolder?TransactionSynchronizationManager？很象呀，继续看看TransactionSynchronizationManager类果真如此，里面使用TreadLocal来保存数据连接和事务状态。原来如此，代码里的各个层没有特殊需要都不用再出现事务了，程序开发人员只要关注业务就可以了，不用再劳心编写事务代码了。<BR></P></FONT><img src ="http://www.blogjava.net/luoqx/aggbug/16451.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/luoqx/" target="_blank">publisher luo</a> 2005-10-22 22:57 <a href="http://www.blogjava.net/luoqx/articles/16451.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Spring远程数据源JTA事务连接配置</title><link>http://www.blogjava.net/luoqx/articles/16447.html</link><dc:creator>publisher luo</dc:creator><author>publisher luo</author><pubDate>Sat, 22 Oct 2005 14:09:00 GMT</pubDate><guid>http://www.blogjava.net/luoqx/articles/16447.html</guid><wfw:comment>http://www.blogjava.net/luoqx/comments/16447.html</wfw:comment><comments>http://www.blogjava.net/luoqx/articles/16447.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/luoqx/comments/commentRss/16447.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/luoqx/services/trackbacks/16447.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;项目组开发服务器使用weblogic，应用服务器上配置了数据源，每个人开发使用eclipse，每人调试程序都使用本机，所以调试使用的服务是跟eclipse的tomcat插件，数据源可以使用tomcat的配置的和weblogic同名的数据源，可是JTA tomcat不支持。<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 因为整个项目组使用统一的配置管理，spring的applicationContext.xml大家都相同，每天还要做每日构建，部署到服务器上也与配置管理上的文件相同，所以想是否可以将数据源和JTAmanager配置成远程的。<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 查找spring官方文档，太简单没有这方面描述，上网google了半天，没找到（奇怪？其实后来想想也不奇怪，大家要么使用本地数据源（开发调试），要么使用应用服务的数据源也是在同一应用服务器上，而不是在远程使用（部署的生产环境）。），所以干脆看看源码算了。<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 已知如下配置可以访问到同一应用服务器的jndi数据源<BR>&lt;bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean"&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&lt;property name="jndiName"&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;value&gt;jdbc/cqccms&lt;/value&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/property&gt;<BR>&nbsp;&lt;/bean&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 记得当初使用jndi时可以远程访问写过client程序，主要除了要知道jndi名，还要设置jndi环境（Environment），所以查找一下JndiObjectFactoryBean的源代码，看看有没有设置jndi环境的方法，果然有setJndiEnvironment方法参数为properties，可以了，如下配置就能访问远程数据源了<BR>&lt;bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean"&gt;<BR>&nbsp;&lt;property name="jndiName"&gt;<BR>&nbsp;&nbsp;&lt;value&gt;jdbc/cqccms&lt;/value&gt;<BR>&nbsp;&lt;/property&gt;<BR>&nbsp;&lt;property name="jndiEnvironment"&gt; <BR>&nbsp;&nbsp;&nbsp; &nbsp;&lt;props&gt; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&lt;prop key="java.naming.factory.initial"&gt; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;weblogic.jndi.WLInitialContextFactory <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&lt;/prop&gt; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&lt;prop key="java.naming.provider.url"&gt;t3://172.16.101.42:7001&lt;/prop&gt; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&lt;prop key="java.naming.security.principal"&gt;weblogic&lt;/prop&gt; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&lt;prop key="java.naming.security.credentials"&gt;weblogic&lt;/prop&gt; <BR>&nbsp;&nbsp;&nbsp; &nbsp;&lt;/props&gt;&nbsp;&nbsp;&nbsp; <BR>&nbsp; &nbsp;&lt;/property&gt;&nbsp;<BR>&nbsp; &lt;/bean&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;不过要记得把weblogic.jar放到自己应用的lib下，要不找不到weblogic.jndi.WLInitialContextFactory类。<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;数据源搞定了，测试一下果真好用，不过jta对象远程访问好像没那么顺利，同理查看org.springframework.transaction.jta.JtaTransactionManager类，没有发现上述方法，不过看到了setJndiTemplate()方法，也不错现配置一个jndiTemplate,如下：<BR>&nbsp;&lt;bean id="jndiTemplate" class="org.springframework.jndi.JndiTemplate" singleton="true"<BR>&nbsp;&nbsp;lazy-init="default" autowire="default" dependency-check="default"&gt;<BR>&nbsp;&nbsp;&lt;property name="environment"&gt; <BR>&nbsp;&nbsp;&nbsp; &nbsp;&lt;props&gt; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&lt;prop key="java.naming.factory.initial"&gt; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;weblogic.jndi.WLInitialContextFactory <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&lt;/prop&gt; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&lt;prop key="java.naming.provider.url"&gt;t3://172.16.101.42:7001&lt;/prop&gt; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&lt;prop key="java.naming.security.principal"&gt;weblogic&lt;/prop&gt; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&lt;prop key="java.naming.security.credentials"&gt;weblogic&lt;/prop&gt; <BR>&nbsp;&nbsp;&nbsp; &nbsp;&lt;/props&gt;&nbsp;&nbsp;&nbsp; <BR>&nbsp; &nbsp;&lt;/property&gt;&nbsp;<BR>&nbsp;&lt;/bean&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;然后在配置一下transactionManager,如下<BR>&nbsp;&lt;bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager" singleton="true"<BR>&nbsp;&nbsp;lazy-init="default" autowire="default" dependency-check="default"&gt;<BR>&nbsp;&nbsp;&lt;property name="jndiTemplate"&gt;<BR>&nbsp;&nbsp;&nbsp;&lt;ref local="jndiTemplate" /&gt;<BR>&nbsp;&nbsp;&lt;/property&gt;<BR>&nbsp;&nbsp;&lt;property name="userTransactionName"&gt;<BR>&nbsp;&nbsp;&nbsp;&lt;value&gt;weblogic/transaction/UserTransaction&lt;/value&gt;<BR>&nbsp;&nbsp;&lt;/property&gt;<BR>&nbsp;&lt;/bean&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;不过JtaTransactionManager默认找jndi name为UserTransaction的jta对象，在同一应用服务器上可以，远程访问不到，后直接查看weblogic的jndi树找到这个jndi名weblogic/transaction/UserTransaction，配置上测试果然成功。<img src ="http://www.blogjava.net/luoqx/aggbug/16447.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/luoqx/" target="_blank">publisher luo</a> 2005-10-22 22:09 <a href="http://www.blogjava.net/luoqx/articles/16447.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>一个简单"决策树"的实现</title><link>http://www.blogjava.net/luoqx/articles/11780.html</link><dc:creator>publisher luo</dc:creator><author>publisher luo</author><pubDate>Thu, 01 Sep 2005 11:55:00 GMT</pubDate><guid>http://www.blogjava.net/luoqx/articles/11780.html</guid><wfw:comment>http://www.blogjava.net/luoqx/comments/11780.html</wfw:comment><comments>http://www.blogjava.net/luoqx/articles/11780.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/luoqx/comments/commentRss/11780.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/luoqx/services/trackbacks/11780.html</trackback:ping><description><![CDATA[<table class="fixedTable blogpost" border="0" cellspacing="0" width="100%">
<tbody><tr><td class="bvh8"><br>
</td><td class="ellipse"><span class="bvTitle" id="subjcns!1ppLlQyegnTGhBatkQ-HqHlQ!110"><br>
</span></td><td class="bvh8"><br>
</td><td id="msgcns!1ppLlQyegnTGhBatkQ-HqHlQ!110">
<p>   客户的权限要求采集回来了，天哪，根本不是什么权限的设置和判断了，原有内容管理中的权限管理(RBAC Role based Access 
Control 
基于角色的访问控制)根本不能解决问题. 经过仔细分析，所有要求具为领导拍脑袋定下来的不符合逻辑的一些逻辑。如何解决？随即想到了采用专家系统来解决这个问题。找到开源的rete算法java实现包Drools(<a href="http://www.theserverside.com/articles/content/Drools/article.html">http://www.theserverside.com/articles/content/Drools/article.html</a>),
并察看了专家系统的部分书籍。但是项目时间紧迫所以放弃了，主要是其规则存放于xml中，没想出好的办法与本工程良好的配合起来。所以还是决定先采用简单
的决策树（本系统中正好有树状结构的内容管理系统，很容易扩展）解决问题。在每个树状决策节点可以加入条件和行为，如何解析？成了一个问题。再
google一下，找找开源的脚本解析，哦不错有java脚本的解析器（ <b>BeanShell---Java应用程序脚本引挚</b> 
）可以直接解析java语句，功能比较强大，包也不大。不得不佩服现在的开源真是如火如荼，还是早早的加入进去吧。</p>
<p>主要测试代码：<br>//创建一个bsh解释器实例<br>  Interpreter bsh = new 
Interpreter();<br>//测试执行一个接口实现的类<br>String program = "public Object excute(int 
aa,String bb){return \"Cool\";}";<br>program ="Command command= new 
Command(){"+program+"};";<br>program += "Object 
obj=command.excute(aa,bb);";<br>bsh.eval(program);<br>//测试执行一个函数<br>String 
program = "Object excute(int aa,String bb){return \"bb+aa\";}";<br>program += 
"Object obj=excute(aa,bb);";String program = "Object excute(int aa,String 
bb){return \"bb+aa\";}";<br>program += "Object 
obj=excute(aa,bb);";<br>bsh.eval(program);<br>  <br>  bsh.eval(program);</p></td></tr></tbody>
</table>
<img src ="http://www.blogjava.net/luoqx/aggbug/11780.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/luoqx/" target="_blank">publisher luo</a> 2005-09-01 19:55 <a href="http://www.blogjava.net/luoqx/articles/11780.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>xalan包的版本问题</title><link>http://www.blogjava.net/luoqx/articles/11779.html</link><dc:creator>publisher luo</dc:creator><author>publisher luo</author><pubDate>Thu, 01 Sep 2005 11:49:00 GMT</pubDate><guid>http://www.blogjava.net/luoqx/articles/11779.html</guid><wfw:comment>http://www.blogjava.net/luoqx/comments/11779.html</wfw:comment><comments>http://www.blogjava.net/luoqx/articles/11779.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/luoqx/comments/commentRss/11779.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/luoqx/services/trackbacks/11779.html</trackback:ping><description><![CDATA[<br>
<table class="fixedTable blogpost" border="0" cellspacing="0" width="100%">
<tbody><tr><td class="ellipse"><span class="bvTitle" id="subjcns!1ppLlQyegnTGhBatkQ-HqHlQ!109"></span><br>
</td><td class="bvh8"><br>
</td><td id="msgcns!1ppLlQyegnTGhBatkQ-HqHlQ!109">
<p>&nbsp;&nbsp;&nbsp; 一直好用的程序竟然不好用了，出现下列异常：</p>
<p>org.apache.xml.utils.WrappedRuntimeException: The output format must have a 
'{http://xml.apache.org/xalan}content-handler' property!</p>
<p>&nbsp; 终于找到原因，tomcat5 中自带了xalan包，并且包的版本提升了，所以程序不好用了。详细原因没有查清。</p></td></tr></tbody>
</table>
<img src ="http://www.blogjava.net/luoqx/aggbug/11779.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/luoqx/" target="_blank">publisher luo</a> 2005-09-01 19:49 <a href="http://www.blogjava.net/luoqx/articles/11779.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>哪里有好的树状结构的容器？没办法自己写一个吧</title><link>http://www.blogjava.net/luoqx/articles/11288.html</link><dc:creator>publisher luo</dc:creator><author>publisher luo</author><pubDate>Sat, 27 Aug 2005 03:18:00 GMT</pubDate><guid>http://www.blogjava.net/luoqx/articles/11288.html</guid><wfw:comment>http://www.blogjava.net/luoqx/comments/11288.html</wfw:comment><comments>http://www.blogjava.net/luoqx/articles/11288.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/luoqx/comments/commentRss/11288.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/luoqx/services/trackbacks/11288.html</trackback:ping><description><![CDATA[<div id="entrycns!1ppLlQyegnTGhBatkQ-HqHlQ!111"><table class="fixedTable blogpost" border="0" cellspacing="0" width="100%"><tbody><tr><td class="ellipse"><span class="bvTitle" id="subjcns!1ppLlQyegnTGhBatkQ-HqHlQ!111"></span><br>
</td></tr>
<tr>
<td class="bvh8"><br>
</td></tr>
<tr>
<td id="msgcns!1ppLlQyegnTGhBatkQ-HqHlQ!111">
<p>到处找树状结构的容器都没找到，TreeMap和TreeSet是什么红-黑树没看明白，没时间仔细研究了，干脆简单写一个吧，反正并发要求不是很高，也不怎么排序，就是内存缓存用。代码如下：</p>
<p>/**<br>&nbsp;* 树操作类，定义树型数据结构的常用操作，其中包括定位树结点，插入树结点 删除树结点，修改树结点等。 
注意：树根节点的标志从0开始<br>&nbsp;*/<br>public class DataTree implements Serializable {</p>
<p>&nbsp;private DataTreeNode rootDataTreeNode = null; //定义树根<br>&nbsp;private Hashtable 
nodeList = new Hashtable();</p>
<p>&nbsp;/**<br>&nbsp; * 设置根节点<br>&nbsp; * @param nodeID 节点nodeid<br>&nbsp; * @param node&nbsp;&nbsp; 
节点数据对象<br>&nbsp; */<br>&nbsp;private void setRoot(String nodeID, Object node) {</p>
<p>&nbsp;&nbsp;DataTreeNode treeNode = new 
DataTreeNode();<br>&nbsp;&nbsp;treeNode.setLevel(0);<br>&nbsp;&nbsp;treeNode.setNode(node);<br>&nbsp;&nbsp;treeNode.setNodeID(nodeID);<br>&nbsp;&nbsp;treeNode.setUpNodeID("0");<br>&nbsp;&nbsp;this.rootDataTreeNode 
= treeNode;<br>&nbsp;&nbsp;nodeList.put(nodeID, treeNode);<br>&nbsp;}</p>
<p>&nbsp;/**<br>&nbsp; * 设置根节点<br>&nbsp; * @param node Object，节点包含数据对象<br>&nbsp; */<br>&nbsp;public void 
setRoot(Object node) {<br>&nbsp;&nbsp;String nodeID = 
DataAccess.getCode();<br>&nbsp;&nbsp;setRoot(node);<br>&nbsp;}<br>&nbsp;/**<br>&nbsp; * 取得根节点<br>&nbsp; * 
@return 树型节点<br>&nbsp; */<br>&nbsp;public DataTreeNode getRoot(){<br>&nbsp;&nbsp;return 
rootDataTreeNode;<br>&nbsp;}<br>&nbsp;/**<br>&nbsp; * 取得节点数据对象<br>&nbsp; * @return 数据对象<br>&nbsp; 
*/<br>&nbsp;public Object getRootNode(){<br>&nbsp;&nbsp;return rootDataTreeNode.getNode() 
;<br>&nbsp;}<br>&nbsp;<br>&nbsp;/**<br>&nbsp; * 给一个节点添加子节点<br>&nbsp; * @param supNode 父节点<br>&nbsp; * @param 
node 数据对象<br>&nbsp; * @return 封装过的树型节点<br>&nbsp; */<br>&nbsp;public DataTreeNode 
addSubNode(DataTreeNode supNode,Object node){<br>&nbsp;&nbsp;DataTreeNode newTreeNode =&nbsp; 
supNode.addSubNode(node);<br>&nbsp;&nbsp;this.nodeList.put( newTreeNode.getNodeID() 
,newTreeNode);<br>&nbsp;&nbsp;return newTreeNode;<br>&nbsp;}<br>&nbsp;/**<br>&nbsp; * 删除一个子节点<br>&nbsp; * 
@param supNode 父节点<br>&nbsp; * @param subNode 子节点<br>&nbsp; * @return 成功，失败<br>&nbsp; 
*/<br>&nbsp;public boolean removeSubNode(DataTreeNode supNode,DataTreeNode 
subNode){<br>&nbsp;&nbsp;if(supNode.removeSubNode( subNode)){<br>&nbsp;&nbsp;&nbsp;this.nodeList.remove( 
subNode.getNodeID() );<br>&nbsp;&nbsp;&nbsp;return true;<br>&nbsp;&nbsp;}else{<br>&nbsp;&nbsp;&nbsp;return 
false;<br>&nbsp;&nbsp;}<br>&nbsp;}<br>&nbsp;/**<br>&nbsp; * 删除一个子节点<br>&nbsp; * @param supNode 父节点<br>&nbsp; * 
@param orderid 序号，从0开始<br>&nbsp; * @return 成功，失败<br>&nbsp; */<br>&nbsp;public boolean 
removeSubNode(DataTreeNode supNode,int orderid){<br>&nbsp;&nbsp;DataTreeNode subNode = 
supNode.getSubNode( orderid);<br>&nbsp;&nbsp;if(supNode.removeSubNode( 
orderid)){<br>&nbsp;&nbsp;&nbsp;this.nodeList.remove( subNode.getNodeID() );<br>&nbsp;&nbsp;&nbsp;return 
true;<br>&nbsp;&nbsp;}else{<br>&nbsp;&nbsp;&nbsp;return false;<br>&nbsp;&nbsp;}<br>&nbsp;}<br>&nbsp;<br>&nbsp;public static 
DataTree creatDataTree(ArrayList nodeList,<br>&nbsp;&nbsp;&nbsp;String 
upNodeIDName,<br>&nbsp;&nbsp;&nbsp;String nodeIDName,<br>&nbsp;&nbsp;&nbsp;Object root){<br>&nbsp;&nbsp;<br>&nbsp;&nbsp;String 
getNodeIDMethodName = "get"+nodeIDName;<br>&nbsp;&nbsp;String getUpNodeIDMethodName = 
"get"+upNodeIDName;<br>&nbsp;&nbsp;String rootNodeid = getValue(root 
,getNodeIDMethodName);<br>&nbsp;&nbsp;String nodeid = "";<br>&nbsp;&nbsp;String upnodeid = 
"";<br>&nbsp;&nbsp;<br>&nbsp;&nbsp;<br>&nbsp;&nbsp;<br>&nbsp;&nbsp;Object[][] nodes = new 
Object[nodeList.size()][3];</p>
<p>&nbsp;&nbsp;int count =0;<br>&nbsp;&nbsp;//将arraylist数据存储到两个Hashtable中<br>&nbsp;&nbsp;for(int 
i=0;i&lt;nodeList.size();i++){<br>&nbsp;&nbsp;&nbsp;Object obj = nodeList.get(i);<br>&nbsp;&nbsp;&nbsp;if (obj 
!= null){<br>&nbsp;&nbsp;&nbsp;&nbsp;nodeid = new 
String(getValue(obj,getNodeIDMethodName));<br>&nbsp;&nbsp;&nbsp;&nbsp;if (nodeid != null 
){<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;upnodeid = new String(getValue(obj 
,getUpNodeIDMethodName));<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (upnodeid != 
null){<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nodes[count][0] = nodeid;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nodes[count][1] = 
upnodeid;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nodes[count][2] = nodeList.get(i);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;count 
++;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;}&nbsp;&nbsp;<br>&nbsp;&nbsp;DataTree dataTree = new 
DataTree();<br>&nbsp;&nbsp;dataTree.setRoot( 
rootNodeid,root);<br>&nbsp;&nbsp;findChildNodeAndAdd(dataTree.getRoot(),nodes);<br>&nbsp;&nbsp;return 
dataTree;<br>&nbsp;}<br>&nbsp;<br>&nbsp;private static void findChildNodeAndAdd(DataTreeNode 
treeNode,Object[][] nodes){<br>&nbsp;&nbsp;String nodeid = treeNode.getNodeID() ;<br>&nbsp;&nbsp;for 
(int i=0;i&lt;nodes.length ;i++){<br>&nbsp;&nbsp;&nbsp;if 
(nodeid.equals(nodes[i][1])){<br>&nbsp;&nbsp;&nbsp;&nbsp;DataTreeNode childTreeNode = 
treeNode.addSubNode( 
(String)nodes[i][0],nodes[i][2]);<br>&nbsp;&nbsp;&nbsp;&nbsp;findChildNodeAndAdd(childTreeNode,nodes);<br>&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;}&nbsp;&nbsp;<br>&nbsp;}<br>&nbsp;<br>&nbsp;private 
static String getValue(Object obj, String functionName){<br>&nbsp;&nbsp;return 
(String)ObjectTool.invokeMethod(obj,null,null,functionName);<br>&nbsp;}<br>&nbsp;/**<br>&nbsp; 
* 树型数据结构定义类。定义树型数据结构的基本单元--树型节点的结构。<br>&nbsp; *&nbsp; <br>&nbsp; */<br>&nbsp;public class 
DataTreeNode&nbsp; {</p>
<p>&nbsp;&nbsp;private String upNodeID; //父节点ID</p>
<p>&nbsp;&nbsp;private String nodeID; //属性节点标志ID</p>
<p>&nbsp;&nbsp;private int level; //层号</p>
<p>&nbsp;&nbsp;private Object node; //存储用数据对象</p>
<p>&nbsp;&nbsp;private ArrayList subNodes; //所有子节点</p>
<p>&nbsp;&nbsp;/**<br>&nbsp;&nbsp; * 空构造<br>&nbsp;&nbsp; *&nbsp; <br>&nbsp;&nbsp; */<br>&nbsp;&nbsp;private DataTreeNode() 
{<br>&nbsp;&nbsp;&nbsp;subNodes = new ArrayList();<br>&nbsp;&nbsp;}</p>
<p>&nbsp;&nbsp;/**<br>&nbsp;&nbsp; * @return Returns the level.<br>&nbsp;&nbsp; */<br>&nbsp;&nbsp;public int getLevel() 
{<br>&nbsp;&nbsp;&nbsp;return level;<br>&nbsp;&nbsp;}</p>
<p>&nbsp;&nbsp;/**<br>&nbsp;&nbsp; * @param level<br>&nbsp;&nbsp; *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; The level to set.<br>&nbsp;&nbsp; 
*/<br>&nbsp;&nbsp;private void setLevel(int level) {<br>&nbsp;&nbsp;&nbsp;this.level = level;<br>&nbsp;&nbsp;}</p>
<p>&nbsp;&nbsp;/**<br>&nbsp;&nbsp; * @return Returns the node.<br>&nbsp;&nbsp; */<br>&nbsp;&nbsp;public Object getNode() 
{<br>&nbsp;&nbsp;&nbsp;return node;<br>&nbsp;&nbsp;}</p>
<p>&nbsp;&nbsp;/**<br>&nbsp;&nbsp; * @param node<br>&nbsp;&nbsp; *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; The node to set.<br>&nbsp;&nbsp; 
*/<br>&nbsp;&nbsp;private void setNode(Object node) {<br>&nbsp;&nbsp;&nbsp;this.node = node;<br>&nbsp;&nbsp;}</p>
<p>&nbsp;&nbsp;/**<br>&nbsp;&nbsp; * @return Returns the nodeID.<br>&nbsp;&nbsp; */<br>&nbsp;&nbsp;public String 
getNodeID() {<br>&nbsp;&nbsp;&nbsp;return nodeID;<br>&nbsp;&nbsp;}</p>
<p>&nbsp;&nbsp;/**<br>&nbsp;&nbsp; * @param nodeID<br>&nbsp;&nbsp; *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; The nodeID to set.<br>&nbsp;&nbsp; 
*/<br>&nbsp;&nbsp;private void setNodeID(String nodeID) {<br>&nbsp;&nbsp;&nbsp;this.nodeID = 
nodeID;<br>&nbsp;&nbsp;}</p>
<p>&nbsp;&nbsp;/**<br>&nbsp;&nbsp; * @return Returns the orderid.<br>&nbsp;&nbsp; */<br>&nbsp;&nbsp;public int 
getSubNodeOrderid(DataTreeNode treeNode) {<br>&nbsp;&nbsp;&nbsp;for (int i = 0; i &lt; 
subNodes.size(); i++) {<br>&nbsp;&nbsp;&nbsp;&nbsp;if (this.getSubNode(i).equals(treeNode)) 
{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return i;<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;return -1;<br>&nbsp;&nbsp;}</p>
<p>&nbsp;&nbsp;/**<br>&nbsp;&nbsp; * @return Returns the subNode.<br>&nbsp;&nbsp; */<br>&nbsp;&nbsp;public ArrayList 
getSubNodes() {<br>&nbsp;&nbsp;&nbsp;return (ArrayList) subNodes.clone();<br>&nbsp;&nbsp;}</p>
<p>&nbsp;&nbsp;/**<br>&nbsp;&nbsp; * @param subNode<br>&nbsp;&nbsp; *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; The subNode to set.<br>&nbsp;&nbsp; 
*/<br>&nbsp;&nbsp;private void setSubNodes(ArrayList subNodes) {<br>&nbsp;&nbsp;&nbsp;this.subNodes = 
subNodes;<br>&nbsp;&nbsp;}</p>
<p>&nbsp;&nbsp;/**<br>&nbsp;&nbsp; * @return Returns the subNodeNo.<br>&nbsp;&nbsp; */<br>&nbsp;&nbsp;private int 
getSubNodeNo() {<br>&nbsp;&nbsp;&nbsp;return this.subNodes.size();<br>&nbsp;&nbsp;}</p>
<p>&nbsp;&nbsp;/**<br>&nbsp;&nbsp; * @return Returns the upNodeID.<br>&nbsp;&nbsp; */<br>&nbsp;&nbsp;public String 
getUpNodeID() {<br>&nbsp;&nbsp;&nbsp;return upNodeID;<br>&nbsp;&nbsp;}</p>
<p>&nbsp;&nbsp;/**<br>&nbsp;&nbsp; * @param upNodeID<br>&nbsp;&nbsp; *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; The upNodeID to set.<br>&nbsp;&nbsp; 
*/<br>&nbsp;&nbsp;private void setUpNodeID(String upNodeID) {<br>&nbsp;&nbsp;&nbsp;this.upNodeID = 
upNodeID;<br>&nbsp;&nbsp;}</p>
<p>&nbsp;&nbsp;/**<br>&nbsp;&nbsp; * 增加一个子节点<br>&nbsp;&nbsp; * <br>&nbsp;&nbsp; * @param treeNode<br>&nbsp;&nbsp; *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
带树结构的节点<br>&nbsp;&nbsp; */<br>&nbsp;&nbsp;private void addSubTreeNode(DataTreeNode treeNode) 
{<br>&nbsp;&nbsp;&nbsp;this.subNodes.add(treeNode);<br>&nbsp;&nbsp;}</p>
<p>&nbsp;&nbsp;/**<br>&nbsp;&nbsp; * 增加一个子节点，指定nodeid<br>&nbsp;&nbsp; * <br>&nbsp;&nbsp; * @param nodeID<br>&nbsp;&nbsp; 
*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 指定的nodeid<br>&nbsp;&nbsp; * @param node<br>&nbsp;&nbsp; *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 节点附带数据对象<br>&nbsp;&nbsp; 
*/<br>&nbsp;&nbsp;private DataTreeNode addSubNode(String nodeID, Object node) 
{<br>&nbsp;&nbsp;&nbsp;DataTreeNode treeNode = new 
DataTreeNode();<br>&nbsp;&nbsp;&nbsp;treeNode.setLevel(this.level + 
1);<br>&nbsp;&nbsp;&nbsp;treeNode.setNode(node);<br>&nbsp;&nbsp;&nbsp;treeNode.setNodeID(nodeID);<br>&nbsp;&nbsp;&nbsp;//treeNode.setOrderid( 
getSubNodeNo() 
);<br>&nbsp;&nbsp;&nbsp;treeNode.setUpNodeID(this.nodeID);<br>&nbsp;&nbsp;&nbsp;addSubTreeNode(treeNode);<br>&nbsp;&nbsp;&nbsp;return 
treeNode;<br>&nbsp;&nbsp;}</p>
<p>&nbsp;&nbsp;/**<br>&nbsp;&nbsp; * 增加一个子节点，自动分配nodeid<br>&nbsp;&nbsp; * <br>&nbsp;&nbsp; * @param node<br>&nbsp;&nbsp; 
*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 节点附带数据对象<br>&nbsp;&nbsp; */<br>&nbsp;&nbsp;private DataTreeNode addSubNode(Object node) 
{<br>&nbsp;&nbsp;&nbsp;String nodeID = DataAccess.getCode();<br>&nbsp;&nbsp;&nbsp;return addSubNode(nodeID, 
node);<br>&nbsp;&nbsp;}</p>
<p>&nbsp;&nbsp;/**<br>&nbsp;&nbsp; * 按序号取出节点<br>&nbsp;&nbsp; * <br>&nbsp;&nbsp; * @param orderid<br>&nbsp;&nbsp; *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
序号<br>&nbsp;&nbsp; * @return<br>&nbsp;&nbsp; */<br>&nbsp;&nbsp;private DataTreeNode getSubNode(int orderid) 
{<br>&nbsp;&nbsp;&nbsp;return (DataTreeNode) this.subNodes.get(orderid);<br>&nbsp;&nbsp;}</p>
<p>&nbsp;&nbsp;private boolean removeSubNode(int orderid) {<br>&nbsp;&nbsp;&nbsp;try 
{<br>&nbsp;&nbsp;&nbsp;&nbsp;subNodes.remove(orderid);<br>&nbsp;&nbsp;&nbsp;&nbsp;return true;<br>&nbsp;&nbsp;&nbsp;} catch (Exception 
ex) {<br>&nbsp;&nbsp;&nbsp;&nbsp;return false;<br>&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;}</p>
<p>&nbsp;&nbsp;private boolean removeSubNode(DataTreeNode treeNode) {<br>&nbsp;&nbsp;&nbsp;return 
subNodes.remove(treeNode);<br>&nbsp;&nbsp;}</p>
<p>&nbsp;&nbsp;/*<br>&nbsp;&nbsp; * (non-Javadoc)<br>&nbsp;&nbsp; * <br>&nbsp;&nbsp; * @see 
java.lang.Object#equals(java.lang.Object)<br>&nbsp;&nbsp; */<br>&nbsp;&nbsp;public boolean 
equals(Object treeNode) {<br>&nbsp;&nbsp;&nbsp;if (treeNode instanceof DataTreeNode) 
{<br>&nbsp;&nbsp;&nbsp;&nbsp;if (this.nodeID.equals(((DataTreeNode) treeNode).getNodeID())) 
{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return true;<br>&nbsp;&nbsp;&nbsp;&nbsp;} else {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return false;<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;} 
else {<br>&nbsp;&nbsp;&nbsp;&nbsp;return false;<br>&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;}</p>
<p>&nbsp;&nbsp;/*<br>&nbsp;&nbsp; * (non-Javadoc)<br>&nbsp;&nbsp; * <br>&nbsp;&nbsp; * @see 
java.lang.Object#toString()<br>&nbsp;&nbsp; */<br>&nbsp;&nbsp;public String toString() 
{<br>&nbsp;&nbsp;&nbsp;return this.nodeID + " " + node.toString();<br>&nbsp;&nbsp;}<br>&nbsp;}</p>
<p>}</p></td></tr>
<tr>
<td>
<table border="0" cellspacing="0">
</table></td></tr>




</tbody></table></div><div id="entrycns!1ppLlQyegnTGhBatkQ-HqHlQ!109"><br>
</div>
<img src ="http://www.blogjava.net/luoqx/aggbug/11288.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/luoqx/" target="_blank">publisher luo</a> 2005-08-27 11:18 <a href="http://www.blogjava.net/luoqx/articles/11288.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>why? EnterpriseBean extend Serializable</title><link>http://www.blogjava.net/luoqx/articles/11287.html</link><dc:creator>publisher luo</dc:creator><author>publisher luo</author><pubDate>Sat, 27 Aug 2005 03:17:00 GMT</pubDate><guid>http://www.blogjava.net/luoqx/articles/11287.html</guid><wfw:comment>http://www.blogjava.net/luoqx/comments/11287.html</wfw:comment><comments>http://www.blogjava.net/luoqx/articles/11287.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/luoqx/comments/commentRss/11287.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/luoqx/services/trackbacks/11287.html</trackback:ping><description><![CDATA[<table _base_href="http://spaces.msn.com/mmm2005-08-03_15.21/" class="fixedTable blogpost" border="0" cellspacing="0" width="100%">
<tbody _base_href="http://spaces.msn.com/mmm2005-08-03_15.21/"><tr><td class="ellipse"><span class="bvTitle" id="subjcns!1ppLlQyegnTGhBatkQ-HqHlQ!115"></span><br>
</td></tr>
<tr>
<td class="bvh8"><br>
</td></tr>
<tr>
<td id="msgcns!1ppLlQyegnTGhBatkQ-HqHlQ!115">
<div>&nbsp;&nbsp;&nbsp; 
同事问了一个这样的问题，大家都知道，ejb的本地接口，远程接口还有参数都需要序列话，这是因为这些东西都需要分布式传输，可是在容器了的bean不需要分布传输为什么也要实现serializable接口呢？</div>
<div>&nbsp;&nbsp;&nbsp; 上网差了些资料，主要有两种说法，一个是app 
server要作cluster，交换内存中数据（包括ejb）。二是ejbPassivate（钝化）和ejbActivate() 
（活化）时需要使用序列话。第二种说法可能性比较大。</div>
<div>参考资料：</div>
<div><a href="http://www.theserverside.com/discussions/thread.tss?thread_id=6966">http://www.theserverside.com/discussions/thread.tss?thread_id=6966</a></div>
<div><a href="http://madbean.com/2003/mb2003-13/">http://madbean.com/2003/mb2003-13/</a></div>
<div><a href="http://www.cnblogs.com/lovewindy/articles/174170.html">http://www.cnblogs.com/lovewindy/articles/174170.html</a></div>
<div>&nbsp;</div></td></tr>
<tr>
<td>
<table border="0" cellspacing="0">
<tbody></tbody></table></td></tr></tbody>
</table>
<img src ="http://www.blogjava.net/luoqx/aggbug/11287.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/luoqx/" target="_blank">publisher luo</a> 2005-08-27 11:17 <a href="http://www.blogjava.net/luoqx/articles/11287.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>如何从response里面取出向客户端输出的html流</title><link>http://www.blogjava.net/luoqx/articles/10338.html</link><dc:creator>publisher luo</dc:creator><author>publisher luo</author><pubDate>Wed, 17 Aug 2005 06:40:00 GMT</pubDate><guid>http://www.blogjava.net/luoqx/articles/10338.html</guid><wfw:comment>http://www.blogjava.net/luoqx/comments/10338.html</wfw:comment><comments>http://www.blogjava.net/luoqx/articles/10338.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/luoqx/comments/commentRss/10338.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/luoqx/services/trackbacks/10338.html</trackback:ping><description><![CDATA[项目里需要在把servlet,jsp生成的html代码存储到数据库中。如何解决，比较直接的想法是客户端用xmlhttp,或者直接在客户端js代码里发出请求，然后把得到的html代码在作为提交数据发送给服务器端，由服务器端程序接受并存入数据库中。
<DIV>&nbsp;&nbsp;&nbsp; 但是此方法需要耗费两次网络传输，肯定性能不加，而且处理起来要几块程序同时协作才行。还是想办法从服务器端直接获取。因为从response无法直接得到输出流，得想其他的办法。一种是干脆在服务器端写一个监控socket接口的客户端程序，或者用httpunit帮助完成，就是把客户端程序移到服务器端执行。还是相对比较复杂，能不能从response入手？</DIV>
<DIV>&nbsp;&nbsp; 答案是肯定的，采用response代理来截获response的几个输出函数，然后存储起来，已备查询。<BR>灵感来自于前一阵一直研究的java动态代理机制（现在应用在spring的aop实现中），此处不用动态代理，就使用静态代理，proxy模式就足够了。
<DIV>&nbsp; 分别实现三个代理类：ServletResponseProxy，ServletOutputStreamProxy，PrintWriterProxy</DIV>
<DIV>Responseproxy&nbsp;主要代码：</DIV>
<DIV>public class ServletResponseProxy implements HttpServletResponse {<BR>&nbsp;private HttpServletResponse obj;//实际的HttpServletResponse&nbsp;实例<BR>&nbsp;</DIV>
<DIV>&nbsp;public ServletResponseProxy(HttpServletResponse obj) {<BR>&nbsp;&nbsp;this.obj = obj;<BR>&nbsp;&nbsp;HtmlBuffer.cleanStr(); //情空缓存<BR>&nbsp;}&nbsp;&nbsp;&nbsp; </DIV>
<DIV>&nbsp;</DIV>
<DIV>//获得outputStreamProxy<BR>&nbsp;public ServletOutputStream getOutputStream() throws IOException {<BR>&nbsp;&nbsp;ServletOutputStream so = obj.getOutputStream();<BR>&nbsp;&nbsp;ServletOutputStreamProxy sop = new ServletOutputStreamProxy(so);<BR>&nbsp;&nbsp;return sop;<BR>&nbsp;}</DIV>
<DIV>&nbsp;//获得printWriterProxy<BR>&nbsp;public PrintWriter getWriter() throws IOException {<BR>&nbsp;&nbsp;PrintWriter pw = obj.getWriter();<BR>&nbsp;&nbsp;PrintWriterProxy pwp = new PrintWriterProxy(pw);<BR>&nbsp;&nbsp;return (PrintWriter) pwp;<BR>&nbsp;}<BR>}<BR>
<DIV>PrintWriterProxy:</DIV>
<DIV>&nbsp;</DIV>
<DIV>public class PrintWriterProxy<BR>&nbsp;&nbsp;&nbsp; extends PrintWriter {<BR>&nbsp; private PrintWriter pw = null;<BR>&nbsp; <BR>&nbsp; public PrintWriterProxy(PrintWriter pw) {<BR>&nbsp;&nbsp;&nbsp; super(pw);<BR>&nbsp;&nbsp;&nbsp; this.pw = pw;<BR>&nbsp; }</DIV>
<DIV>//截获写内容写入buffer</DIV>
<DIV>&nbsp; public void write(int c) {<BR>&nbsp;&nbsp;&nbsp; char a = (char) c;<BR>&nbsp;&nbsp;&nbsp; String s = new String(new char[] {a});<BR>&nbsp;&nbsp;&nbsp; HtmlBuffer.addStr(s);<BR>&nbsp;&nbsp;&nbsp; pw.write(c);<BR>&nbsp; }</DIV>
<DIV>}</DIV>
<DIV>&nbsp;</DIV>
<DIV>ServletOutputStreamProxy:</DIV>
<DIV>public class ServletOutputStreamProxy<BR>&nbsp;&nbsp;&nbsp; extends ServletOutputStream {<BR>&nbsp; private ServletOutputStream obj;</DIV>
<DIV>&nbsp; public ServletOutputStreamProxy(ServletOutputStream obj){<BR>&nbsp;&nbsp;&nbsp; this.obj = obj;<BR>&nbsp; }</DIV>
<DIV>//截获写内容写入buffer</DIV>
<DIV>&nbsp; public void write(int b) throws IOException {<BR>&nbsp;&nbsp;&nbsp; Integer it = new Integer(b);<BR>&nbsp;&nbsp;&nbsp; HtmlBuffer.addStr(new String(new byte[]{it.byteValue()}));<BR>&nbsp;&nbsp;&nbsp; obj.write(b);<BR>&nbsp; }</DIV>
<DIV>}</DIV>
<DIV><BR>&nbsp;
<DIV>&nbsp;&nbsp;&nbsp; 由于web Httpserver 是多线程执行服务端程序，所以buffer应该分线程来存取，这样大家才能不互相干扰。所以buffer需要实现TreadLocal接口。</DIV>
<DIV>&nbsp;&nbsp;&nbsp; HtmlBuffer代码简单实现如下：</DIV>
<DIV>public class HtmlBuffer {</DIV>
<DIV>&nbsp;private static class HtmlInfo extends ThreadLocal {<BR>&nbsp;&nbsp;private Map values = Collections.synchronizedMap(new HashMap());</DIV>
<DIV>&nbsp;&nbsp;public Object initialValue() {<BR>&nbsp;&nbsp;&nbsp;return new String();<BR>&nbsp;&nbsp;}</DIV>
<DIV>&nbsp;&nbsp;public String getHtmlStr() {<BR>&nbsp;&nbsp;&nbsp;return (String) this.get();<BR>&nbsp;&nbsp;}</DIV>
<DIV>&nbsp;&nbsp;public Object get() {<BR>&nbsp;&nbsp;&nbsp;Thread curThread = Thread.currentThread();<BR>&nbsp;&nbsp;&nbsp;Object o = values.get(curThread);<BR>&nbsp;&nbsp;&nbsp;if (o == null &amp;&amp; !values.containsKey(curThread)) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;o = initialValue();<BR>&nbsp;&nbsp;&nbsp;&nbsp;values.put(curThread, o);<BR>&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;&nbsp;return o;<BR>&nbsp;&nbsp;}</DIV>
<DIV>&nbsp;&nbsp;public void set(Object newValue) {<BR>&nbsp;&nbsp;&nbsp;values.put(Thread.currentThread(), newValue);<BR>&nbsp;&nbsp;}<BR>&nbsp;}&nbsp;</DIV>
<DIV>&nbsp;private static HtmlInfo htmlInfo = new HtmlInfo();<BR>&nbsp;<BR>&nbsp;public static void cleanStr(){<BR>&nbsp;&nbsp;htmlInfo.set( "");<BR>&nbsp;}</DIV>
<DIV>&nbsp;public static void addStr(String htmlStr) {<BR>&nbsp;&nbsp;String htmlstr = (String)htmlInfo.get();<BR>&nbsp;&nbsp;if(htmlstr == null) htmlstr ="";<BR>&nbsp;&nbsp;htmlstr += htmlStr;<BR>&nbsp;&nbsp;htmlInfo.set( htmlstr);<BR>&nbsp;}</DIV>
<DIV>&nbsp;public static String getStr() {<BR>&nbsp;&nbsp;return (String)htmlInfo.get();<BR>&nbsp;}<BR>}</DIV></DIV></DIV></DIV><img src ="http://www.blogjava.net/luoqx/aggbug/10338.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/luoqx/" target="_blank">publisher luo</a> 2005-08-17 14:40 <a href="http://www.blogjava.net/luoqx/articles/10338.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>