`

Jakarta Commons Chain学习(一)

 
阅读更多

原文:http://phil-xzh.javaeye.com/blog/321536

使用Commons Chain

作为程序开发人员,我们经常需要对一个实际上程序性的系统应用面向对象的方法。商业分析家和管理人员描述这样的系统时通常不使用类层次和序列图,而 是使用流程图和工作流图表。但是不论如何,使用面向对象的方法解决这些问题时会带来更多的灵活性。面向对象的设计模式提供了有用的结构和行为来描述这种顺 序的处理,比如模版方法(Template Method)[GoF]和责任链(Chain of Responsibility)[GoF]。

Jakarta Commons的子项目Chain将上述两个模式组合成一个可复用的Java框架用于描述顺序的处理流程 。这个在Jakarta Commons project社区中开发的框架,已经被广泛的接受并且使用于许多有趣的应用中,特别的是他被Struts和Shale应用框架作为处理HTTP请求处理的基础机制。你可以在需要定义和执行一组连续的步骤时使用Commons Chain。


至于经典设计模式,开发者和架构师普遍使用模版方法(Template Method)造型顺序处理。模版方法(Template Method)中使用一个抽象的父类定义使用的算法:处理的步骤,具体实现交给子类。当然,父类也可以为算法所使用的方法提供一个缺省实现。由于模版方法 (Template Method)依赖继承——子类必须继承定义了算法的父类——因此使用这个模式的软件表现出紧耦合而且缺少灵活性。又由于实现类添加自己的行为前必须扩展 父类,导致开发人员被限制于类层次中,从而限制了程序设计的灵活性。Commons Chain使用配置文件定义算法,在程序运行时解析配置文件,从而很好的解决了这个问题。

 

现在来看一下Commons Chain是怎样工作的,我们从一个人造的例子开始:二手车销售员的商业流程。下面是销售流程的步骤:

  1. 得到用户信息
  2. 试车
  3. 谈判销售
  4. 安排财务
  5. 结束销售

现在假设使用模版方法(Template Method)造型这个流程。首先建立一个定义了算法的抽象类:

  1. public  abstract  class  SellVehicleTemplate {   
  2.     public  void  sellVehicle() {  
  3.         getCustomerInfo();  
  4.         testDriveVehicle();  
  5.         negotiateSale();  
  6.         arrangeFinancing();  
  7.         closeSale();  
  8.     }  
  9.     public  abstract  void  getCustomerInfo();  
  10.     public  abstract  void  testDriveVehicle();  
  11.     public  abstract  void  negotiateSale();   
  12.     public  abstract  void  arrangeFinancing();   
  13.     public  abstract  void  closeSale();  
  14. }  
  1. public abstract class SellVehicleTemplate {  
  2.   
  3.     public void sellVehicle() {  
  4.         getCustomerInfo();  
  5.         testDriveVehicle();  
  6.         negotiateSale();  
  7.         arrangeFinancing();  
  8.         closeSale();  
  9.     }  
  10.   
  11.     public abstract void getCustomerInfo();  
  12.   
  13.     public abstract void testDriveVehicle();  
  14.   
  15.     public abstract void negotiateSale();  
  16.   
  17.     public abstract void arrangeFinancing();  
  18.   
  19.     public abstract void closeSale();  
  20. }  


现在来看一下怎样用Commons Chain实现这个流程。首先,下载Commons Chain。你可以直接下载最新的zip或tar文件,也可以从CVS或者SubVersion源码库检出Commons Chain模块得到最新的代码。解压缩打包文件,将commons-chain.jar放入你的classpath中。
使用Commons Chain实现这个商业流程,必须将流程中的每一步写成一个类,这个类需要有一个public的方法execute()。这和传统的命令模式(Command pattern)实现相同。下面简单实现了“得到用户信息”:

  1. package  com.jadecove.chain.sample;  
  2. import  org.apache.commons.chain.Command;  
  3. import  org.apache.commons.chain.Context;  
  4. public  class  GetCustomerInfo implements  Command {  
  5.     public  boolean  execute(Context ctx) throws  Exception  
  6.         System.out.println("Get customer info" );  
  7.         ctx.put("customerName" ,"George Burdell" );  
  8.         return  false ;  
  9.     }  
  10.   
由于只是演示,这个类并没有做很多工作。这里将用户名放入了Context对象ctx中。这个Context对象连接了各个命令。暂时先将这个对象想象成 根据关键字存取值的哈希表。所有后来的命令可以通过它访问刚才放入的用户名。 TestDriveVehicle,NegotiateSale和 ArrangeFinancing命令的实现只是简单的打印了将执行什么操作。
  1. package  com.jadecove.chain.sample;   
  2. import  org.apache.commons.chain.Command;  
  3. import  org.apache.commons.chain.Context;  
  4. public  class  TestDriveVehicle implements  Command {   
  5.     public  boolean  execute(Context ctx) throws  Exception {  
  6.         System.out.println("Test drive the vehicle" );  
  7.         return  false ;  
  8.     }  
  9.   
  10. }  
  11.   
  12. public  class  NegotiateSale implements  Command {  
  13.     public  boolean  execute(Context ctx) throws  Exception {  
  14.         System.out.println("Negotiate sale" );  
  15.         return  false ;  
  16.     }  
  17.   
  18. }  
  19.   
  20. public  class  ArrangeFinancing implements  Command {   
  21.     public  boolean  execute(Context ctx) throws  Exception {  
  22.         System.out.println("Arrange financing" );  
  23.         return  false ;  
  24.     }  
  25.   
CloseSale从Context对象中取出GetCustomerInfo放入的用户名,并将其打印。
  1. package  com.jadecove.chain.sample;   
  2. import  org.apache.commons.chain.Command;  
  3. import  org.apache.commons.chain.Context;  
  4. public  class  CloseSale implements  Command {   
  5.     public  boolean  execute(Context ctx) throws  Exception {  
  6.         System.out.println("Congratulations "  + ctx.get("customerName" ) +", you bought a new car!" );  
  7.         return  false ;  
  8.     }  
  9.   
现在你可以将这个流程定义成一个序列(或者说“命令链”)。
 
  1. package  com.jadecove.chain.sample;  
  2. import  org.apache.commons.chain.impl.ChainBase;  
  3. import  org.apache.commons.chain.Command;  
  4. import  org.apache.commons.chain.Context;  
  5. import  org.apache.commons.chain.impl.ContextBase;  
  6.   
  7. public  class  SellVehicleChain extends  ChainBase {  
  8.     public  SellVehicleChain() {  
  9.         super ();  
  10.         addCommand(new  GetCustomerInfo());  
  11.         addCommand(new  TestDriveVehicle());  
  12.         addCommand(new  NegotiateSale());  
  13.         addCommand(new  ArrangeFinancing());  
  14.         addCommand(new  CloseSale());  
  15.     }  
  16.   
  17.     public  static  void  main(String[] args) throws  Exception {  
  18.         Command process = new  SellVehicleChain();  
  19.         Context ctx = new  ContextBase();  
  20.         process.execute(ctx);  
  21.     }   
  22. }  
  1. package com.jadecove.chain.sample;  
  2.   
  3. import org.apache.commons.chain.impl.ChainBase;  
  4. import org.apache.commons.chain.Command;  
  5. import org.apache.commons.chain.Context;  
  6. import org.apache.commons.chain.impl.ContextBase;  
  7.   
  8. public class SellVehicleChain extends ChainBase {  
  9.   
  10.     public SellVehicleChain() {  
  11.         super();  
  12.         addCommand(new GetCustomerInfo());  
  13.         addCommand(new TestDriveVehicle());  
  14.         addCommand(new NegotiateSale());  
  15.         addCommand(new ArrangeFinancing());  
  16.         addCommand(new CloseSale());  
  17.     }  
  18.   
  19.     public static void main(String[] args) throws Exception {  
  20.         Command process = new SellVehicleChain();  
  21.         Context ctx = new ContextBase();  
  22.         process.execute(ctx);  
  23.     }  
  24.   
  25. }  

运行这个类将会输出以下结果:
Get customer info
Test drive the vehicle
Negotiate sale
Arrange financing
Congratulations George Burdell, you bought a new car!
 
在进一步深入之前,让我们来看一下我们使用了的Commons Chain的类和接口。
Command 类和Chain类的关系就是组合模式(Composite pattern)[GoF]的例子:Chain不仅由多个Command组成,而且自己也是Command。这使你可以非常简单得将单个命令 (Command)替换成由多个命令(Command)组成的链(Chain)。这个由Command对象唯一操作定义的方法代表了一个直接的命令:

public boolean execute(Context context);

参数context仅仅是一个存放了名称-值对的集合。接口Context在这里作为一个标记接口:它扩展了java.util.Map但是没有 添加任何特殊的行为。于此相反,类ContextBase不仅提供了对Map的实现而且增加了一个特性:属性-域透明。这个特性可以通过使用Map的 put和get 方法操作JavaBean的域,当然这些域必须使用标准的get*和set*方法定义。那些通过JavaBean的“setter”方法设置的 值,可以通过对应的域名称,用Map的get方法得到。同样,那些用Map的put方法设置的值可以通过JavaBean的“getter”方法得到。

例如,我们可以创建一个专门的context提供显式的customerName属性支持。

  1. package  com.jadecove.chain.sample;   
  2. import  org.apache.commons.chain.impl.ContextBase;   
  3. public  class  SellVehicleContext extends  ContextBase {   
  4.     private  String customerName;   
  5.     public  String getCustomerName() {  
  6.         return  customerName;  
  7.     }  
  8.   
  9.     public  void  setCustomerName(String name) {  
  10.         this .customerName = name;  
  11.     }  
  12.   
  13. }  
  1. package com.jadecove.chain.sample;  
  2.   
  3. import org.apache.commons.chain.impl.ContextBase;  
  4.   
  5. public class SellVehicleContext extends ContextBase {  
  6.   
  7.     private String customerName;  
  8.   
  9.     public String getCustomerName() {  
  10.         return customerName;  
  11.     }  
  12.   
  13.     public void setCustomerName(String name) {  
  14.         this.customerName = name;  
  15.     }  
  16.   
  17. }  


现在你既可以进行Map的一般属性存取操作,同时也可以使用显式的JavaBean的访问和修改域的方法,这两个将产生同样的效果。但是首先你需要在运行SellVehicleChain时实例化SellVehiceContext而不是ContextBase。

  1. public  static  void  main(String[] args) throws  Exception {  
  2.     Command process = new  SellVehicleChain();  
  3.     Context ctx = new  SellVehicleContext();  
  4.     process.execute(ctx);  
  5. }  
  1. public static void main(String[] args) throws Exception {  
  2.     Command process = new SellVehicleChain();  
  3.     Context ctx = new SellVehicleContext();  
  4.     process.execute(ctx);  
  5. }  


尽管你不改变GetCustomerInfo中存放用户名的方法——仍然使用ctx.put("customerName", "George Burdell")——你可以在CloseSale中使用getCustomerName()方法得到用户名。

 
  1. public  boolean  execute(Context ctx) throws  Exception {  
  2.     SellVehicleContext myCtx = (SellVehicleContext) ctx;  
  3.     System.out.println("Congratulations "  + myCtx.getCustomerName() + ", you bought a new car!" );  
  4.     return  false ;  
那些依赖类型安全和context的显式域的命令(Command)可以利用标准的getter和setter方法。当一些新的命令(Command)被 添加时,它们可以不用考虑context的具体实现,直接通过Map的get和put操作属性。不论采用何种机制,ContextBase类都可以保证命 令(Command)间可以通过context互操作。

下面这个例子展示了如何使用Commons Chain的API建立并执行一组顺序的命令。当然,和现在大多数Java软件一样,Commons Chain可以使用XML文件作为配置文件。 你可以将“汽车销售”流程的步骤在XML文件中定义。这个文件有个规范的命名chain- config.xml。
Xml代码
  1. < catalog >   
  2.   < chain  name ="sell-vehicle" >   
  3.     < command  id ="GetCustomerInfo"  className ="com.jadecove.chain.sample.GetCustomerInfo" />   
  4.     < command  id ="TestDriveVehicle"  className ="com.jadecove.chain.sample.TestDriveVehicle" />   
  5.     < command  id ="NegotiateSale"  className ="com.jadecove.chain.sample.NegotiateSale" />   
  6.     < command  id ="ArrangeFinancing"  className ="com.jadecove.chain.sample.ArrangeFinancing" />   
  7.     < command  id ="CloseSale"  className ="com.jadecove.chain.sample.CloseSale" />   
  8.   </ chain >   
  9. </ catalog >   
  1. <catalog>  
  2.   <chain name="sell-vehicle">  
  3.     <command id="GetCustomerInfo" className="com.jadecove.chain.sample.GetCustomerInfo"/>  
  4.     <command id="TestDriveVehicle" className="com.jadecove.chain.sample.TestDriveVehicle"/>  
  5.     <command id="NegotiateSale" className="com.jadecove.chain.sample.NegotiateSale"/>  
  6.     <command id="ArrangeFinancing" className="com.jadecove.chain.sample.ArrangeFinancing"/>  
  7.     <command id="CloseSale" className="com.jadecove.chain.sample.CloseSale"/>  
  8.   </chain>  
  9. </catalog>  

Chain的配置文件可以包含多个链定义,这些链定义可以集合进不同的编目中。在这个例子中,链定义在一个默认的编目中定义。事实上,你可以在这个文件中定义多个名字的编目,每个编目可拥有自己的链组。
现在你可以使用Commons Chain提供的类载入编目并得到指定的链,而不用像SellVehicleChain中那样自己在程序中定义一组命令:
  1. package  com.jadecove.chain.sample;   
  2. import  org.apache.commons.chain.Catalog;  
  3. import  org.apache.commons.chain.Command;  
  4. import  org.apache.commons.chain.Context;  
  5. import  org.apache.commons.chain.config.ConfigParser;  
  6. import  org.apache.commons.chain.impl.CatalogFactoryBase;   
  7. public  class  CatalogLoader {  
  8.   
  9.     private  static  final  String CONFIG_FILE = "/com/jadecove/chain/sample/chain-config.xml" ;  
  10.   
  11.     private  ConfigParser parser;  
  12.   
  13.     private  Catalog catalog;  
  14.   
  15.     public  CatalogLoader() {  
  16.         parser = new  ConfigParser();  
  17.     }  
  18.   
  19.     public  Catalog getCatalog() throws  Exception {  
  20.         if  (catalog == null ) {  
  21.             parser.parse(this .getClass().getResource(CONFIG_FILE));  
  22.         }  
  23.         catalog = CatalogFactoryBase.getInstance().getCatalog();  
  24.         return  catalog;  
  25.     }  
  26.   
  27.     public  static  void  main(String[] args) throws  Exception {  
  28.         CatalogLoader loader = new  CatalogLoader();  
  29.         Catalog sampleCatalog = loader.getCatalog();  
  30.         Command command = sampleCatalog.getCommand("sell-vehicle" );  
  31.         Context ctx = new  SellVehicleContext();  
  32.         command.execute(ctx);  
  33.     }  
Chain 使用Commons Digester来读取和解析配置文件。因此你需要将Commons Digester.jar加入classpath中。我使用了1.6版本并且工作得很好。Digester使用了Commons Collectios(我使用的版本是3.1),Commons Logging(版本1.0.4),Commons BeanUtils(1.7.0),因此你也需要将它们的jar文件加入classpath中。在加入这些jar后,CatalogLoader就可以被 编译和运行,它的输出和另外两个测试完全相同。
 
现在你可以在XML文件中定义链,并可以在程序中得到这个链(别忘了链也是命令),这样扩展的可能性和程序的灵活性可以说是无限的。假设过程“安排财务” 实际上由一个完全分离的商业部门处理。这个部门希望为这种销售建立自己的工作流程。 Chain提供了嵌套链来实现这个要求。因为链本身就是命令,因此你可以用指向另一个链的引用替换一个单一用途的命令。下面是增加了新流程的链的定义:
Xml代码
  1. < catalog  name ="auto-sales" >   
  2.   < chain  name ="sell-vehicle" >   
  3.     < command  id ="GetCustomerInfo"  className ="com.jadecove.chain.sample.GetCustomerInfo" />   
  4.     < command  id ="TestDriveVehicle"  className ="com.jadecove.chain.sample.TestDriveVehicle" />   
  5.     < command  id ="NegotiateSale"  className ="com.jadecove.chain.sample.NegotiateSale" />   
  6.     < command  className ="org.apache.commons.chain.generic.LookupCommand"   catalogName ="auto-sales"  name ="arrange-financing"  optional ="true" />   
  7.     < command  id ="CloseSale"  className ="com.jadecove.chain.sample.CloseSale" />   
  8.   </ chain >   
  9.   < chain  name ="arrange-financing" >   
  10.     < command  id ="ArrangeFinancing"  className ="com.jadecove.chain.sample.ArrangeFinancing" />   
  11.   </ chain >   
  12. </ catalog >   
Commons Chain提供了一个常用的命令LookupCommand来查找和执行另一个链。属性optional用于控制当指定的嵌套链没有找到时如何处理。 optional=true时,即使链没找到,处理也会继续。反之,LookupCommand将抛出 IllegalArgumentException,告知指定的命令未找到。

在下面三种情况下,命令链将结束:
  1. 命令的execute方法返回true
  2. 运行到了链的尽头
  3. 命令抛出异常
当链完全处理完一个过程后,命令就返回true。这是责任链模式(Chain of Responsibility)的基本概念。处理从一个命令传递到另一个命令,直到某个命令(Command)处理了这个命令。如果在到达命令序列尽头时 仍没有处理返回true,也假设链已经正常结束。
当有命令抛出错误时链就会非正常结束。在Commons Chain中,如果有命令抛出错误,链的执行就会中断。不论是运行时错误(runtime exception)还是应用错误(application exception),都会抛出给链的调用者。但是许多应用都需要对在命令之外定义的错误做明确的处理。Commons Chain提供了Filter接口来满足这个要求。Filter继承了Command,添加了一个名为postprocess的方法。

public boolean postprocess(Context context, Exception exception);

只要Filter的execute方法被调用,不论链的执行过程中是否抛出错误,Commons Chain都将保证Filter的postprocess方法被调用。和servlet的过滤器(filter)相同,Commons Chain的Filter按它们在链中的顺序依次执行。同样,Filter的postprocess方法按倒序执行。 你可以使用这个特性实现自己的错误处 理。下面是一个用于处理我们例子中的错误的Filter:
  1. package  com.jadecove.chain.sample;    
  2. import  org.apache.commons.chain.Context;  
  3. import  org.apache.commons.chain.Filter;  
  4. public   class  SellVehicleExceptionHandler  implements  Filter {  
  5.     public   boolean  execute(Context context)  throws  Exception {  
  6.         System.out.println("Filter.execute() called." );  
  7.         return   false ;  
  8.     }  
  9.   
  10.     public   boolean  postprocess(Context context, Exception exception) {  
  11.         if  (exception ==  null )  
  12.             return   false ;  
  13.         System.out.println("Exception "  + exception.getMessage() +  " occurred." );  
  14.         return   true ;  
  15.     }  
  16.   

Filter在配置文件中的定义就和普通的命令(Command)定义相同:
Xml代码
  1. < chain   name = "sell-vehicle" >   
  2.   < command   id = "ExceptionHandler"   className  =  "com.jadecove.chain.sample.SellVehicleExceptionHandler" />   
  3.   < command   id = "GetCustomerInfo"   className = "com.jadecove.chain.sample.GetCustomerInfo" />  
  4. ......
  1. <chain name="sell-vehicle">  
  2.   <command id="ExceptionHandler" className = "com.jadecove.chain.sample.SellVehicleExceptionHandler"/>  
  3.   <command id="GetCustomerInfo" className="com.jadecove.chain.sample.GetCustomerInfo"/>  

Filter 的execute方法按定义的序列调用。然而,它的postprocess方法将在链执行完毕或抛出错误后执行。当一个错误被抛出时, postprocess方法处理完后会返回true,表示错误处理已经完成。链的执行并不会就此结束,但是本质上来说这个错误被捕捉而且不会再向外抛出。 如果postprocess方法返回false,那错误会继续向外抛出,然后链就会非正常结束。

让我们假设ArrangeFinancing因为用户信用卡损坏抛出错误。SellVehicleExceptionHandler就能捕捉到这个错误,程序输出如下:
Filter.execute() called.
Get customer info
Test drive the vehicle
Negotiate sale
Exception Bad credit occurred.


结合了过滤器(filter)和子链技术后,你就可以造型很复杂的工作流程。
 
Commons Chain是一个很有前途的框架,现在仍在开发,新的功能被频繁地添加到其中。在下一篇关于Commons Chain的文章中,我们将研究Struts 1.3中是如何使用Commons Chain的。 Struts 1.3中用完全使用Commons Chain的类替换了原来的处理HTTP请求的类。如果你以前自己定制过Struts的请求处理(request processor),你将发现处理这个问题时Commons Chain为程序带来了很好的灵活性。
  1. public boolean execute(Context ctx) throws Exception {  
  2.     SellVehicleContext myCtx = (SellVehicleContext) ctx;  
  3.     System.out.println("Congratulations " + myCtx.getCustomerName() + ", you bought a new car!");  
  4.     return false;  

分享到:
评论

相关推荐

    JAKARTA COMMONS

    4. **Commons Chain**: 实现了设计模式中的“责任链模式”,允许构建复杂的处理流程,每个处理者可以决定是否处理请求,或者传递给下一个处理者。 5. **Commons CLI**: 提供命令行参数、选项、选项组等的处理,简化...

    Jakarta Commons Online Bookshelf

    《Jakarta Commons在线书架》一书深入探讨了Jakarta Commons框架的核心概念与应用实践,为读者提供了一次全面理解并掌握Jakarta Commons组件的机会。本书由Vikram Goyal编写,版权归属Manning Publications,出版于...

    Jakarta commons docs API CHM 格式

    commons-chain 提供实现组织复杂的处理流程的“责任链模式” commons-cli 命令行参数解析 , 由 Werken, Avalon 和 Optz 组成 commons-codec 包含一些通用的编码解码算法。包括一些语音编码器, Hex, Base64, 以及...

    比较全面的:Jakarta-commons jar包(附: chm参考手册 & 资源简介)

    commons-chain 提供实现组织复杂的处理流程的“责任链模式” commons-cli 命令行参数解析 , 由 Werken, Avalon 和 Optz 组成 commons-codec 包含一些通用的编码解码算法。包括一些语音编码器, Hex, Base64, 以及...

    commons chain api

    Apache Commons Chain API 是一个用于构建和执行工作流程的Java库,它源于Apache Jakarta项目,旨在提供一种灵活且可扩展的方式来组织和执行一系列处理任务。这个API的核心概念是“链”(Chain),它允许开发者定义...

    apache-commons源码及jar文件

    Apache Commons是一个非常有用的工具包,解决各种实际的通用问题。(附件中提供了该工具包的jar包,及源文件以供研究) BeanUtils Commons-BeanUtils 提供对 Java 反射和自省API的包装 Betwixt Betwixt提供将 ...

    jar包介绍大全

    Commons Chain 提供了一种基于链式设计模式的框架,用于构建复杂的业务流程。在处理复杂的请求或执行一系列操作时,这种模式能够使代码更加清晰和易于维护。 #### Commons Validator (commons-validator.jar) ...

    Chain.NET-开源

    Chain.NET 的设计灵感来源于 Apache Jakarta Commons Chain,这是一个 Java 平台上的类似库,提供了构建复杂业务逻辑的能力。在 .NET 社区,Chain.NET 提供了类似的抽象,使得.NET 开发者也能受益于这种强大的设计...

    s2sh整合中jar包作用介绍

    12. 其他Jakarta Commons库:如commons-包含其他Apache Commons项目的组件,增强Java的功能。 五、总结: S2SH整合涉及的Jar包涵盖了Web应用开发的多个层面,包括MVC框架、持久层管理、依赖注入、模板渲染、AOP、...

    JSF与Shale开发用包

    其中包含:shale-core.jar commons-beanutils.jar commons-chain.jar commons-codec.jar commons-collections.jar commons-digester.jar commons-el.jar commons-fileupload.jar commons-...

    SSH基于Eclipse实现Web层的分页功能源代码

    commons-chain-1.2.jar commons-digester-1.8.jar commons-fileupload-1.1.1.jar commons-io-1.1.jar commons-logging-1.0.4.jar commons-validator-1.3.1.jar jstl-1.0.2.jar(改为:\spring-framework-2.5.5\lib\...

    实现Web层的分页功能源代码

    commons-chain-1.2.jar commons-digester-1.8.jar commons-fileupload-1.1.1.jar commons-io-1.1.jar commons-logging-1.0.4.jar commons-validator-1.3.1.jar jstl-1.0.2.jar(改为:\spring-framework-2.5.5\lib\...

    将Web层分页封装成通用模块源代码

    commons-chain-1.2.jar commons-digester-1.8.jar commons-fileupload-1.1.1.jar commons-io-1.1.jar commons-logging-1.0.4.jar commons-validator-1.3.1.jar jstl-1.0.2.jar(改为:\spring-framework-2.5.5\lib\...

    SSH基于Eclipse将Web层分页封装成通用模块

    commons-chain-1.2.jar commons-digester-1.8.jar commons-fileupload-1.1.1.jar commons-io-1.1.jar commons-logging-1.0.4.jar commons-validator-1.3.1.jar jstl-1.0.2.jar(改为:\spring-framework-2.5.5\lib\...

    传智播客ppt,关于struts1的

    在开发过程中,还需要依赖一些特定的库,例如Commons BeanUtils、Commons Chain、Commons Digester、Commons Logging以及Struts的核心和扩展包。这些库提供了诸如对象映射、日志记录、XML解析等功能,对Struts1的...

    jsf实现基于ajax的上传例子

    幸运的是,Apache Jakarta Commons 提供了一个强大的工具包,可以帮助我们轻松地实现这一功能。 **实现步骤:** 1. **引入依赖库**:首先,确保项目中已经包含了Jakarta Commons FileUpload 库。这个库提供了处理...

    struts1.3 jar包

    Struts1.3 jar包是Apache软件基金会的Jakarta Struts项目中的一个核心组件,它是一个基于MVC(Model-View-Controller)设计模式的Java Web应用框架。这个框架极大地简化了开发人员在构建动态、数据驱动的Web应用程序...

    OGNL中文参考手册.pdf

    - **Jakarta Commons BeanUtils及JSTL的替代品**:OGNL比Jakarta Commons BeanUtils和JSTL的EL表达式更加灵活和强大,支持复杂的属性导航和索引操作。 #### 三、OGNL的历史背景 - **起源**:最初的设计目标是为了...

Global site tag (gtag.js) - Google Analytics