SpringBoot项目--电脑商城【新增收货地址】
1.新增收货地址
t_address
CREATE TABLE t_address (aid INT AUTO_INCREMENT COMMENT '收货地址id',uid INT COMMENT '归属的用户id',`name` VARCHAR(20) COMMENT '收货人姓名',province_name VARCHAR(15) COMMENT '省-名称',province_code CHAR(6) COMMENT '省-行政代号',city_name VARCHAR(15) COMMENT '市-名称',city_code CHAR(6) COMMENT '市-行政代号',area_name VARCHAR(15) COMMENT '区-名称',area_code CHAR(6) COMMENT '区-行政代号',zip CHAR(6) COMMENT '邮政编码',address VARCHAR(50) COMMENT '详细地址',phone VARCHAR(20) COMMENT '手机',tel VARCHAR(20) COMMENT '固话',tag VARCHAR(6) COMMENT '标签',is_default INT COMMENT '是否默认:0-不默认,1-默认',created_user VARCHAR(20) COMMENT '创建人',created_time DATETIME COMMENT '创建时间',modified_user VARCHAR(20) COMMENT '修改人',modified_time DATETIME COMMENT '修改时间',PRIMARY KEY (aid)
) ENGINE=INNODB DEFAULT CHARSET=utf8;
注意name是关键字,所以需要用``
2.创建收货地址的实体类
在entity包下创建实体类Address继承BaseEntity类
/*** 收货地址的实体类*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Address extends BaseEntity {private Integer aid;//收货地址idprivate Integer uid;//归属用户idprivate String name;//收货人姓名private String provinceName;//省private String provinceCode;//省行政代号private String cityName;//市名private String cityCode;//市行政代号private String areaName;//区名private String areaCode;//区行政代号private String zip;//邮政编码private String address;//详细地址private String phone;//手机private String tel;//固话private String tag;//标签private Integer isDefault;//是否默认 0-不默认,1-默认
}
3.持久层[Mapper]
1 各功能的开发顺序
当前收货地址功能模块:
- 第一个页面:列表的展示,修改,删除,设置默认
- 第二个页面:新增收货地址
开发顺序:新增收货地址->列表的展示->设置默认收货地址->删除收货地址->修改收货地址
2 需要规划要执行的sql语句
1.新增收货地址对应的是插入语句:
insert into t_address (aid以外的所有字段) values (字段值)
2. 大部分平台都会规定一个用户的收货地址数量,这里规定最多20个.那么在插入用户新的地址之前就要先做查询操作.如果查询到的是刚好20,这并不是一个java语法的异常,可以认为是业务控制的异常,这个异常随后在service抛,在controller捕获
select count(*) from t_address where uid=?
2.设置接口和抽象方法
创建接口AddressMapper,在这个接口中定义上面两个SQL语句抽象方法定义
//收货地址持久层接口
public interface AddressMapper {/*** 插入用户的收货地址数据** @param address 收货地址* @return 受影响的行数*/Integer insertAddress(Address address);/*** 获取收货地址的数量(不能超过20),根据用户的uid** @param uid 用户uid* @return 收货地址数量*/Integer countAddress(Integer uid);
}
3.编写映射
1.在mapper标签中配置Address类属性与数据库中表的字段映射
<resultMap id="AddressEntityMap" type="com.example.mycomputerstore.entity.Address"><id column="aid" property="aid"/><result column="province_code" property="provinceCode"/><result column="province_name" property="provinceName"/><result column="city_code" property="cityCode"/><result column="city_name" property="cityName"/><result column="area_code" property="areaCode"/><result column="area_name" property="areaName"/><result column="is_default" property="isDefault"/><result column="created_user" property="createdUser"/><result column="created_time" property="createdTime"/><result column="modified_user" property="modifiedUser"/><result column="modified_time" property="modifiedTime"/></resultMap>
判断该映射是否配置成功:按着ctrl并点击type="com.cy.store.entity.Address"中的Address,如果能跳转到Address类说明映射成功
2.在AddressMapper.xml中配置以上两个抽象方法的映射
<insert id = "insertAddress" useGeneratedKeys="true" keyProperty="aid">INSERT INTO t_address (uid, name, province_name, province_code, city_name, city_code, area_name, area_code, zip,address, phone, tel, tag, is_default, created_user, created_time, modified_user, modified_time)VALUES (#{uid}, #{name}, #{provinceName}, #{provinceCode}, #{cityName}, #{cityCode},#{areaName}, #{areaCode}, #{zip}, #{address}, #{phone}, #{tel}, #{tag},#{isDefault}, #{createdUser},#{createdTime}, #{modifiedUser}, #{modifiedTime})</insert><select id="countAddress" resultType="java.lang.Integer">SELECT count(*) FROM t_address WHERE uid = #{uid}</select>
4.单元测试
@SpringBootTest
@RunWith(SpringRunner.class)
public class AddressMapperTests {@Autowiredprivate AddressMapper addressMapper;@Testpublic void insert() {Address address = new Address();address.setUid(11);address.setPhone("133336");address.setName("女朋友");addressMapper.insert(address);}@Testpublic void countByUid() {Integer count = addressMapper.countByUid(11);System.out.println(count);}
}
4.业务层[service]
1. 规划异常
- 插入数据时用户不存在(被管理员误删等等),抛UsernameNotFoundException异常(已经有了,不需要重复创建)
- 当用户插入的地址是第一条时,需要将当前地址作为默认收货地址
- 实现办法:如果查询到统计总数为0则将当前地址的is_default值设置为1
- 如果查询的结果>=20,这时需要抛出业务控制的异常AddressCountLimitException
/**收货地址总数超出限制的异常(20条)*/
public class AddressCountLimitException extends ServiceException {/**重写ServiceException的所有构造方法*/
}
-
插入数据时产生未知的异常InsertException(已经有了,不需要重复创建)
2 设计接口和抽象方法及实现
1.创建一个IAddressService接口,在接口中定义业务的抽象方法
因为mapper层接口该功能模块定义了两个抽象方法,所以就要在service层接口该功能模块也定义两个抽象方法?不是这样的,要看mapper层的这两个方法是依赖关系还是独立关系,如果某一个抽象方法依赖于另一个抽象方法,那就需要在业务层将这两个方法整合到一个方法中.一句话来说就是:一个功能模块可能需要多条sql语句
//收货地址业务层接口
public interface IAddressService {/***这三个参数的由来:* 1.首先肯定要有address* 2.业务层需要根据uid查询该用户收货地址总数及新建地址时给字段uid赋值* 但新建收货地址的表单中并没有哪个控件让输入用户uid,所以需要控制层将uid传给业务层* 3.业务层在创建/修改收货地址时需要同时修改数据库中创建人/修改人的字段* 但新建收货地址的表单中并没有哪个控件让输入用户username,所以需要控制层将username传给业务层* 注意:> 可以用HttpSession session代替Integer uid, String username,但* 这样写的话就需要把BaseController类下获取uid,username的方法重新封装到一个* 类中并让IAddressServiceImp实现类继承该类,这样就需要微调一下代码逻辑,太麻* 烦,并且,最好每一层只处理该层需要做的事情,session对象是控制层传递的,所以就* 把session对象定义封装在控制层中,不需要在业务层中额外处理以降低耦合*/void addAddress(Integer uid, String username, Address address);
}
方法addNewAddress中三个参数的由来:
- 首先肯定要有address
- 业务层需要根据uid查询该用户收货地址总数及新建地址时给字段uid赋值
- 但新建收货地址的表单中并没有哪个控件让输入用户uid,所以需要控制层将uid传给业务层并在业务层封装到address对象中
- 业务层在创建/修改收货地址时需要同时修改数据库中创建人/修改人的字段
- 但新建收货地址的表单中并没有哪个控件让输入用户username,所以需要控制层将username传给业务层并在业务层封装到address对象中
可以用HttpSession session代替Integer uid, String username,但这样写的话就需要把BaseController类下获取uid,username的方法重新封装到一个类中并让AddressServiceImpl实现类继承该类,这样就需要微调一下代码逻辑,太麻烦,并且,最好每一层只处理该层需要做的事情,session对象是控制层传递的,所以就把session对象定义封装在控制层中,不需要在业务层中额外处理,这样可以降低耦合
2.创建一个AddressServiceImpl类实现接口中抽象方法
@Service
public class IAddressServiceImpl implements IAddressService {@Autowiredprivate AddressMapper addressMapper;//在添加用户的收货地址的业务层依赖于DistrictService的业务层接口@Autowiredprivate IDistrictService districtService;/*** 为了方便日后修改最大收货地址数量,可以在配置文件* application.properties中定义user.address.max-count=20*/@Value("${user.address.max-count}")private Integer MaxAddress ;@Overridepublic void addAddress(Integer uid, String username, Address address) {//查询收货地址信息是否大于20Integer count = addressMapper.countAddress(uid);if(count >= MaxAddress) {throw new AddressCountLimitException("收货地址不能超过20条");}//设置信息address.setUid(uid);Integer isDelete = count == 0 ? 1 : 0;//1表示默认收货地址,0反之address.setIsDefault(isDelete);address.setCreatedTime(new Date());address.setCreatedUser(username);address.setModifiedTime(new Date());address.setModifiedUser(username);//对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);//插入收货地址Integer row = addressMapper.insertAddress(address);if(row != 1) {throw new InsertException("未知错误 在 新建收货地址");}}
}
别忘了在配置文件application.properties中定义user.address.max-count=20
3 单元测试
在test下的service文件夹下创建AddressServiceTests测试类
@SpringBootTest
@RunWith(SpringRunner.class)
public class AddressServiceTests {@Autowiredprivate IAddressService addressService;@Testpublic void addNewAddress() {Address address = new Address();address.setPhone("175726");address.setName("男朋友");addressService.addNewAddress(11,"mxy",address);}
}
5.控制层[Controller]
1 处理异常
义务层抛出了收货地址总数超出上限的异常,在BaseController中进行捕获处理
else if (e instanceof AddressCountLimitException) {result.setState(4003);result.setMessage("用户的收货地址超出上限的异常");
}
2 设计请求
- /addresses/add_new_address
- post
- Address address,HttpSession session
- JsonResult<Void>
3. 处理请求
在controller包下创建AddressController并继承BaseController,该类用来处理用户收货地址的请求和响应
/*** 用户收货地址*/
@RestController
@RequestMapping("/address")
public class AddressController extends BaseController {@Autowiredprivate IAddressService addressService;/*** 新增用户收货地址** @param address* @param session:这里使用session 是为了获取用户的uid和username* @return*/@PostMapping("/add_new_address")public JsonResult<Void> addAddress(Address address, HttpSession session) {//先获取用户uid和usernameInteger uid = getuidFromSession(session);String username = getUsernameFromSession(session);addressService.addAddress(uid, username, address);return new JsonResult<>(OK);}
}
6.前端页面
$("#btn-add-new-address").click(function (){$.ajax({url:"/address/add_new_address",type:"POST",data:$("#form-add-new-address").serialize(),dataType:"JSON",success(e){if(e.state==200){alert("新增收货地址成功")}else{alert("新增收货地址失败")}},error(xhr){alert("新增收货地址产生未知的异常"+xhr.status)}})})
相关文章:
SpringBoot项目--电脑商城【新增收货地址】
1.新增收货地址 t_address CREATE TABLE t_address (aid INT AUTO_INCREMENT COMMENT 收货地址id,uid INT COMMENT 归属的用户id,name VARCHAR(20) COMMENT 收货人姓名,province_name VARCHAR(15) COMMENT 省-名称,province_code CHAR(6) COMMENT 省-行政代号,city_name VARC…...
[HNCTF 2022 Week1]——Web方向 详细Writeup
Week1 [HNCTF 2022 Week1]2048 f12查看源代码 可以看出游戏的分数是score 修改score的值 得到flag [HNCTF 2022 Week1]Interesting_include 得到源码 <?php //WEB手要懂得搜索 //flag in ./flag.phpif(isset($_GET[filter])){$file $_GET[filter];if(!preg_match(&qu…...
3dmax vray如何创建真实的灯光?3dmax vray 室内照明教程
为什么良好的照明很重要? 通过仔细操纵光源并利用 V-Ray 的功能,您将解锁制作超越普通渲染的能力,让观众着迷。每个阴影和每个高光都有一个目的 - 通过注意掌握照明,您的渲染将变得栩栩如生,并为您的室内设计赋予独特…...
如何在本地使用Docker搭建和运行Kubernetes集群
文章目录 1. 准备环境2. 安装Minikube3. 启动Minikube集群4. 验证集群5. 部署一个示例应用创建一个Deployment部署应用检查部署 6. 访问应用创建一个Service部署Service获取Service的访问地址 7. 清理资源结论 🎈个人主页:程序员 小侯 🎐CSDN…...
每天几道Java面试题(第二天)
目录 第二幕、第一场)公司前台第二场)公司卫生间 友情提醒 背面试题很枯燥,加入一些戏剧场景故事人物来加深记忆。PS:点击文章目录可直接跳转到文章指定位置。 第二幕、 第一场)公司前台 【接待人员埃斯卡莱罗,面试…...
Java | 线程的生命周期和安全
不爱生姜不吃醋⭐️ 如果本文有什么错误的话欢迎在评论区中指正 与其明天开始,不如现在行动! 🌴线程的生命周期 sleep方法会让线程睡眠,睡眠时间到了之后,立马就会执行下面的代码吗? 答:不会&am…...
Bootstrap的一些主要作用
Bootstrap是一个流行的前端开发框架,它主要用于快速构建响应式、移动优先的网站和网络应用程序。它提供了一套CSS样式和JavaScript插件,帮助开发者轻松地创建漂亮、一致和交互丰富的用户界面。 以下是Bootstrap的一些主要作用: 响应式布局&a…...
网络编程套接字 | UDP套接字
前面的文章中我们叙述了网络编程套接字的一些预备知识点,从本文开始我们就将开始UDP套接字的编写。本文中的服务端与客户端都是在阿里云的云服务器进行编写与测试的。 udp_v1 在v1的版本中我们先来使用一下前面讲过得一些接口,简单的构建一个udp服务器…...
网络层IP协议
目录 前言 1.如何理解IP协议 2.IP协议格式 3.网段划分 4.特殊的IP地址 5.IP地址的数量限制 6.私有IP地址和公网IP地址 7.路由 总结 前言 在前面的文章中介绍了关于传输层常用的两个协议,UDP协议和TCP协议,当数据经过传输层之后,进入网…...
C++ Day4
目录 仿照string类,完成myString 类 思维导图 仿照string类,完成myString 类 #include <iostream> #include<cstring>using namespace std;class myString {private:char *str; //记录c风格的字符串int size; //记录…...
2024字节跳动校招面试真题汇总及其解答(二)
1. 微服务的好处,划分原则 微服务是软件架构的一种模式,它将应用程序划分为一系列小型、独立的服务。每个服务都提供一个单独的功能,并使用轻量级的接口相互通信。 微服务架构具有以下好处: 灵活性:微服务可以独立部署、扩展和更新,这使得它们能够随着业务需求的变化而…...
SpringBoot集成websocket(4)|(使用okhttp3实现websocket)
SpringBoot集成websocket(4)|(使用okhttp3实现websocket) 文章目录 SpringBoot集成websocket(4)|(使用okhttp3实现websocket)[TOC] 前言一、实现步骤1.实现步骤 二、websocket服务代…...
【MySQL】JDBC编程
MySQL-JDBC编程 文章目录 MySQL-JDBC编程Java的数据库编程JDBC工作原理JDBC的使用驱动包下载导入代码编写 Java的数据库编程 JDBC,即Java Database Connectivity,java数据库连接。是一种用于执行SQL语句的Java API,它是 Java中的数据库连接…...
数据结构——二叉树线索化遍历(前中后序遍历)
二叉树线索化 线索化概念: 为什么要转换为线索化 二叉树线索化是一种将普通二叉树转换为具有特殊线索(指向前驱和后继节点)的二叉树的过程。这种线索化的目的是为了提高对二叉树的遍历效率,特别是在不使用递归或栈的情况下进行遍历…...
GO语言网络编程(并发编程)Channel
GO语言网络编程(并发编程)Channel 1、Channel 1.1.1 Channel 单纯地将函数并发执行是没有意义的。函数与函数间需要交换数据才能体现并发执行函数的意义。 虽然可以使用共享内存进行数据交换,但是共享内存在不同的goroutine中容易发生竞态…...
c++day3
stack.h #ifndef STACK_H #define STACK_H #include <iostream> //#define max 128 using namespace std; class Stack { private:int* stack;//数组指针int top;//栈顶元素int max;//栈容量 public://构造函数Stack();//析构函数~Stack();//定义拷贝构造函数Stack(cons…...
算法通过村第六关-树青铜笔记|中序后序
文章目录 前言1. 树的常见概念2. 树的性质3. 树的定义与存储方式4. 树的遍历方式5. 通过序列构建二叉树5.1 前中序列恢复二叉树5.2 中后序列恢复二叉树 总结 前言 提示:瑞秋是个小甜心,她只喜欢被爱,不懂的去爱人。 --几米《你们 我们 他们》…...
C++动态内存管理+模板
💓博主个人主页:不是笨小孩👀 ⏩专栏分类:数据结构与算法👀 C👀 刷题专栏👀 C语言👀 🚚代码仓库:笨小孩的代码库👀 ⏩社区:不是笨小孩👀 🌹欢迎大…...
SQL 注入漏洞攻击
文章目录 1. 介绍2. 无密码登录3. 无用户名无密码登录4. 合并表获取用户名密码 1. 介绍 假设你用自己的用户名和密码登录了一个付费网站,网站服务器就会查询一下你是不是 VIP 用户,而用户数据都是放在数据库中的,服务器通常都会向数据库进行查…...
一篇五分生信临床模型预测文章代码复现——Figure 10.机制及肿瘤免疫浸润(四)
之前讲过临床模型预测的专栏,但那只是基础版本,下面我们以自噬相关基因为例子,模仿一篇五分文章,将图和代码复现出来,学会本专栏课程,可以具备发一篇五分左右文章的水平: 本专栏目录如下: Figure 1:差异表达基因及预后基因筛选(图片仅供参考) Figure 2. 生存分析,…...
Transformer 模型中常见的特殊符号
Transformer 模型中常见的特殊符号 通过代码一起理解一下 Transformer 模型中常见的特殊符号, 示例代码, special_tokens{unk_token: [UNK], sep_token: [SEP], pad_token: [PAD], cls_token: [CLS], mask_token: [MASK]}这段代码是定义了一个字典spec…...
C# halcon SubImage的使用
SubImage(HObject imageMinuend, HObject imageSubtrahend, out HObject imageSub, HTuple mult, HTuple add) 公式 x1imageMinuend此行此列的灰度 x2imageSubtrahend此行此列的灰度 则imageSub此行此列的灰度为;(x1-x2)*multadd 溢出裁剪 以byte图为例,小于0&a…...
每天几道Java面试题:异常机制(第三天)
目录 第三幕、第一场)异常机制面试题 友情提醒 背面试题很枯燥,加入一些戏剧场景故事人物来加深记忆。PS:点击文章目录可直接跳转到文章指定位置。 第三幕、 第一场)异常机制面试题 【面试官老吉,面试官潘安,面试者…...
Linux 中的 chattr 命令及示例
Linux 中的chattr命令是一个文件系统命令,用于更改目录中文件的属性。该命令的主要用途是使多个文件无法被超级用户以外的用户更改。管理员表示,众所周知,Linux 是一个多用户操作系统,一个用户有可能删除另一个用户非常关心的文件。为了避免这种情况,Linux 提供了“ chatt…...
LeetCode 2605. Form Smallest Number From Two Digit Arrays【数组,哈希表,枚举;位运算】1241
本文属于「征服LeetCode」系列文章之一,这一系列正式开始于2021/08/12。由于LeetCode上部分题目有锁,本系列将至少持续到刷完所有无锁题之日为止;由于LeetCode还在不断地创建新题,本系列的终止日期可能是永远。在这一系列刷题文章…...
VoxWeekly|The Sandbox 生态周报|20230904
欢迎来到由 The Sandbox 发布的《VoxWeekly》。我们会在每周发布,对上一周 The Sandbox 生态系统所发生的事情进行总结。 如果你喜欢我们内容,欢迎与朋友和家人分享。请订阅我们的 Medium 、关注我们的 Twitter,并加入 Discord 社区…...
antd setFieldsValue 设置初始值无效AutoComplete 设置默认值失败
antd form setFieldsValue 设置初始值无效 解决方案 setTimeout(()>{setFieldsValue(values)},100)antd AutoComplete 设置默认值失败 defaultValue 设置无效 解决方案 设置value,搭配onChange来设置修改...
01-Redis核心数据结构与高性能原理
上一篇: 1.Redis安装 下载地址:http://redis.io/download 安装步骤: # 安装gcc yum install gcc# 把下载好的redis-5.0.3.tar.gz放在/usr/local文件夹下,并解压 wget http://download.redis.io/releases/redis-5.0.3.tar.gz…...
预防Dos攻击
Dos----拒绝服务攻击,一般是构造特殊的输入,使得后台的处理耗时远超正常水平,随着请求越来越多,后台服务越发疲于奔命,最后因资源耗尽,无法再接受新的请求,最终造成拒绝服务的效果。 特殊输入例…...
ant design的文档真的是一坨屎
很多基础设置 高傲的写都不写 要自己去index.d.ts里查 这就算了,为什么还有错的。。。。。 即使因为版本号而不同,起码把差异说明一下吧,直接丢个错的什么意思,。。。。。。。。 没点子功夫还真用不了 文档 进度条 Progress -…...
网站建设全视频教程下载/近期重大新闻
0基本数据类型包装类1intInteger2charCharacter3shortShort4longLong5floatFloat6doubleDouble7booleanBoolean8byteByte(1)Integer,Character,Short,Long,Float,Double都属于Number类的子类(2)Boolean和Byte都直接属于Object的子类Number类的方法 byteValue() intValue() floa…...
海南城乡与建设厅网站/seo入门黑帽培训教程
干货:必须要有反馈,不断调整,多读书,多些笔记。 解释:不练习你以为你能掌握?笑话,只有自己根据一个个小目标不断的敲,运行,给予你反馈,这样才会真的进步。 纸…...
网站建设费用明细报价/凡科建站下载
2023年司法考试分为主观题和客观题,报名需要具备全日制普通高等学校法学类本科学历并获得学士及以上学位,非法学毕业也可以考。 司法考试2023年报考条件 符合以下条件人员,可报名参加司法考试: 1.具有中华人民共和国国籍; 2.坚决拥…...
那些做环保网站的好/网站建设网络推广平台
我们会骂 12306 的网站界面挫,效果差,速度慢,回头看看自己写的代码,是不是也一样的狗血!在前端,很多看似简单的东西,内藏无数玄机。本文将以一个小小的登录框为入口,谈一谈如何完善自…...
wordpress无法修改主页/网络营销是做什么的
4.2.2 Intermediate Sensors and Devices 中间传感器和设备是: •分光光度计 •安培 - 小时 Spectrophotometers 分光光度计是最常见的光谱传感器。这些仪器具有在190-1100 nm的大光谱范围内工作并使用浓度单位(如每升克数)的优势。最常见的分…...
网页制作实践 做网站/互联网营销师培训内容
借鉴php安装错误 2013-01-04 19:16:49分类:系统运维环境:centos X64 最小化安装php版本:php-5.4.3安装前.先安装些软件和库文件yum install -y gcc gcc-c make zlib zlib-devel pcre pcre-devel libjpeg libjpeg-devel libpng libpng-devel…...