
		 
		2006年7月31日		  
	
 
	
			
			 
 
1      基本介绍
可以说CSV格式的文件经常碰到,何为CSV格式,CVS全称comma-separated values,就是典型的用逗号隔开的文件,比如下面这种文件格式
Name,company
zhangsan,ibm
lisi,oracle
这种就是典型的CSV格式文件。不过也可以扩展到其它符号隔开的字符,比如
Name#company
Zhangsan#ibm
Lisi#oracle
这种也算CSV格式
Java开源框架CVSReader提供了一个轻量级、简单方便的统一操作接口可用,下面具体讲解如何操作CVS格式
2      安装和使用
2.1下载
目前CSV reader的最新发布版本是1.8。我们可以从
http://opencsv.sourceforge.net/
上面下载到最新的csvreader包。
2.2安装
直接把jar包分别存放到开发工程的类路径下面即可使用。
3      读取CSV格式文件
3.1基本简介
首先,读取CSV格式的文件需要创建一个CSVReader,如下
CsvReader reader = new CsvReader(Reader r,  char c);
其中第一个参数为读取文件,第二个参数为分割符,比如“,”,或者“#”
另外,也有其它几个参数,可以查阅API,比如
CsvReader reader = new CsvReader(InputStream r,  char c, Charset charset);等等
其次,一般需要读取头信息,如下:
reader.readHeaders();
String[] headers = reader.getHeaders();
读取了后,指针就会移动到下一行,也就是可以开始读取文件内容
假如,有多行的话,可以用一个循环套入,例如下面:
             while (reader.readRecord()) {
                    for (int i = 0; i < headers.length; i++) {
                           String value = reader.get(headers[i]);
                           System.out.print(value+" ");
                    }
                    System.out.println("");
             }
3.2综合例子
在C盘下创建一个测试文件test.cvs,内容如下:
a#b#c
1#2#3
4#5#6
下面是解析代码:
      public static void main(String[] args) throws Exception {
CsvReader reader = new CsvReader(new FileReader("c://csv.txt"), '#');
             reader.readHeaders();
             String[] headers = reader.getHeaders();
             while (reader.readRecord()) {
                    for (int i = 0; i < headers.length; i++) {
                           String value = reader.get(headers[i]);
                           System.out.print(value+" ");
                    }
                    System.out.println("");
             }
      }
运行以上程序,可以看到输出
 1 2 3
 4 5 6
4      写CSV格式文件
写CSV格式文件也比较简单,写每一列只要直接调用
csvWriter.write()即可
另外,写完每行结束后,都要调用 csvWriter.endRecord();
表示结束一行
文件写完毕后,要记得刷新一下并关掉,如下:
       csvWriter.flush();
       csvWriter.close();
代码如下:
    publicstaticvoid main(String[] args) throws Exception {
       CsvWriter csvWriter = new CsvWriter(new FileWriter("c://test.text"), '#');
       csvWriter.write("name");
       csvWriter.write("company");
       csvWriter.endRecord();
       csvWriter.write("11");
       csvWriter.write("12");
       csvWriter.endRecord();
       csvWriter.write("21");
       csvWriter.write("22");
       csvWriter.flush();
       csvWriter.close();
   }
}
运行以上程序,可以看到C盘下面创建了一个文件
test.text
内容如下:
name#company
11#12
21#22
			posted @ 
2008-10-31 14:42 jspark 阅读(11833) | 
评论 (3) | 
编辑 收藏
			     摘要: (本文档的全篇可以到博客下面的文件列表下载,地址下面)  
http://www.blogjava.net/jspark/admin/Files.aspx
为了让尽快对jbossRules有一个感官的认识,下面先开发一个HelloWorld的程序。
建立一个java工程,目录如下:
 
 
如上所示,建立一个com包,然后在下面分别建立一个Sa...  
阅读全文
			posted @ 
