您的位置:首页 > 其它

Ajax实现省市无穷级联动

2011-02-02 04:49 393 查看
这是一个Servlet应用。。

这里用到了Json-lib工具包,关于Json-lib的使用,请参见我的博文

http://blog.csdn.net/jadyer/archive/2011/02/01/6171659.aspx

首先是web.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
 http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> 	<servlet>
		<servlet-name>InitProvinceServlet</servlet-name>
		<servlet-class>com.jadyer.servlet.InitProvinceServlet</servlet-class>
	</servlet>
	<servlet>
		<servlet-name>GetCityServlet</servlet-name>
		<servlet-class>com.jadyer.servlet.GetCityServlet</servlet-class>
	</servlet>
	<servlet>
		<servlet-name>GetAreaServlet</servlet-name>
		<servlet-class>com.jadyer.servlet.GetAreaServlet</servlet-class>
	</servlet>
	
	<servlet-mapping>
		<servlet-name>InitProvinceServlet</servlet-name>
		<url-pattern>/servlet/InitProvinceServlet</url-pattern>
	</servlet-mapping>
	<servlet-mapping>
		<servlet-name>GetCityServlet</servlet-name>
		<url-pattern>/servlet/GetCityServlet</url-pattern>
	</servlet-mapping>
	<servlet-mapping>
		<servlet-name>GetAreaServlet</servlet-name>
		<url-pattern>/servlet/GetAreaServlet</url-pattern>
	</servlet-mapping>

	<!-- 在version="2.5"中,可以直接在<welcome-file-list>里执行Servlet应用 -->
	<welcome-file-list>
		<welcome-file>servlet/InitProvinceServlet</welcome-file>
	</welcome-file-list>
</web-app>


然后是用来显示省市无穷级联动效果的index.jsp页面

<%@ page language="java" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>

<script type="text/javascript">
	var xmlHTTP = new XMLHttpRequest(); //支持Internet Explorer-8.0.6001.18702
	
	var theTagID; //定义的全局变量,以便于在回调函数中使用之
	function getCityList(provinceID, tagID){
		var isDelete = false;
		theTagID = tagID;
		var sons = document.getElementById(tagID).childNodes;
		for(var i=(sons.length-1); i>=0; i--){
			if("A" != sons[i].nodeName.toUpperCase()){
			//if("UL" == sons[i].nodeName.toUpperCase()){ //二者等效
				sons[i].parentNode.removeChild(sons[i]);
				isDelete = true;
			}
		}
		if(isDelete){
			return;
		}
		xmlHTTP.open('GET', '${pageContext.request.contextPath}/servlet/GetCityServlet?provinceID='+provinceID, true);
		xmlHTTP.onreadystatechange = callbackCityList;
		xmlHTTP.setRequestHeader("if-Modified-Since", "0");
		xmlHTTP.send(null);
		return false;
	}
	
	function callbackCityList(){
		if(4==xmlHTTP.readyState && 200==xmlHTTP.status){
			var citys = eval(xmlHTTP.responseText);
			if(0 == citys.length){
				return;
			}
			var parentLI = document.getElementById(theTagID);
			var newUL = document.createElement("ul");
			
			for(var i=0; i<citys.length; i++){
				var newLI = document.createElement("li");
				newLI.id = "tag" + citys[i].cityID;
				newLI.innerHTML = "<a href='#' onclick='getCityList(" + citys[i].cityID + ", /"tag" + citys[i].cityID + "/");'>" + citys[i].cityName + "</a>";
				newUL.appendChild(newLI);
			}
			parentLI.appendChild(newUL);
		}
	}
</script>

<ul>
	<c:forEach items="${requestScope.provinces}" var="province">
		<li id="tag${province.cityID}"><a href="#" onclick="return getCityList(${province.cityID}, 'tag${province.cityID}');">${province.cityName}</a></li>
	</c:forEach>
</ul>


然后是用于从数据库执行查询操作的CityDao.java

package com.jadyer.dao;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;

import com.jadyer.model.City;

/**
 * 这里的代码,应该重构一下,但为了演示方便,就没有重构
 */
public class CityDao {
	/**
	 * 根据父ID得到所有一级子类
	 * @see 如果传递为0,则得到所有根节点
	 */
	public List<City> findByParentID(int parentID){
		String sql = "select cityID, cityName from city where parentID=?";
		List<City> citys = new ArrayList<City>();
		try {
			Context context = new InitialContext();
			//有关jdbc/oracleds连接池的配置,参见http://blog.csdn.net/jadyer/archive/2010/11/10/6001023.aspx
			DataSource ds = (DataSource)context.lookup("java:/comp/env/jdbc/oracleds");  
			Connection conn = ds.getConnection();
			PreparedStatement pstmt = conn.prepareStatement(sql);
			pstmt.setInt(1, parentID);
			ResultSet rs = pstmt.executeQuery();
			while(rs.next()){
				citys.add(new City(rs.getInt("cityID"), rs.getString("cityName")));
			}
		} catch (NamingException e) {
			e.printStackTrace();
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return citys;
	}
	
	/**
	 * 根据ID得到该城市的详细信息
	 */
	public City fingByCityID(int cityID){
		String sql = "select cityName from city where cityID=?";
		City city = null;
		try {
			Context context = new InitialContext();  
			DataSource ds = (DataSource)context.lookup("java:/comp/env/jdbc/oracleds");  
			Connection conn = ds.getConnection();
			PreparedStatement pstmt = conn.prepareStatement(sql);
			pstmt.setInt(1, cityID);
			ResultSet rs = pstmt.executeQuery();
			while(rs.next()){
				city = new City(cityID, rs.getString("cityName"));
			}
		} catch (NamingException e) {
			e.printStackTrace();
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return city;
	}
}


用于储存City信息的实体类

package com.jadyer.model;

import java.util.List;

public class City {
	private Integer parentID;
	private Integer cityID;
	private String cityName;
	private List<City> areas; //用于储存该城市下所有区县的详细信息
	
	/* 四个属性的getter和setter方法略 */
	
	public City(){}
	
	public City(Integer cityID, String cityName){
		this.cityID = cityID;
		this.cityName = cityName;
	}
}


用于初始化所有省份信息的InitProvinceServlet.java

package com.jadyer.servlet;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.jadyer.dao.CityDao;

@SuppressWarnings("serial")
public class InitProvinceServlet extends HttpServlet {
	public void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {
		CityDao cityDao = new CityDao();
		//获取所有省份的信息
		request.setAttribute("provinces", cityDao.findByParentID(0));
		request.getRequestDispatcher("/index.jsp").forward(request, response);
	}
}


用于获取指定省份下的所有城市信息的GetCityServlet.java

package com.jadyer.servlet;

import java.io.IOException;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import net.sf.json.JSONArray;

import com.jadyer.dao.CityDao;
import com.jadyer.model.City;

@SuppressWarnings("serial")
public class GetCityServlet extends HttpServlet {
	public void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {
		response.setContentType("text/html; charset=UTF-8");
		int provinceID = Integer.parseInt(request.getParameter("provinceID"));
		CityDao cityDao = new CityDao();
		//返回该省份下的所有城市的信息
		List<City> citys = cityDao.findByParentID(provinceID);
		JSONArray jsonObject = JSONArray.fromObject(citys);
		response.getWriter().println(jsonObject.toString());
	}
}


用于获取指定城市下的所有区县信息的GetAreaServlet.java

package com.jadyer.servlet;

import java.io.IOException;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import net.sf.json.JSONObject;

import com.jadyer.dao.CityDao;
import com.jadyer.model.City;

@SuppressWarnings("serial")
public class GetAreaServlet extends HttpServlet {
	public void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {
		response.setContentType("text/html; charset=UTF-8");
		int cityID = Integer.parseInt(request.getParameter("cityID"));
		CityDao cityDao = new CityDao();
		//得到该城市下所有区县的详细信息的集合
		List<City> areas = cityDao.findByParentID(cityID);
		//得到当前城市的详细信息
		City city22 = cityDao.fingByCityID(cityID);
		city22.setAreas(areas);
		JSONObject jsonObject = JSONObject.fromObject(city22);
		response.getWriter().println(jsonObject.toString());
	}
}


最后是数据库脚本文件

--Oracle 11g
--创建表格
create table city(
	id number(3) primary key,
	parentID number(3), --0表示根节点
	cityID number(3),
	cityName varchar(20)
)

--创建序列
create sequence city_sequence increment by 1 start with 1 nomaxvalue nocycle;

--添加一级菜单
insert into city values(city_sequence.nextval, 0, 1, '黑龙江');
insert into city values(city_sequence.nextval, 0, 2, '吉林省');
insert into city values(city_sequence.nextval, 0, 3, '辽宁省');
--添加二级菜单
insert into city values(city_sequence.nextval, 1, 4, '哈尔滨');
insert into city values(city_sequence.nextval, 1, 5, '佳木斯');
insert into city values(city_sequence.nextval, 1, 6, '双鸭山');
insert into city values(city_sequence.nextval, 2, 7, '长春');
insert into city values(city_sequence.nextval, 2, 8, '辽源');
insert into city values(city_sequence.nextval, 2, 9, '通化');
insert into city values(city_sequence.nextval, 3, 10, '沈阳');
insert into city values(city_sequence.nextval, 3, 11, '大连');
insert into city values(city_sequence.nextval, 3, 12, '铁岭');
--添加三级菜单
--这里只提供了黑龙江省的三级联动数据,关于其它省份的数据,请自行添加
insert into city values(city_sequence.nextval, 4, 13, '巴彦县');
insert into city values(city_sequence.nextval, 4, 14, '延寿县');
insert into city values(city_sequence.nextval, 4, 15, '木兰县');
insert into city values(city_sequence.nextval, 5, 16, '抚远县');
insert into city values(city_sequence.nextval, 5, 17, '汤原县');
insert into city values(city_sequence.nextval, 5, 18, '桦川县');
insert into city values(city_sequence.nextval, 6, 19, '集贤县');
insert into city values(city_sequence.nextval, 6, 20, '宝清县');
insert into city values(city_sequence.nextval, 6, 21, '友谊县');
--添加四级菜单
--这里只提供了哈尔滨市的四级联动数据,其它数据,请自行添加
insert into city values(city_sequence.nextval, 13, 22, '兴隆镇');
insert into city values(city_sequence.nextval, 13, 23, '龙庙镇');
insert into city values(city_sequence.nextval, 13, 24, '洼兴镇');
insert into city values(city_sequence.nextval, 14, 25, '六团镇');
insert into city values(city_sequence.nextval, 14, 26, '中和镇');
insert into city values(city_sequence.nextval, 14, 27, '加信镇');
insert into city values(city_sequence.nextval, 15, 28, '东兴镇');
insert into city values(city_sequence.nextval, 15, 29, '大贵镇');
insert into city values(city_sequence.nextval, 15, 30, '新民镇');
--添加五级菜单
--这里只提供了巴彦县的五级联动数据,其它数据,请自行添加
insert into city values(city_sequence.nextval, 22, 31, '长春乡');
insert into city values(city_sequence.nextval, 22, 32, '丰乐乡');
insert into city values(city_sequence.nextval, 22, 33, '德祥乡');
insert into city values(city_sequence.nextval, 23, 34, '山后乡');
insert into city values(city_sequence.nextval, 23, 35, '华山乡');
insert into city values(city_sequence.nextval, 23, 36, '红光乡');
insert into city values(city_sequence.nextval, 24, 36, '镇东乡');
insert into city values(city_sequence.nextval, 24, 36, '富江乡');
insert into city values(city_sequence.nextval, 24, 36, '松花乡');
--添加六级菜单
--理论上可无限添加。但实际中,用到四级菜单的情况都不是太多,故以下数据略
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: