JSP+AJAX省市区级联

时间:2021-09-07 11:37:02

省市区级联是日常注册网页常用的一个功能,模拟实现如下:

显示界面ProCityArea.jsp

JSP+AJAX省市区级联JSP+AJAX省市区级联
 1 <%@ page language="java" contentType="text/html; charset=UTF-8"
 2     pageEncoding="UTF-8"%>
 3 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
 4 <html>
 5 <head>
 6 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
 7 <title>省市区级联</title>
 8 <script type="text/jscript" src="js/ProCityArea.js" language="javascript"></script>
 9 </head>
10 <body>
11     
12     <span>
13         <select id="selPro">
14         </select>
15     </span>
16     
17     <span >
18         <select id="selCity">
19         </select>
20     </span>
21     
22     <span >
23         <select id="selArea">
24         </select>
25     </span>
26 
27 </body>
28 </html>
ProCityArea.jsp

相关的JS代码

JSP+AJAX省市区级联JSP+AJAX省市区级联
 1 //JavaScript
 2 var xhr;    //XMLHttpRequest对象
 3 window.onload=function(){
 4     var selPro=$("selPro");
 5     var selCity=$("selCity");
 6     var selArea=$("selArea");
 7 
 8     //初次加载
 9     createXMLObject();  //创建XMLHttpRequest对象
10     doProAjax(false);
11     doCityAjax(selPro.value,false);
12     doAreaAjax(selCity.value,false)
13     
14     selPro.onchange=function(){
15         doCityAjax(this.value,false);
16         doAreaAjax(selCity.value,false);
17     }
18     selCity.onchange=function(){
19         doAreaAjax(this.value,true);
20     }
21 }
22 
23 //创建一个XMLRequest对象
24 var createXMLObject=function(){
25     if(window.XMLHttpRequest){
26         xhr=new XMLHttpRequest();
27     }
28     else{
29         xhr=new ActiveXObject("Microsoft.XMLHTTP");
30     }
31 }
32 
33 
34 var doCityAjax=function(proCode,synFlag){
35     xhr.open("Get","city.let?proCode="+proCode, synFlag,"admin","admin");
36     xhr.onreadystatechange=getCity;
37     xhr.send(null);
38 }
39 
40 var doProAjax=function(synFlag){
41     xhr.open("Get","province.let" , synFlag,"admin","admin");
42     xhr.onreadystatechange=getProvince;
43     xhr.send(null);
44 }
45 
46 var doAreaAjax=function(cityCode,synFlag){
47     xhr.open("Get","area.let?cityCode="+cityCode, synFlag,"admin","admin");
48     xhr.onreadystatechange=getArea;
49     xhr.send(null);
50 }
51 
52 
53 //sel:option组件名  tag:自定义标签
54 var getPlaceName=function(sel,tag){
55     if(xhr.readyState==4 && xhr.status==200){
56       var xml=xhr.responseXML;  
57       sel.innerHTML="";
58       //解析XML
59       var provinces=xml.getElementsByTagName(tag);
60       
61       for(var i=0;i<provinces.length;i++){
62           var tmp=provinces[i];
63         //获取相关节点的信息
64         var code=tmp.childNodes[0].textContent;
65         var name=tmp.childNodes[1].textContent;
66         var op=document.createElement("option");
67           op.setAttribute("value",code);
68         op.innerHTML=name;
69         sel.appendChild(op);
70       }
71     }
72 
73 }
74 
75 var getProvince=function(){
76     getPlaceName(selPro,"province");
77 }
78 
79 var getCity=function(){
80     getPlaceName(selCity,"city");
81 }
82 
83 var getArea=function(){
84     getPlaceName(selArea,"area");
85 }
86 
87 /*通过Id获取相对应的组件*/
88 var $=function(id){
89     return document.getElementById(id);
90 }
js/ProCityArea.js

com.cnblogs.servlet包下的类:

AreaServlet

JSP+AJAX省市区级联JSP+AJAX省市区级联
 1 package com.cnblogs.servlet;
 2 
 3 import java.io.IOException;
 4 import java.io.PrintWriter;
 5 import java.util.ArrayList;
 6 
 7 import javax.servlet.ServletException;
 8 import javax.servlet.http.HttpServlet;
 9 import javax.servlet.http.HttpServletRequest;
10 import javax.servlet.http.HttpServletResponse;
11 
12 import com.cnblogs.dao.AreaDao;
13 import com.cnblogs.dao.CityDao;
14 import com.cnblogs.vo.Place;
15 
16 public class AreaServlet extends HttpServlet {
17     @Override
18     protected void doGet(HttpServletRequest req, HttpServletResponse resp)
19             throws ServletException, IOException {
20         resp.setContentType("text/xml;charset=utf-8");
21         PrintWriter  out= resp.getWriter();
22         //取出其中的数据
23         String cityCode=req.getParameter("cityCode");
24         
25         //System.out.println(cityCode);
26         ArrayList<Place> arrArea=new AreaDao().getArea(cityCode);
27         
28         //拼 xml数据
29         StringBuilder sb=new StringBuilder("<?xml version='1.0' encoding='UTF-8'?>");
30         sb.append("<areas>");
31         for(Place tmp:arrArea){
32             sb.append("<area>");
33             sb.append("<code>"+tmp.getCode()+"</code>");
34             sb.append("<name>"+tmp.getName()+"</name>");
35             sb.append("</area>");
36         }
37         
38         sb.append("</areas>");
39         //System.out.println(sb.toString());
40         out.print(sb.toString());
41     }
42 
43     @Override
44     protected void doPost(HttpServletRequest req, HttpServletResponse resp)
45             throws ServletException, IOException {
46         doGet(req, resp);
47     }
48     
49 }
AreaServlet

CityServlet

JSP+AJAX省市区级联JSP+AJAX省市区级联
 1 package com.cnblogs.servlet;
 2 
 3 import java.io.IOException;
 4 import java.io.PrintWriter;
 5 import java.util.ArrayList;
 6 
 7 import javax.servlet.ServletException;
 8 import javax.servlet.http.HttpServlet;
 9 import javax.servlet.http.HttpServletRequest;
10 import javax.servlet.http.HttpServletResponse;
11 
12 import com.cnblogs.dao.CityDao;
13 import com.cnblogs.dao.ProDao;
14 import com.cnblogs.vo.Place;
15 
16 public class CityServlet extends HttpServlet {
17     @Override
18     protected void doGet(HttpServletRequest req, HttpServletResponse resp)
19             throws ServletException, IOException {
20         resp.setContentType("text/xml;charset=utf-8");
21         PrintWriter  out= resp.getWriter();
22         //取出其中的数据
23         String proCode=req.getParameter("proCode");
24         ArrayList<Place> arrCity=new CityDao().getCity(proCode);
25         
26         
27         //拼 xml数据
28         StringBuilder sb=new StringBuilder("<?xml version='1.0' encoding='UTF-8'?>");
29         sb.append("<citys>");
30         for(Place tmp:arrCity){
31             sb.append("<city>");
32             sb.append("<code>"+tmp.getCode()+"</code>");
33             sb.append("<name>"+tmp.getName()+"</name>");
34             sb.append("</city>");
35         }
36         
37         sb.append("</citys>");
38         //System.out.println(sb.toString());
39         out.print(sb.toString());
40     }
41 
42     @Override
43     protected void doPost(HttpServletRequest req, HttpServletResponse resp)
44             throws ServletException, IOException {
45         doGet(req, resp);
46     }
47     
48 }
CityServlet

ProServlet

JSP+AJAX省市区级联JSP+AJAX省市区级联
 1 package com.cnblogs.servlet;
 2 
 3 import java.io.IOException;
 4 import java.io.PrintWriter;
 5 import java.util.ArrayList;
 6 
 7 import javax.servlet.ServletException;
 8 import javax.servlet.http.HttpServlet;
 9 import javax.servlet.http.HttpServletRequest;
10 import javax.servlet.http.HttpServletResponse;
11 
12 import com.cnblogs.dao.ProDao;
13 import com.cnblogs.vo.Place;
14 
15 public class ProServlet extends HttpServlet {
16 
17     @Override
18     protected void doGet(HttpServletRequest req, HttpServletResponse resp)
19             throws ServletException, IOException {
20         resp.setContentType("text/xml;charset=utf-8");
21         PrintWriter  out= resp.getWriter();
22         //取出其中的数据
23         ArrayList<Place> arrPro=new ProDao().getProvince();
24         
25         
26         //拼 xml数据
27         StringBuilder sb=new StringBuilder("<?xml version='1.0' encoding='UTF-8'?>");
28         sb.append("<provinces>");
29         for(Place tmp:arrPro){
30             sb.append("<province>");
31             sb.append("<code>"+tmp.getCode()+"</code>");
32             sb.append("<name>"+tmp.getName()+"</name>");
33             sb.append("</province>");
34         }
35         
36         sb.append("</provinces>");
37         //System.out.println(sb.toString());
38         out.print(sb.toString());
39     }
40 
41     @Override
42     protected void doPost(HttpServletRequest req, HttpServletResponse resp)
43             throws ServletException, IOException {
44         doGet(req, resp);
45     }
46     
47 }
ProServlet

com.cnblogs.vo包下的类

JSP+AJAX省市区级联JSP+AJAX省市区级联
 1 package com.cnblogs.vo;
 2 
 3 import java.io.Serializable;
 4 
 5 public class Place implements Serializable{
 6     String code;
 7     String name;
 8     
 9     public Place(){}
10     public Place(String code,String name){
11         this.code=code;
12         this.name=name;
13     }
14     
15     
16     public String getCode() {
17         return code;
18     }
19     public void setCode(String code) {
20         this.code = code;
21     }
22     public String getName() {
23         return name;
24     }
25     public void setName(String name) {
26         this.name = name;
27     }
28     
29     
30 }
Place

com.cnblogs.dao下的类

JSP+AJAX省市区级联JSP+AJAX省市区级联
 1 package com.cnblogs.dao;
 2 
 3 import java.sql.Connection;
 4 import java.sql.PreparedStatement;
 5 import java.sql.ResultSet;
 6 import java.sql.SQLException;
 7 import java.util.ArrayList;
 8 
 9 import com.cnblogs.comm.DBConnection;
10 import com.cnblogs.vo.Place;
11 
12 public class ProDao {
13     //本类主要处理的是省份表的读取
14     public ArrayList<Place> getProvince(){
15         Connection conn=null;
16         PreparedStatement stmt=null;
17         ResultSet rs=null;
18         
19         ArrayList<Place> provinces=null;
20         Place place=null;
21         
22         conn=DBConnection.getInstance().getCon();
23         String sql="select * from province";
24         try {
25             stmt=conn.prepareStatement(sql);
26             rs=stmt.executeQuery();
27             
28             boolean startFlag=true;
29             while(rs.next()){
30                 if(startFlag){
31                     provinces=new ArrayList<>();
32                     startFlag=false;
33                 }
34                 String code=rs.getString("code");
35                 String name=rs.getString("name");
36                 place=new Place(code, name);
37                 //System.out.println(code+"\t"+name);
38                 provinces.add(place);
39                 
40             }
41         } catch (SQLException e) {
42             e.printStackTrace();
43         }finally{
44             DBConnection.close(rs, stmt, conn);
45         }
46         return provinces;
47     }
48 }
ProDao
JSP+AJAX省市区级联JSP+AJAX省市区级联
 1 package com.cnblogs.dao;
 2 
 3 import java.sql.Connection;
 4 import java.sql.PreparedStatement;
 5 import java.sql.ResultSet;
 6 import java.sql.SQLException;
 7 import java.util.ArrayList;
 8 
 9 import com.cnblogs.comm.DBConnection;
10 import com.cnblogs.vo.Place;
11 
12 public class CityDao {
13     //本类主要处理的是市的读取
14     public ArrayList<Place> getCity(String proCode){
15         Connection conn=null;
16         PreparedStatement stmt=null;
17         ResultSet rs=null;
18         
19         ArrayList<Place> city=null;
20         Place place=null;
21         
22         conn=DBConnection.getInstance().getCon();
23         String sql="select * from city c where c.provincecode=?";
24         try {
25             stmt=conn.prepareStatement(sql);
26             stmt.setString(1, proCode);
27             rs=stmt.executeQuery();
28             
29             
30             boolean startFlag=true;
31             while(rs.next()){
32                 if(startFlag){
33                     city=new ArrayList<>();
34                     startFlag=false;
35                 }
36                 String code=rs.getString("code");
37                 String name=rs.getString("name");
38                 place=new Place(code, name);
39                 //System.out.println(code+"\t"+name);
40                 city.add(place);
41                 
42             }
43         } catch (SQLException e) {
44             e.printStackTrace();
45         }finally{
46             DBConnection.close(rs, stmt, conn);
47         }
48         return city;
49     }
50 }
CityDao
JSP+AJAX省市区级联JSP+AJAX省市区级联
 1 package com.cnblogs.dao;
 2 
 3 import java.sql.Connection;
 4 import java.sql.PreparedStatement;
 5 import java.sql.ResultSet;
 6 import java.sql.SQLException;
 7 import java.util.ArrayList;
 8 
 9 import com.cnblogs.comm.DBConnection;
