![](https://i-blog.csdnimg.cn/direct/b57901cfec5247d79d461a7460c9a7ab.jpeg)
🧸安清h:个人主页****
🎥个人专栏:【Spring篇】【计算机网络】** 【Mybatis篇】**
**🚦作者简介:**一个有趣爱睡觉的intp,期待和更多人分享自己所学知识的真诚大学生。
![](https://i-blog.csdnimg.cn/direct/f27f7d6a2d5d4246b3f7bee8b779e76d.gif)
目录
[🚀3.获取省市区列表- 持久层](#🚀3.获取省市区列表- 持久层)
[🚀4.获取省市区列表- 业务层](#🚀4.获取省市区列表- 业务层)
[🚀5.获取省市区列表- 控制层](#🚀5.获取省市区列表- 控制层)
[🚀6.获取省市区列表- 前端页面](#🚀6.获取省市区列表- 前端页面)
🚀1.获取省市区列表-创建数据表
sql
CREATE TABLE t_dict_district (
id INT(11) NOT NULL AUTO_INCREMENT,
parent VARCHAR(6) DEFAULT NULL,
`code` VARCHAR(6) DEFAULT NULL,
`name` VARCHAR(16) DEFAULT NULL,
PRIMARY KEY (id)
) ENGINE=INNODB DEFAULT CHARSET=utf8;
id属性:唯一标识这一条记录。
code属性:它本身的代号。
name属性:这个代号所表示的名称。
parent属性:父区域的代码号,省的代码号+86。任何一个区域的信息依赖于上级信息,例如:南阳市依赖于河南省,河南省依赖于中国。
2.向表中插入省市区数据
sql
LOCK TABLES t_dict_district WRITE;
INSERT INTO t_dict_district VALUES
(1,'110100','110101','东城区'),
(2,'110100','110102','西城区'),
(3,'110100','110103','朝阳区'),
(4,'110100','110104','海淀区');
......
UNLOCK TABLES;
🚀2.获取省市区列表-实体类
创建实体类District。
java
public class District extends BaseEntity{
private Integer id;
private String parent;
private String code;
private String name;
......
}
🚀3.获取省市区列表- 持久层
✨3.1规划SQL语句
查询语句,根据父代号进行查询。
sql
select * from t_dict_district where parent=?
order by code ASC
✨3.2接口设计和抽象方法的实现
1.抽象方法的定义,DistrictMapper接口。
java
public interface DistrictMapper {
/**
* 根据父代号查询区域信息
* @param parent 父代号
* @return 某个父区域下的所有区域列表
*/
List<District> findByParent(String parent);
}
2.实现映射
XML
<?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="com.cy.store.mapper.DistrictMapper">
<select id="findByParent" resultType="com.cy.store.entity.District">
select * from t_dict_district where parent=#{parent}
order by code ASC
</select>
</mapper>
3.进行测试
java
@Test
public void findByParent(){
List<District> list = districtMapper.findByParent("210100");
for(District d : list){
System.out.println(d);
}
}
🚀4.获取省市区列表- 业务层
1.创建接口IDistrictService,并定义抽象方法。
java
/**
* 根据父代号来查询区域的信息(省市区)
* @param parent 父代号
* @return 多个区域的信息
*/
List<District> getByParent(String parent);
2.创建DistrictServiceImpl实现类,实现抽象的方法。
java
@Override
public List<District> getByParent(String parent) {
List<District> list = districtMapper.findByParent(parent);
// 在进行网络数据传输时,为了尽量避免无效数据的传递,可以将无效数据设置为null,
// 可以节省流量,另一方面提升了效率
for(District d : list){
d.setId(null);
d.setParent(null);
}
return list;
}
3.单元测试
java
@SpringBootTest
public class DistrictServiceTests {
@Autowired
private IDistrictService districtService;
@Test
public void getByParent(){
List<District> list = districtService.getByParent("86");
for(District d : list){
System.err.println(d);
}
}
}
🚀5.获取省市区列表- 控制层
✨5.1设计请求
请求路径:/districts/
请求参数:String parent
请求类型:GET
响应结果:JsonResult<List<District>>
✨5.2处理请求
创建一个DistrictController类,在这个类中编写请求的方法。
java
@RestController
@RequestMapping("districts")
public class DistrictController extends BaseController{
@Autowired
private IDistrictService districtService;
// districts开头的请求都被拦截到getByParent()方法
@RequestMapping({"/",""})
public JsonResult<List<District>> getByParent(String parent){
List<District> data = districtService.getByParent(parent);
return new JsonResult<>(OK,data);
}
}
在LoginInterceptorConfigurer中添加如下代码:
java
patterns.add("/districts/**");
直接请求服务器,来访问localhost:8080/districts?parent=86访问进行测试。
🚀6.获取省市区列表- 前端页面
1.通过注释掉js来完成省市区列表加载的js代码。由于省市区数据已经被我们放到了数据库中,而原来在页面上显示的数据是通过前端中引用的两个js文件来实现的,所以这里注释掉addAddress中的下面两行。
java
<!-- <script type="text/javascript" src="../js/distpicker.data.js"></script>-->
<!-- <script type="text/javascript" src="../js/distpicker.js"></script>-->
2.检查前端页面在提交省市区数据时是否有相关name属性和id属性。
3.运行前端看是否可以正常的保存数据(除了省市区之外)。
🎯1.获取省市区的名称-持久层
1.根据当前code来获取当前省市区的名称,对应就是一条查询语句。
sql
select * from t_dict_district where code=?
2.在DistrictMapper接口定义出来。
java
String findNameByCode(String code);
3.在DistrictMapper.xml文件中添加抽象方法的映射。
XML
<select id="findNameByCode" resultType="java.lang.String">
select name from t_dict_district where code=#{code}
</select>
4.单元测试方法编写
java
@Test
public void findNameByCode(){
System.out.println(districtMapper.findNameByCode("610000"));
}
🎯2.获取省市区的名称-业务层
1.在业务层没有异常需要处理
2.定义对应的业务层接口中的抽象方法。
java
String getNameByCode(String code);
3.在子类中实现
java
@Override
public String getNameByCode(String code) {
return districtMapper.findNameByCode(code);
}
4.测试可以省略(超过八行以上的代码都要进行独立的测试)。
🎯3.获取省市区的名称-业务层优化
1.添加地址层依赖于IDistrictService层。在AddressServiceImpl中添加如下代码:
java
// 在添加用户的收货地址的业务层依赖于DistrictService的业务层接口,为了完整的添加到收货地址中,而省市区刚好是独立出来的
@Autowired
private IDistrictService districtService;
2.在addNewAddress方法中将DisdrictService接口中获取到的省市区数据转移到address对象中,这个对象中就包含了所有用户的收货地址数据。
java
// 对address对象中的数据进行补全:省市区
String provinceName = districtService.getNameByCode(address.getProvinceCode());
String cityName = districtService.getNameByCode(address.getCityCode());
String areaName = districtService.getNameByCode(address.getAreaCode());
address.setProvinceName(provinceName);
address.setCityName(cityName);
address.setAreaName(areaName);
🎯4.获取省市区-前端页面
1.addAddress.html页面中来编写对应的省市区展示及根据用户的不同选择来限制对应的标签中的内容。
2.编写相关的事件代码。
javascript
<script>
<!-- value属性用于表示当前这个区域的code值,这里的value给负数或0都可-->
let defaultOption = "<option value='0'>----请选择----</option>"
$(document).ready(function (){
showProvinceList();
//设置默认的请选择的值,作为默认值
$("#city-list").append(defaultOption);
$("#area-list").append(defaultOption);
});
//change函数用于监听某个控件是否发生改变,一旦发声改变就会触发参数的函数。
//需要传递一个function(){}
$("#province-list").change(function (){
//先获取到行政五区父代号
let parent = $("#province-list").val();
//表示清空select下拉列表中的所有option元素
$("city-list").empty();
$("area-list").empty();
//填充默认值
$("city-list").append(defaultOption)
$("area-list").append(defaultOption);
if(parent == 0){
return;
}
$.ajax({
url:"/districts/",
type:"POST",
data:"parent="+parent, //检测到这个页面就向86发请求作为父代号
dataType:"JSON",
success:function (json){
if(json.state==200){
let list = json.data;
for(let i = 0;i<list.length;i++){
let opt = "<option value='"+list[i].code+"'>"+list[i].name+"</option>"
$("#city-list").append(opt);
}
}else{
alert("城市信息加载失败");
}
}
})
});
$("#city-list").change(function (){
//先获取到行政五区父代号
let parent = $("#city-list").val();
//表示清空select下拉列表中的所有option元素
$("area-list").empty();
//填充默认值
$("area-list").append(defaultOption);
if(parent == 0){
return;
}
$.ajax({
url:"/districts/",
type:"POST",
data:"parent="+parent, //检测到这个页面就向86发请求作为父代号
dataType:"JSON",
success:function (json){
if(json.state==200){
let list = json.data;
for(let i = 0;i<list.length;i++){
let opt = "<option value='"+list[i].code+"'>"+list[i].name+"</option>"
$("#area-list").append(opt);
}
}else{
alert("县区信息加载失败");
}
}
})
});
//省的下拉列表数据展示
function showProvinceList(){
$.ajax({
url:"/districts/",
type:"POST",
data:"parent=86", //检测到这个页面就向86发请求作为父代号
dataType:"JSON",
success:function (json){
if(json.state==200){
let list = json.data;
for(let i = 0;i<list.length;i++){
let opt = "<option value='"+list[i].code+"'>"+list[i].name+"</option>"
$("#province-list").append(opt);
}
}else{
alert("省/直辖市信息加载失败");
}
}
})
}
$("#btn-add-new-address").click(function (){
$.ajax({
url:"/addresses/add_new_address",
type:"POST",
data:$("#form-add-new-address").serialize(),
dataType:"JSON",
success:function (json){
if(json.state==200){
alert("新增收货地址成功");
}else{
alert("新增收货地址失败");
}
},
error:function (xhr){
alert("新增收货地址时产生未知的异常"+xhr.message);
}
});
});
</script>
🎃1.收货地址列表展示-持久层
1.数据库数据的查询操作:
sql
select * from t_address where uid=?
order by is_default DESC,
created_time DESC
2.接口和抽象方法
java
/**
* 根据用户的id查询用户的收货地址数据
* @param uid 用户id
* @return 收货地址数据
*/
List<Address> findByUid(Integer uid);
3.在xml文件中添加SQL语句映射
XML
<select id="findByUid" resultMap="AddressEntityMap">
select * from t_address where uid=#{uid} order by is_default DESC,created_time DESC
</select>
4.完成单元测试
java
@Test
public void findByUid(){
List<Address> list = addressMapper.findByUid(6);
System.out.println(list);
}
🎃收货地址列表展示-业务层
1.不用抛出相关的异常,也不用进行异常的设计。
2.在业务层中设计接口和抽象方法。
抽象方法目的类似于AddressMapperTests的单元测试,来调用mapper的findByUid方法。
java
List<Address> getByUid(Integer uid);
3.在实现类中实现此方法的逻辑。
java
@Override
public List<Address> getByUid(Integer uid) {
List<Address> list = addressMapper.findByUid(uid);
for(Address address : list){
address.setAid(null);
address.setUid(null);
address.setProvinceCode(null);
address.setCityCode(null);
address.setAreaCode(null);
address.setZip(null);
address.setTel(null);
address.setIsDefault(null);
address.setCreatedTime(null);
address.setCreatedUser(null);
address.setModifiedTime(null);
address.setModifiedUser(null);
}
return list;
}
4.单元测试省略。
🎃收货地址列表展示-控制层
✨设计请求
请求路径:/addresses
请求参数:HttpSession session(上面抽象方法所写的代码依赖于uid,而uid来源于此)
请求类型:GET(发送这个请求不需要提交数据,uid是从后端封装的,所以本质上从前端过来没有数据)
响应结果:JsonResult<List<Address>>
✨处理请求
1.在AddressController中编写如下代码:
java
@RequestMapping({"/",""})
public JsonResult<List<Address>> getByUid(HttpSession session){
List<Address> data = addressService.getByUid(getuidFromSession(session));
return new JsonResult<>(OK,data);
}
2.测试,先登录,再访问请求的地址进行数据的测试。http://localhost:8080/addresses?uid=6
🎃收货地址列表展示-前端页面
在address.html页面中编写查询用户收货地址数据的展示列表。
javascript
<script>
$(document).ready(function (){
showAddressList();
});
// 展示用户收货地址列表
function showAddressList(){
$.ajax({
url:"/addresses/",
type:"GET",
// data:"",这里不需要提交数据
dataType:"JSON",
success:function (json){
if(json.state==200){
let list = json.data;
for(let i = 0;i<list.length;i++){
var tr = '<tr>\n' +
'<td>#{tag}</td>\n' +
'<td>#{name}</td>\n' +
'<td>#{address}</td>\n' +
'<td>#{phone}</td>\n' +
'<td><a class="btn btn-xs btn-info"><span class="fa fa-edit"></span> 修改</a></td>\n' +
'<td><a class="btn btn-xs add-del btn-info"><span class="fa fa-trash-o"></span> 删除</a></td>\n' +
'<td><a class="btn btn-xs add-def btn-default">设为默认</a></td>\n' +
'</tr>';
//#{tag}等只是占位符,不是像映射文件里的参数,没有任何意义
tr = tr.replace(/#{tag}/g,list[i].tag);
tr = tr.replace(/#{name}/g,list[i].name);
tr = tr.replace("#{address}",list[i].address);
tr = tr.replace("#{phone}",list[i].phone);
$("#address-list").append(tr);
}
//将某个元素隐藏使用hide方法
$(".add-def:eq(0)").hide();
}else{
alert("用户收货地址加载失败");
}
}
})
}
</script>