联动选择下拉菜单是我们在开发中经常遇到的问题,一般来讲,三级联动是最为常见的。具体实现方式有很多种:比如每一次下拉选择change的时候发一次ajax请求调数据库加载,或者全部加载信息使用dom方式控制菜单。从性能上来说,第二种实现方式优于第一种,减少了数据库调用次数,并且也能很好地控制菜单显示速度。本文将使用第二种实现方式:
1表设计和准备数据:建立以下数据表并插入示例数据,用于反映学院、专业、班级的三个层级关系,使用lvl和parcode来表示层次关系。
create table grade_tab( code varchar2(20) primary key, codenm varchar2(40), parcode varchar2(20), lvl varchar2(1) ); --lvl1 data insert into grade_tab (code, codenm, parcode, lvl) values ('ETC', 'Electric', '', '1'); insert into grade_tab (code, codenm, parcode, lvl) values ('ECO', 'Economics', '', '1'); insert into grade_tab (code, codenm, parcode, lvl) values ('STW', 'softwa', '', '1'); --lvl2 data insert into grade_tab (code, codenm, parcode, lvl) values ('ETC01', 'Electric automatic', 'ETC', '2'); insert into grade_tab (code, codenm, parcode, lvl) values ('ETC02', 'Electric machintic', 'ETC', '2'); insert into grade_tab (code, codenm, parcode, lvl) values ('ETC03', 'Electric emmbed', 'ETC', '2'); insert into grade_tab (code, codenm, parcode, lvl) values ('ECO01', 'E-commerce', 'ECO', '2'); insert into grade_tab (code, codenm, parcode, lvl) values ('ECO02', 'National trade', 'ECO', '2'); insert into grade_tab (code, codenm, parcode, lvl) values ('SE', 'Software erginerring', 'STW', '2'); --lvl3 data insert into grade_tab (code, codenm, parcode, lvl) values ('ETCC1', '011007', 'ETC01', '3'); insert into grade_tab (code, codenm, parcode, lvl) values ('ETCC2', '011008', 'ETC01', '3'); insert into grade_tab (code, codenm, parcode, lvl) values ('ETCC3', '011009', 'ETC02', '3'); insert into grade_tab (code, codenm, parcode, lvl) values ('ETCC4', '011010', 'ETC02', '3'); insert into grade_tab (code, codenm, parcode, lvl) values ('ETCC5', '011011', 'ETC03', '3'); insert into grade_tab (code, codenm, parcode, lvl) values ('ETCC6', '011012', 'ETC03', '3'); insert into grade_tab (code, codenm, parcode, lvl) values ('ETCC7', '011014', 'ETC03', '3'); insert into grade_tab (code, codenm, parcode, lvl) values ('STWC1', '011201', 'SE', '3'); insert into grade_tab (code, codenm, parcode, lvl) values ('STWC2', '011202', 'SE', '3'); insert into grade_tab (code, codenm, parcode, lvl) values ('STWC3', '011203', 'SE', '3'); insert into grade_tab (code, codenm, parcode, lvl) values ('STWC4', '011204', 'SE', '3');
2前端页面:
页面将使用ajax作为请求处理技术,同时使用json作为数据传输格式,使用JQuery作为dom操作的主要工具,具体代码如下:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>choose</title> <c:set var="root" value="${pageContext.request.contextPath}"></c:set> <script src="js/jquery-1.9.0.min.js"></script> <script> var lvl1; var lvl2; var lvl3; $(function(){ $.ajax({ type : "POST", url : "${root}/GradeServ", dataType : "json", //data : "method=init", success : function(data){ lvl1 = data.lvl1; lvl2 = data.lvl2; lvl3 = data.lvl3; var cell1 = $("#lvl1"); for(var i = 0;i<lvl1.length;i++){ var school = lvl1[i]; cell1.append("<option value="+school.code+">"+school.codenm+"</option>"); } cell1.change(function(){ nextVal("2"); nextVal("3"); }) var cell2 = $("#lvl2"); cell2.change(function(){ nextVal("3"); }) } }) }); function nextVal(level){ var now_node = $("#lvl"+level); now_node.empty(); var parcode = $("#lvl"+(level-1)).val(); console.log(parcode); var list = null; if(level==2){ list = lvl2; } else { list = lvl3; } for(var i =0;i<list.length;i++){ var node = list[i]; if(node.parcode==parcode && level==node.lvl){ now_node.append("<option value="+node.code+">"+node.codenm+"</option>"); } } if(now_node.find("option").length==0){ now_node.append("<option value='0'>--Choose--</option>"); } } </script> </head> <body> <select name='lvl1' id='lvl1'> <option value='0'>--Choose--</option> </select> <select name='lvl2' id='lvl2'> <option value='0'>--Choose--</option> </select> <select name='lvl3' id='lvl3'> <option value='0'>--Choose--</option> </select> </body> </html>
页面在加载时即发送请求到服务程序,加载所有的层级信息,并将这些信息使用Array形式进行存放。
3.服务端代码
Bean类:
package com.any.grade; /** * @ClassName: GradeBean * @author Helen */ public class GradeBean { private String code; private String codenm; private String parcode; private String lvl; public String getCode() { return code; } public void setCode(String code) { this.code = code; } public String getCodenm() { return codenm; } public void setCodenm(String codenm) { this.codenm = codenm; } public String getParcode() { return parcode; } public void setParcode(String parcode) { this.parcode = parcode; } public String getLvl() { return lvl; } public void setLvl(String lvl) { this.lvl = lvl; } public GradeBean(String code, String codenm, String parcode, String lvl) { super(); this.code = code; this.codenm = codenm; this.parcode = parcode; this.lvl = lvl; } public GradeBean(){} @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((code == null) ? 0 : code.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; GradeBean other = (GradeBean) obj; if (code == null) { if (other.code != null) return false; } else if (!code.equals(other.code)) return false; return true; } }
使用Servlet作为数据准备程序,用于处理请求并将数据发送给前端页面:
package com.any.grade; import java.io.IOException; import java.util.List; import java.util.Map; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import net.sf.json.JSONArray; /** * Servlet implementation class GradeServ */ @WebServlet("/GradeServ") public class GradeServ extends HttpServlet { private static final long serialVersionUID = 1L; private GradeDao gd = new GradeDao(); public GradeServ() { super(); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doPost(request,response); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { Map<String, List<GradeBean>> data = gd.loadData(); List<GradeBean> lvl1 = data.get("lvl1"); List<GradeBean> lvl2 = data.get("lvl2"); List<GradeBean> lvl3 = data.get("lvl3"); JSONArray j_lvl1 = JSONArray.fromObject(lvl1); JSONArray j_lvl2 = JSONArray.fromObject(lvl2); JSONArray j_lvl3 = JSONArray.fromObject(lvl3); String json = "{\"lvl1\":"+j_lvl1.toString()+",\"lvl2\":"+j_lvl2.toString()+",\"lvl3\":"+j_lvl3.toString()+"}"; response.setContentType("text/json"); response.setCharacterEncoding("UTF-8"); response.getWriter().println(json); } }
Dao类,查询数据库并将数据通过bean传递:
package com.any.grade; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import com.any.servlet.DbUtil; /** * @ClassName: GradeDao * @author Helen */ public class GradeDao { private List<GradeBean> getPriGrade(String lvl){ String sql = "select code,codenm,parcode,lvl from grade_tab " + "where lvl=? " + "and codenm is not null "; ResultSet rs = DbUtil.executeQuery(sql, lvl); List<GradeBean> list = new ArrayList<GradeBean>(); try { while(rs.next()){ list.add(new GradeBean(rs.getString("code"), rs.getString("codenm"), rs.getString("parcode"), rs.getString("lvl"))); } return list; } catch (SQLException e) { e.printStackTrace(); } return null; } public Map<String, List<GradeBean>> loadData(){ Map<String, List<GradeBean>> data = new HashMap<String, List<GradeBean>>(); List<GradeBean> lvl1 = getPriGrade("1"); List<GradeBean> lvl2 = getPriGrade("2"); List<GradeBean> lvl3 = getPriGrade("3"); data.put("lvl1", lvl1); data.put("lvl2", lvl2); data.put("lvl3", lvl3); return data; } }
数据库工具类,用于连接数据库并执行SQL,返回对应的结果:
package com.any.servlet; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; public class DbUtil { private static String url="jdbc:oracle:thin:@localhost:1521:orcl"; private static String user="scott"; private static String password="tiger"; private static Connection conn; private static Connection getConnection(){ try { Class.forName("oracle.jdbc.driver.OracleDriver"); conn=DriverManager.getConnection(url, user, password); return conn; } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); } return null; } public static int executeUpdate(String sql,Object... params){ PreparedStatement pmst = null; try { pmst = getConnection().prepareStatement(sql); for (int i = 0; i < params.length; i++) { pmst.setObject(i+1, params[i]); } return pmst.executeUpdate(); } catch (SQLException e) { try {conn.rollback();} catch (SQLException e1) {e1.printStackTrace();} e.printStackTrace(); } return -1; } public static ResultSet executeQuery(String sql,Object... params){ PreparedStatement pmst = null; try { pmst = getConnection().prepareStatement(sql); for (int i = 0; i < params.length; i++) { pmst.setObject(i+1, params[i]); } return pmst.executeQuery(); } catch (SQLException e) { try {conn.rollback();} catch (SQLException e1) {e1.printStackTrace();} e.printStackTrace(); } return null; } public static void closeConnection(){ if(conn!=null){ try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } }
经过以上步骤,就初步完成了三级联动选择菜单的制作。在页面加载时,必须首先选择第一层级下拉选项,从而进行后续选项的选择。