Sung in Blog

                     一些技術(shù)文章 & 一些生活雜碎
          本文講述了如何利用Java的反射的機(jī)制來簡化Structs應(yīng)用程序的開發(fā)。

          一、Struts中引入ActionForm類的意義與缺陷:

          在Struts應(yīng)用程序中,ActionForm是一個(gè)很重要的概念,它的主要功能就是為Action的操作提供與客戶表單相映射的數(shù)據(jù)(如果在客戶指定的情況下,還包括對(duì)數(shù)據(jù)進(jìn)行校驗(yàn))。Action根據(jù)業(yè)務(wù)邏輯的需要,對(duì)數(shù)據(jù)狀態(tài)進(jìn)行修改,在改變系統(tǒng)狀態(tài)后,ActionForm則自動(dòng)的回寫新的數(shù)據(jù)狀態(tài)并保持。程序員對(duì)JSP與ActionForm Bean的對(duì)應(yīng)關(guān)系,通常感到很迷惑,JSP與ActionForm到底是1:1,還是N:1,對(duì)此,Struts本身對(duì)此并沒有提出自己的觀點(diǎn)。無論是一對(duì)一,還是多對(duì)一,Struts本身并不關(guān)心,它都能很好得工作。Struts在它的開發(fā)文檔中指出,對(duì)于較小規(guī)模的開發(fā),開發(fā)人員可以根據(jù)自己的需要,每個(gè)模塊只寫一個(gè)ActionForm Bean,甚至整個(gè)應(yīng)用程序只寫一個(gè)ActionForm Bean.當(dāng)然,Struts也不反對(duì)每個(gè)ActionForm Bean只對(duì)應(yīng)一個(gè)JSP,他們之間的對(duì)應(yīng)關(guān)系,由開發(fā)人員自己決定。

          在我看來,正如Entity EJB對(duì)J2EE的重大貢獻(xiàn)一樣,Entity EJB使得程序員對(duì)二維關(guān)系數(shù)據(jù)庫的存取對(duì)象化了,程序員可以使用Set 或者Get等面向?qū)ο蟮姆椒▉聿倏v關(guān)系數(shù)據(jù)庫的數(shù)據(jù),而ActionForm也使得程序員對(duì)網(wǎng)頁的數(shù)據(jù)存取奇跡般的對(duì)象化了,程序員同樣也可以使用Set 或者Get等面向?qū)ο蟮姆椒ù嫒【W(wǎng)頁上的數(shù)據(jù),這是一個(gè)開發(fā)模式方式上的重大轉(zhuǎn)變。基于此,我個(gè)人認(rèn)為ActionForm與JSP即VIEW層的關(guān)系最好是一對(duì)一的關(guān)系,這樣,在理解上會(huì)更清晰一些。但是,這樣也會(huì)帶來一個(gè)很現(xiàn)實(shí)的問題,在一個(gè)應(yīng)用程序中,也許有非常多得JSP頁面,如果每個(gè)ActionForm 都只對(duì)應(yīng)一個(gè)JSP頁面,那么系統(tǒng)的Java代碼就會(huì)急劇膨脹起來,而且,每個(gè)ActionForm都是只有很簡單的Set或者Get方法存取數(shù)據(jù),那么,如何簡化Struts應(yīng)用程序的開發(fā)呢?

          在Struts1.1 中,Struts引入了DynaActionForm和Dyna Bean,試圖解決這個(gè)問題,在我看來,DynaActionForm的引入,破壞了對(duì)網(wǎng)頁存取對(duì)象化的概念,使開發(fā)人員重新回到了使用HashTable、Map、Collection、ArrayList等集合對(duì)象來實(shí)現(xiàn)對(duì)數(shù)據(jù)進(jìn)行存取的老路上來。雖然應(yīng)用程序的靈活性大大增加了,但是代碼的可讀性也大大降低了,開發(fā)人員之間的交流難度也增加了。

          在傳統(tǒng)的應(yīng)用程序?qū)ctionForm 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方法中,我們 把這個(gè)集合用request.setAttribute("array", array)存儲(chǔ)起來,然后在JSP頁面中,我們用iterate Tag把數(shù)據(jù)循環(huán)現(xiàn)實(shí)出來。代碼通常都是這個(gè)樣子:

          <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中,對(duì)數(shù)據(jù)的訪問和顯示的寫法通常都是很固定的,在VIEW層,我們是沒有辦法簡化自己的代碼的,在Action層,其寫法通常也很固定,只是做一個(gè)頁面的跳轉(zhuǎn),商業(yè)邏輯和對(duì)數(shù)據(jù)得訪問,通常都是放在JavaBean中。那么,在此,我提出一種運(yùn)用類反射的機(jī)制,使應(yīng)用程序?qū)ctionForm Bean的賦值自動(dòng)化,即應(yīng)用程序通過一個(gè)簡單的接口,使用一個(gè)通用的方法,就可以完成對(duì)ActionForm Bean的賦值,而不必在每個(gè)使用ActionFormBean的地方,都把數(shù)據(jù)庫中的值手動(dòng)賦值給ActionForm Bean,然后再在JSP頁面中顯示出來。雖然它不能減少ActionForm Bean的數(shù)量,但是,它至少使應(yīng)用程序?qū)ctionForm Bean的賦值自動(dòng)化了,從而減少了程序出錯(cuò)概率,提高了程軟件開發(fā)效率。

          二、類反射的概念:

          關(guān)于類反射的概念,在此我就不詳細(xì)介紹了,它不是本文的重點(diǎn),IBM developerWorks網(wǎng)站上有大量介紹類反射概念的文章,大家可以找出來參考一下。其實(shí),Struts本身就大量利用了類反射的機(jī)制.

          .

          三、如何應(yīng)用類反射機(jī)制簡化Struts應(yīng)用程序的開發(fā):





          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對(duì)象向ArrayList對(duì)象為集合的對(duì)象的轉(zhuǎn)化
              //Para:sql,指定的查詢Sql
             //Para:className,Sql相對(duì)應(yīng)得JavaBean/FormBean類的名字
             //Return:以類className為一條記錄的結(jié)果集,完成ResultSet對(duì)象向ArrayList對(duì)象為集
             //合的className對(duì)象的轉(zhuǎn)化
            //////////////////////////////////////////////////////////////////////////////
            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封裝的商業(yè)邏輯中調(diào)用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方法中調(diào)用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" >姓  名</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>


          四、結(jié)語:

          我們通過運(yùn)用類反射機(jī)制,在一個(gè)Struts應(yīng)用開發(fā)中,完成了一個(gè)通用查詢方法的實(shí)現(xiàn)。它使得程序員擺脫了在每個(gè)應(yīng)用程序中都要編寫枯燥的set、get等方法來訪問ActionForm Bean,從而簡化了Struts應(yīng)用程序的開發(fā)。

          posted on 2005-10-24 22:10 Sung 閱讀(191) 評(píng)論(0)  編輯  收藏 所屬分類: Struts
          主站蜘蛛池模板: 大田县| 嘉禾县| 富源县| 金乡县| 垣曲县| 布尔津县| 始兴县| 连城县| 大洼县| 阿坝| 白朗县| 桂东县| 视频| 济南市| 台湾省| 湖北省| 吴旗县| 舟山市| 荣昌县| 翁牛特旗| 花垣县| 弥渡县| 宁城县| 永嘉县| 湘潭市| 清水县| 漾濞| 扎赉特旗| 桐柏县| 宜阳县| 社旗县| 松溪县| 乐安县| 松滋市| 桐柏县| 宝山区| 石嘴山市| 茶陵县| 榆社县| 共和县| 汝州市|