2008-10-28 15:54 jspark 阅读(1648) | 
评论 (0) | 
编辑 收藏1      Java规则系统简介
在大型商业系统中,业务规则、商业逻辑等等都会比较复杂。而且在很多大型系统当中,很多业务规则、商业逻辑并不是一成不变的。甚至当系统进入生产阶段时,客户的业务规则、商业逻辑也会改变。某些系统要求甚至更高,要求能24小时不停机,并且能够实时修改商业规则。这就对商业系统提出了较大的挑战。如果将这些可变的规则直接编写到代码里面的话,业务规则一旦改变,就要修改代码。并由此带来编译、打包、发布等等问题。这对于生产系统来说是极不方便的。因此,如何考虑把一些可变的业务规则抽取到外面,使这些业务规则独立于程序代码。并最好是能够实时的修改业务规则,这样就可以做到不用打包编译发布等等。
值得庆幸的是现在出现了一些Java规则引擎(Rule Engine),专门解决以上所述的问题。利用它,我们就可以在应用系统中分离客户的商业决策逻辑和应用开发者的技术决策,并把这些商业规额则放在中心数据库或其他统一的地方,让它们能在运行时可以动态地管理和修改。
JbossRules是一个优秀的JAVA规则引擎,其前身是Drools3,后来被Jboss合并并改名为JbossRules
1.1基于规则的专家系统简介
人工智能是一个新兴的学科,它是想让计算机模拟人脑的思维和推理模式。人工智能分成如下几个主要的分学科:
知识表示
神经网络
基因算法
决策树
专家系统
等等几个学科
知识表示是人工智能中的一个基础领域,其目的是如何更好的在计算机当中描述已存在的事实。专家系统就是使用知识表示,来做规则推理,得出最后的结论来。
Java规则引擎起源于基于规则的专家系统,而基于规则的专家系统又是专家系统的其中一个分支。专家系统属于人工智能的范畴,它模仿人类的推理方式,使用试探性的方法进行推理,并使用人类能理解的术语解释和证明它的推理结论。为了更深入地了解Java规则引擎,下面简要地介绍基于规则的专家系统。RBES包括三部分:Rule Base(knowledge base)、Working Memory(fact base)和Inference Engine。它们的结构如下系统所示:
如上图所示,推理引擎包括三部分:模式匹配器(Pattern Matcher)、议程(Agenda)和执行引擎(Execution Engine)。推理引擎通过决定哪些规则满足事实或目标,并授予规则优先级,满足事实或目标的规则被加入议程。模式匹配器决定选择执行哪个规则,何时执行规则;议程管理模式匹配器挑选出来的规则的执行次序;执行引擎负责执行规则和其他动作。
和人类的思维相对应,推理引擎存在两者推理方式:演绎法(Forward-Chaining)和归纳法(Backward-Chaining)。演绎法从一个初始的事实出发,不断地应用规则得出结论(或执行指定的动作)。而归纳法则是根据假设,不断地寻找符合假设的事实。Rete算法是目前效率最高的一个Forward-Chaining推理算法,许多Java规则引擎都是基于Rete算法来进行推理计算的。
l 正向推理:
 
正向推理图形如下:
正向推理引擎的推理步骤如下:
n 将初始数据(fact)输入Working Memory。
n 使用Pattern Matcher比较规则库(rule base)中的规则(rule)和数据(fact)。
n 如果执行规则存在冲突(conflict),即同时激活了多个规则,将冲突的规则放入冲突集合。
n 解决冲突,将激活的规则按顺序放入Agenda。
n 使用执行引擎执行Agenda中的规则。重复步骤2至5,直到执行完毕所有Agenda中的规则。
n 直到得出最终的结果为止
l 反向推理:
 
反向推理是目标驱动的推理方式。从目标出发,找出所有能满足该目
标的子目标。这样一直推导下去,直到所有的子目标都已经满足为止。
1.2Java规则引擎
Java规则引擎是一种嵌入在Java程序中的组件,它的任务是把当前提交给引擎的Java数据对象与加载在引擎中的业务规则进行测试和比对,激活那些符合当前数据状态下的业务规则,根据业务规则中声明的执行逻辑,触发应用程序中对应的操作。
一般来说,一条规则的形式如下:
when
    <conditions>
then
    <actions>
也就是说,当conditions成立的话,就做下面的actions。其中actions可以为生成新的事实、或者做其他动作,比如,发送email通知、执行一些本地任务等等。
1.3    JAVA规则引擎的优点
n 声明式编程
声明式编程,规则引擎让我们直到“做什么”,而不用直到“怎么做”。我们只要把一系列规则表示出来后。具体的推理动作就交给规则引擎来处理。
n 逻辑和数据分开
将可变的业务逻辑和数据分开。虽然,这违背了面向对象原则。面向对象强调数据和业务逻辑耦合。但是,对于一些易变而复杂的业务规则。如果散步在程序的各个地方、各个层次。那么一旦业务规则更改的话,就会出现“牵一发而动全身”的局面。因此,将可变的业务逻辑独立出来管理,将有助于后面的业务变更。
n 性能
Rete算法的性能比较高。
n 知识集中表示
通过使用规则,我们把规则集中存放起来,从而使系统知识能够集中表示。
n 可读性
规则的可读性比较高。对于熟悉业务规则。但不会程序开发的业务专家,只要熟悉规则的标示,也可以编写和修改业务规则。
1.4    使用JAVA规则系统的场合
那么,在那些场合下适合应用JAVA规则系统呢?总而言之,可以用一句话来概括:当用传统的程序开发,无法得到一种优雅的解决方法的时候,就可以考虑使用规则系统。如下的一些场合:
n 用传统的代码开发比较复杂、繁琐
n 问题虽然不复杂,但是用传统的代码开发比较脆弱,也就是经常修改
n 没有优雅的算法
n 业务规则频繁改变
n 有很多业务专家、不懂技术开发
1.5    不适合使用JAVA规则系统场合
虽然规则系统看起来比较不错,但是并不是任何地方都可以使用规则系统。很多简单、固定的业务系统,可以不用使用规则系统。规则系统也不能用来作为标示重要的业务流程、不能用来作为工作流引擎。
有很多程序员把JAVA规则系统当成是一种动态修改配置。也就是把一部分代码逻辑抽取到外面,统一存放起来。这样,当一些配置修改的话,通过修改规则,就能修改代码的一部分逻辑。如果把JAVA规则仅仅用在这个场合下的话,可以考虑采用脚本引擎。比如BeanShell、JEXL、Groovy等等。
			posted @ 
2008-10-28 12:15 jspark 阅读(1576) | 
评论 (1) | 
编辑 收藏grant {
    permission java.lang.RuntimePermission  "loadLibrary.*";
    permission java.lang.RuntimePermission  "queuePrintJob";
    permission java.lang.RuntimePermission  "setContextClassLoader";
    permission java.lang.RuntimePermission  "getProtectionDomain";
    permission java.lang.reflect.ReflectPermission "suppressAccessChecks";
    };
grant {
    permission java.util.PropertyPermission   "*" ,  " read,write " ;
};  
     最近一个项目需要用到SUN ONE APPSERVER8.1,本人在WINDOWS SERVER 2003中安装,碰到一些问题,不过比较幸运的是都解决了,下面大概描述一下个人碰到的问题,期望能给别人带来帮助 
   一、DNS服务器问题
    安装SUN ONE APPSERVER8.1必须要在服务器上安装,而且必须要将该服务器设置为DNS服务器。关于WINDOWS SERVER 2003
    如何设置DNS服务器,网上很多资料,可以查阅
   二、文件系统权限访问问题
 也许SUN ONE APPSERVER8.1服务器在文件访问方面控制比较严格,如果按照默认安装上去的系统。对于一些文件夹、文件读取是会有一些控制的。比如说,当将应用部署上去,然后访问应用,会抛出SecurityException。这是因为需要编译jsp页面,生成class文件,由于没有写权限,所以会出错。解决的方法是为SUN ONE APPSERVER增加文件访问权限。修改方法如下:
 找到安装路径,下面以本人的安装路径为例子:
 c\sunjes\ApplicationServer\domains\domain1\config
 该目录下面有一个文件叫server.policy,打开该页面,可以看到里面是一些关于文件访问权限的例子
    
//  Core server classes get all permissions by default 
grant codeBase  " file:${com.sun.aas.installRoot}/lib/- "  {
    permission java.security.AllPermission;
};
    
    下面为文件路径增加访问权限,个人把整个c盘设置为可读可写,如下
    grant codeBase  " file:c:/- "  {
    permission java.security.AllPermission;
};
grant {
    permission java.io.FilePermission  " c:/- " ,  " read,write,execute,delete " ;
};   
 编辑完毕,保存,重启服务器,OK,该问题解决。 :) 
  三、其他几个权限问题:
         编辑以上问题后,重新自动,可能还会发现以下几个异常,比如 permission java.util.PropertyPermission   "*" ,  " read,write " ;
      因此,分别加上如下几个权限设置即可
    
  四、ORACLE10.2.0.1驱动问题
 本人部署的应用是spring+hb架构,里面用到blog/clob大字段处理,因此驱动程序用最新的驱动程序10g,版本为10.2.0.1。在部署到SUN ONE APPSERVER8.1时,也抛出类访问异常,异常信息是:oracle.sql is sealed。没办法,上网搜索了一下,发现有很多人也遇过这个情况。主要是oracle10g.jar里面的Meta-inf定义,增加了sealed属性。打开该文件MANIFEST.MF,内容如下:
  
    Manifest - Version:  1.0 
Specification - Title:    Oracle JDBC driver classes  for  use with JDK14
Created - By:  1.4 .2_08 (Sun Microsystems Inc.)
sealed: true 
Implementation - Title:   ojdbc14.jar
Specification - Vendor:   Oracle Corporation
Specification - Version:  Oracle JDBC Driver version  -   " 10.2.0.1.0 " 
Implementation - Version: Oracle JDBC Driver version  -   " 10.2.0.1.0 " 
Implementation - Vendor:  Oracle Corporation
Implementation - Time:    Wed Jun  22   18 : 55 : 48   2005 
 关于sealed属性网上也有
 很多资料介绍,有兴趣的网友可以参阅一下。网上同行的解决方法是下载10g,低点的版本。本人的解决方法是修改一下里面的MANIFEST.MF文件,把sealed:true去掉即可。 
 四、包版本不兼容。
 解决完以上几个问题后,重新启动,本以为万事大吉,很不幸运的是,再次抛出异常:
 ClassNotFoundException: org.hibernate.hql.ast.HqlToken。同样,上网搜索了一下,发现是hibernate的antlr.jar和SUN ONE APPSERVER的antlr.jar存在冲突。hibernate3.0版本用
 的antlr.jar包版本是2.7.5,比SUN ONE APPSERVER的高。以前在weblogic部署应用时,也出现过类似的问题。由于这些服务器会优先装载自己的类,因此会出现一些问题。解决方法是把hibernate下较高版本的antlr.jar放在classpath的前面。在SUN ONE APPSERVER
 下最快捷的方式就是将antlr-2.7.5H3.jar拷贝到ApplicationServer\lib目录下面即可 
 解决完以上几个问题后,再次重启,访问,OK,一切正常!好有成就感 :) 
			posted @ 
2006-11-29 14:42 jspark 阅读(1708) | 
评论 (1) | 
编辑 收藏
        Sun HotSpot 1.4.1使用分代收集器,它把堆分为三个主要的域:新域、旧域以及永久域。Jvm生成的所有新对象放在新域中。一旦对象经历了一定数量的垃圾收集循环后,便获得使用期并进入旧域。在永久域中jvm则存储class和method对象。就配置而言,永久域是一个独立域并且不认为是堆的一部分。
    下面介绍如何控制这些域的大小。可使用-Xms和-Xmx 控制整个堆的原始大小或最大值。
    下面的命令是把初始大小设置为128M:    
java –Xms128m     –Xmx256m为控制新域的大小,可使用-XX:NewRatio设置新域在堆中所占的比例。
   下面的命令把整个堆设置成128m,新域比率设置成3,即新域与旧域比例为1:3,新域为堆的1/4或32M:   
java –Xms128m –Xmx128m    –XX:NewRatio =3可使用-XX:NewSize和-XX:MaxNewsize设置新域的初始值和最大值。
   下面的命令把新域的初始值和最大值设置成64m:      
java –Xms256m –Xmx256m –Xmn64m   永久域默认大小为4m。运行程序时,jvm会调整永久域的大小以满足需要。每次调整时,jvm会对堆进行一次完全的垃圾收集。
   使用-XX:MaxPerSize标志来增加永久域搭大小。在WebLogic Server应用程序加载较多类时,经常需要增加永久域的最大值。当jvm加载类时,永久域中的对象急剧增加,从而使jvm不断调整永久域大小。为了避免调整,可使用-XX:PerSize标志设置初始值。
   下面把永久域初始值设置成32m,最大值设置成64m。    
java -Xms512m -Xmx512m -Xmn128m -XX:PermSize=32m -XX:MaxPermSize=64m    默认状态下,HotSpot在新域中使用复制收集器。该域一般分为三个部分。第一部分为Eden,用于生成新的对象。另两部分称为救助空间,当Eden充满时,收集器停止应用程序,把所有可到达对象复制到当前的from救助空间,一旦当前的from救助空间充满,收集器则把可到达对象复制到当前的to救助空间。From和to救助空间互换角色。维持活动的对象将在救助空间不断复制,直到它们获得使用期并转入旧域。使用-XX:SurvivorRatio可控制新域子空间的大小。
    同NewRation一样,SurvivorRation规定某救助域与Eden空间的比值。比如,以下命令把新域设置成64m,Eden占32m,每个救助域各占16m:    
java -Xms256m -Xmx256m -Xmn64m -XX:SurvivorRation =2    如前所述,默认状态下HotSpot对新域使用复制收集器,对旧域使用标记-清除-压缩收集器。在新域中使用复制收集器有很多意义,因为应用程序生成的大部分对象是短寿命的。理想状态下,所有过渡对象在移出Eden空间时将被收集。如果能够这样的话,并且移出Eden空间的对象是长寿命的,那么理论上可以立即把它们移进旧域,避免在救助空间反复复制。但是,应用程序不能适合这种理想状态,因为它们有一小部分中长寿命的对象。最好是保持这些中长寿命的对象并放在新域中,因为复制小部分的对象总比压缩旧域廉价。为控制新域中对象的复制,可用-XX:TargetSurvivorRatio控制救助空间的比例(该值是设置救助空间的使用比例。如救助空间位1M,该值50表示可用500K)。该值是一个百分比,默认值是50。当较大的堆栈使用较低的sruvivorratio时,应增加该值到80至90,以更好利用救助空间。用-XX:maxtenuring threshold可控制上限。
   为放置所有的复制全部发生以及希望对象从eden扩展到旧域,可以把MaxTenuring Threshold设置成0。设置完成后,实际上就不再使用救助空间了,因此应把SurvivorRatio设成最大值以最大化Eden空间,设置如下:   
java … -XX:MaxTenuringThreshold=0 –XX:SurvivorRatio=50000 …
			posted @ 
2006-11-28 11:58 jspark 阅读(668) | 
评论 (0) | 
编辑 收藏
				Wecould try something like 
		
		
				window.opener.name="opener728"; 
form.target="opener728"; 
		
		
				however, I suspect the window.name property is read-only. 
		
		
				Alternatively, if We are certain that the opener already has a name then this might work 
		
		
				form.target=window.opener.name; 
		
		
				It's also possible that browsers assign unique names to otherwise unnamed windows, so the above would always work - I've never checked this. 
		
		
				
						
				
				
				
				
		
			posted @ 