10 import com.cnblogs.vo.Place;
11 
12 public class AreaDao {
13     //本类主要处理的是区的读取
14         public ArrayList<Place> getArea(String cityCode){
15             Connection conn=null;
16             PreparedStatement stmt=null;
17             ResultSet rs=null;
18             
19             ArrayList<Place> area=null;
20             Place place=null;
21             
22             conn=DBConnection.getInstance().getCon();
23             String sql="select * from area a where a.citycode=?";
24             try {
25                 stmt=conn.prepareStatement(sql);
26                 stmt.setString(1, cityCode);
27                 rs=stmt.executeQuery();
28                 
29                 
30                 boolean startFlag=true;
31                 while(rs.next()){
32                     if(startFlag){
33                         area=new ArrayList<>();
34                         startFlag=false;
35                     }
36                     String code=rs.getString("code");
37                     String name=rs.getString("name");
38                     place=new Place(code, name);
39                     //System.out.println(code+"\t"+name);
40                     area.add(place);
41                     
42                 }
43             } catch (SQLException e) {
44                 e.printStackTrace();
45             }finally{
46                 DBConnection.close(rs, stmt, conn);
47             }
48             return area;
49         }
50         
51 }
AreaDao

数据库脚本

 http://pan.baidu.com/s/1GI3Ut 

注意:region-oracle(修改版)是本例使用的数据库脚本

以上代码基本可以实现省市区的级联,其中最关键的技术Ajax的异步与同步的运用。

如xx省的改变,必须同时改变市以及区的数据,

 selPro.onchange=function(){
15         doCityAjax(this.value,false);
16         doAreaAjax(selCity.value,false);
17     }

此处必须使用同步的方式,否则数据无法同时修改,还有本例无法再IE中运行,关键原因是IE无法解析XML=xhr.responseXML;暂时无法知晓原因

2013-11-05排除兼容性问题
上面谈到xhr.responseXML在IE中出现undefined问题
解决方法为:

  var code=tmp.childNodes[0].firstChild.nodeValue;
  var name=tmp.childNodes[1].firstChild.nodeValue;

 

  2013-11-06JSON技术处理

  其中主要修改的内容为:

 如AreaServlet类中部分代码修改如下:

JSP+AJAX省市区级联JSP+AJAX省市区级联
 1 protected void doGet(HttpServletRequest req, HttpServletResponse resp)
 2             throws ServletException, IOException {
 3         resp.setContentType("text/html;charset=utf-8");
 4         PrintWriter  out= resp.getWriter();
 5         //取出其中的数据
 6         String cityCode=req.getParameter("cityCode");
 7         
 8         //System.out.println(cityCode);
 9         ArrayList<Place> arrArea=new AreaDao().getArea(cityCode);
10         
11         //拼 xml数据
12         StringBuilder sb=new StringBuilder();
13         sb.append("[");
14         for(Place tmp:arrArea){
15             sb.append("{");
16             sb.append("code:\""+tmp.getCode()+"\",");
17             sb.append("name:\""+tmp.getName()+"\"");
18              sb.append("},");
19         }
20         sb.deleteCharAt(sb.length()-1);
21         sb.append("]");
22         //System.out.println(sb.toString());
23         out.print(sb.toString());
24     }
doGet

 ProCityArea.js文件中getArea()方法调用以下方法

 

JSP+AJAX省市区级联JSP+AJAX省市区级联
 1 var getJSON=function(sel){
 2     if(xhr.readyState==4 && xhr.status==200){
 3         var jsonStr=xhr.responseText;
 4         
 5         sel.innerHTML="";
 6         var area=eval("("+jsonStr+")");
 7         
 8         for(var i=0;i<area.length;i++){
 9               var tmp=area[i];
10             //获取相关节点的信息
11             var code=tmp.code;
12             var name=tmp.name;
13             var op=document.createElement("option");
14               op.setAttribute("value",code);
15             op.innerHTML=name;
16             sel.appendChild(op);
17           }
18         
19     }
20 }
getJSON

JSON可以完美兼容浏览器而且其数据量小