Struts原理與實(shí)踐(7) - -
在上一篇文章中介紹校驗時(shí)提到客戶(hù)邊的校驗用到了JavaScript,實(shí)際上用Struts配合JavaScript還可以實(shí)現許多有用的功能,比如,級聯(lián)下拉菜單的實(shí)現就是一個(gè)典型的例子:
本例假設要實(shí)現的是一個(gè)文章發(fā)布系統,我們要發(fā)布的文章分為新聞類(lèi)和技術(shù)類(lèi),其中新聞類(lèi)又分為時(shí)事新聞和行業(yè)動(dòng)態(tài);技術(shù)類(lèi)又分為操作系統、數據庫、和編程語(yǔ)言等,為了便于添加新的條目,所有這些都保存在數據庫表中。
為此,我們建立一個(gè)名為articleClass的表和一個(gè)名為articleSubClass的表。
articleClass表的結構如下:articleClassID字段:char類(lèi)型,長(cháng)度為2,主鍵articleClassName字段:varchar類(lèi)型,長(cháng)度為20articleSubClass表的結構如下:articleClassID字段:char類(lèi)型,長(cháng)度為2articleSubClassID字段:char類(lèi)型,長(cháng)度為2與articleClassID一起構成主鍵articleSubClassName字段:varchar類(lèi)型,長(cháng)度為20
表建好后,在articleClass表中錄入如下數據:如,01、新聞類(lèi);02、技術(shù)類(lèi)
在articleSubClass表中錄入:01、01、時(shí)事新聞;01、02、行業(yè)動(dòng)態(tài);02、01、操作系統等記錄。到這里,數據庫方面的準備工作就已做好。
有了前面做登錄例子的基礎,理解下面要進(jìn)行的工作就沒(méi)有什么難點(diǎn)了,我們現在的工作也在原來(lái)mystruts項目中進(jìn)行。首先,建立需要用到的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;//子類(lèi)所在行數 private String subJ;//子類(lèi)所在列數 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中。其次,我們的系統要訪(fǎng)問(wèn)數據庫,因此也要建立相應的數據庫訪(fǎng)問(wèn)對象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;//大類(lèi)記數器 int j=0;//小類(lèi)記數器 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("請輸入一個(gè)小類(lèi)"); articleClassForm.setArticleSubClassName("請輸入一個(gè)小類(lèi)"); 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目錄中。它們的目的是將文章的類(lèi)和子類(lèi)信息從數據庫表中讀出,以一定的格式保存在集合對象中以供頁(yè)面顯示。
再次,我們要建立相應的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>選擇文件類(lèi)別</title></head><body bgcolor="#ffffff"><h3>選擇文件所屬類(lèi)型</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">文章大類(lèi)*</td> <td> <html:select property="articleClassID" styleClass="word" onchange="articleClassFormredirect(this.options.selectedIndex)"> <html:option value="">請選擇一個(gè)大類(lèi)</html:option> <html:optionsCollection name="articleClassForm" property="beanCollection" styleClass="word"/> </html:select> </td> </tr> <tr> <td align="right">文章小類(lèi)*</td> <td> <select name="articleSubClassID" Class="word" > <option value="">請選擇一個(gè)小類(lèi)</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>
這里值得重點(diǎn)關(guān)注的是其中的JavaScript代碼,有興趣的可以仔細分析一下它們是怎樣配合集合中的元素來(lái)實(shí)現級聯(lián)選擇的。
最后,為了例子的完整。我們將涉及到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); //處理子類(lèi)選項 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" />
,我們還要提供一個(gè)顯示錯誤信息的jsp頁(yè)面,其代碼如下:
<%@ 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)