ExtJS(三)--Ajax实现省份城市联动

        今天学习了Ajax技术,刚刚做了一个省份-城市联动的Ajax应用示例。可能很多人都已经写过了,也是一个比较简单的例子,在这里分享出来大家共同学习交流一下。希望能给到那些像我一样的菜鸟程序员参考一点帮助吧!

效果截图:

       省份-城市联动就是当你在省份下拉列表框选择一个省份的时候,旁边的城市下拉列表框就会动态地生成该省份对应的城市列表。如:省份是广东,则城市的下拉框对应显示广州、茂名、梅州等城市;省份是北京,城市的下拉列表框则显示海淀、朝阳等城市。因为我本人主要从事JavaEE的相关开发,因此这个小应用示例也就写专业一点啦!使用model2的两层架构。因为是一个小应用示例,因此没有跟数据库打交道,数据就都保存到内存中。

       好了,我讲的废话太多了,下面开始叙述省份-城市联动的开发过程。

  实施步骤:

  1. 编写后台service层。在三层架构中,层与层之间使用接口连接,因此要编写service接口。
  2. 编写后台web层的控制器servlet(省份的控制器和城市的控制器),主要负责加载后台省份和城市的数据,并将其传输到前台页面。
  3. 编写前台html静态页面,负责给用户显示数据。
  4. 编写javascript脚本程序,处理用户选择省份的请求操作。

整个应用的流程图:

 

(一)service层的接口代码

package cn.itcast.ajax.service;

import java.util.List;

public interface ProvinceCityService {
	/**
	 * 返回省份数据集合
	 * @return
	 */
	List<String> loadProvince();
	/**
	 * 根据省份返回城市的集合
	 * @param province
	 * @return
	 */
	List<String> loadCity(String province);
}

实现接口中定义的功能

package cn.itcast.ajax.service.impl;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import cn.itcast.ajax.service.ProvinceCityService;

public class ProvinceCityServiceImpl implements ProvinceCityService {
	/*
	 * 因为是一个省份与城市下拉的ajax小应用实例,因此不与数据库交道了,使用map存储数据 (non-Javadoc)
	 * 
	 * @see cn.itcast.ajax.service.ProvinceService#loadProvince()
	 */
	private Map<String, List<String>> provinceMap = new HashMap<String, List<String>>();
	String[] gdCity = new String[] { "广州", "汕头", "梅州", "茂名" };
	String[] bjCity = new String[] { "海淀", "朝阳", "中关村" };

	public ProvinceCityServiceImpl() {
		provinceMap.put("广东", Arrays.asList(gdCity));
		provinceMap.put("北京", Arrays.asList(bjCity));
	}

	@Override
	public List<String> loadProvince() {
		List<String> provinces = new ArrayList<String>();
		Set<String> keySet = provinceMap.keySet();
		for (Iterator<String> iterator = keySet.iterator(); iterator.hasNext();) {
			String province = iterator.next();
			provinces.add(province);
		}
		return provinces;
	}

	@Override
	public List<String> loadCity(String province) {
		return provinceMap.get(province);
	}

}

(二)控制层Servlet代码

因为需要对省份和城市分开不同处理,所以使用ProvinceServlet和CityServlet两个servlet控制器

ProvinceServlet:

package cn.itcast.ajax.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 cn.itcast.ajax.service.ProvinceCityService;
import cn.itcast.ajax.service.impl.ProvinceCityServiceImpl;

/**
 * Servlet implementation class ProvinceServlet
 */
public class ProvinceServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
	private ProvinceCityService provinceService = new ProvinceCityServiceImpl();

	protected void doGet(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		request.setCharacterEncoding("UTF-8");
		List<String> provinces = provinceService.loadProvince();
		StringBuffer sb = new StringBuffer();
		sb.append("[");
		for (int i =0;i<provinces.size();i++) {
			String province = provinces.get(i);
			sb.append("\"").append(province).append("\"");
			// 如果i的值小于list的长度的时候就添加一个逗号,确保最后一个不会添加多一个逗号
			if (i < provinces.size() - 1) {
				sb.append(",");
			}
		}
		sb.append("]");
		response.setHeader("Content-Type", "text/html; charset=UTF-8");
		response.getWriter().println(sb.toString());
	}

	protected void doPost(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		doGet(request, response);
	}
	
	public void testData() {
		List<String> provinces = provinceService.loadProvince();
		StringBuffer sb = new StringBuffer();
		sb.append("[");
		for (int i =0;i<provinces.size();i++) {
			String province = provinces.get(i);
			sb.append("\"").append(province);
			// 如果i的值小于list的长度的时候就添加一个逗号,确保最后一个不会添加多一个逗号
			if (i < provinces.size() - 1) {
				sb.append(",");
			}
		}
		sb.append("]");
		System.out.println(sb.toString());
	}

}

CityServlet:

package cn.itcast.ajax.servlet;

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

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

import cn.itcast.ajax.service.ProvinceCityService;
import cn.itcast.ajax.service.impl.ProvinceCityServiceImpl;

/**
 * Servlet implementation class CityServlet
 */
public class CityServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;

	private ProvinceCityService cityService = new ProvinceCityServiceImpl();

	protected void doGet(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		String province = request.getParameter("province");
		List<String> citys = cityService.loadCity(province);
		StringBuffer sb = new StringBuffer("[");
		for (int i = 0; i < citys.size(); i++) {
			sb.append("\"").append(citys.get(i)).append("\"");
			if (i < citys.size() - 1) {
				sb.append(",");
			}
		}
		sb.append("]");
		response.setHeader("Content-Type", "text/html; charset=UTF-8");
		response.getWriter().println(sb.toString());
		response.getWriter().close();
	}

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

}

(三)前台html静态页面province_city.html

这里要注意一点,省份的数据需要首先加载出来,添加到省份的下拉列表框中,因此在这个页面载入的时候就必须从后台加载数据出来。

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>省份-城市下拉联动</title>
<script type="text/javascript" src="province_city.js"></script>
</head>
<body>
	请选择省份:<select id="province" οnchange="provinceChange()"></select>
	请选择城市:<select id="city"></select>
</body>
</html>


(四)javascript脚本程序province_city.js

// 初始化XMLHttpRequest对象
function createXmlHttpRequest() {
	var xmlhttp = null;
	try {
		// Firefox, Opera 8.0+, Safari
		xmlhttp = new XMLHttpRequest();
	} catch (e) {// IE7.0以下的浏览器以ActiveX组件的方式来创建XMLHttpRequest对象
		var MSXML = [ 'MSXML2.XMLHTTP.6.0', 'MSXML2.XMLHTTP.5.0',
				'MSXML2.XMLHTTP.4.0', 'MSXML2.XMLHTTP.3.0', 'MSXML2.XMLHTTP',
				'Microsoft.XMLHTTP' ];
		for ( var i = 0; i < MSXML.length; i++) {
			try {
				xmlhttp = new ActiveXObject(MSXML[i]);
				break;
			} catch (e) {

			}
		}
	}
	// 返回对象
	return xmlhttp;
}
window.onload = function() {
	loadProvinces();
};
// 加载省份数据
function loadProvinces() {
	var province = document.getElementById("province");
	//alert("sdhgjf");
	// 创建XMLHttpRequest对象
	var xhr = createXmlHttpRequest();
	// 发送请求
	xhr.open("get", "ProvinceServlet", true);
	xhr.send(null);
	// 接收服务器端传递回来的数据
	xhr.onreadystatechange = function() {
		// 判断数据是否处理完全
		if (xhr.readyState == 4 && (xhr.status == 200 || xhr.status == 304)) {
			var provinces = eval("(" + xhr.responseText + ")");
			//alert(provinces);
			// 处理返回来的字符串
			var s = "<option>请选择</option>";
			for ( var i = 0; i < provinces.length; i++) {
				s+="<option>"+provinces[i]+"</option>";
			}
			province.innerHTML = s;
		}
	};
}
// 省份选择发生改变的时候的处理函数
function provinceChange() {
	// 获取当前选中的省份
	var provinces = document.getElementById("province");
	var province = provinces.options[provinces.selectedIndex].value;
	var city = document.getElementById("city");
	//alert(province);
	var xhr = createXmlHttpRequest();
	xhr.open("post", "CityServlet", true);
	// 以post方式发送请求的时候需要设置请求的方式
	xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
	xhr.send("province="+province);
	// 处理服务器端返回来的数据
	xhr.onreadystatechange = function() {
		// 判断数据是否处理完全
		if (xhr.readyState == 4 && (xhr.status == 200 || xhr.status == 304)) {
			var citys = eval("(" + xhr.responseText + ")");
			//alert(provinces);
			// 处理返回来的字符串
			var s = "<option>--</option>";// 创建一个option子元素
			for ( var i = 0; i < citys.length; i++) {// 将返回来的城市数据添加到option元素中
				s+="<option>"+citys[i]+"</option>";
			}
			city.innerHTML = s;
		}
	};
}

 

示例源代码下载

 

       因为这个小应用纯粹用于学习总结,因此写了比较多的注释,但是总体还算比较易于阅读的。





 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Seven的代码实验室

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值