如何实现省市区三级联动的效果(从前台页面、后台、数据库详细阐述)

1、在做这个小项目前的准备工作:

1.1、分析:

    由于省、市、县城(区)这些数据是存储到了MySQL数据库中的,我们要通过后台servlet获取数据库中的数据,然后再通过转发或者重定向的方式将数据呈现到前台页面中。

1.2、需要导入的jar包有:

mysql驱动包:mysql-connector-java-5.1.7-bin.jar

c3p0数据库连接池:c3p0-0.9.2.1.jar、mysql-connector-java-5.1.7-bin.jar(c3p0依赖包)

前台c标签(需要通过遍历的方式呈现——c:forEach):jstl-1.0.2.jar、standard-1.0.1.jar(jstl依赖包)

将集合或者数组转换成json数据格式(Jackson包):jackson-annotations-2.2.1.jar、jackson-core-2.2.1.jar、jackson-databind-2.2.1.jar

前台页面需要用到jquery,故还需要导入jquery-1.7.2.js库文件

1.3、该小项目用到的技术:

jdbc的知识、servlet的知识、jquery的知识、Ajax的知识(局部刷新)、标签的知识、EL表达式的知识、JSP的知识

2、开发过程:

2.1、准备数据源

创建一个数据库,命名为thereaction并创建三个表——province(省)、city(市)、county(县/区)

2.2后台开发

创建三个Javabean分别是Province、City、County。(由于太过简单,这里就不粘代码了)
创建Java类和c3p0连接池实现与数据库的连接:DAO.java(实现获取数据库数据的功能)、jdbctools.java(实现获取数据库连接、释放连接的功能)、c3p0-config.xml
jdbctools.java代码如下:
package com.xiaojie.dao;

import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import javax.sql.DataSource;

import com.mchange.v2.c3p0.ComboPooledDataSource;

public class Jdbctools {
	private static DataSource ds=null;  
    //数据库连接池应只被初始化一次  
    static{  
        ds=new ComboPooledDataSource("helloc3p0");  
    }  
    //获取数据库连接  
    public static  Connection getConnection() throws ClassNotFoundException, SQLException, IOException{  
        return ds.getConnection();      
    } 
    public static void shifanglianjie(Connection ct, PreparedStatement ps,ResultSet rs) { 
    	if(rs!=null){
    		try {
				rs.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
    	}
    	if(ps!=null){
    		try {
				ps.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
    	}
    	if(ct!=null){
    		try {
				ct.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
    	}
    }

}

DAO.java的代码如下
package com.xiaojie.dao;

import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import com.xiaojie.beans.City;
import com.xiaojie.beans.County;
import com.xiaojie.beans.Province;

public class DAO {
	public List<Province> getprovince(String sql ,Object...args) throws ClassNotFoundException, SQLException, IOException{
		List<Province> provinces=new ArrayList<Province>();
		//准备去查数据库
		Connection ct=null;
		ct=Jdbctools.getConnection();
		System.out.println("获取到数据库的连接了");
		PreparedStatement ps=null;
		ResultSet rs=null;
		ps=ct.prepareStatement(sql);
		for(int i=0;i<args.length;i++){
			ps.setObject(i+1, args[i]);
		}
		rs=ps.executeQuery();
		while(rs.next()){
			provinces.add(new Province(rs.getInt("province_id"),rs.getString("province_name")));
		}
		Jdbctools.shifanglianjie(ct, ps, rs);
		return provinces;
		
	}
	public List<City> getcity(String sql ,Object...args) throws SQLException, ClassNotFoundException, IOException{
		List<City> cities=new ArrayList<City>();
		//准备去查数据库
		Jdbctools jt=new Jdbctools();
		Connection ct=null;
		ct=jt.getConnection();
		PreparedStatement ps=null;
		ResultSet rs=null;
		ps=ct.prepareStatement(sql);
		for(int i=0;i<args.length;i++){
			ps.setObject(i+1, args[i]);
		}
		rs=ps.executeQuery();
		while(rs.next()){
			cities.add(new City(rs.getInt("city_id"),rs.getString("city_name")));
		}
		jt.shifanglianjie(ct, ps, rs);
		return cities;
		
	}
	public List<County> getcounty(String sql,Object...args ) throws SQLException, ClassNotFoundException, IOException{
		List<County> counties=new ArrayList<County>();
		//准备去查数据库
		Jdbctools jt=new Jdbctools();
		Connection ct=null;
		ct=jt.getConnection();
		PreparedStatement ps=null;
		ResultSet rs=null;
		ps=ct.prepareStatement(sql);
		for(int i=0;i<args.length;i++){
			ps.setObject(i+1, args[i]);
		}
		rs=ps.executeQuery();
		while(rs.next()){
			counties.add(new County(rs.getInt("county_id"),rs.getString("county_name")));
		}
		jt.shifanglianjie(ct, ps, rs);
		return counties;
		
	}
}
c3p0-config.xml的代码如下:
<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config> 
    <named-config name="helloc3p0"> 
<!--     连接数据源的基本属性 -->
    <property name="user">root</property> 
     <property name="password"></property> 
     <property name="driverClass">com.mysql.jdbc.Driver</property> 
     <property name="jdbcUrl">jdbc:mysql:///thereaction</property> 
    
<!--     若数据库中连接数不足时,一次向数据库服务器申请多少个连接  -->
    <property name="acquireIncrement">5</property> 
<!--     	初始化数据库连接池时连接的数量 -->
    <property name="initialPoolSize">5</property> 
<!--     数据库连接池中的最小的数据库连接数 -->
    <property name="minPoolSize">5</property> 
    <!--     数据库连接池中的最大的数据库连接数 -->
    <property name="maxPoolSize">10</property> 
<!--     c3p0数据库连接可以维护的statement的个数 -->
    <property name="maxStatements">20</property> 
<!--     每个连接同时可以使用的statement对象的个数 -->
    <property name="maxStatementsPerConnection">5</property> 
    </named-config> 
</c3p0-config> 

创建servlet.java 文件
package com.xiaojie.servlet;

import java.io.IOException;
import java.lang.reflect.Method;
import java.sql.SQLException;
import java.util.List;

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

import com.fasterxml.jackson.databind.ObjectMapper;
import com.xiaojie.beans.City;
import com.xiaojie.beans.County;
import com.xiaojie.beans.Province;
import com.xiaojie.dao.DAO;
/**
 * Servlet implementation class ThreeactiondServlet
 */
@WebServlet("/threeactiondServlet")
public class ThreeactiondServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
	    String methodname=request.getParameter("method");  
	    try {  
	        Method method=getClass().getDeclaredMethod(methodname,HttpServletRequest.class,HttpServletResponse.class);  
	        method.invoke(this, request,response);//调用各自的方法  
	    } catch (Exception e) {  
	        e.printStackTrace();  
	    }
	}
	private DAO dao=new DAO();
	protected void province(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException, ClassNotFoundException, SQLException {
		System.out.println("province的servlet进入了");
		String sql="select province_id,province_name from province";		
		List<Province> provinces=dao.getprovince(sql);
		request.setAttribute("provinces", provinces);
		System.out.println(provinces);
		//注意:这里不能用重定向的形式,因为我们好不容易在request请求域中存储了省的信息,目的是在前台页面中能够从请求域中获取到我们存在数据库中的值
		//故这里只能用转发的方式
		request.getRequestDispatcher("/index2.jsp").forward(request, response);
	}
	protected void city(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException, ClassNotFoundException, SQLException {
		System.out.println("city的servlet进入了");
		String province_id=request.getParameter("province_id");
		String sql="select city_id,city_name from city where province_id=?";
		List<City> cities=dao.getcity(sql,Integer.parseInt(province_id));
		ObjectMapper mapper=new ObjectMapper();
		String result=mapper.writeValueAsString(cities);
		System.out.println(result);
		response.setContentType("text/javascript");
		response.getWriter().print(result);
	}
	protected void county(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException, ClassNotFoundException, SQLException {
		System.out.println("county的servlet进入了");
		String city_id=request.getParameter("city_id");
		String sql="select county_id,county_name from county where city_id=?";
		List<County> counties=dao.getcounty(sql,Integer.parseInt(city_id));
		ObjectMapper mapper=new ObjectMapper();
		String result=mapper.writeValueAsString(counties);
		System.out.println(result);
		response.setContentType("text/javascript");
		response.getWriter().print(result);
	}
}

2.3前台开发

首先通过重定向的方式到后台获取数据将省份的信息显示在前台页面,这里创建一个index.jsp
<%
 response.sendRedirect("threeactiondServlet?method=province");
%>
通过ajax技术实现三级联动的效果,这里创建一个index2.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core_rt" %>
<!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="jquery-1.7.2.js"></script>
<script type="text/javascript">
	$(function(){
		alert("jquery起作用了");
		$("#province").change(function(){
			//使#city只保留第一个option子节点
			$("#city option:not(:first)").remove();
			var province_id=$(this).val();
			if(province_id!=""){
				var url="<%=request.getContextPath()%>/threeactiondServlet?method=city";
				var args={"province_id":province_id,"time":new Date()};
				$.getJSON(url,args,function(data){
						for(var i=0;i<data.length;i++){
							var city_id=data[i].city_id;
							var city_name=data[i].city_name;
							$("#city").append("<option value='"+city_id+"'>"+city_name+"</option>");
						}				
				});
			}
		
			
		});
		$("#city").change(function(){
			//使#county只保留第一个option子节点
			$("#county option:not(:first)").remove();
			var city_id=$(this).val();
			if(city_id!=""){
				var url="<%=request.getContextPath()%>/threeactiondServlet?method=county";
				var args={"city_id":city_id,"time":new Date()};
				$.getJSON(url,args,function(data){
						for(var i=0;i<data.length;i++){
							var county_id=data[i].county_id;
							var county_name=data[i].county_name;
							$("#county").append("<option value='"+county_id+"'>"+county_name+"</option>");
						}				
				});
			}
		
			
		});
	});
</script>
</head>
<body>

<center>
	省:<select id="province" >
		<option value="">请选择...</option>
		<c:forEach items="${provinces }" var="province">
			<option value="${ province.province_id}">${ province.province_name}</option>
		</c:forEach>
	</select>
	市:<select id="city">
		<option value="">请选择...</option>
	</select>
	县:<select id="county">
		<option value="">请选择...</option>
	</select>
</center>
</body>
</html>

2.4、最后的效果

运行index.jsp 文件得到的效果
如果您还有什么不懂的地方,请点击下面的链接,可以直接下载整个工程文件哦
https://yunpan.cn/cPz9rff5k4iaY  访问密码 4940



你可能感兴趣的:(三级联动)