2006-11-22 15:39 jspark 阅读(484) | 
评论 (0) | 
编辑 收藏今天从网上找了一个读写csv格式的开源程序,还挺好用的。
下面是一个读取例子:
源文件格式:
		 ProductID,ProductName,SupplierID,CategoryID,QuantityPerUnit,UnitPrice,UnitsInStock,UnitsOnOrder,ReorderLevel,Discontinued
 1,Chai,1,1,10 boxes x 20 bags,18,39,0,10,FALSE
 2,Chang,1,1,24 - 12 oz bottles,19,17,40,25,FALSE
 下面读取程序
		 
		
				 CsvReader reader 
				=
				 
				new
				 CsvReader(
				"
				products.csv
				"
				);
				 CsvReader reader 
				=
				 
				new
				 CsvReader(
				"
				products.csv
				"
				);

 reader.readHeaders();
 reader.readHeaders();

 while
				 (reader.readRecord())
 
				while
				 (reader.readRecord())

 
 
				
						 {
				
				
						{
 String productID 
						=
						 reader.get(
						"
						ProductID
						"
						);
  String productID 
						=
						 reader.get(
						"
						ProductID
						"
						);
 String productName 
						=
						 reader.get(
						"
						ProductName
						"
						);
  String productName 
						=
						 reader.get(
						"
						ProductName
						"
						);
 String supplierID 
						=
						 reader.get(
						"
						SupplierID
						"
						);
  String supplierID 
						=
						 reader.get(
						"
						SupplierID
						"
						);
 String categoryID 
						=
						 reader.get(
						"
						CategoryID
						"
						);
  String categoryID 
						=
						 reader.get(
						"
						CategoryID
						"
						);
 String quantityPerUnit 
						=
						 reader.get(
						"
						QuantityPerUnit
						"
						);
  String quantityPerUnit 
						=
						 reader.get(
						"
						QuantityPerUnit
						"
						);
 String unitPrice 
						=
						 reader.get(
						"
						UnitPrice
						"
						);
  String unitPrice 
						=
						 reader.get(
						"
						UnitPrice
						"
						);
 String unitsInStock 
						=
						 reader.get(
						"
						UnitsInStock
						"
						);
  String unitsInStock 
						=
						 reader.get(
						"
						UnitsInStock
						"
						);
 String unitsOnOrder 
						=
						 reader.get(
						"
						UnitsOnOrder
						"
						);
  String unitsOnOrder 
						=
						 reader.get(
						"
						UnitsOnOrder
						"
						);
 String reorderLevel 
						=
						 reader.get(
						"
						ReorderLevel
						"
						);
  String reorderLevel 
						=
						 reader.get(
						"
						ReorderLevel
						"
						);
 String discontinued 
						=
						 reader.get(
						"
						Discontinued
						"
						);
  String discontinued 
						=
						 reader.get(
						"
						Discontinued
						"
						);
 
  
 //
						 perform program logic here
  
						//
						 perform program logic here
						
								
								 
						
						
								
								 }
 }
				
				
						
						 
						
						 reader.close();
 reader.close();
 
		 
		
				
				
				
写CSV例子:
 CsvWriter writer = new CsvWriter(new FileWriter(new File("c:\\1.csv")),',');
  writer.write("aa");
  writer.write("bb");
  writer.write("cc");
  writer.endRecord();
  writer.write("1");
  writer.write("2");
  writer.write("3");
  writer.close();
			posted @ 
2006-11-07 12:05 jspark 阅读(6576) | 
评论 (0) | 
编辑 收藏
		
		
				
						
								| 在spring中如何处理oracle大字段 
 在spring中采用OracleLobHandler来处理oracle大字段(包括clob和blob),则在程序中不需要引用oracle的特殊类,从而能够保证支持我们的代码支持多数据库。
 
 1、首先数据表中的clob类型对应java持久化类的String类型;而blob类型对应byte[]类型
 2、定义hibernate标签时,持久化类中对应clob类型的属性的hibernate type应为org.springframework.orm.hibernate.support.ClobStringType;而对应blob类型的属性的hibernate type应为org.springframework.orm.hibernate.support.BlobByteArrayType。
 3、以后访问这些对应clob和blob类型的属性时,按普通属性处理,不需要特别编码。
 
 java代码:
 | 
						
								| 
												
												
												
														 <
														bean 
														id
														="mySessionFactory2"
														 class
														="org.springframework.orm.hibernate.LocalSessionFactoryBean"
														> 
  <
														property 
														name
														="dataSource"
														> 
  <
														ref 
														bean
														="myDataSource2"
														/> 
  </
														property
														> 
  <
														property 
														name
														="lobHandler"
														> 
  <
														ref 
														bean
														="oracleLobHandle"
														/> 
  </
														property
														> 
  </
														bean
														> 
  <
														bean 
														id
														="nativeJdbcExtractor"
														 class
														="org.springframework.jdbc.support.nativejdbc.SimpleNativeJdbcExtractor"
														/> 
  
  <
														bean 
														id
														="oracleLobHandle"
														 class
														="org.springframework.jdbc.support.lob.OracleLobHandler"
														 Lazy-init
														="true"
														> 
  <
														property 
														name
														="nativeJdbcExtractor"
														> 
  <
														ref 
														local
														="nativejdbcExtractor"
														/> 
  </
														property
														> 
  </
														bean
														> 
 | 
				
		
		Spring为处理数据库Lob字段,特别提供了LobHandler接口。在操作Oracle RDBMS过程中,由于Oracle JDBC Driver实现的问题,应用必须采用Oracle原生的数据库连接(比如,oracle.jdbc.OracleConnection)、LOB原生实现(比如,oracle.sql.BLOB、oracle.sql.CLOB)。因此,LobHandler接口存在上述两种实现。简而言之,为操作Oracle数据库,必须使用OracleLobHandler实现。如果操作其他RDBMS类型,则使用DefaultLobHandler。NativeJdbcExtractor是个接口,通过它能够抽象各种连接池。另外Spring还提供两个接口存取Blob,LobCreator及LobHandler 
			
posted @ 
2006-08-28 11:58 jspark 阅读(902) | 
评论 (0) | 
编辑 收藏   jdk提供的正则表达式是非常强大的,只要用过正则表达式的程序员应该是为其功能叹为观止。不过,正则表达式中的一个group概念相信应该不多人熟悉。
		    正则表达式中的group,主要是用来区分子序列的,所谓子序列是用()之内的表达式。下面以一段程序为例
		
				 String regex = "\\$\\{(I)(love)(java)\\}";
				        String regex = "\\$\\{(I)(love)(java)\\}";
 System.out.println(Pattern.compile(regex).matcher("${Ilovejava}P)").groupCount());
        System.out.println(Pattern.compile(regex).matcher("${Ilovejava}P)").groupCount());
		 
		 运行上面的代码段,结果为:3
 其中(I)为一个组, (love)为一个组,(java)为一个组。  
  也许有人觉得这只是一个小功能,但是正则表达式的group,还有一个更加强大的地方就是在String.replaceAll方法中。
  public 
StringreplaceAll(
String regex,                         
String replacement)
 其中第一个参数当然是政则表达式,第二个一般是普通的文本;但是第二个参数可以应用group的地方,这个功能用在一些场合是非常方便的。
      比如,下面这个例子  <driverClass>${driverClass}</driverClass>,要将${}去掉,即将这个例子替换成<driverClass>driverClass</driverClass>,可以用下面的代码来替换。例如
 String text = "<driverClass>${driverClass}</driverClass>";
        String text = "<driverClass>${driverClass}</driverClass>";
 String result = replaceStr(text,"\\$\\{(driverClass)\\}","$1");
        String result = replaceStr(text,"\\$\\{(driverClass)\\}","$1");
 System.out.println("result is:"+result);
        System.out.println("result is:"+result);   运行结果:result is:<driverClass>driverClass</driverClass>
  从上面可以看出,$1就是正则表达式中匹配的第一个序列,同样$2...表示第几个序列。如果$index中的index超出了表达式中子序列的个数的话,将抛出异常信息。 $0表示整个正则表达式。
			
posted @ 
2006-08-15 15:30 jspark 阅读(506) | 
评论 (0) | 
编辑 收藏
			在tomcat5.5版本以前,可以说jndi配置相对是比较复杂的,而且据网友说用tomcat5.0的控制台配置数据库连接池经常有问题,而且文档写得又不详细。
tomcat5.5出来后,jndi的配置方法是大大地节省,而且很简洁,个人觉得比以前的版本好很多。这里大概给出一个配置例子。tomcat数据库连接池jndi配置有两种,一种是全局的,一种是context的,下面主要是讲全局的,并且以一个实例jdbc/byisdb为例子   
一、tomcat5.0配置方法
1、首先在server.xml里面配置,找到下面的配置
  <!-- Global JNDI resources -->
  <GlobalNamingResources>
 </GlobalNamingResources>
2、在里面增加一个Resource
 <Resource name="jdbc/byisdb"
      <Resource name="jdbc/byisdb"
 auth="Container"
               auth="Container"
 type="javax.sql.DataSource"/>
               type="javax.sql.DataSource"/>3、在下面增加属性
 <ResourceParams name="jdbc/byisdb">
  <ResourceParams name="jdbc/byisdb">
 <parameter>
    <parameter>
 <name>factory</name>
      <name>factory</name>
 <value>org.apache.commons.dbcp.BasicDataSourceFactory</value>
      <value>org.apache.commons.dbcp.BasicDataSourceFactory</value>
 </parameter>
    </parameter>

 <!-- Maximum number of dB connections in pool. Make sure you
    <!-- Maximum number of dB connections in pool. Make sure you
 configure your mysqld max_connections large enough to handle
         configure your mysqld max_connections large enough to handle
 all of your db connections. Set to 0 for no limit.
         all of your db connections. Set to 0 for no limit.
 -->
         -->
 <parameter>
    <parameter>
 <name>maxActive</name>
      <name>maxActive</name>
 <value>100</value>
      <value>100</value>
 </parameter>
    </parameter>

 <!-- Maximum number of idle dB connections to retain in pool.
    <!-- Maximum number of idle dB connections to retain in pool.
 Set to -1 for no limit.  See also the DBCP documentation on this
         Set to -1 for no limit.  See also the DBCP documentation on this
 and the minEvictableIdleTimeMillis configuration parameter.
         and the minEvictableIdleTimeMillis configuration parameter.
 -->
         -->
 <parameter>
    <parameter>
 <name>maxIdle</name>
      <name>maxIdle</name>
 <value>30</value>
      <value>30</value>
 </parameter>
    </parameter>

 <!-- Maximum time to wait for a dB connection to become available
    <!-- Maximum time to wait for a dB connection to become available
 in ms, in this example 10 seconds. An Exception is thrown if
         in ms, in this example 10 seconds. An Exception is thrown if
 this timeout is exceeded.  Set to -1 to wait indefinitely.
         this timeout is exceeded.  Set to -1 to wait indefinitely.
 -->
         -->
 <parameter>
    <parameter>
 <name>maxWait</name>
      <name>maxWait</name>
 <value>10000</value>
      <value>10000</value>
 </parameter>
    </parameter>

 <!-- MySQL dB username and password for dB connections  -->
    <!-- MySQL dB username and password for dB connections  -->
 <parameter>
    <parameter>
 <name>username</name>
     <name>username</name>
 <value>una_oa</value>
     <value>una_oa</value>
 </parameter>
    </parameter>
 <parameter>
    <parameter>
 <name>password</name>
     <name>password</name>
 <value>una_oa</value>
     <value>una_oa</value>
 </parameter>
    </parameter>

 <!-- Class name for the old mm.mysql JDBC driver - uncomment this entry and comment next
    <!-- Class name for the old mm.mysql JDBC driver - uncomment this entry and comment next
 if you want to use this driver - we recommend using Connector/J though
         if you want to use this driver - we recommend using Connector/J though
 <parameter>
    <parameter>
 <name>driverClassName</name>
       <name>driverClassName</name>
 <value>org.gjt.mm.mysql.Driver</value>
       <value>org.gjt.mm.mysql.Driver</value>
 </parameter>
    </parameter>
 -->
     -->
 
    
 <!-- Class name for the official MySQL Connector/J driver -->
    <!-- Class name for the official MySQL Connector/J driver -->
 <parameter>
    <parameter>
 <name>driverClassName</name>
       <name>driverClassName</name>
 <value>oracle.jdbc.driver.OracleDriver</value>
       <value>oracle.jdbc.driver.OracleDriver</value>
 </parameter>
    </parameter>
 
    
 <!-- The JDBC connection url for connecting to your MySQL dB.
    <!-- The JDBC connection url for connecting to your MySQL dB.
 The autoReconnect=true argument to the url makes sure that the
         The autoReconnect=true argument to the url makes sure that the
 mm.mysql JDBC Driver will automatically reconnect if mysqld closed the
         mm.mysql JDBC Driver will automatically reconnect if mysqld closed the
 connection.  mysqld by default closes idle connections after 8 hours.
         connection.  mysqld by default closes idle connections after 8 hours.
 -->
         -->
 <parameter>
    <parameter>
 <name>url</name>
      <name>url</name>
 <value>jdbc:oracle:thin:@192.168.1.210:1521:byisdb</value>
      <value>jdbc:oracle:thin:@192.168.1.210:1521:byisdb</value>
 </parameter>
    </parameter>
 </ResourceParams>
  </ResourceParams>4、在你的应用的web.xml里面增加
 <resource-ref>
<resource-ref>
 <description>postgreSQL Datasource example</description>
 <description>postgreSQL Datasource example</description>
 <res-ref-name>jdbc/byisdb</res-ref-name>
 <res-ref-name>jdbc/byisdb</res-ref-name>
 <res-type>javax.sql.DataSource</res-type>
 <res-type>javax.sql.DataSource</res-type>
 <res-auth>Container</res-auth>
 <res-auth>Container</res-auth>
 </resource-ref>
</resource-ref>OK,到此配置完毕,可以用下面的几段代码进行测试
 Context initContext = new InitialContext();
Context initContext = new InitialContext();
 Context envContext  = (Context)initContext.lookup("java:/comp/env");
Context envContext  = (Context)initContext.lookup("java:/comp/env");
 DataSource ds = (DataSource)envContext.lookup("jdbc/byisdb");
DataSource ds = (DataSource)envContext.lookup("jdbc/byisdb");
 Connection conn = ds.getConnection();
Connection conn = ds.getConnection();
 out.println("conn is:"+conn);
out.println("conn is:"+conn);二、tomcat5.5配置
1、打开conf/context.xml里面
  添加下面的配置
 <Resource name="jdbc/byisdb" auth="Container" type="javax.sql.DataSource" driverClassName="oracle.jdbc.driver.OracleDriver" url="jdbc:oracle:thin:@192.168.1.210:1521:byisdb" username="una_oa" password="una_oa" maxActive="20" maxIdle="10" maxWait="10000"/>
    <Resource name="jdbc/byisdb" auth="Container" type="javax.sql.DataSource" driverClassName="oracle.jdbc.driver.OracleDriver" url="jdbc:oracle:thin:@192.168.1.210:1521:byisdb" username="una_oa" password="una_oa" maxActive="20" maxIdle="10" maxWait="10000"/> 
2在你的应用的web.xml里面增加
 <resource-ref>
<resource-ref>
 <description>postgreSQL Datasource example</description>
 <description>postgreSQL Datasource example</description>
 <res-ref-name>jdbc/byisdb</res-ref-name>
 <res-ref-name>jdbc/byisdb</res-ref-name>
 <res-type>javax.sql.DataSource</res-type>
 <res-type>javax.sql.DataSource</res-type>
 <res-auth>Container</res-auth>
 <res-auth>Container</res-auth>
 </resource-ref>
</resource-ref>同样,可以用上面的代码进行测试。
			
posted @ 
2006-08-11 14:03 jspark 阅读(2963) | 
评论 (1) | 
编辑 收藏 最近由于需要用到ThreadLocal,在网上搜索了一些相关资料,发现对ThreadLocal经常会有下面几种误解
 一、ThreadLocal是java线程的一个实现
      ThreadLocal的确是和java线程有关,不过它并不是java线程的一个实现,它只是用来维护本地变量。针对每个线程,提供自己的变量版本,主要是为了避免线程冲突,每个线程维护自己的版本。彼此独立,修改不会影响到对方。
		 二、ThreadLocal是相对于每个session的
		        ThreadLocal顾名思义,是针对线程。在java web编程上,每个用户从开始到会话结束,都有自己的一个session标识。但是ThreadLocal并不是在会话层上。其实,Threadlocal是独立于用户session的。它是一种服务器端行为,当服务器每生成一个新的线程时,就会维护自己的ThreadLocal。对于这个误解,个人认为应该是开发人员在本地基于一些应用服务器测试的结果。众所周知,一般的应用服务器都会维护一套线程池,也就是说,对于每次访问,并不一定就新生成一个线程。而是自己有一个线程缓存池。对于访问,先从缓存池里面找到已有的线程,如果已经用光,才去新生成新的线程。所以,由于开发人员自己在测试时,一般只有他自己在测,这样服务器的负担很小,这样导致每次访问可能是共用同样一个线程,导致会有这样的误解:每个session有一个ThreadLocal
		 三、ThreadLocal是相对于每个线程的,用户每次访问会有新的ThreadLocal
		  理论上来说,ThreadLocal是的确是相对于每个线程,每个线程会有自己的ThreadLocal。但是上面已经讲到,一般的应用服务器都会维护一套线程池。因此,不同用户访问,可能会接受到同样的线程。因此,在做基于TheadLocal时,需要谨慎,避免出现ThreadLocal变量的缓存,导致其他线程访问到本线程变量
		 四、对每个用户访问,ThreadLocal可以多用
        可以说,ThreadLocal是一把双刃剑,用得来的话可以起到非常好的效果。但是,ThreadLocal如果用得不好,就会跟全局变量一样。代码不能重用,不能独立测试。因为,一些本来可以重用的类,现在依赖于ThreadLocal变量。如果在其他没有ThreadLocal场合,这些类就变得不可用了。个人觉得ThreadLocal用得很好的几个应用场合,值得参考
		  1、存放当前session用户:quake want的jert
		  2、存放一些context变量,比如webwork的ActionContext
		  3、存放session,比如Spring hibernate orm的session
			posted @ 
2006-08-01 12:09 jspark 阅读(30795) | 
评论 (12) | 
编辑 收藏
				       说真的,对于spring提供AOP的功能,个人实在不敢太过于恭维。主要是Spring的AOP功能没那么强大,而且必须是对于spring容器管理的bean才能实施AOP功能,对于容器外的bean就无能为力了。而且spring没有提供属性的AOP功能。在这些方面,spring AOP真的不能和Aspectj相比。Aspectj的AOP功能才真的是真正意义的AOP框架,提供的功能非常强大,几乎可以实现任何类型的AOP。不过Aspectj的学习曲线相对要比spring AOP稍微陡峭一点,主要是spring AOP可以当成普通javabean来处理,而Aspectj还要另外做编译器,比较麻烦。不过,庆幸的是,eclipse下面有Aspectj插件,开发起来也是很方便。所以一般,复杂的AOP功能,还是推荐用Aspectj
     对于一般的J2EE开发来说,要实现一些比较常用的AOP,Spring 还是能满足的。比如事务、异常、日志、权限等等,在这些方面,spring AOP还是比较方便的,特别是事务处理,spring提供了相当好的集成。如果事务处理用Aspectj来实现,不见得好多少。
    一直以来,觉得spring AOP最好用的一个地方就是提供了BeanNameAutoProxyCreator,这个类真的非常方便,以至于个人一旦遇到要实现AOP,首先就是求组于BeanNameAutoProxyCreator,如果BeanNameAutoProxyCreator实现不了,再考虑别的。不过,一般情况来说,BeanNameAutoProxyCreator的确能满足需要了,除非你的需求真的千奇百怪。
   在应用spring AOP功能时,优先考虑用接口。因为如果用接口的话,那么spring会创建一个代理,并在代理里面实现AOP增强代码,并调用真正的实例对象。不过,spring AOP功能不一定非要用接口,一些普通类也是可以的。对于普通类,spring会用CGLIB来动态生成一个新类。并且CGLIB会保持一个生成类的cache,因此它不会一直生成新类。spring使用ProxyCallbackFilter对象把其它对象放进map进行管理。如果没有管理好cache,将会产生大量的java对象,直至出现OutOfMemoryErrors。因此使用spring的aop时,一定要正确实现equals and hashCode。
   不过,不管怎么样,在应用spring AOP时,还是优先考虑接口方式,毕竟面向接口方式还是值得推荐的一个编程思想。
		
			posted @ 
2006-07-31 19:37 jspark 阅读(4141) | 
评论 (11) | 
编辑 收藏