需求:
我们要实现的界面如上图,具体需求如下:
- 省、市、县/区数据从数据库读取;
- 选择省份后,该省对应的市添加在“请选择市”的下拉列表中供用户选择;
- 选择市后,该市对应的县/区添加在“请选择县/区”的下拉列表中供用户选择;
- 没有选择省份时,无法选择市、县/区;
- 没有选择市时,无法选择县/区;
- 切换省份时,后面的市、县/区恢复无选择状态;
- 切换市时,后面的县/区恢复无选择状态。
数据准备:
建表:打开Navicat --> 新建数据库“mytest” --> 选择“Queries” --> 选择“New Query”,然后将下面的代码拷贝进去,点击“Run”
CREATE TABLE `area` (
`id` varchar(36) NOT NULL COMMENT '地域ID',
`code` varchar(30) NOT NULL COMMENT '地域编码',
`name` varchar(30) NOT NULL COMMENT '地域名称',
`parent_code` varchar(30) DEFAULT NULL COMMENT '父节点编码',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='地域';
插入数据:前往下载省市县数据
步骤:
1、创建Web项目:打开eclipse(自选,这里用eclipse) --> 新建Web项目“area”
2、拷贝相关文件:
- 将之前“com.jdbc.dbutil”包和数据库的配置文件“app.properties ”一同拷贝到“area”项目中“Java Resources”目录下的“src”文件夹中,修改“app.properties ”文件中的数据库名、用户名和密码等信息;
- 将“gson-2.8.4.jar”、“mysql-connector-java-5.1.9.jar”和“servlet-api.jar”文件拷贝到“WebContent”目录下的“WEB-INF”文件夹下的“lib”文件夹中;
- 在“WebContent”目录下新建文件夹“js”,将“jquery-3.3.1.min.js”和“json2.js”拷贝进去;
3、新建servlet文件:在“src”文件夹中新建“com.jpc.servlet”包,在该包中新建DataServlet类,继承HttpServlet类并重写其方法“doGet()”
4、修改“PropertiesUtil.java”文件:将“PropertiesUtil.java”文件中的“inuptStream”做如下修改:
InputStream inputStream = DataServlet.class.getClassLoader().getResourceAsStream("app.properties");
5、新建Area类:在“src”文件夹中新建“com.jpc.vo”包,在该包中新建Area类,如下,用于将每条省市县信息作为一个对象存储起来:
package com.jpc.vo;
public class Area {
private String id;
private String name;
private String code;
private String parentCode;
public Area(String id, String name, String code, String parentCode) {
this.id = id;
this.name = name;
this.code = code;
this.parentCode = parentCode;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getParentCode() {
return parentCode;
}
public void setParentCode(String parentCode) {
this.parentCode = parentCode;
}
@Override
public String toString() {
return "Area [id=" + id + ", name=" + name + ", code=" + code + ", parentCode=" + parentCode + "]";
}
}
6、“doGet()”方法的思路及代码实现:
1. 设置响应的字符集为“UTF-8”;
2. 声明字符串变量code,用于接收浏览器客户端传来的code的值
3. 定义实现IRowMapper接口的内部类RowMapper,在内部类中声明一个泛型为Area类的ArrayList集合,用于将存储每条省市县信息的Area对象添加进其中
4. 声明一条sql语句,创建一个RowMapper对象rowMapper
5. 调用DBUtil的select方法(这里用的是防sql注入的方法)将创建的sql语句、对象rowMapper和从浏览器客户端获取的code作为该方法的三个参数传进去
6. 由于DBUtil的select方法会回调当前doGet()方法中内部类RowMapper的rowMapper()方法,而该方法将Area对象逐个添加进了内部类RowMapper的list中,所以在内部类外面声明的接收rowMapper.list的list中存储的也都是Area对象
7. 新建Gson匿名对象,调用其tojson()方法,将list作为参数传入,返回一个字符串,将该字符串直接传递(赋值)给调用jquery的ajax()方法并且参数对象的url指向本servlet文件的外部文件中该ajax()方法的参数对象的success函数的形参
package com.jpc.servlet;
import java.io.IOException;
import java.io.PrintWriter;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.google.gson.Gson;
import com.jdbc.dbutil.DBUtil;
import com.jdbc.dbutil.IRowMapper;
import com.jpc.vo.Area;
public class DataServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setCharacterEncoding("UTF-8");
String code = request.getParameter("code");
class RowMapper implements IRowMapper {
List<Area> list = new ArrayList<Area>();
public void rowMapper(ResultSet resultSet) {
try {
while(resultSet.next()) {
list.add(new Area(resultSet.getString("id"), resultSet.getString("name"), resultSet.getString("code"), resultSet.getString("parent_code")));
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
String sql = "select * from area where parent_code = ?";
RowMapper rowMapper = new RowMapper();
DBUtil.select(sql, rowMapper, code);
List<Area> list = rowMapper.list;
PrintWriter writer = response.getWriter();
writer.write(new Gson().toJson(list));
writer.flush();
writer.close();
}
}
7、创建jsp文件:
1. 在“WebContent”文件夹中创建“index.jsp”文件
2. 导入“jquery-3.3.1.min.js”文件与“json2.js”文件
3. 创建三个select下拉列表标签,分别用于选择省市县
4. 声明JavaScript区域,在其中直接定义一个ajax,并且定义两个方法,分别给市、县两个select标签绑定为onchange事件
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script type="text/javascript" src="./js/jquery-3.3.1.min.js"></script>
<script type="text/javascript" src="./js/json2.js"></script>
</head>
<body>
<select id="one" onchange="select_first()">
<option>--请选择省份--</option>
</select>
<select id="two" onchange="select_second()">
<option>--请选择市--</option>
</select>
<select id="three">
<option>--请选择县/区--</option>
</select>
<script type="text/javascript">
//定义第一个异步
var one = {
//code传入空值,意为检索所有的省份
url:"./DataServlet?code="+"",
type:"get",
success:function(data){
//JSON.parse(data),用于将DataServlet传来的字符串转换为对象数组
var area_objs = JSON.parse(data);
for (var i = 0; i < area_objs.length; i++) {
//为省份的下拉列表添加option标签,顺便为该标签添加value属性
$("#one").append("<option value=\""+area_objs[i].code+"\">"+area_objs[i].name+"</option>");
}
}
};
//触发异步
$.ajax(one);
var select_first = function(){
//声明一个数组,接收省份下拉列表的所有option
var one_area = $("#one option");
//遍历省份下拉列表的所有option,找到被选中的option
for(i = 0; i < one_area.length; i++){
if(one_area[i].selected){
var two = {
//将被选中的省份的value赋值给code,最终匹配数据库中parent_code等于该值的所有区域信息
url:"./DataServlet?code=" + one_area[i].value,
type:"get",
success:function(data){
//将由数据库中parent_code等于该值的所有区域信息组成的字符串转换为对象数组
var area_objs = JSON.parse(data);
//每次触发事件就将市、县下拉列表恢复无选择状态
$("#two").html("<option>--请选择市--</option>");
$("#three").html("<option>--请选择县/区--</option>");
for (var i = 0; i < area_objs.length; i++) {
//为市的下拉列表添加option标签,顺便为该标签添加value属性
$("#two").append("<option value=\""+area_objs[i].code+"\">"+area_objs[i].name+"</option>");
}
}
};
//触发异步
$.ajax(two);
//由于已经找到了被选择项,所以不再遍历
break;
}
}
};
//该方法的处理思路与流程与select_first方法一致,不再注释
var select_second = function(){
var two_area = $("#two option");
for(i = 0; i < two_area.length; i++){
if(two_area[i].selected){
var select_two = two_area[i].value;
var three = {
url:"./DataServlet?code="+select_two,
type:"get",
success:function(data){
var area_objs = JSON.parse(data);
$("#three").html("<option>--请选择县/区--</option>");
for (var i = 0; i < area_objs.length; i++) {
$("#three").append("<option value=\""+area_objs[i].code+"\">"+area_objs[i].name+"</option>");
}
}
};
$.ajax(three);
break;
}
}
};
</script>
</body>
</html>