Ajax实现省市区三级联动(JavaWeb)

先看下效果图:
在这里插入图片描述
项目结构:
在这里插入图片描述

1.准备数据库

表结构:
在这里插入图片描述
我把数据库、jquery和项目所用的jar包上传到了百度云盘,如果有需要可以下载。
链接:https://pan.baidu.com/s/1VijPG7LPeJoOHCa2mZsrww
提取码:fz86


先分析下数据库里面的数据,分析省份、城市、地区之间的联系。
在这里插入图片描述


分析ajax执行过程:
ajax向服务器发送请求,Servlet接收ajax发来的请求,获取ajax传递的数据。服务器内部调用dao类,获取数据库中的数据,此时数据是Java对象或Java数组格式的。然后将数据转为json格式的数据,返回给ajax。ajax就在success函数中将响应回来的json数据进行解析,然后输出到jsp页面。

2.编写前端页面

index.jsp:

 <body>
 <table>
   <tr>
     <td>
       <%--省份的parentid为0,故value不能取0,否则当你选择“请选择省份”时,城市就显示省份--%>
       <select id="province">
         <option value="-1">--请选择省份--</option>
       </select>
     </td>
     <td>
       <select id="city">
         <option value="-1">--请选择城市--</option>
       </select>
     </td>
     <td>
       <select id="area">
         <option value="-1">--请选择地区--</option>
       </select>
     </td>
   </tr>
 </table>
 </body>

加点css样式:

<style>
  select{
    width:110px;
    height: 25px;
  }
</style>

3.编写实体类

Area.java:

public class Area {
    private Integer baseAreaId;
    private String name;
    private Integer parentId;
    private Integer viewOrder;

    public Area() {
    }

    public Area(Integer baseAreaId, String name, Integer parentId, Integer viewOrder) {
        this.baseAreaId = baseAreaId;
        this.name = name;
        this.parentId = parentId;
        this.viewOrder = viewOrder;
    }

    public Integer getBaseAreaId() {
        return baseAreaId;
    }

    public void setBaseAreaId(Integer baseAreaId) {
        this.baseAreaId = baseAreaId;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getParentId() {
        return parentId;
    }

    public void setParentId(Integer parentId) {
        this.parentId = parentId;
    }

    public Integer getViewOrder() {
        return viewOrder;
    }

    public void setViewOrder(Integer viewOrder) {
        this.viewOrder = viewOrder;
    }
}

4.编写dao接口并实现接口

AreaDao.java:

public interface AreaDao {
    /**
     * 查询所有省份信息
     * @return 省份信息
     */
    public List<Area> findProvinceList();

    /**
     * 查询所有城市信息
     * @param parentId
     * @return 城市信息
     */
    public List<Area> findCityList(Integer parentId);

    /**
     * 查询地区信息(点击省份就出现的地区)
     * @param parentId
     * @return
     */
    public List<Area> findAreaList(Integer parentId);
}

AreaDaoImpl.java:

package com.dao.impl;

import com.bean.Area;
import com.dao.AreaDao;
import com.util.DruidUtil;

import java.sql.*;
import java.util.ArrayList;
import java.util.List;

public class AreaDaoImpl extends DruidUtil implements AreaDao  {
    Connection conn = null;
    PreparedStatement ps = null;
    ResultSet rs = null;

