程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> JAVA編程入門知識 >> Struts開發技巧

Struts開發技巧

編輯:JAVA編程入門知識

  Struts開發技巧
   在經歷了《中國電信大客戶貼心服務》項目的開發以及目前正在進行開發中的《中國電信總部經營分析》項目,累計了一些對於Struts1.1和Tiles開發的一些技術和技巧,特寫出來,方便以後的開發,同時也相信能給讀者在開發Struts提供一些幫助
  模塊配置
  1. Struts配置文件定義
   對於系統中的某個模塊,需要在開發前定義該模塊的配置,該struts的配置文件命名為:
  struts-config-xxx.XML
  xxx為模塊的小寫英文名或縮寫,如:struts-config-sysman.xml
  注重:中間為“-”,而不是“_”連接符
  統一保存在“WEB-INFxml”文件夾下,並需要在web.xml中添加相應的配置文件
  地址,具體如下例:
   …
   <init-param>
   <param-name>config</param-name>
   <param-value>/WEB-INF/struts-config.xml, /WEB-INF/xml/struts-config-pages.xml,/WEB-INF/xml/struts-config-sysman.xml</param-value>
   </init-param>
  …
  注重:需要用“,”連接符隔開各個配置文件名
  另外,所有的靜態jsp需要通過配置文件定義其“.do”形式的訪問,保存在
  struts-config-pages.xml文件中,內容如下例:
   …
   <!--主頁轉向-->
   <action path="/main" type="org.apache.struts.actions.ForwardAction" parameter="/main.jsp"/>
   …
  2. Tiles配置文件定義
  系統的框架配置文件為tiles-defs_zh_CN.xml(通過.properties屬性文件支持國際化應用,默認是tiles-defs.xml),模塊的框架結構需要定義在裡面,如下例:
  …
  <!-- 定義默認首頁 -->
   <definition name="default.frame" path="/layouts/defaultLayout.jsp">
   <put name="title" value="歡迎進入電信經營分析系統" />
   <put name="header" value="/top.jsp" />
   <put name="body" value="default.body" />
   <put name="footer" value="/buttom.jsp" />
   </definition>
  <!-- 定義默認首頁的body -->
   <definition name="default.body" path="/layouts/main.jsp" >
   <put name="Logon" value="/Logon.jsp" />
   <put name="date" value="/layouts/date.jsp" />
   <put name="linkSite" value="/layouts/link.Html" />
   </definition>
  …
  框架命名規范按“系統(子系統).功能模塊.頁面模塊”,如上面的“default.frame”
  在struts-config-pages.xml文件中的設置的頁面action可以這樣寫:
  <action path="/main" type="org.apache.struts.actions.ForwardAction" parameter=" default.frame "/>
  這樣就不必單獨寫一個tiles:insert的頁面,如下:
  <tiles:insert definition="vip.warn.day" flush="true" />
  3. 模塊中的注釋
  不但需要在程序中添加必要的注釋,在定義配置文件的時候也必須需要添加相應注釋,主要是在struts-config-xxx.xml和tiles-defs_zh_CN.xml這些文件中添加注釋,要把action或配置模塊的功能解釋清楚,放在配置項的前面,參見上面的配置文件
  4. 對於配置文件的編輯
  不能使用Jbuilder裡面的xml編輯功能,因為JB會自動地改變xml裡面的編碼和內容,因此,對xml配置文件的編輯,要使用編輯軟件,如UE等
  事件定義
  事件對應的類主要有Action、ActionForm,還有jsp中提交的“.do”定義,以及頁面動作的提交,以login登錄為例:
  1. 類的命名定義(首字母需大寫)
  形式為“動作名+Action/Form”
  如:LoginAction.class、LoginForm.class
  2. 頁面地址定義(首字母需小寫)
  假如有兩個單詞以上,第二個單詞首字母大寫,依此類推
  形式為“動作名”
  如:login.do或loginSys.do
  jsp文件命名也按此規范
  3. 頁面動作定義
  因為jsp頁面中的Form對應ActionForm,其本身有action這個屬性,所以頁面動作假如定義也為action,會引起不必要的麻煩,所以,把頁面動作統一定義為“act”,
  如需要編輯某條記錄,地址如下:
  “/editRecord.do?act= Edit”
  如需要刪除,地址如下:
  “/editRecord.do?act=Delete”
  4. 對於菜單和操作事件觸發的控制機制
  由於系統中的菜單和操作都是由“.do”形式向服務端發請求的,因此需要一套機制來控制哪些是對菜單的事件請求,哪些是對操作的事件請求;
  我們在系統中引入了Filter過濾器,對所有請求進行控制,以及判定用戶是否登錄和是否有對資源(菜單等)訪問權限等;
  約定:
  jsp頁面上對於系統中菜單的請求都是“GET”方法,對於操作的Action都是“POST”方法;
  有了這樣的約定,在Filter中先判定request的請求方法,假如是“GET”方法,則認為是對菜單的請求,所以去“菜單表”根據請求地址讀取相應的記錄,並讀取用戶的權限表,判定用戶的菜單權限;
  假如是“POST”的方法,則認為是對操作的請求,並提取request中的“act”動作,進行對用戶的權限點的判定。
  
  參數信息獲取
  1. 公共參數信息通過Plugin方式在Web服務啟動時將變量放入application中,使得在任何需要該變量的jsp中都可以調用;
  方式如下:
  public void setServletContext(ActionServlet actionServlet) {
  try {
   ServletContext sc = actionServlet.getServletContext();
   //SysInitPwd
   sc.setAttribute(Constants.SYS_INIT_PWD,SelectLists.getSysConfig("PWDINIT"));
  …
  在action等程序中的調用方式:
  getServlet().getServletContext().getAttribute(“…”);
  
  2. 對於頁面上需要展示的數據盡量存放在request這個范圍裡,可以減輕服務器端內存負載,方式如下:
  //調用員工處理類
  StaffDeal sd=new StaffDeal();
  //根據員工狀態查詢員工
  ArrayList al=sd.qryStaff(strState);
  //放入request
   request.setAttribute("staffInfo",al);
  3. 私有的或需要根據用戶的屬性來獲取參數信息的,可以在tiles的定義中使用“controlClass=xxx”這個方式獲取,配置如下例:
  <definition name="vip.welcome" path="/vip/welcome.jsp" controllerClass="viptx.logic.vip.welcomeAction" />
  需implements Controller中的perform方法,代碼如下例:
  public void perform(ComponentContext componentContext,
   HttpServletRequest request,
   HttpServletResponse response,
   ServletContext servletContext) throws IOException,ServletException {
   HttpSession session = request.getSession();
   // Get current session.
   User user = (User) session.getAttribute(Constants.USER_KEY);
   if (user == null) {
   return null;
   }
   String uid = user.getUserid();
   String sql = "select userid,content from ti_salutatory where userid=´"+uid+"´";
   try {
   …
   }
   catch (Exception ex) {
   throw new ServletException(ex.getMessage());
   }
  }
  4. 對於後台出錯信息在前台頁面顯示的技巧
  首先在properties配置“message.common={0}”
  然後在Action類中使用ActionErrors或ActionMessages時,方法如下:
  …
  ActionMessages ams = new ActionMessages(); //例外處理
  Try{
  …
  }
  catch (Exception ex) {
   ex.printStackTrace();
   ams.add(ActionMessages.GLOBAL_MESSAGE,
   new ActionMessage("message.common", ex.getMessage()));
  }
   finally {
  if (!ams.isEmpty()) {
   saveMessages(request, ams);
   }
  }
  …
   在jsp頁面中使用方法如下:
   <html:messages id="msg" message="true">
   <font color="red"><bean:write name="msg"/></font>
   </html:messages>
   假如有後台的messages產生,前台頁面就可以出現報錯信息
  5. 系統配置文件
  系統參數如數據庫連接等在sysConfi.xml文件中配置,存放在“WEB-INF/xml”文件夾下,請參見該文件。
  開發規范和公用方法
  關於Java的開發規范參見《Java 編程規范.doc》,這裡僅給出用struts開發中一些的規范:
  1. java文件存放按業務邏輯劃分,並用模塊作為包名的形式,如:telecombi.logic.sysman.security
  包名都為小寫形式
  所有的Action和ActionForm都存放在同一包下,便於治理,不要跨包調用
  2. 所有ActionForm中的屬性均為“首單詞小寫+第二個單詞首字母大寫+…”的形式,如:staffId、staffName,不答應使用“_”為單詞連接符
  3. 需要驗證的頁面,均需要客戶端和服務端兩次驗證(即對jsp中的Form進行javascript驗證和Action中的excute方法中進行驗證),不能只采用其中一種方法,防止客戶繞過js直接提交;
  在驗證登錄提交的form時,必須使用staticJavascript="false",否則就會把javascript寫到頁面裡,如:
  <html:javascript formName="LogonForm"
   dynamicJavascript="true"
   staticJavascript="false"/>
  <script language="Javascript1.1" src="staticJavascript.jsp"></script>
  驗證的formName必須和validation.xml中的Form的名字對應起來,否則驗證無效
  4. ActionForm是代表html中的Form的,其中的變量需要和Form中的屬性對應起來,如:要在jsp中使用<form:text property="userName"/>,則使用的ActionForm中就必須有userName這個變量
  5. 對於Action中的邏輯,假如處理方法在一個以上,需要另外新建一個處理類,負責對Action中的邏輯集中處理,命名為xxxDeal,如:LoginDeal;
  Action通過調用該處理類的方法,實現業務邏輯處理
  6. 對數據庫的操作使用DBManager這個類,對其中的一些方法,具體介紹如下:
   查詢結果對象化的Select操作,使用Select(String sql,String className)方法
  StringBuffer sql = new StringBuffer(
   "select staff_id staffId from ts_m_staff ")
   .append("where staff_id=´").append(uid).append("´");
   try {
  /**
  * User是一個用戶對象類,其中有staffId這個屬性,以及對應的get/set方法,通過
  * DBManager的Select方法獲得一個User的ArrayList集合
  */
  ArrayList rs = DBManager.Select(sql.toString(), User.class.getName());
  /**
  * 假如確定返回的只有一個對象,則可以使用
  *
  */
  User user=(User)rs.get(0);
   }
   catch (Exception ex) {
   throw new ServletException(ex.getMessage());
  }
  取出來的數據可以存放在session或page等裡,供jsp頁面調用,方法為session.setAttribute(“user”,user1)
  …
   Insert或Update等操作
  使用DBManager裡面的executeSql(String sql)方法,假如是批量處理,使用executeBatchSql(String[] sqls)方法,返回成功標志為Constants.OPERATE_SUCCESS
  失敗標志為Constants.OPERATE_FAILED
  暫無其它信息返回
   ResultSet對象向Hashtable集合對象的轉化,使用select(String sql)方法:
  除了可以使用DBManager的Select把查詢結果轉為對象以外,還可以使用以前的直接使用ResultSet對象的方式,不過這裡返回的數據集對象為Hashtable;
  Hashtable存放的數據結構為:
  columnName1 ? ArrayList1(該字段的結果集)
  columnName2 ? ArrayList2(該字段的結果集)
  …
   系統中使用該方法的比較多的是用在生成下拉框數據,從select方法返回的Hashtable取到字段值,並生成LabelValueBean,具體方法如下:
   /**公用函數 Hashtable 轉換成 ArrayList (LabelValueBean)*/
   private static ArrayList hashToLVB(Hashtable ht, String id, String name,boolean hasBlank) {
   if (ht!=null){
   ArrayList al = new ArrayList();
   ArrayList alId = (ArrayList) ht.get(id.toUpperCase());
   ArrayList alName = (ArrayList) ht.get(name.toUpperCase());
   int iLen = alId.size();
   if (hasBlank)
   al.add(new LabelValueBean("未知", "-1"));
   for (int i = 0; i < iLen; i++) {
   al.add(new LabelValueBean( (String) alName.get(i),
   (String) alId.get(i)));
   }
   return al;
   }
   else{
   return null;
   }
   }
   AutoSetForm(String sql, Object frm)方法介紹:
  a) 該方法可以返回一個查詢數據庫後已對其中的屬性賦值的對象,使用方法如下:
  User user=DBManager. AutoSetForm(sql,new User());
  sql為查詢語句
  b) 該方法還可以對頁面操作後的Form進行賦值,比如在頁面上提交一個對某條記錄進行編輯的操作,當Action得到該條記錄的Id號並查詢數據庫成功後,需要把各個具體信息set到ActionForm的屬性變量中去,這個時候就可以使用該方法,方法如下:
  form= DBManager. AutoSetForm(sql,form);
  form為Action的excute方法中傳入的ActionForm
  
  7. 調用存儲過程
  使用DBManager中的execProc(String procName,ArrayList procPrts)方法
  procName為存儲過程名,procPrts是該存儲過程的入口參數集,返回的是ProcOuts的對象,其中有Result和ExceptionInfo兩個屬性,表示返回的處理標記和異常信息(假如有的話)
  8. 數據操作返回信息的處理
  在對數據操作完成後,需要返回操作是否成功等信息,具體步驟如下:
   使用屬性文件中的“messages.comm”這個key,可以對該key添加具體返回信息
   程序中使用“ActionMessages”這個對象,java程序如下:
  ActionMessages ams = new ActionMessages();
  …
  //執行結果
   ProcOuts pResult=null;
  //是否調用成功
   if (pResult.getResult() == -1) {
   ams.add(ActionMessages.GLOBAL_MESSAGE,
   new ActionMessage("message.common",
   pResult.getExceptionInfo()));
   }
  if (!ams.isEmpty()) {
   saveMessages(request, ams);
   }
  Jsp中調用方法如下:
  <html:messages id="msg" message="true">
   <font color="red"><bean:write name="msg"/></font>
  </html:messages>
 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved