宁静以思远

Java使人内心宁静

BlogJava 首页 新随笔 联系 聚合 管理
  8 Posts :: 0 Stories :: 17 Comments :: 0 Trackbacks

[IBM developerWorks 中国  ]

本文讲述了如何利用Java的反射的机制来简化Structs应用程序的开发。

Struts中引入ActionForm类的意义与缺陷:

在Struts应用程序中,ActionForm是一个很重要的概念,它的主要功能就是为Action的操作提供与客户表单相映射的数据(如果在客户指定的情况下,还包括对数据进行校验)。Action根据业务逻辑的需要,对数据状态进行修改,在改变系统状态后,ActionForm则自动的回写新的数据状态并保持。程序员对JSP与ActionForm Bean的对应关系,通常感到很迷惑,JSP与ActionForm到底是1:1,还是N:1,对此,Struts本身对此并没有提出自己的观点。无论是一对一,还是多对一,Struts本身并不关心,它都能很好得工作。Struts在它的开发文档中指出,对于较小规模的开发,开发人员可以根据自己的需要,每个模块只写一个ActionForm Bean,甚至整个应用程序只写一个ActionForm Bean.当然,Struts也不反对每个ActionForm Bean只对应一个JSP,他们之间的对应关系,由开发人员自己决定。

在我看来,正如Entity EJB对J2EE的重大贡献一样,Entity EJB使得程序员对二维关系数据库的存取对象化了,程序员可以使用Set 或者Get等面向对象的方法来操纵关系数据库的数据,而ActionForm也使得程序员对网页的数据存取奇迹般的对象化了,程序员同样也可以使用Set 或者Get等面向对象的方法存取网页上的数据,这是一个开发模式方式上的重大转变。基于此,我个人认为ActionForm与JSP即VIEW层的关系最好是一对一的关系,这样,在理解上会更清晰一些。但是,这样也会带来一个很现实的问题,在一个应用程序中,也许有非常多得JSP页面,如果每个ActionForm 都只对应一个JSP页面,那么系统的Java代码就会急剧膨胀起来,而且,每个ActionForm都是只有很简单的Set或者Get方法存取数据,那么,如何简化Struts应用程序的开发呢?

在Struts1.1 中,Struts引入了DynaActionForm和Dyna Bean,试图解决这个问题,在我看来,DynaActionForm的引入,破坏了对网页存取对象化的概念,使开发人员重新回到了使用HashTable、Map、Collection、ArrayList等集合对象来实现对数据进行存取的老路上来。虽然应用程序的灵活性大大增加了,但是代码的可读性也大大降低了,开发人员之间的交流难度也增加了。

在传统的应用程序对ActionForm Bean的访问中,我们通常都写成如下的形式:

Connection conn = DriverManager.getConnection( " JDBC URL  " );
      sql
= "  select *  from some tables  " ;
PreparedStatement stmt 
=  conn.prepareStatement(sql);
      ResultSet rs 
=  stmt.executeQuery();
ArrayList array
= new  ArrayList();
while  (rs.next())  {
   AActionForm actionForm 
= new  AActionForm ();
   actionForm.setId(rs.getString(
" Id " ));
   actionForm.setName(rs.getString(
" Name " ));           
   array.add(actionForm);
}


在Action 的Execute方法中,我们 把这个集合用request.setAttribute("array", array)存储起来,然后在JSP页面中,我们用iterate Tag把数据循环现实出来。代码通常都是这个样子:

 

< logic:present  name =" array "  scope ="request" >
< logic:iterate  name =" array "  id =" array "  
type
="com.bhsky.webis.Goods" >
  
< tr  align ="center" >  
     
< td  class ="table2" >
< bean:write  name =" array "  property ="goodsid" />
</ td >
  
< td  class ="table2" >
< bean:write  name =" array "  property ="goodsname" />
</ td >
   
</ tr >
  
</ logic:iterate >  
</ logic:present >

在Struts中,对数据的访问和显示的写法通常都是很固定的,在VIEW层,我们是没有办法简化自己的代码的,在Action层,其写法通常也很固定,只是做一个页面的跳转,商业逻辑和对数据得访问,通常都是放在JavaBean中。那么,在此,我提出一种运用类反射的机制,使应用程序对ActionForm Bean的赋值自动化,即应用程序通过一个简单的接口,使用一个通用的方法,就可以完成对ActionForm Bean的赋值,而不必在每个使用ActionFormBean的地方,都把数据库中的值手动赋值给ActionForm Bean,然后再在JSP页面中显示出来。虽然它不能减少ActionForm Bean的数量,但是,它至少使应用程序对ActionForm Bean的赋值自动化了,从而减少了程序出错概率,提高了程软件开发效率。


类反射的概念:

关于类反射的概念,在此我就不详细介绍了,它不是本文的重点,IBM developerWorks网站上有大量介绍类反射概念的文章,大家可以找出来参考一下。其实,Struts本身就大量利用了类反射的机制。


如何应用类反射机制简化Struts应用程序的开发:

1、 先定义Action FormBean:

     package  com.bhsky.webis.system;
import  org.apache.struts.action. * ;
import  javax.servlet.http. * ;
    
public   class  UsersActionForm  extends  ActionForm  {
private  String usr_id;
private  String usr_name;
public   void  setUsr_id(String usr_id)  {
    
this .usr_id  =  usr_id;
}

public  String getUsr_id()  {
    
return  usr_id;
}

public  String getUsr_memo()  {
    
return  usr_memo;
}

public   void  setUsr_name(String usr_name)  {
    
this .usr_name  =  usr_name;
}

}



2、 编写通用的为ActionFormBean赋值的方法:

    //////////////////////////////////////////////////////////////////////////// /
    
// Function: 完成ResultSet对象向ArrayList对象为集合的对象的转化
    
// Para:sql,指定的查询Sql
   
// Para:className,Sql相对应得JavaBean/FormBean类的名字
   
// Return:以类className为一条记录的结果集,完成ResultSet对象向ArrayList对象为集 // 合的className对象的转化
   //////////////////////////////////////////////////////////////////////////////
   public  ArrayList Select(String sql,String className) {
    ArrayList paraList
= new  ArrayList();
    
try {
      
if  (conn  ==   null ) {
        Connection();
      }

      PreparedStatement stmt 
=  conn.prepareStatement(sql);
      ResultSet rs 
=  stmt.executeQuery();
      String recordValue
= "" ;
      Object c1
= null ;
      paraList
= new  ArrayList();
      ResultSetMetaData rsmd 
=  rs.getMetaData();
      
int  columnCount  =  rsmd.getColumnCount();
      
while  (rs.next()) {
          c1
= Class.forName(className).newInstance();
          
for  ( int  i = 1 ; i <= columnCount; i ++ {
            
if (rs.getString(rsmd.getColumnName(i)) != null ) {
              recordValue
= rs.getString(rsmd.getColumnName(i));
            }
else {
              recordValue
= "" ;
            }

Method 
m
= c1.getClass().getMethod(getSetMethodName(rsmd.getColumnName(i)),
new  Class[] {recordValue.getClass()} );
            m.invoke (c1, 
new  Object[] {recordValue} );
          }

          paraList.add(c1);
      }

    }
catch (SQLException ex) {
      
}
catch (ClassNotFoundException e) {
}
catch (NoSuchMethodException e)  {
}
catch (InvocationTargetException e) {
}
catch  (IllegalAccessException e) {
}
catch (InstantiationException e) {
}
 finaly {
        closeConnection();
return  paraList;
}

  }


3、 在JavaBean封装的商业逻辑中调用Select 方法,然后在JSP页面上显示出来:

// Function:取得用户列表
  
// Para:
  
// Return:返回用户列表
   //////////////////////////////////////////////////////////////////////////// /
   public  ArrayList getUsers() {
      ArrayList ret
= null ;
      DatabaseManage db
= new  DatabaseManage();
      String sql
= "  select usr_id,usr_name  "
          
+ "  from users  "  ;
      ret
= db.Select(sql, "  com.bhsky. webis.system.UsersActionForm " );
      
return  ret;
  }

4、 在Action的execute方法中调用getUsers()方法:

  public  ActionForward execute(ActionMapping actionMapping, ActionForm actionForm, 
     HttpServletRequest request, HttpServletResponse httpServletResponse) 
   
{
    
/** @todo: complete the business logic here, this is just a skeleton. */
    UsersActionForm uaf
= (UsersActionForm)actionForm;
    SystemService ubb
= new  SystemService();
    ArrayList userList
= ubb.getUsers();
    request.setAttribute(
" userList " ,userList);
    ActionForward actionForward
= actionMapping.findForward(url);
    
return  actionForward;
  }


5、 在JSP中显示:

 

    < table  width ="700"  class ="1"  border ="1"  cellspacing ="1"  align ="center" >
  
< tr >
    
< td  class ="list"   > 用户ID </ td >
    
< td  class ="list"   > 姓&#160&#160名 </ td >
  
</ tr >
  
< logic:present  name ="userList"  scope ="request" >
       
< logic:iterate  name ="userList"  id ="userList"  
type
="com.bhsky.webis.system.UsersActionForm" >
  
< tr >
    
< td  class ="cell1"   height ="22" >< bean:write  name ="userList"  
property
="usr_id" /></ td >
    
< td  class ="cell1"   height ="22" >< bean:write  name ="userList"  
property
="usr_name" /></ td >
     
</ tr >
  
</ logic:iterate >
      
</ logic:present >
</ table >


 
结语:

我们通过运用类反射机制,在一个Struts应用开发中,完成了一个通用查询方法的实现。它使得程序员摆脱了在每个应用程序中都要编写枯燥的set、get等方法来访问ActionForm Bean,从而简化了Struts应用程序的开发。
 

posted on 2007-03-21 10:05 Aaronbamoo 阅读(205) 评论(1)  编辑  收藏

Feedback

# re: [转载]运用类反射机制简化Struts应用程序的开发 2007-03-21 10:08 Aaronbamoo
P.S.
看完文章后,第一感受是这可能就是Hibernate的一种技术基础吧。  回复  更多评论
  


只有注册用户登录后才能发表评论。


网站导航: