AJAX Java 二级联动菜单


需求:使用Servlet+DBUtils+XML完成异步的二级联动菜单

一、建立数据库和表

create database ajax;
CREATE TABLE `t_types` (
   `id` bigint(20) NOT NULL AUTO_INCREMENT,
   `pid` bigint(20) DEFAULT NULL,
   `name` varchar(100) DEFAULT NULL,
   PRIMARY KEY (`id`)
 ) ENGINE=InnoDB AUTO_INCREMENT=29 DEFAULT CHARSET=utf8

二、导入相关jar包

三、编写C3P0工具类和c3p0-config配置

/**
 * @author http://www.yiidian.com
 *
 */
public class C3P0Util {
	private static ComboPooledDataSource ds = new ComboPooledDataSource();
	
	/**
	 * 获取连接对象
	 * @return
	 */
	public static Connection getConnection(){
		try {
			Connection conn = ds.getConnection();
			return conn;
		} catch (SQLException e) {
			e.printStackTrace();
			throw new RuntimeException(e);
		}
	}
	
	/**
	 * 获取连接池
	 * @return
	 */
	public static DataSource getDataSource(){
		return ds;
	}
	
}

在src目录建立c3p0-config.xml:

<c3p0-config>

	<!-- 默认配置 -->
	<default-config>
		<!-- 属性名称就是setter方法名称 -->
		<property name="driverClass">com.mysql.jdbc.Driver</property>
		<property name="jdbcUrl">jdbc:mysql://localhost:3306/ajax?useUnicode=true&amp;characterEncoding=utf-8</property>
		<property name="user">root</property>
		<property name="password">root</property>
		
		<property name="initialPoolSize">5</property>
		<property name="maxPoolSize">12</property>
		<property name="checkoutTimeout">3000</property>
	</default-config>

	
</c3p0-co

四、建立Types实体类

/**
 * @author http://www.yiidian.com
 *
 */
public class Types {

	private Integer id;
	private Integer pid;
	private String name;

 五、编写Dao和Service

Dao:

/**
 * @author http://www.yiidian.com
 *
 */
public class TypesDao {
	private QueryRunner qr = new QueryRunner(C3P0Util.getDataSource());

	/**
	 * 查询所有一级分类数据
	 */
	public List<Types> findAllFirstLevel(){
		try {
			return qr.query("SELECT * FROM t_types WHERE pid=0", new BeanListHandler(Types.class));
		} catch (SQLException e) {
			e.printStackTrace();
			throw new RuntimeException(e);
		}
	}
	
	/**
	 * 根据指定的一级分类的ID查询对应的二级分类数据
	 */
	public List<Types> findSecondLevel(Integer pid){
		try {
			return qr.query("SELECT * FROM t_types WHERE pid=?", new BeanListHandler(Types.class), pid);
		} catch (SQLException e) {
			e.printStackTrace();
			throw new RuntimeException(e);
		}
	}
	
}

Service:

/**
 * @author http://www.yiidian.com
 *
 */
public class TypesBiz {
	private TypesDao typesDao = new TypesDao();
	
	public List<Types> findAllFirstLevel(){
		return typesDao.findAllFirstLevel();
	}
	
	public List<Types> findSecondLevel(Integer pid){
		return typesDao.findSecondLevel(pid);
	}
}

六、编写GetTypes的Servlet程序

/**
 * @author http://www.yiidian.com
 *
 */
public class GetTypes extends HttpServlet {
	private TypesBiz typesBiz = new TypesBiz();
	
	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		String action = request.getParameter("action");
		if("firstLevel".equals(action)){
			//查询一级分类
			List<Types> tList = typesBiz.findAllFirstLevel();
			//设计自己的XML格式: 
			/**
			 *  <types>
			 *    <type>
			 *     	<id>1</id>
			 *     	<name>手机</name>
			 *    </type>
			 *    <type>
			 *     	<id>2</id>
			 *     	<name>食品</name>
			 *    </type>  
			 * </types> 
			 */
			StringBuffer str = new StringBuffer();
			str.append("<types>");
			for (Types types : tList) {
				str.append("<type>");
				str.append("<id>"+types.getId()+"</id>");
				str.append("<name>"+types.getName()+"</name>");
				str.append("</type>");
			}
			str.append("</types>");
			
			//设置后台数据的码表
			response.setContentType("text/xml;charset=utf-8");
			PrintWriter out = response.getWriter();
			out.write(str.toString());
			
		}
		
		
		if("secondLevel".equals(action)){
			//查询二级分类
			String pid = request.getParameter("pid");
			
			List<Types> tList = typesBiz.findSecondLevel(Integer.parseInt(pid));
			
			//以XML格式返回
			StringBuffer str = new StringBuffer();
			str.append("<types>");
			for (Types types : tList) {
				str.append("<type>");
				str.append("<id>"+types.getId()+"</id>");
				str.append("<name>"+types.getName()+"</name>");
				str.append("</type>");
			}
			str.append("</types>");
			
			//设置后台数据的码表
			response.setContentType("text/xml;charset=utf-8");
			PrintWriter out = response.getWriter();
			out.write(str.toString());
		}
		
		
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		doGet(request, response);
	}

}

七、编写JSP页面

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>服务器返回的数据类型 - XML格式</title>
    
	<meta http-equiv="pragma" content="no-cache">
	<meta http-equiv="cache-control" content="no-cache">
	<meta http-equiv="expires" content="0">    
	<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
	<meta http-equiv="description" content="This is my page">
	<script type="text/javascript" src="ajaxUtil.js"></script>

  </head>
  
  <body>
    <script type="text/javascript">
    	window.onload = function(){
    		//1.到后台加载所有一级分类的数据
    		var ajax = createAjax();
    		ajax.open("GET","${pageContext.request.contextPath}/GetTypes?action=firstLevel");
    		ajax.send(null);
    		ajax.onreadystatechange=function(){
    			if(ajax.readyState==4 && ajax.status==200){
    				//接收后台的XML
    				var xmlDoc = ajax.responseXML;
    				var typeArray = xmlDoc.getElementsByTagName("type");
    				for(var i=0;i<typeArray.length;i++){
    					//分类ID
    					var id = typeArray[i].getElementsByTagName("id")[0].innerHTML;
    					//分类name
    					var name = typeArray[i].getElementsByTagName("name")[0].innerHTML;
    					
    					//把一级分类的数据填充到fLevel的select
    					var opt = document.createElement("option");
    					opt.setAttribute("value", id);
    					opt.innerHTML = name;
    					document.getElementById("fLevel").appendChild(opt);
    				}
    				
    			}
    		};
    		
    		//2.选项改变事件
    		document.getElementById("fLevel").onchange = function(){
    			//一级分类的ID
    			var pid = this.value;
    			
    			//2.1 加载到一级分类对应二级分类的数据
    			var ajax = createAjax();
	    		ajax.open("GET","${pageContext.request.contextPath}/GetTypes?action=secondLevel&pid="+pid);
	    		ajax.send(null);
	    		ajax.onreadystatechange=function(){
	    			if(ajax.readyState==4 && ajax.status==200){
	    				//接收后台的XML
	    				var xmlDoc = ajax.responseXML;
	    				var typeArray = xmlDoc.getElementsByTagName("type");
	    				
	    				document.getElementById("sLevel").options.length=0;
	    				for(var i=0;i<typeArray.length;i++){
	    					//分类ID
	    					var id = typeArray[i].getElementsByTagName("id")[0].innerHTML;
	    					//分类name
	    					var name = typeArray[i].getElementsByTagName("name")[0].innerHTML;
	    					
	    					//把一级分类的数据填充到fLevel的select
	    					var opt = document.createElement("option");
	    					opt.setAttribute("value", id);
	    					opt.innerHTML = name;
	    					document.getElementById("sLevel").appendChild(opt);
	    				}
	    			}
    			};
    		};
    		
    	};
    
    </script>
    
   品牌:<select id="fLevel"></select>
  子品牌: <select id="sLevel"></select>  
    
  </body>
</html>

八、运行结果

案例源码下载:http://pan.baidu.com/s/1gfNCBBX