bianbian coding life

便便代码人生: 关注技术, 翻译文档, 偶尔动动手

Archive for the 'Java' Category

Java….

[原] ftp4j的解析list的bug及解决

Posted by bianbian on 2008-06-19 08:08


本文Tags: , , ,

上次推荐的ftp4j在解析部分FTP站点的目录list的时候遇到了FTPListParseException(也怪FTP协议没有对LIST格式作出标准)。查看源码发现,主要是两个问题:
1)文件权限不只rwx这三个,附加了s、t(详见http://en.wikipedia.org/wiki/File_system_permissions
2)部分ftpd似乎直接调用的“ls -l”输出目录,第一行是“total xxx”
给作者写信了,说不定下个版本就有Sepcial Thanks to bianbian 了。嘿嘿嘿嘿。。。
修正后的代码(省略后面没有变化的部分):
Read the rest of this entry »

标签: , , ,

遵守创作共用协议,转载请链接形式注明来自http://bianbian.org 做人要厚道

相关日志

Posted in Java, Technology | 4 Comments »

[原] Shibboleth 2.0 Identity Provider (IdP) LDAP认证配置指南

Posted by bianbian on 2008-05-14 01:15


本文Tags: , , , ,

首先佩服老外:1)把简单的东西搞得很复杂 2)很会创造标准和协议
这次遇到的Shibboleth就是这么个东西,看了两天英文,对人为复杂、创造协议痛恨中。简单写个配置指南,给其他人做个参考,少走弯路。

注意:
1) 系统时间必须设置正确
2) apache 需要 mod_ssl mod_proxy_ajp,假设安装在 /etc/httpd
3) 必须使用 tomcat-5.5.x+,假设安装在 /opt/apache-tomcat-5.5.26
4) 如果需要改变安装目录重新安装,必须退到解压那步(否则很多和目录有关的代码不会重新编译,导致严重错误–啊!我整整一天的痛苦啊!)
Read the rest of this entry »

标签: , , , ,

遵守创作共用协议,转载请链接形式注明来自http://bianbian.org 做人要厚道

相关日志

Posted in Java, Technology | No Comments »

[原] solr 1.3 multicore使用指南

Posted by bianbian on 2008-05-05 10:42


本文Tags: , ,

尽管solr 1.3还是dev版,目前还没release,它比1.2多的很多特性(特别是multicore的支持)还是让我选择了1.3(1.2用了一段时间,多个索引要复制多份,非常麻烦)。
使用基本和solr 1.2差不多,几乎没什么难度就切换到1.3了。只是多了multicore的配置:
solr/home比如设为/opt/solrs
在/opt/solrs下新建multicore.xml

  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <multicore adminPath="/admin/multicore" persistent="true" sharedLib="lib">
  3.  <core name="core0" instanceDir="core0" default="true"/>
  4.  <core name="core1" instanceDir="core1" />
  5. </multicore>

Read the rest of this entry »

标签: , ,

遵守创作共用协议,转载请链接形式注明来自http://bianbian.org 做人要厚道

相关日志

Posted in Java, Technology | No Comments »

[原] spring的事件监听和java反射及IoC注入还是很强大的

Posted by bianbian on 2008-04-25 09:16


本文Tags: , ,

这几天做了一个东西:在DAO上往数据库插入一个bean的时候,用java反射机制自动产生SQL语句,同时publishEvent触发bean更新事件,事件监听类根据配置文件处理bean并自动提交到Lucene(Solr)全文检索(主要是bean的属性跟Solr字段的对应)进行准实时的索引更新(当然bean有缓冲);反过来,检索结果有望自动转成bean丢给用户callback。
danny这个巨牛完成的基于spring的再次开发框架除了自动controller Action绑定、ResultSet自动转成bean、自动分页、自动View视图等等快捷开发功能外(Orz),现在支持自动全文检索了,而且整个过程对其他开发人员是无缝过渡的,建立全文索引不需要修改任何一处代码(其实概念上用AOP比事件监听更适合:“可热插拔”的全文检索切面,但是事件监听最大的优势是异步的,全文检索准实时索引更新这种需求用AOP同步包装一层实在是太不实际了):只要在配置文件里指定哪些数据表的bean哪些字段需要全文检索,OK。。。添加或者全记录更新的时候索引都会准实时更新——而且几乎近似热插拔。

标签: , ,

遵守创作共用协议,转载请链接形式注明来自http://bianbian.org 做人要厚道

相关日志

Posted in Java, Technology | 1 Comment »

[原] 强烈推荐一个纯java的FTP Client库:ftp4j

Posted by bianbian on 2008-04-15 11:08


本文Tags: , ,

ftp4j是个很年轻的开源项目,但是试用后发现很好很强大,如果你找一个纯java的FTP库,要支持socks4,socks4a,socks5,http代理,就是他了!
比apache的FTPClient(不支持代理)、半商业的edtFTPj(PRO支持代理,但是要$,而且是系统变量级的代理,不能单个指定)等好用多了,而且是LGPL协议,源码质量很高。(不过如果你需要FTPS及SFTP,那ftp4j不支持)
jar包只有50多k,地址在这里:ftp4j
使用代理的代码:

  1. import java.util.ArrayList;
  2. import it.sauronsoftware.ftp4j.FTPClient;
  3. import it.sauronsoftware.ftp4j.FTPFile;
  4. import it.sauronsoftware.ftp4j.connectors.SOCKS4Connector;
  5. ......
  6. //ftp4j使用socks4代理连接FTP示例,by http://bianbian.org
  7. FTPClient ftp = new FTPClient();
  8. SOCKS4Connector socks4 = new SOCKS4Connector("127.0.0.1", 1080);
  9. ftp.setConnector(socks4);
  10. ftp.connect("an.ip.or.host", 21);
  11. ftp.login("anonymous", "bianbian@bianbian.org");
  12. ftp.setCharset("gbk");
  13. //list files
  14. FTPFile[] list = ftp.list();
  15. for(FTPFile file : list) {
  16.     System.out.println(file);
  17. }
  18. ftp.disconnect(true);
标签: , ,

遵守创作共用协议,转载请链接形式注明来自http://bianbian.org 做人要厚道

相关日志

Posted in Java, Technology | 2 Comments »

[转] Hibernate映射对象标识符(OID)与数据库主键对应关系

Posted by bianbian on 2007-07-13 04:36


本文Tags:

原文:http://www.blogjava.net/action/archive/2007/05/22/119134.html
Hibernate采用对象标识符,也就是通常我们所说的OID来创建对象和数据库表里记录的对应关系,对象的OID和表里的主键对应,所以说OID是非常重要的,不应该让程序来给它赋值.数据库区分同一表的不同记录是用主键来区分.数据库中的主键最重要的3个基本要素就是不允许为null,不允许有重复值,主键永远不会改变.所以通常我们设计表都会设计主键的值为自动增加,没有业务逻辑含义的一组数字,当然针对每个数据库,设置的方法也不同.但是都非常简单.加一个属性就可以了.
而JAVA区分同一类的不同对象是用内存地址,在JAVA语言中判断两个对象的引用变量是否想相等,有以下两种比较方式.1)用运算符”==”比较内存地址,此外还可以用Object的equals方法也是按内存地址比较.2)比较两个对象的值是否相同,JAVA中的一些覆盖了Object类的equals方法实现比较合适.例如String和Date类,还有JAVA包装类.如果是String.equals(String)这种方式的比较就是比较这两个String的值的.如果是Object原是的equals方法就是比较地址了.这点很容易混淆.
通常,为了包装Hibernate的OID的唯一性和不可变性,由Hibernate或者底层数据库来给OID赋值比较合理.因此我们在编程的时候最好把持久化类的OID设置为private或者protected类型,这样可以防止JAVA程序随便更改OID.而OID的get方法我们还是要设置为public类型,这样方便我们读取. 在对象-关系映射文件里的 1)increment 代理主键,hibernate自动以递增的方式来生成标识符,每次增加1.
2)identity 代理主键,由底层数据库生成标识符,前提就是底层的数据库支持自动增长的类型.
3)sequence 代理主键,hibernate根据底层数据库生成的标识符,前提是底层数据库支持序列
4)hilo 代理主键,hibernate根据higg/low算法来生成的标识符,把特定表的字段作为high的值,默认选用hibernate_unique_key表的next_hi字段
5)native 代理主键,根据底层数据库对自动生成标识符的支持能力,还选择identity,sequence,或hilo.
6)uuid.hex 代理主键,hibernate采用128位的UUID算法生成标识符,UUID算法能够在网络环境下生成唯一字符串标识符.不过字符串要比数据占用的空间多的多.所以不流行使用.
7)assigned 适用于自然主键,由JAVA应用程序负责生成标识符,为了能让JAVA设置OID.不能吧setId方法设置为非公共类型了,这种方式也尽量避免使用.
这里个人觉得第一种方式,也就是说由Hibernate来生成对象标识符的方式比较好.但是这种方式的缺点是只能一个Hibernate对应一个数据库的表.当同时创建了SeesionFactory实例的时候.两个或者更多的Hibernate对应同一个数据库的时候就会插入出错.这个时候我们可以选择第二种方式把标识符的生成工作交给底层数据库.还有一个小知识点要注意就是OID必须定义为long,int,short类型,如果定义为byte会报异常,这里推荐用long.
总结一下,这7中生成OID标识符的方法,increment 比较常用,把标识符生成的权力交给Hibernate处理.但是当同时多个Hibernate应用操作同一个数据库,甚至同一张表的时候.就推荐使用identity 依赖底层数据库实现,但是数据库必须支持自动增长,sequence 以来底层数据库实现,但是数据库必须支持系列.hilo 根据特定的表实现.这三种方式了.当然针对不同的数据库选择不同的方法.如果你不能确定你使用的数据库具体支持什么的情况下.可以选择第三种.或者用native 让Hibernate来帮选择identity,sequence,或hilo.后边的自然主键不推荐使用,因为自然主键就是具有业务含义的主键,在现在的软件开发结构中,已经很少有人用了.下面总结一下几种常用数据库,可以使用的标识符类型.
MySQL:identity数据库底层实现,需要支持自动增长,increment由Hibernate实现,hilo用特定的表实现,
MSSQL:identity数据库底层实现,需要支持自动增长,increment由Hibernate实现,hilo用特定的表实现,
Oracle:sequence数据库底层实现,需要支持序列,increment由Hibernate实现,hilo用特定的表实现,
以上不难发现,所有的数据库都支持Hibernate用increment实现OID的生成,MYSQL和MSSQL数据库底层实现支持自动增长,而Oracle支持序列,还有用特殊表的实现方式这三个数据库都支持.还有一种实现方式适用于所有的数据库,就是native,由Hibernate去选择使用什么样的方式来生成IOD对象标识符,这种方式也是跨平台的.下面是各种设置方式的例子*.hbm.xml文件四个.例题来源孙MM的<<精通Hibernate>>一书.我非常喜欢这本书,讲的非常简单明了.感兴趣的朋友可以去买一本看看(当当打7.3折哦).

  1. <?xml version="1.0"?>
  2. <!DOCTYPE hibernate-mapping
  3. PUBLIC "-//Hibernate/Hibernate Mapping DTD 2.0//EN"
  4. "http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">
  5. <hibernate-mapping>
  6.  
  7.   <class name="mypack.HiloTester"  table="HILO_TESTER">
  8.    
  9.     <id name="id" type="long" column="ID">
  10.     <generator class="hilo">
  11.                 <param name="table">hi_value</param>
  12.                 <param name="column">next_value</param>
  13.                 <param name="max_lo">100</param>
  14.         </generator>
  15.     </id>
  16.  
  17.     <property name="name" type="string" >
  18.         <column name="name" length="15" />
  19.     </property>
  20.    
  21.   </class>
  22.  
  23. </hibernate-mapping>
  24.  
  25. <?xml version="1.0"?>
  26. <!DOCTYPE hibernate-mapping
  27. PUBLIC "-//Hibernate/Hibernate Mapping DTD 2.0//EN"
  28. "http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">
  29. <hibernate-mapping>
  30.  
  31.   <class name="mypack.IdentityTester"  table="IDENTITY_TESTER">
  32.    
  33.     <id name="id" type="long" column="ID">
  34.       <generator class="identity"/>
  35.     </id>
  36.  
  37.     <property name="name" type="string" >
  38.         <column name="name" length="15"/>
  39.     </property>
  40.    
  41.   </class>
  42.  
  43. </hibernate-mapping>
  44.  
  45. <?xml version="1.0"?>
  46. <!DOCTYPE hibernate-mapping
  47. PUBLIC "-//Hibernate/Hibernate Mapping DTD 2.0//EN"
  48. "http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">
  49. <hibernate-mapping>
  50.  
  51.   <class name="mypack.NativeTester" table="NATIVE_TESTER" >
  52.    
  53.     <id name="id" type="long" column="ID">
  54.       <generator class="native"/>
  55.     </id>
  56.  
  57.     <property name="name" type="string" >
  58.         <column name="name" length="15" />
  59.     </property>
  60.    
  61.   </class>
  62.  
  63. </hibernate-mapping>
  64.  
  65. <?xml version="1.0"?>
  66. <!DOCTYPE hibernate-mapping
  67. PUBLIC "-//Hibernate/Hibernate Mapping DTD 2.0//EN"
  68. "http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">
  69. <hibernate-mapping>
  70.  
  71.   <class name="mypack.IncrementTester" table="INCREMENT_TESTER" >
  72.    
  73.     <id name="id" type="long" column="ID">
  74.       <meta attribute="scope-set">private</meta>
  75.       <generator class="increment"/>
  76.     </id>
  77.  
  78.     <property name="name" type="string" >
  79.         <column name="NAME" length="15" />
  80.     </property>
  81.    
  82.   </class>
  83.  
  84. </hibernate-mapping>
标签:

遵守创作共用协议,转载请链接形式注明来自http://bianbian.org 做人要厚道

相关日志

Posted in Database, Java, Technology | No Comments »

[译]volatile关键字有什么用?

Posted by bianbian on 2006-12-13 07:52


本文Tags: ,

最近看LumaQQ的源码发现一个volatile(中文意思是“可变的、不稳定的”),找了篇英文介绍。抽空我翻译了一下,翻错了大家不要见笑。。。

volatile关键字有什么用?
  恐怕比较一下volatile和synchronized的不同是最容易解释清楚的。volatile是变量修饰符,而synchronized则作用于一段代码或方法;看如下三句get代码:

  1. int i1;              int geti1() {return i1;}
  2. volatile int i2;              int geti2() {return i2;}
  3.          int i3; synchronized int geti3() {return i3;}

  geti1()得到存储在当前线程中i1的数值。多个线程有多个i1变量拷贝,而且这些i1之间可以互不相同。换句话说,另一个线程可能已经改变了它线程内的i1值,而这个值可以和当前线程中的i1值不相同。事实上,Java有个思想叫“主”内存区域,这里存放了变量目前的“准确值”。每个线程可以有它自己的变量拷贝,而这个变量拷贝值可以和“主”内存区域里存放的不同。因此实际上存在一种可能:“主”内存区域里的i1值是1,线程1里的i1值是2,线程2里的i1值是3——这在线程1和线程2都改变了它们各自的i1值,而且这个改变还没来得及传递给“主”内存区域或其他线程时就会发生。
  而geti2()得到的是“主”内存区域的i2数值。用volatile修饰后的变量不允许有不同于“主”内存区域的变量拷贝。换句话说,一个变量经volatile修饰后在所有线程中必须是同步的;任何线程中改变了它的值,所有其他线程立即获取到了相同的值。理所当然的,volatile修饰的变量存取时比一般变量消耗的资源要多一点,因为线程有它自己的变量拷贝更为高效。
  既然volatile关键字已经实现了线程间数据同步,又要synchronized干什么呢?呵呵,它们之间有两点不同。首先,synchronized获得并释放监视器——如果两个线程使用了同一个对象锁,监视器能强制保证代码块同时只被一个线程所执行——这是众所周知的事实。但是,synchronized也同步内存:事实上,synchronized在“主”内存区域同步整个线程的内存。因此,执行geti3()方法做了如下几步:
1. 线程请求获得监视this对象的对象锁(假设未被锁,否则线程等待直到锁释放)
2. 线程内存的数据被消除,从“主”内存区域中读入(Java虚拟机能优化此步。。。[后面的不知道怎么表达,汗])
3. 代码块被执行
4. 对于变量的任何改变现在可以安全地写到“主”内存区域中(不过geti3()方法不会改变变量值)
5. 线程释放监视this对象的对象锁
  因此volatile只是在线程内存和“主”内存间同步某个变量的值,而synchronized通过锁定和解锁某个监视器同步所有变量的值。显然synchronized要比volatile消耗更多资源。

附英文原文:
What does volatile do?

This is probably best explained by comparing the effects that volatile and synchronized have on a method. volatile is a field modifier, while synchronized modifies code blocks and methods. So we can specify three variations of a simple accessor using those two keywords:

  1. int i1;              int geti1() {return i1;}
  2. volatile int i2;              int geti2() {return i2;}
  3.          int i3; synchronized int geti3() {return i3;}

geti1() accesses the value currently stored in i1 in the current thread. Threads can have local copies of variables, and the data does not have to be the same as the data held in other threads. In particular, another thread may have updated i1 in it’s thread, but the value in the current thread could be different from that updated value. In fact Java has the idea of a “main” memory, and this is the memory that holds the current “correct” value for variables. Threads can have their own copy of data for variables, and the thread copy can be different from the “main” memory. So in fact, it is possible for the “main” memory to have a value of 1 for i1, for thread1 to have a value of 2 for i1 and for thread2 to have a value of 3 for i1 if thread1 and thread2 have both updated i1 but those updated value has not yet been propagated to “main” memory or other threads.

On the other hand, geti2() effectively accesses the value of i2 from “main” memory. A volatile variable is not allowed to have a local copy of a variable that is different from the value currently held in “main” memory. Effectively, a variable declared volatile must have it’s data synchronized across all threads, so that whenever you access or update the variable in any thread, all other threads immediately see the same value. Of course, it is likely that volatile variables have a higher access and update overhead than “plain” variables, since the reason threads can have their own copy of data is for better efficiency.

Well if volatile already synchronizes data across threads, what is synchronized for? Well there are two differences. Firstly synchronized obtains and releases locks on monitors which can force only one thread at a time to execute a code block, if both threads use the same monitor (effectively the same object lock). That’s the fairly well known aspect to synchronized. But synchronized also synchronizes memory. In fact synchronized synchronizes the whole of thread memory with “main” memory. So executing geti3() does the following:

1. The thread acquires the lock on the monitor for object this (assuming the monitor is unlocked, otherwise the thread waits until the monitor is unlocked).
2. The thread memory flushes all its variables, i.e. it has all of its variables effectively read from “main” memory (JVMs can use dirty sets to optimize this so that only “dirty” variables are flushed, but conceptually this is the same. See section 17.9 of the Java language specification).
3. The code block is executed (in this case setting the return value to the current value of i3, which may have just been reset from “main” memory).
4. (Any changes to variables would normally now be written out to “main” memory, but for geti3() we have no changes.)
5. The thread releases the lock on the monitor for object this.

So where volatile only synchronizes the value of one variable between thread memory and “main” memory, synchronized synchronizes the value of all variables between thread memory and “main” memory, and locks and releases a monitor to boot. Clearly synchronized is likely to have more overhead than volatile.

标签: ,

遵守创作共用协议,转载请链接形式注明来自http://bianbian.org 做人要厚道

相关日志

Posted in Java, Technology | 4 Comments »

[原]Java正则表达式获取匹配结果

Posted by bianbian on 2006-12-02 10:41


本文Tags: ,

  1. Pattern p = Pattern.compile("正则表达式");
  2. Matcher m = p.matcher("预匹配的字符串");
  3. if(m.matches()) {
  4.     m.group(1); //匹配第1项
  5.     m.group(2); //匹配第2项
  6. }

有关正则表达式语法,请参考:文档 Document

标签: ,

遵守创作共用协议,转载请链接形式注明来自http://bianbian.org 做人要厚道

相关日志

Posted in Java, Technology | No Comments »

[嗯]OSCache很不错啊

Posted by bianbian on 2006-11-07 07:47


本文Tags: , ,

比较好用,改天再来说一下。
http://www.opensymphony.com/oscache/wiki/JSP%20Tags.html#JSPTags-cache

标签: , ,

遵守创作共用协议,转载请链接形式注明来自http://bianbian.org 做人要厚道

相关日志

Posted in Java, Technology | No Comments »

[原]Memory/logger leak with multiple VelocityEngine instances

Posted by bianbian on 2006-09-12 03:32


本文Tags:

之前有问过这个奇怪的问题,日志一直报错:
log4j:ERROR Attempted to append to closed appender named [null].

原来是velocity的bug,目前为止所有release都有这个bug (velocity的网站上说1.5版会fix这个bug)
> Key: VELOCITY-193
> URL: http://issues.apache.org/jira/browse/VELOCITY-193
> Project: Velocity
> Type: Bug
When creating and then releasing to garbage collection multiple VelocityEngine instances, the
instances are apparently not closing out or otherwise letting go of their logger instances. As a
result, code that needs to create and destroy several VelocityEngine instances will eventually choke and die. This happens with either Avalon Logkit or Log4j, although the exact nature of the choking differs. This test program isolates the problem:

import org.apache.velocity.app.VelocityEngine;
public class IsolateVelocityBug {
static public void main( String[] args ) {
int repCount = Integer.parseInt( args[0] );
for( int i = 0; i < repCount; i++ ) {
System.out.println( "Test repetition " + i + "..." );
try {
final VelocityEngine velocityEngine = new VelocityEngine();
velocityEngine.init();
} catch( Exception e ) {
throw new Error( e );
}
}
}
}

Run the program with an integer command-line argument specifying the number of times to cycle through the loop, and make sure velocity-1.3.1.jar, commons-collections.jar, and either an Avalon Logkit or Log4j JAR are on your classpath. (I tested with logkit-1.0.1.jar and log4j-1.1.3.jar.) What *should* happen is that the program completes its specified number of loops, doing nothing but writing “Test repetition” over and over with an incrementing number. What *does* happen, at least on my machine, depends on which logging package is provided for Velocity.

Using Avalon Logkit 1.0.1, the program runs fine for 252 iterations; on the 253nd, it aborts with
the following message:

“PANIC : Error configuring AvalonLogSystem : java.io.FileNotFoundException: /Users/ibeatty/
Development/javaDev/VelocityBugIsolator/velocity.log (Too many open files)”

Using Log4j 1.1.3, the program runs fine for only one iteration; on the second and any subsequent iterations, it continues but prints out a whole mess of

“log4j:ERROR Attempted to append to closed appender named [null].
log4j:WARN Not allowed to write to a closed appender.”

That happens for as long as I care to let it run (95 iterations, with something over 800 lines of
such errors per iteration by the end).

To me, it sure looks like Velocity is leaving dangling loggers behind as VelocityEngine instances
are created and discarded, and that the two logging systems respond differently to this but both have problems.

Why, might you ask, should anyone care about making many VelocityEngine instances? I ran into it when developing a major web app using JUnit to build comprehensive test suites. To run
independently, every test has to start from scratch, which means getting its own VelocityEngine.
Many tests means many instances, and the logging problem kicks in. Running JUnit test suites
within Intellij IDEA and using Log4j, the ERROR/WARN messages were more than a nuicanse;
eventually, I’d start getting out-of-memory errors, too. These went away when I changed the tests to use a shared VelocityEngine instance (which caused its own set of problems).

Using binary download of Velocity 1.3.1, which claims to have been created on 2003-04-01.

I find it hard to believe nobody else has tripped over this before, so maybe it’s sensitive to the OS or something. It happened whether I compiled the test code with Javac or Jikes. Using Java
1.4.1_01.

标签:

遵守创作共用协议,转载请链接形式注明来自http://bianbian.org 做人要厚道

相关日志

Posted in Java, Technology | No Comments »

[原]利用HttpServletResponseWrapper获取jsp输出内容

Posted by bianbian on 2006-08-29 07:17


本文Tags:

有时候我们需要得到某个jsp的输出内容。比如说在servlet里处理了Module Controller后,需要不同的jsp页面来展示view;又或者得到不同的模板内容(jsp本身可以作为模板语言)并将其缓冲到内存里。
利用 javax.servlet.http.HttpServletResponseWrapper 可以很好地实现我们所需要的功能。下面是使用方法:

  1. ....
  2. public static String getJspOutput(String jsppath, HttpServletRequest request, HttpServletResponse response)
  3.     throws Exception
  4. {
  5.     WrapperResponse wrapperResponse = new WrapperResponse(response);
  6.     request.getRequestDispatcher(jsppath).include(request, wrapperResponse);
  7.     return wrapperResponse.getContent();
  8. }

可以看到,使用起来还是挺方便的。getJspOutput(”/view/header.jsp”, request, response) 就完成了对”/view/header.jsp”的输出内容获取,之后可以进行其他操作。
附WrapperResponse类代码:

  1. import java.io.ByteArrayOutputStream;
  2. import java.io.IOException;
  3. import java.io.PrintWriter;
  4. import java.io.UnsupportedEncodingException;
  5.  
  6. import javax.servlet.ServletOutputStream;
  7. import javax.servlet.http.HttpServletResponse;
  8. import javax.servlet.http.HttpServletResponseWrapper
  9. /**
  10. * @see http://bianbian.sunshow.net/
  11. * @author dannyzhu, bianbian
  12. * @version 1.0
  13. */
  14. public class WrapperResponse extends HttpServletResponseWrapper
  15. {
  16.     private PrintWriter tmpWriter;
  17.     private ByteArrayOutputStream output;
  18.     private ByteArrayServletOutputStream servletOutput;
  19.  
  20.     public WrapperResponse(HttpServletResponse httpServletResponse)
  21.     {
  22.         super(httpServletResponse);
  23.         output = new ByteArrayOutputStream();
  24.         tmpWriter = new PrintWriter(output);
  25.         servletOutput = new ByteArrayServletOutputStream(output);
  26.     }
  27.  
  28.     public void finalize() throws Throwable
  29.     {
  30.         super.finalize();
  31.         servletOutput.close();
  32.         output.close();
  33.         tmpWriter.close();
  34.     }
  35.  
  36.     public String getContent()
  37.     {
  38.         try{
  39.             String s = output.toString("UTF-8");
  40.             reset();
  41.             return s;
  42.         } catch(UnsupportedEncodingException e) {
  43.             return "UnsupportedEncoding";
  44.         }
  45.     }
  46.  
  47.     public PrintWriter getWriter() throws IOException
  48.     {
  49.         // return servletResponse.getWriter();
  50.         return tmpWriter;
  51.     }
  52.  
  53.     public ServletOutputStream getOutputStream() throws IOException
  54.     {
  55.         return servletOutput;
  56.     }
  57.  
  58.     public byte[] toByteArray()
  59.     {
  60.         return output.toByteArray();
  61.     }
  62.  
  63.     public void flushBuffer() throws IOException
  64.     {
  65.         tmpWriter.flush();
  66.         servletOutput.flush();
  67.     }
  68.  
  69.     public void reset()
  70.     {
  71.         output.reset();
  72.     }
  73.  
  74.     public void close() throws IOException
  75.     {
  76.         tmpWriter.close();
  77.     }
  78.  
  79.     private static class ByteArrayServletOutputStream extends ServletOutputStream
  80.     {
  81.  
  82.         ByteArrayOutputStream baos;
  83.  
  84.         public ByteArrayServletOutputStream(ByteArrayOutputStream baos)
  85.         {
  86.             this.baos = baos;
  87.         }
  88.  
  89.         public void write(int i) throws IOException
  90.         {
  91.             baos.write(i);
  92.         }
  93.  
  94.     }
  95. }
标签:

遵守创作共用协议,转载请链接形式注明来自http://bianbian.org 做人要厚道

相关日志

Posted in Java, Technology | No Comments »