    /**
     * 查询所有省份信息
     *
     * @return 省份信息
     */
    @Override
    public List<Area> findProvinceList() {
        List<Area> provinceList = new ArrayList<>();
        try {
            conn = getConnection();
            ps = conn.prepareStatement("select base_areaid,name,parentid,vieworder from area where parentid=0 order by base_areaid");
            rs = ps.executeQuery();
            while(rs.next()){
                Area province = new Area();
                province.setBaseAreaId(rs.getInt("base_areaid"));
                province.setName(rs.getString("name"));
                province.setParentId(rs.getInt("parentid"));
                province.setViewOrder(rs.getInt("vieworder"));
                provinceList.add(province);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            close(conn,ps,rs);
        }
        return provinceList;
    }

    /**
     * 查询所有城市信息
     *
     * @return 城市信息
     */
    @Override
    public List<Area> findCityList(Integer parentId) {
        List<Area> cityList =  new ArrayList<>();
        try {
            conn = getConnection();
            ps = conn.prepareStatement("select base_areaid,name,parentid,vieworder from area where parentid=? order by base_areaid");
            ps.setInt(1,parentId);
            rs = ps.executeQuery();
            while(rs.next()){
                Area city = new Area();
                city.setBaseAreaId(rs.getInt("base_areaid"));
                city.setName(rs.getString("name"));
                city.setParentId(rs.getInt("parentid"));
                city.setViewOrder(rs.getInt("vieworder"));
                cityList.add(city);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            close(conn,ps,rs);
        }
        return cityList;
    }

    /**
     * 查询地区信息(点击省份就出现的地区)
     * 省份的base_areaid=城市的parentid,通过选择省份,获取到省份的base_areaid,将它赋给城市的parentid,然后再选择城市的vieworder=1的地区
     * @param parentId
     * @return
     */
    @Override
    public List<Area> findAreaList(Integer parentId) {
        List<Area> areaList = new ArrayList<>();
        try {
            conn = getConnection();
            ps = conn.prepareStatement("select diqu.base_areaid,diqu.name,diqu.parentid,diqu.vieworder from area as city,area as diqu where city.parentid=? and city.base_areaid=diqu.parentid and city.vieworder=1");
            ps.setInt(1,parentId);
            rs = ps.executeQuery();
            while(rs.next()){
                Area area = new Area();
                area.setBaseAreaId(rs.getInt("base_areaid"));
                area.setName(rs.getString("name"));
                area.setParentId(rs.getInt("parentid"));
                area.setViewOrder(rs.getInt("vieworder"));
                areaList.add(area);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            close(conn,ps,rs);
        }
        return areaList;
    }
}

注意:
由于点击省份获取城市数据点击城市获取地区数据的实现方式一模一样,所以findCityList(Integer parentId)该方法可以用于城市和地区,
而findAreaList(Integer parentId)用于点击省份时城市和地区一并出现的情况。

分析SQL语句

select diqu.base_areaid,diqu.name,diqu.parentid,diqu.vieworder 
from area as city,area as diqu 
where city.parentid=? 
and city.base_areaid=diqu.parentid 
and city.vieworder=1

省份的base_areaid=城市的parentid,通过选择省份,获取到省份的base_areaid,将它赋给城市的parentid,然后再选择城市的vieworder=1的地区。
也就是说点击省份就可以获取正在显示的城市的各个地区。

5.编写ajax请求

<script type="text/javascript" src="js/jquery-3.5.0.min.js"></script>
<script type="text/javascript">
  $(function () {
    //dom对象加载成功后发起ajax
    loadProvince();

    $("#province").change(function () {
      loadCity();
    })

    $("#city").change(function () {
      loadArea();
    })
  })

  //加载省下拉列表
  function loadProvince(){
    $.ajax({
      url:"/queryProvince",
      dataType:"json",
      success:function (data) {
        $("#province:gt(0)").empty();
        $.each(data,function (index,element) {
          $("#province").append("<option value='"+element.baseAreaId+"'>"+element.name+"</option>");
        })
      }
    })
  }

  //加载城市的下拉列表(点击省份,获取城市和地区的数据)
  function loadCity(){
    //获取到base_areaid的值
    var provinceId = $("#province>option:selected").val();
    //ajax以post方式发起请求,获取城市的数据
    $.post("/queryCity",{parentid:provinceId},function (data) {
      $("#city").empty();
      //当用户选到"请选择省份",城市变为"请选择城市"
      if(provinceId == -1){
        $("#city").append("<option value='-1'>"+"--请选择城市--"+"</option>");
      }
      $.each(data,function (index,element) {
        $("#city").append("<option value='"+element.baseAreaId+"'>"+element.name+"</option>");
      })
    },"json");

    //ajax以post方式发起请求,获取地区的数据
    $.post("/queryArea",{parentid:provinceId},function (data) {
      $("#area").empty();
      if(provinceId == -1){
        $("#area").append("<option value='-1'>"+"--请选择地区--"+"</option>");
      }
      $.each(data,function (index,element) {
        $("#area").append("<option>"+element.name+"</option>");
      })
    },"json");
  }

  //加载地区的下列列表(和请求城市数据方式一模一样,就直接使用city的servlet路径)
  function loadArea() {
    var cityId = $("#city>option:selected").val();
    $.post("/queryCity",{parentid:cityId},function (data) {
      $("#area").empty();
      $.each(data,function (index,element) {
        $("#area").append("<option value='"+element.baseAreaId+"'>"+element.name+"</option>");
      })
    },"json");
  }
</script>

在这里插入图片描述

6.编写Servlet

FindProvinceServlet.java(返回省份数据):

@WebServlet("/queryProvince")
public class FindProvinceServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        AreaDao dao = new AreaDaoImpl();
        List<Area> provinceList = dao.findProvinceList();
        //java->json
        JSONArray jsonArray = JSONArray.fromObject(provinceList);

        //输出json数据,响应ajax请求的,返回数据
        resp.setContentType("application/json;charset=utf-8");
        PrintWriter writer = resp.getWriter();
        writer.println(jsonArray);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req,resp);
    }
}

FindCityServlet.java(返回城市和地区数据):

@WebServlet("/queryCity")
public class FindCityServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doPost(req,resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        AreaDao dao = new AreaDaoImpl();
        int parentid = Integer.parseInt(req.getParameter("parentid"));
        List<Area> cityList = dao.findCityList(parentid);

        JSONArray jsonArray = JSONArray.fromObject(cityList);

        resp.setContentType("application/json;charset=utf-8");
        PrintWriter writer = resp.getWriter();
        writer.println(jsonArray);
    }
}

