今天學習了Ajax技術,剛剛做了一個省份-城市聯動的Ajax應用樣本。可能很多人都已經寫過了,也是一個比較簡單的例子,在這裡分享出來大家共同學習交流一下。希望能給到那些像我一樣的菜鳥程式員參考一點協助吧!
效果:
省份-城市聯動就是當你在省份下拉式清單方塊選擇一個省份的時候,旁邊的城市下拉式清單方塊就會動態地產生該省份對應的城市列表。如:省份是廣東,則城市的下拉框對應顯示廣州、茂名、梅州等城市;省份是北京,城市的下拉式清單方塊則顯示海澱、朝陽等城市。因為我本人主要從事JavaEE的相關開發,因此這個小應用樣本也就寫專業一點啦!使用model2的兩層架構。因為是一個小應用樣本,因此沒有跟資料庫打交道,資料就都儲存到記憶體中。
好了,我講的廢話太多了,下面開始敘述省份-城市聯動的開發過程。
實施步驟:
- 編寫後台service層。在三層架構中,層與層之間使用介面串連,因此要編寫service介面。
- 編寫後台web層的控制器servlet(省份的控制器和城市的控制器),主要負責載入後台省份和城市的資料,並將其傳輸到前台頁面。
- 編寫前台html靜態頁面,負責給使用者顯示資料。
- 編寫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));}@Overridepublic 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;}@Overridepublic 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" onchange="provinceChange()"></select>請選擇城市:<select id="city"></select></body></html>
(四)javascript指令碼程式province_city.js
// 初始化XMLHttpRequest對象function createXmlHttpRequest() {var xmlhttp = null;try {// Firefox, Opera 8.0+, Safarixmlhttp = 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;}};}
樣本原始碼下載
因為這個小應用純粹用於學習總結,因此寫了比較多的注釋,但是總體還算比較易於閱讀的。