Struts原理與實踐 之級聯菜單

本例假設要實現的是一個文章發佈系統,我們要發佈的文章分爲新聞類和技術類,其中新聞類又分爲時事新聞和行業動態;技術類又分爲操作系統、數據庫、和編程語言等,爲了便於添加新的條目,所有這些都保存在數據庫表中。

爲此,我們建立一個名爲articleClass的表和一個名爲articleSubClass的表。

articleClass表的結構如下:
articleClassID字段:char類型,長度爲2,主鍵
articleClassName字段:varchar類型,長度爲20
articleSubClass表的結構如下:
articleClassID字段:char類型,長度爲2
articleSubClassID字段:char類型,長度爲2與articleClassID一起構成主鍵
articleSubClassName字段:varchar類型,長度爲20


表建好後,在articleClass表中錄入如下數據:如,01、新聞類;02、技術類

在articleSubClass表中錄入:01、01、時事新聞;01、02、行業動態;02、01、操作系統等記錄。到這裏,數據庫方面的準備工作就已做好。

有了前面做登錄例子的基礎,理解下面要進行的工作就沒有什麼難點了,我們現在的工作也在原來mystruts項目中進行。首先,建立需要用到的formbean即ArticleClassForm,其代碼如下:

package entity;
import org.apache.struts.action.*;
import javax.servlet.http.*;
import java.util.Collection;

public class ArticleClassForm extends ActionForm {
  //爲select的option做準備
  private Collection beanCollection;
  private String singleSelect = "";
  private String[] beanCollectionSelect = { "" };
  private String articleClassID;
  private String articleClassName;
  private String subI;//子類所在行數
  private String subJ;//子類所在列數
  private String articleSubClassID;
  private String articleSubClassName;

  public Collection getBeanCollection(){
    return beanCollection;
  }

  public void setBeanCollection(Collection beanCollection){
    this.beanCollection=beanCollection;
  }

  public String getSingleSelect() {
    return (this.singleSelect);
  }
  public void setSingleSelect(String singleSelect) {
    this.singleSelect = singleSelect;
  }
  public String[] getBeanCollectionSelect() {
    return (this.beanCollectionSelect);
  }
  public void setBeanCollectionSelect(String beanCollectionSelect[]) {
    this.beanCollectionSelect = beanCollectionSelect;
  }

  public String getArticleClassID() {
    return articleClassID;
  }
  public void setArticleClassID(String articleClassID) {
    this.articleClassID = articleClassID;
  }
  public String getArticleClassName() {
    return articleClassName;
  }
  public void setArticleClassName(String articleClassName) {
    this.articleClassName = articleClassName;
  }

  public String getSubI() {
    return subI;
  }
  public void setSubI(String subI) {
    this.subI = subI;
  }

  public String getSubJ() {
    return subJ;
  }
  public void setSubJ(String subJ) {
    this.subJ = subJ;
  }

  public String getArticleSubClassID() {
    return articleSubClassID;
  }
  public void setArticleSubClassID(String articleSubClassID) {
    this.articleSubClassID = articleSubClassID;
  }

  public String getArticleSubClassName() {
    return articleSubClassName;
  }
  public void setArticleSubClassName(String articleSubClassName) {
    this.articleSubClassName = articleSubClassName;
  }
}


將它放在包entity中。其次,我們的系統要訪問數據庫,因此也要建立相應的數據庫訪問對象ArticleClassDao,其代碼如下:

package db;

import entity.ArticleClassForm;
import db.*;
import java.sql.*;

import java.util.Collection;
import java.util.ArrayList;
import org.apache.struts.util.LabelValueBean;
public class ArticleClassDao {
  private Connection con;

  public ArticleClassDao(Connection con) {
    this.con=con;
  }
  public Collection findInUseForSelect(){
    PreparedStatement ps=null;
    ResultSet rs=null;
    ArrayList list=new ArrayList();
    String sql="select * from articleClass order by articleClassID";
    try{
      if(con.isClosed()){
        throw new IllegalStateException("error.unexpected");
      }
      ps=con.prepareStatement(sql);
      rs=ps.executeQuery();

      while(rs.next()){
        String value=rs.getString("articleClassID");
        String label=rs.getString("articleClassName");
        list.add(new LabelValueBean(label,value));
      }
      return list;
    }
    catch(SQLException e){
      e.printStackTrace();
      throw new RuntimeException("error.unexpected");
    }
    finally{
      try{
        if(ps!=null)
          ps.close();
        if(rs!=null)
          rs.close();

      }
      catch(SQLException e){
        e.printStackTrace();
        throw new RuntimeException("error.unexpected");
      }
    }
  }

  public Collection findInUseForSubSelect(){
    PreparedStatement ps=null;
    ResultSet rs=null;
    PreparedStatement psSub=null;
    ResultSet rsSub=null;
    int i=0;//大類記數器
    int j=0;//小類記數器
    String classID="";
    String subClassID="";
    String subClassName="";

    ArrayList list=new ArrayList();
    ArticleClassForm articleClassForm;


    String sql="select * from articleClass order by articleClassID";
    try{
      if(con.isClosed()){
        throw new IllegalStateException("error.unexpected");
      }
      ps=con.prepareStatement(sql);
      rs=ps.executeQuery();

      while(rs.next()){
        i++;
        classID=rs.getString("articleClassID");
        String sqlSub="select * from articleSubClass where articleClassID=? 
		order by articleSubClassID";
        psSub=con.prepareStatement(sqlSub);
        psSub.setString(1,classID);
        rsSub=psSub.executeQuery();

        articleClassForm=new ArticleClassForm();
        articleClassForm.setSubI(""+i);
        articleClassForm.setSubJ(""+j);
        articleClassForm.setArticleSubClassID("請輸入一個小類");
        articleClassForm.setArticleSubClassName("請輸入一個小類");
        list.add(articleClassForm);

        while(rsSub.next()){
          subClassID=rsSub.getString("articleSubClassID");
          subClassName=rsSub.getString("articleSubClassName");
          j++;
          //optionStr="articleSubClassGroup[" + i + "][" + j + "]=
new Option('"+ subClassName +"','"+ subClassID+ "')";
          articleClassForm=new ArticleClassForm();
          articleClassForm.setSubI(""+i);
          articleClassForm.setSubJ(""+j);
          articleClassForm.setArticleSubClassID(subClassID);
          articleClassForm.setArticleSubClassName(subClassName);
          list.add(articleClassForm);
        }

        j=0;
      }
      return list;
    }
    catch(SQLException e){
      e.printStackTrace();
      throw new RuntimeException("error.unexpected");
    }
    finally{
      try{
        if(ps!=null)
          ps.close();
        if(rs!=null)
          rs.close();

      }
      catch(SQLException e){
        e.printStackTrace();
        throw new RuntimeException("error.unexpected");
      }
    }
  }
}


將它保存在db目錄中。它們的目的是將文章的類和子類信息從數據庫表中讀出,以一定的格式保存在集合對象中以供頁面顯示。

再次,我們要建立相應的jsp文件,文件名爲selectArticleClass.jsp,代碼如下:

<%@ page contentType="text/html; charset=UTF-8" %>
<%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %>
<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>
<%@ taglib uri="/WEB-INF/struts-logic.tld" prefix="logic" %>
<html>
<head>
<title>
選擇文件類別
</title>
</head>
<body bgcolor="#ffffff">
<h3>
選擇文件所屬類型
</h3>
<html:errors/>
<table width="500" border="0" cellspacing="0" cellpadding="0">
  <tr>
    <td><html:form name="articleClassForm" type="entity.ArticleClassForm"
	action="selectArticleClassAction.do">
        <table width="500" border="0" cellspacing="0" cellpadding="0">
          <tr>
            <td align="right">文章大類*</td>
            <td>
              <html:select property="articleClassID" styleClass="word"
			 οnchange="articleClassFormredirect(this.options.selectedIndex)">
                <html:option value="">請選擇一個大類</html:option>
                <html:optionsCollection name="articleClassForm" property="beanCollection" styleClass="word"/>
              </html:select>
            </td>
          </tr>
          <tr>
            <td align="right">文章小類*</td>
            <td>
              <select name="articleSubClassID" Class="word" >
                <option value="">請選擇一個小類</option>
              </select>
              <SCRIPT language=JavaScript>
              <!--
              var articleSubClassGroups=document.articleClassForm.articleClassID.
			 options.length
              var articleSubClassGroup=new Array(articleSubClassGroups)
              for (i=0; i<articleSubClassGroups; i++)
              articleSubClassGroup[i]=new Array()
              <logic:iterate name="articleSubClassList" id="articleClassForm"
			  scope="request" type="entity.ArticleClassForm">
                articleSubClassGroup[<bean:write name="articleClassForm"
				property="subI"/>][<bean:write name="articleClassForm"
				property="subJ"/>]=new Option("<bean:write name="articleClassForm"
			property="articleSubClassName"/>","<bean:write name="articleClassForm"
			property="articleSubClassID"/>")
              </logic:iterate>
              var articleSubClassTemp=document.articleClassForm.articleSubClassID
              function articleClassFormredirect(x){
                for (m=articleSubClassTemp.options.length-1;m>0;m--)
                articleSubClassTemp.options[m]=null
                for (i=0;i<articleSubClassGroup[x].length;i++){
                  articleSubClassTemp.options[i]=new
		Option(articleSubClassGroup[x][i].text,
                   articleSubClassGroup[x][i].value)
                }
                articleSubClassTemp.options[0].selected=true
              }
             //-->
           </SCRIPT>
            </td>
          </tr>
        </table>
      </html:form>
    </td>
  </tr>
</table>
</body>
</html>


這裏值得重點關注的是其中的JavaScript代碼,有興趣的可以仔細分析一下它們是怎樣配合集合中的元素來實現級聯選擇的。

最後,爲了例子的完整。我們將涉及到action代碼和必要的配置代碼在下面列出:其中,action的文件名爲SelectArticleClassAction.java,代碼如下:

package action;
import entity.*;
import org.apache.struts.action.*;
import javax.servlet.http.*;
import javax.sql.DataSource;
import java.sql.Connection;
import db.ArticleClassDao;
import java.util.Collection;
import java.sql.SQLException;
public class SelectArticleClassAction extends Action {
  public ActionForward execute(ActionMapping actionMapping, ActionForm actionForm,
  HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) {
    /**@todo: complete the business logic here, this is just a skeleton.*/
    ArticleClassForm articleClassForm = (ArticleClassForm) actionForm;
    DataSource dataSource;
    Connection cnn=null;
    ActionErrors errors=new ActionErrors();
    try{
      dataSource = getDataSource(httpServletRequest,"A");
      cnn = dataSource.getConnection();
      ArticleClassDao articleClassDao=new ArticleClassDao(cnn);

      Collection col=articleClassDao.findInUseForSelect();
      articleClassForm.setBeanCollection(col);
      httpServletRequest.setAttribute("articleClassList",col);

      //處理子類選項
      Collection subCol=articleClassDao.findInUseForSubSelect();
      httpServletRequest.setAttribute("articleSubClassList",subCol);
      return actionMapping.findForward("success");
    }
    catch(Throwable e){
      e.printStackTrace();
      //throw new RuntimeException("未能與數據庫連接");
      ActionError error=new ActionError(e.getMessage());
      errors.add(ActionErrors.GLOBAL_ERROR,error);
    }
    finally{
      try{
        if(cnn!=null)
          cnn.close();
      }
      catch(SQLException e){
        throw new RuntimeException(e.getMessage());
      }
    }
    saveErrors(httpServletRequest,errors);
    return actionMapping.findForward("fail");
  }
}


將其保存在action目錄中。

在struts-config.xml文件中做如下配置:

<form-beans>
中加入
<form-bean name="articleClassForm" type="entity.ArticleClassForm" />


><action-mappings>
中加入:

<action name="articleClassForm" path="/selectArticleClassAction" scope="session"
	type="action.SelectArticleClassAction" validate="false">
<forward name="success" path="/selectArticleClass.jsp" />
<forward name="fail" path="/genericError.jsp" />
</action>


爲了對應配置中的
<forward name="fail" path="/genericError.jsp" />
,我們還要提供一個顯示錯誤信息的jsp頁面,其代碼如下:

<%@ page contentType="text/html; charset=UTF-8" %>
<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>
<html>
<head>
<title>
genericError
</title>
<link href="css/mycss.css" rel="stylesheet" type="text/css">
</head>
<body bgcolor="#ffffff">
<html:errors/>
</body>
</html>


現在一切就緒,可以編譯執行了。在瀏覽器中輸入:http://127.0.0.1:8080/mystruts/selectArticleClassAction.do就可以看到該例子的運行結果了。(T111)

本文作者:張永美 羅會波 湖北省當陽市國稅局 可通過[email protected]與他們聯繫
發佈了27 篇原創文章 · 獲贊 0 · 訪問量 12萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章