FindAreaServlet.java(返回点击省份时出现的地区数据):

@WebServlet("/queryArea")
public class FindAreaServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doPost(req,resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        AreaDao dao = new AreaDaoImpl();
        int parentid = Integer.parseInt(req.getParameter("parentid"));
        List<Area> areaList = dao.findAreaList(parentid);

        JSONArray jsonArray = JSONArray.fromObject(areaList);

        resp.setContentType("application/json;charset=utf-8");
        PrintWriter writer = resp.getWriter();
        writer.println(jsonArray);
    }
}

7.工具类

druid.properties:

url=jdbc:mysql://localhost:3306/springdb?useUnicode=true&characterEncoding=utf-8
username=root
password=123
driverClassName=com.mysql.jdbc.Driver
initialSize=5
maxActive=10
minIdle=5
maxWait=3000

DruidUtil.java:

public class DruidUtil {
    private static DataSource ds;
    static {
        try {
            Properties ppt = new Properties();
            ppt.load(DruidUtil.class.getClassLoader().getResourceAsStream("druid.properties"));
            ds = DruidDataSourceFactory.createDataSource(ppt);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 从连接池中取出一个连接给用户
     * @return
     */
    public static Connection getConnection(){
        try {
            return ds.getConnection();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static void close(Connection conn, Statement state, ResultSet rs){
        try {
            if(rs!=null){
                rs.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        close(conn,state);
    }

    public static void close(Connection conn,Statement state){
        try {
            if(state!=null){
                state.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        try {
            if(conn!=null){
                conn.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

难点:

  • 当选择回默认的“请选择省份”,城市要显示为“请选择城市”,地区也要显示为“请选择地区”
  • 点击省份时,不仅显示城市,地区也要一并出现
  • 5
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 9
    评论
实现省市区三级联动的关键是建立好数据库,并且编写好对应的 SQL 语句。以下是一个简单的数据库设计: - 省份表 province,包括字段 id 和 name。 - 城市表 city,包括字段 id、name 和省份的外键 province_id。 - 区县表 district,包括字段 id、name 和城市的外键 city_id。 接下来是建表语句: ```sql -- 省份表 CREATE TABLE `province` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(20) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -- 城市表 CREATE TABLE `city` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(20) NOT NULL, `province_id` int(11) NOT NULL, PRIMARY KEY (`id`), KEY `province_id` (`province_id`), CONSTRAINT `city_ibfk_1` FOREIGN KEY (`province_id`) REFERENCES `province` (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -- 区县表 CREATE TABLE `district` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(20) NOT NULL, `city_id` int(11) NOT NULL, PRIMARY KEY (`id`), KEY `city_id` (`city_id`), CONSTRAINT `district_ibfk_1` FOREIGN KEY (`city_id`) REFERENCES `city` (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; ``` 接下来是查询省份、城市、区县的 SQL 语句: ```sql -- 查询所有省份 SELECT id, name FROM province; -- 查询某个省份下的所有城市 SELECT id, name FROM city WHERE province_id = ?; -- 查询某个城市下的所有区县 SELECT id, name FROM district WHERE city_id = ?; ``` 在 Java Web 项目中,可以使用 Ajax 和 JSON 技术实现省市区三级联动。前端页面发送 Ajax 请求,后端通过 JDBC 连接数据库,查询对应的省份、城市、区县信息,并以 JSON 格式返回给前端页面。前端页面再解析 JSON 数据,更新页面的省份、城市、区县下拉框选项。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值