项目总结01:JSP mysql SpringMvc下中国省市县三级联动下拉框

JSP mysql SpringMvc下中国省市县三级联动下拉框

关键词

  JSP  mysql数据库  SpringMvc  ajax   Controller层  Service层  中国地区  省市县  三级联动  下拉框选择

摘要

  因项目需要,写了一个省市县三级联动下拉框,省市县数据由mysql数据库调用,实现联动查询选择省市县后,将数据返回目标数据表,并且可以查看选择结果。

  功能:项目要求可以新增货编辑商品收件人信息,其中省市县信息可以下拉逐级选择

  基本思路:加载jsp页面时,通过java Controller层和Service层,调用获取全部省份,显示省份下拉框;选择省份后,通过change事件调用ajax,通过java Controller层和Service层,找到目标省份下的所有城市,并将数据返回给前台,市下拉框出现对应城市;选择城市后,通过change事件调用ajax,通过java Controller层和Service层,找到目标城市下的劝募县,并将数据返回给前台,县下拉框出现对应县;选择县后,保存数据,并将数据传回mysql数据表union_shop.sql;同考虑一些可能出现的bug;

  为了突出主题内容,以下只贴出主要代码块,供大家参考,个人认为重点难点在于数据传出传入,以及避免市县重名的情况;欢迎大家相互交流!

正文

  效果展示,如图:

项目总结01:JSP mysql SpringMvc下中国省市县三级联动下拉框

  jsp部分:主要进行页面展示,文件名--unionshop_edit.jsp,对应java Controller层提到的mv.setViewName()的路径

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE html>
<html lang="en">
<head>
<base href="<%=basePath%>">
/*javascript放在这里*/
</head>
<body>
<form action="unionshop/rest/save.do" name="Form" id="Form" method="post" enctype="multipart/form-data" onsubmit="return save();">
<input type="hidden" name="id" id="id" value="${pd.id}"/>">
<table id="table_report" class="table noline">
<tr>
          
<td style="width:90px;text-align: right;padding-top: 13px;"><em>*</em>所在省:</td>
<td>
            //以下显示省份下拉框
<select name="addr_province" class="addr_province" id="addr_province" >
<c:if test="${pd.addr_province != null && pd.addr_province != ''}"><option value="${pd.addr_province}" selected="selected">${pd.addr_province}</option></c:if>//数据库有对应数据时(即编辑或查看该条数据),显示对应数据
<c:if test="${pd.addr_province == null || pd.addr_province == ''}"><option value="请选择省份">请选择省份</option></c:if> //数据库没有对应数据时(即新建一个项目数据),显示“请选择省份”
//生成全部省份下拉框
              <c:choose>
<c:when test="${not empty addr_province}">
<c:forEach items="${addr_province}" var="var" varStatus="vs">
<option value="${var.region_name}" >${var.region_name}</option>
</c:forEach>
</c:when>
</c:choose>
</select>
</td>
<td style="width:90px;text-align: right;padding-top: 13px;"><em>*</em>所在城市:</td>
<td>
            //以下显示城市信息
<select name="addr_city" class="addr_city" id="addr_city" >
<c:if test="${pd.addr_city != null && pd.addr_city != ''}"><option value="${pd.addr_city}" selected="selected">${pd.addr_city}</option></c:if>
<c:if test="${pd.addr_city == null || pd.addr_city == ''}"><option value="请选择城市">请选择城市</option></c:if>
              /*这里对应的城市option标签是由JavaScript动态生成*/
</select>
</td> </tr>
<tr>
<td style="width:90px;text-align: right;padding-top: 13px;"><em>*</em>所在区县:</td>
//以下显示县信息
<td>
<select name="addr_county" class="addr_county" id="addr_county" >
<c:if test="${pd.addr_county != null && pd.addr_county != ''}"><option value="${pd.addr_county}" selected="selected">${pd.addr_county}</option></c:if>
<c:if test="${pd.addr_county == null || pd.addr_county == ''}"><option value="请选择县">请选择县</option></c:if>
               /*这里对应的县option标签有JavaScript自动生成*/
</select>
</td>
<td style="width:90px;text-align: right;padding-top: 13px;"><em>*</em>地址详情:</td>
<td><input type="text" name="addr_detail" id="addr_detail" value="${pd.addr_detail}" maxlength="32" placeholder="请输入地址详情" title="地址详情"/></td>
</tr>
<tr>
<td style="text-align: center;" colspan="10">
<button id="saveBtn" class="btn btn-primary" type="submit" style="width:100px">保存</button> //保存提交数据,触发form表头的onsubmit时间
</td> </tr> </table> </div> </form> </body> </html> 

  JavaScript部分:实现数据交互

<script type="text/javascript">

    //保存
function save(){
//以下是当用户未选择省市县是,提醒用户
if($("#addr_province").val()=="" || $("#addr_province").val()=="请选择省份"){
popupTip('addr_province', '请选择省份');
return false;
}
if($("#addr_city").val()=="" || $("#addr_city").val()=="请选择城市"){
popupTip('addr_city', '请选择城市');
return false;
}
if($("#addr_county").val()=="" || $("#addr_county").val()=="请选择县"){
popupTip('addr_county', '请选择县');
return false;
}
return true //返回TRUE后,提交数据到后台
} function popupTip(field, msg){
$("#"+field).tips({
side:3,
msg:msg,
bg:'#AE81FF',
time:2
});
$("#field").focus();
} /* 选择省份,并展示城市 */
$(".addr_province").change(function(){
var addr_province=$(this).val();
if(addr_province=="请选择省份"){
$(".addr_city").empty();
$(".addr_country").empty();
return false;
}
$(".addr_city").empty();
$(".addr_county").empty();
var ajaxObject={
url:"unionshop/rest/goSelectCity",
data:{
region_name:addr_province
},
success:function (data) {
var str="<option>请选择城市</option>";
for(var i=0;i<data.data.length;i++){
str=str+"<option value="+data.data[i].region_name+">"+data.data[i].region_name+"</option>";
}
$(".addr_city").html(str);
},
fail:function(){console.log("fail")},
error:function(){console.log("error")},
}
ajaxPost(ajaxObject);
})
/* 选择城市,并展示县*/
$(".addr_city").change(function(){
var addr_city=$(this).val();
if(addr_city=="请选择城市"){
alert("请选择城市");
$(".addr_county").empty();
return false;
}
var addr_province=$(".addr_province").val(); //通过省份 城市双选 确保县范围正确(避免同名市县情况)
$(".addr_county").empty();
var ajaxObject={
url:"unionshop/rest/goSelectCounty",
data:{
addr_province:addr_province,
region_name:addr_city
},
success:function (data) {
var str="<option>请选择县</option>";
for(var i=0;i<data.data.length;i++){
str=str+"<option value="+data.data[i].region_name+">"+data.data[i].region_name+"</option>";
}
$(".addr_county").html(str);
console.log(data.data.length);
console.log(data.data[0].region_name);
},
fail:function(){console.log("fail")},
error:function(){console.log("error")},
}
ajaxPost(ajaxObject);
})
$(".addr_county").change(function(){
var addr_county=$(this).val();
if(addr_county=="请选择县"){
alert("请选择县");
return false;
} }) </script>

  java:controller层,后台接收数据

package com.fh.controller.youbao.information.unionshop;

/*import ……*/ 

@Controller
@RequestMapping(value="/unionshop")
public class UnionShopController extends BaseController { String menuUrl = "unionshop/list.do"; //菜单地址(权限用)
@Resource(name="unionshopService")
private UnionShopService unionshopService; /**
* rest新增
*/
/* @RequestMapping(value="/rest/save" , method=RequestMethod.POST ,
produces="application/json;charset=UTF-8")*/
@RequestMapping(value="/rest/save")
@ResponseBody
public ModelAndView restSave(@RequestParam Map<String, Object> params) throws Exception{ PageData pd = new PageData();
pd.putAll(params); //保存数据
unionshopService.save(pd);
return list(this.getPage()); } /**
* 通过省份确认城市
*/
@RequestMapping(value="/rest/goSelectCity" , method=RequestMethod.POST ,
produces="application/json;charset=UTF-8")
@ResponseBody
public String goSelectCity(@RequestBody Map<String,String> map) throws Exception{
PageData pd = new PageData();
pd.putAll(map);
pd.put("parent_id", 1);
//获取省份id
PageData provinceInfor=unionshopService.confirmByRegionNameAndParentId(pd);
int province_id=Integer.parseInt(String.valueOf(provinceInfor.get("region_id"))); //获取目标省份下的所有city
PageData thisProvince = new PageData();
thisProvince.put("parent_id", province_id);
List<PageData> addr_city = unionshopService.findByParentId(thisProvince);
return ResponseMessageEnum.SUCCESS.appendPageDataListToString(addr_city); //该步骤将目标省份下 的城市信息转化为String格式传给ajax的success函数的data形参
} /**
* 通过省份,城市确认县城
*/
@RequestMapping(value="/rest/goSelectCounty" , method=RequestMethod.POST ,
produces="application/json;charset=UTF-8")
@ResponseBody
public String goSelectCounty(@RequestBody Map<String,String> map) throws Exception{ //获取省份id
PageData pd_province = new PageData();
pd_province.put("parent_id", "1");
pd_province.put("region_name", String.valueOf(map.get("addr_province")));
PageData provinceInfor=unionshopService.confirmByRegionNameAndParentId(pd_province);
int province_id=Integer.parseInt(String.valueOf(provinceInfor.get("region_id"))); //获取城市id
PageData pd_city= new PageData();
pd_city.put("parent_id", province_id);
pd_city.put("region_name", String.valueOf(map.get("region_name")));
PageData cityInfor=unionshopService.confirmByRegionNameAndParentId(pd_city);
int city_id=Integer.parseInt(String.valueOf(cityInfor.get("region_id"))); //获取目标城市下的所有县
PageData thisCity = new PageData();
thisCity.put("parent_id", city_id);
List<PageData> addr_county = unionshopService.findByParentId(thisCity);
return ResponseMessageEnum.SUCCESS.appendPageDataListToString(addr_county); //将目标城市下的县数据返回给ajax
} /**
* 去新增页面,跳转到我们上面提到的jsp界面
*/
@RequestMapping(value="/goAdd")
public ModelAndView goAdd(){
ModelAndView mv = this.getModelAndView();
PageData pd = new PageData();
PageData pdlist = new PageData();
pd = this.getPageData();
try {
//获取全部省份数据
pdlist.put("parent_id", 1);
List<PageData> addr_province = unionshopService.findByParentId(pdlist);
mv.addObject("addr_province",addr_province);
mv.addObject("pdlist", pdlist); mv.setViewName("information/unionshop/unionshop_edit");
mv.addObject("msg", "save");
mv.addObject("pd", pd);
} catch (Exception e) {
logger.error(e.toString(), e);
}
return mv;
} /**
* 去编辑页面,跳转到我们前面提到的jsp界面
*/
@RequestMapping(value="/goEdit")
public ModelAndView goEdit(){
logBefore(logger, "去修改UnionShop页面");
ModelAndView mv = this.getModelAndView();
PageData pd = new PageData();
PageData pdlist = new PageData();
pd = this.getPageData();
try {
//获取全部省份数据
pdlist.put("parent_id", 1);
List<PageData> addr_province = unionshopService.findByParentId(pdlist);
mv.addObject("addr_province",addr_province);
mv.addObject("pdlist", pdlist); pd = unionshopService.findById(pd); //根据ID读取该条数据,包括省市县
mv.setViewName("information/unionshop/unionshop_edit");
mv.addObject("msg", "edit");
mv.addObject("pd", pd);
} catch (Exception e) {
logger.error(e.toString(), e);
}
return mv;
}
}

    java:service层

package com.fh.service.information.unionshop;

@Service("unionshopService")
public class UnionShopService { @Resource(name = "daoSupport")
private DaoSupport dao; /*
* 新增
*/
public void save(PageData pd)throws Exception{
dao.save("UnionShopMapper.save", pd);
} /*
* 修改
*/
public void edit(PageData pd)throws Exception{
dao.update("UnionShopMapper.edit", pd);
} /*
*列表
*/
public List<PageData> list(Page page)throws Exception{
return (List<PageData>)dao.findForList("UnionShopMapper.datalistPage", page);
} /*
*查找省份
*/
public List<PageData> findByParentId(PageData pd)throws Exception{
return (List<PageData>)dao.findForList("UnionShopMapper.findByParentId", pd);
} /*
* 通过id获取数据
*/
public PageData findById(PageData pd)throws Exception{
return (PageData)dao.findForObject("UnionShopMapper.findById", pd);
}
/*
* 通过省份选择城市
*/
public PageData confirmByRegionNameAndParentId(PageData pd)throws Exception{
return (PageData)dao.findForObject("UnionShopMapper.confirmByRegionNameAndParentId", pd);
} }

    XML:mysql数据操作指令

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="UnionShopMapper"> <!-- 新增-->
<insert id="save" parameterType="pd">
insert into union_shop(
addr_province,
addr_city,
addr_county,
addr_detail ) values (
#{addr_province},
#{addr_city},
#{addr_county},
#{addr_detail} )
</insert> <!-- 修改 -->
<update id="edit" parameterType="pd">
update union_shop
set addr_province = #{addr_province},
addr_city = #{addr_city},
addr_county = #{addr_county},
addr_detail = #{addr_detail}
id = id
where
id = #{id}
</update> <!-- 通过id获取数据 -->
<select id="findById" parameterType="pd" resultType="pd">
select * from
union_shop
where
id = #{id}
</select> <!-- 通过省份选城市 -->
<select id="confirmByRegionNameAndParentId" parameterType="pd" resultType="pd">
select * from
region
where
region_name = #{region_name} and parent_id=#{parent_id}
</select>
</mapper>

  mysql文件:中国省市县全部数据信息,文件名--region.sql链接:http://files.cnblogs.com/files/wobuchifanqie/region-mysql.rar;部分内容如下:

项目总结01:JSP mysql SpringMvc下中国省市县三级联动下拉框

  mysql文件:项目接收选择后的省市县具体数据 ,文件名--union_shop.sql,如图:

项目总结01:JSP mysql SpringMvc下中国省市县三级联动下拉框

 

结论

  本人新手一枚,对我而言,难点在于数据如何交互,以及处理用户一些奇葩操作(比如重新选择,不选择等情况),主要集中在JavaScript部分;,还有要考虑省市县出现同名的情况

  写于此,2017-04-20-下午;备用

上一篇:Java 状态模式


下一篇:如何选择适合的前端UI框架