【基于SprintBoot+Mybatis+Mysql】电脑商城项目之获取省市区列表名称及收货地址列表展示

🧸安清h:个人主页****

🎥个人专栏:【Spring篇】【计算机网络】** 【Mybatis篇】**

**🚦作者简介:**一个有趣爱睡觉的intp,期待和更多人分享自己所学知识的真诚大学生。


目录

🚀1.获取省市区列表-创建数据表

🚀2.获取省市区列表-实体类

[🚀3.获取省市区列表- 持久层](#🚀3.获取省市区列表- 持久层)

✨3.1规划SQL语句

✨3.2接口设计和抽象方法的实现

[🚀4.获取省市区列表- 业务层](#🚀4.获取省市区列表- 业务层)

[🚀5.获取省市区列表- 控制层](#🚀5.获取省市区列表- 控制层)

✨5.1设计请求

✨5.2处理请求

[🚀6.获取省市区列表- 前端页面](#🚀6.获取省市区列表- 前端页面)

🎯1.获取省市区的名称-持久层

🎯2.获取省市区的名称-业务层

🎯3.获取省市区的名称-业务层优化

🎯4.获取省市区-前端页面

🎃1.收货地址列表展示-持久层

🎃收货地址列表展示-业务层

🎃收货地址列表展示-控制层

✨设计请求

✨处理请求

🎃收货地址列表展示-前端页面


🚀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>
相关推荐
JavaGuide6 分钟前
Spring 项目接入 DeepSeek,分享两种超简单的方式!
数据库·python·spring
Minxinbb23 分钟前
MySQL 中可以通过添加主键来节省磁盘空间吗?(译文)
数据库·mysql·dba
115432031q38 分钟前
基于SpringBoot养老院平台系统功能实现十七
java·前端·后端
(; ̄ェ ̄)。1 小时前
在nodejs中使用RabbitMQ(二)发布订阅
javascript·后端·node.js·rabbitmq
qq_13948428821 小时前
springboot239-springboot在线医疗问答平台(源码+论文+PPT+部署讲解等)
java·数据库·spring boot·后端·spring·maven·intellij-idea
蔚一1 小时前
微服务SpringCloud Alibaba组件nacos教程【详解naocs基础使用、服务中心配置、集群配置,附有案例+示例代码】
java·后端·spring cloud·微服务·架构·intellij-idea·springboot
神仙别闹1 小时前
基于Springmvc+MyBatis+Spring+Bootstrap+EasyUI+Mysql的个人博客系统
java·mysql·ssm
指尖下的技术1 小时前
SpringCloud面试题----.Ribbon和Feign调用服务的区别
spring·spring cloud·ribbon
Hello.Reader2 小时前
将错误消息输出到标准错误流:Rust中的最佳实践
开发语言·后端·rust
Asthenia04122 小时前
深入理解 Java 线程池:参数、拒绝策略与常见问题
后端