Project(7)——收货地址 - 增加

1、分析项目

当需要开发某个项目时,首先,应该分析这个项目中,需要处理哪些种类的数据!例如:用户、商品、商品类别、收藏、订单、购物车、收货地址…

然后,将以上这些种类的数据的处理排个顺序,即先处理哪种数据,后处理哪种数据!通常,应该先处理基础数据,再处理所相关的数据,例如需要先处理商品数据,才可以处理订单数据,如果多种数据之间没有明显的关联,则应该先处理简单的,再处理较难的!

则以上这些数据的处理顺序应该是:用户 > 收货地址 > 商品类别 > 商品 > 收藏 > 购物车 > 订单

当确定了数据处理顺序后,就应该分析某个用户对应的功能有哪些,以“用户”数据为例,相关功能有:注册、登录、修改密码、修改资料、上传头像…

然后,还是需要确定以上功能的开发顺序,通常,遵循 “增 > 查 > 删 > 改” 的顺序,则以上功能的开发顺序应该是:注册 > 登录 > 修改密码 > 修改资料 > 上传头像。

每个功能的开发都应该遵循 创建数据表 > 创建实体类 > 持久层 > 业务层 > 控制器层 > 前端页面

一次只解决一个问题
大问题拆成小问题

2、用户 - 注册 - 创建数据表

3、用户 - 注册 - 创建实体类

4、用户 - 注册 - 持久层

a.规划SQL语句

b.接口与抽象方法

c.配置映射

5、用户 - 注册 - 业务层

业务层的基本定位

a.规划异常

b.接口与抽象方法

c.实现类与重写方法

6、用户 - 注册 - 控制器层

a.处理异常

b.设计请求

c.处理请求

7、用户 - 注册 - 前端页面

……

收货地址 - 分析

关于收货地址的管理,涉及的功能有:增加,查看列表,修改,删除,设为默认。

以上功能的开发顺序应该是:增加 > 查看列表 > 设为默认 > 删除 > 修改。

25、收货地址 - 创建数据表

CREATE TABLE t_address(aid INT PRIMARY KEY AUTO_INCREMENT COMMENT '收货地址aid',uid INT COMMENT '用户uid',name VARCHAR(50) COMMENT '收货人姓名',province_code CHAR(6) COMMENT '省 - 代号',province_name VARCHAR(50) COMMENT '省 - 名称',city_code CHAR(6) COMMENT '市 - 代号',city_name VARCHAR(50) COMMENT '市 - 名称',area_code CHAR(6) COMMENT '区 - 代号',area_name VARCHAR(50) COMMENT '区 - 名称',zip CHAR(6) COMMENT '邮编',address VARCHAR(100) COMMENT '详细地址',phone VARCHAR(20) COMMENT '手机',tel VARCHAR(20) COMMENT '固话',tag VARCHAR(20) COMMENT '地址类型',is_default INT COMMENT '是否默认 0 - 非默认;1 - 默认',is_delete INT COMMENT '是否标记为删除 0 - 未删除;1 - 已删除',created_user VARCHAR(20) COMMENT '创建人',created_time DATETIME COMMENT '创建时间',modified_user VARCHAR(20) COMMENT '修改人',modified_time DATETIME COMMENT '修改时间'
)  DEFAULT CHARSET UTF8;

26、收货地址 - 创建实体类

创建cn.tedu.store.entity.Address继承自BaseEntity

package cn.tedu.store.entity;public class Address extends BaseEntity {private static final long serialVersionUID = 1L;private Integer aid;private Integer uid;private String name;private String provinceCode;private String provinceName;private String cityCode;private String cityName;private String areaCode;private String areaName;private String zip;private String address;private String phone;private String tel;private String tag;private Integer isDefault;// get、set、toString、hashCode&equals// hashCode&equals 只以主键 aid 生成}

添加 get / set 方法,toString,hashCode & equals

27、收货地址 - 增加 - 持久层

a.规划SQL语句

INSERT INTO t_address (除了aid以外的所有字段
) VALUES (匹配的实体类的属性值
);

在增加时,还需要考虑当前增加的收货地址是不是当前用户的默认收货地址,可以设定规则“用户的第1条收货地址是默认的,后续增加的都不是默认的”,则可以查询该用户的收货地址数量,如果为0,则即将增加的就是第1条,就应该是默认的,如果不为0,表示用户已经有一些收货地址数据了,即将增加的不是第1条,则应该是非默认的!所以,需要“查询该用户的收货地址数量”的查询功能,对应的SQL语句应该是:

SELECT count(*) FROM t_address WHERE uid = ?;

b.接口与抽象方法

创建cn.tedu.store.mapper.AddressMapper接口,并添加抽象方法:

/*** 新增收货地址* @param address 地址数据对象* @return 受影响的行数*/Integer insert(Address address);/*** 根据 uid 查询用户的收货地址数量* @param uid 用户 uid* @return 返回收货地址的数量*/Integer countByUid(Integer uid);

c.配置映射

复制得到AddressMapper.xml文件,确定根节点的namespace对应以上接口,然后,配置以上两个抽象方法对应的的映射:

<?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">
<!-- namespace:xml文件对应哪个接口 -->
<mapper namespace="cn.tedu.store.mapper.AddressMapper"><!-- 增加地址信息 --><!-- Integer insert(Address address) --><insert id="insert" useGeneratedKeys="true" keyProperty="aid">INSERT INTO t_address (uid, name, province_code, province_name, city_code, city_name, area_code, area_name,zip, address, phone, tel, tag, is_default, created_user,created_time, modified_user, modified_time) VALUES (#{uid}, #{name}, #{provinceCode}, #{provinceName}, #{cityCode}, #{cityName}, #{areaCode}, #{areaName},#{zip}, #{address}, #{phone}, #{tel}, #{tag}, #{isDefault}, #{createdUser},#{createdTime}, #{modifiedUser}, #{modifiedTime})</insert><!-- 根据用户uid查询用户地址数量 --><!-- Integer countByUid(Integer uid) --><select id="countByUid" resultType="java.lang.Integer">SELECT count(*) FROM t_addressWHERE uid=#{uid}</select></mapper>

src/test/java下创建AddressMapperTests单元测试类,添加测试相关注解,编写并执行以上两个功能的单元测试:

package cn.tedu.store.mapper;import java.util.Date;import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;import cn.tedu.store.entity.Address;@SpringBootTest
public class AddressMapperTests {@Autowiredprivate AddressMapper addressMapper;/*** 测试插入新地址*/@Testpublic void testInsert() {Address address = new Address();address.setUid(62);address.setName("Tom5");address.setProvinceCode("000001");address.setProvinceName("江苏省");address.setPhone("123456");address.setTel("010101");Date now = new Date();address.setCreatedTime(now);address.setCreatedUser("Tom5");Integer rows = addressMapper.insert(address);System.err.println("rows = " + rows);}/*** 测试根据uid查询用户的地址数量*/@Testpublic void testCountByUid() {Integer uid = 62;Integer count = addressMapper.countByUid(uid);System.err.println("count = " + count);}}

28、收货地址 - 增加 - 业务层

业务层的基本定位

a.规划异常

增加收货地址会执行INSERT操作,则可能抛出InsertException

还可以设定规则,当收货地址的数量达到指定值后,不允许再创建,即每个用户最多只可以有 x 条收货地址,如果用户创建的收货地址达到上限后仍尝试继续创建,则可以抛出:AddressCountLimitException

则需要创建cn.tedu.store.service.ex.AddressCountLimitException继承ServiceException

b.接口与抽象方法

创建cn.tedu.store.service.IAddressService业务层接口并添加抽象方法:

/*** 新增收货地址* @param uid 用户 uid* @param username 用户名* @param address 收货地址信息* @throws AddressCountLimitException 收货地址数量超出异常* @throws InsertException 插入数据异常*/void addnew(Address address, Integer uid, String username) throws AddressCountLimitException, InsertException;

并在接口中声明:


// public static final int ADDRESS_MAX_COUNT = 20;
int ADDRESS_MAX_COUNT = 20;  // 接口中可以省略 public static final

c.实现类与重写方法

创建cn.tedu.store.service.impl.AddressServiceImpl业务层实现类,实现以上接口,添加@Service注解,并在类中添加持久层接口对象AddressMapper addressMapper,并重写以上抽象方法:


public class AddressServiceImpl implements IAddressService(){@Autowiredprivate AddressMapper addressMapper;public void addnew(Address address, Integer uid, String username) throws AddressCountLimitException, InsertException{// TODO}
}

在持久层中已经完成的增、删、改、查相关方法,每一个方法都有可能出现在多个业务中!在业务层调用时,可能都需要经过某些验证才可以保证正常使用,而多次调用,不应该多次编写验证的代码或复制这些代码,而应该把验证和持久层的功能封装在业务层中的某个方法中,以便于后续统一使用,例如,在业务层实现类中:


private void insert(Address address){Integer rows = addressMapper.insert(address);if(rows != 1){throw new InsertException("增加收货地址失败!出现未知错误,请联系系统管理员!");}
}private Integer countByUid(Integer uid){Integer count = addressMapper.countByUid(uid);return count;
}

所以,总的看来,在业务层实现类中,会把持久层接口中已有方法都添加一个同名的、私有的方法,并调用持久层对象来实现相关功能,添加相关验证和判断。

后续,在业务层的公有方法(重写的接口中的方法)中,都不会直接调用持久层对象来实现某种操作,而是调用自身的私有方法来实现。

然后,重写接口中的抽象方法:


public void addnew(Address address, Integer uid, String username) throws AddressCountLimitException, InsertException{// 根据参数uid查询当前用户的收货地址数量// 判断收货地址数量是否达到上限值ADDRESS_MAX_COUNT// 是:抛出 AddressCountLimitException// 补全数据:uid// TODO 补全数据:province_name,city_name,area_name// 判断当前用户的收货地址数量是否为0,并决定is_default的值// 补全数据:is_default// 创建当前时间对象// 补全数据:4个日志// 插入收货地址数据
}

具体实现:


package cn.tedu.store.service.impl;import java.util.Date;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import cn.tedu.store.entity.Address;
import cn.tedu.store.mapper.AddressMapper;
import cn.tedu.store.service.IAddressService;
import cn.tedu.store.service.ex.AddressCountLimitException;
import cn.tedu.store.service.ex.InsertException;@Service
public class AddressServiceImpl implements IAddressService {@Autowiredprivate AddressMapper addressMapper;@Overridepublic void addnew(Address address, Integer uid, String username)throws AddressCountLimitException, InsertException {// 根据参数uid查询当前用户的收货地址数量// 判断收货地址数量是否达到上限值ADDRESS_MAX_COUNT// 是:抛出 AddressCountLimitExceptionInteger count = countByUid(uid);if(count >= ADDRESS_MAX_COUNT) {throw new AddressCountLimitException("增加收货地址失败!收货地址数量已达上限!"+ "最多允许创建" + ADDRESS_MAX_COUNT + "条,已经创建" + count + "条。");}// 补全数据:uidaddress.setUid(uid);// TODO 补全数据:province_name,city_name,area_name// 判断当前用户的收货地址数量是否为0,并决定is_default的值// 补全数据:is_defaultInteger isDefault = count == 0 ? 1 : 0;address.setIsDefault(isDefault);// 创建当前时间对象// 补全数据:4个日志Date now = new Date();address.setCreatedUser(username);address.setCreatedTime(now);address.setModifiedUser(username);address.setModifiedTime(now);// 插入收货地址数据insert(address);}/*** 新增收货地址* @param address 地址信息* @throws InsertException 插入异常*/private void insert(Address address) throws InsertException{Integer rows = addressMapper.insert(address);if(rows != 1) {throw new InsertException("增加收货地址失败!出现未知错误,请联系系统管理员!");}}/*** 通过用户uid查询地址数量* @param uid 用户uid* @return 地址数量*/private Integer countByUid(Integer uid) {return addressMapper.countByUid(uid);}}

最后,在src/test/java下创建cn.tedu.store.service.AddressServiceTests测试类,编写并执行单元测试:


/*** 收货地址数据业务层测试类* @author DELL**/
@SpringBootTest
public class AddressServiceTests {@Autowiredprivate IAddressService service;/*** 测试增加新的收货地址*/@Testpublic void testAddNew() {try {Integer uid = 6;String username = "管理员Gin6";Address address = new Address();address.setPhone("666666");address.setProvinceCode("Gin666");address.setProvinceName("Gin省6");address.setTel("Gin666");address.setName("Gin6");service.addnew(uid, username, address);System.err.println("OK");}catch(ServiceException e) {System.err.println(e.getClass().getName());System.err.println(e.getMessage());}}}

29、收货地址 - 增加 - 控制器层

a.处理异常

BaseController 中处理AddressCountLimitException异常

b.设计请求


请求路径:/addresses/addnew
请求参数:Address address, HttpSession session
请求类型:POST
响应数据:JsonResult<Void>

c.处理请求

创建cn.tedu.store.controller.AddressController控制器类,继承自BaseController,添加@RestController注解和@RequestMapping("addresses")注解,并在类中添加业务层接口对象IAddressService service


@RestController
@RequestMapping("addresses")
public class AddressController extends BaseController {@AutoWiredprivate IAddressService service;}

然后,在类中添加处理请求的方法:


@RequestMapping("addnew")
public JsonResult<Void> addnew(Address address, HttpSession session){// 从session中获取uid和username// 调用业务层对象执行增加// 响应成功
}

具体实现:


/*** 收货地址业务层数据控制器类* @author DELL**/
@RestController
@RequestMapping("addresses")
public class AddressController extends BaseController {@Autowiredprivate IAddressService service;@RequestMapping("addnew")public JsonResult<Void> addnew(Address address, HttpSession session){// 通过 session 获取 uid、usernameInteger uid = getUidFromSession(session);String username = getUsernameFromSession(session);// 调用业务层对象执行增加操作service.addnew(uid, username, address);// 返回结果return new JsonResult<Void>(SUCCESS);    }}

完成后,打开浏览器,先登录,然后可以通过http://localhost:8080/addresses/addnew?name=Bourbon&phone=Bourbon666&provinceCode=666666进行验证

30、收货地址 - 增加 - 前端页面

省市区的<select>标签内暂不添加name属性

<script type="text/javascript">
$(document).ready(function(){$("#btn-addnew").click(function(){$.ajax({"url" : "/addresses/addnew","data" : $("#form-addnew").serialize(),"type" : "post","dataType" : "json","success" : function(json){if(json.state == 2000){alert("增加成功!");}else{alert(json.message);}},"error" : function(){alert("您的登录信息已过期!请重新登录!");}});});
});
</script>

Project(7)——收货地址 - 增加相关推荐

  1. 电商项目之收货地址理解

    1.收货地址增加(请求参数:HttpSession session,Shipping shipping) a.获取session中当前登陆用户 b.将用户id和地址进行关联,防止横向越权,没有用户id ...

  2. 39 Flutter仿京东商城项目 收货地址列表、增加 修改收货地址布局、弹出省市区选择器...

    加群452892873 下载对应39课文件,运行方法,建好项目,直接替换lib目录 pubspec.yaml city_pickers: ^0.1.22 AddressAdd.dart import ...

  3. ecshop“发货查询”中加入收货人、收货地址、发货时间、配送方式

    1.修改 index.php 的 index_get_invoice_query() 函数部分 将 $sql = 'SELECT o.order_sn, o.invoice_no, s.shippin ...

  4. 云炬Android开发笔记 14 个人中心、图片裁剪、图片上传、收货地址、消息推送、权限管理等功能开发与一键式封装

    阅读目录 0.优化 1.个人中心页面的布局 2. 订单列表逻辑梳理与实现 3. 个人信息的更新实现 3.1 个人信息页面的布局 3.3 数据的转化  5.3 图片库中图片选择事件的处理  5.4 相机 ...

  5. 微信支付开发(6) 收货地址共享接口

    关键字:微信支付 收货地址共享 作者:方倍工作室 原文: http://www.cnblogs.com/txw1958/p/weixin-editAddress.html 请看新版教程  微信支付开发 ...

  6. jssdk 获取微信收货地址_微信收货地址共享开发接口讲解

    写在前面的话:微信开发者文档写的比较清楚,也不容易出错,可是偏偏收货地址共享那儿写的比较绕,同时也会有很多坑,这里总结一下. ======正文开始====== 微信收货地址共享开发接口基本使用场景是: ...

  7. android 京东收货地址,手机京东商城怎么添加收货地址?

    想必有很多人都使用过手机京东购物,购物就需要一个收货地址,在手机京东上,具体怎么添加一个收货地址呢?或者说,由于某些特殊的原因,比如帮别人买东西,或者自己不在原来的地方住了,需要修改原来的收货地址,这 ...

  8. 新零售系统mysql设计(会员等级表 客户表 收货地址表)二次修改

    作者:陈业贵 华为云享专家 51cto(专家博主 明日之星 TOP红人) 阿里云专家博主 文章目录 sql 会员等级表 数据 客户表 数据 收货地址表 数据 会员等级表(解析) 字段解析: 类型大小 ...

  9. html收货地址填写怎么做才合理_拼多多发货地不在同一个地方有影响吗?怎么设置发货地址?...

    卖家在拼多多开店之后,需要对商品进行基本设置.其中就涉及到了发货地址,卖家需要把发货的地址设置好,但是有的卖家有不同的发货地址,那么拼多多发货地不在同一个地方有影响吗? 拼多多发货地不在同一个地方是有 ...

  10. html收货地址填写怎么做才合理_匀思电商:拼多多卖家设置发货地址有哪些注意事项?...

    拼多多卖家在开店之后,需要对店铺的商品进行各种基本设置,比如设置发货地址,卖家会遇到自己有好几个不同的发货地址需要怎么设置呢?不同的发货地址对拼多多店铺有影响那?今天匀思电商拼多多网店培训小编就来给大 ...

最新文章

  1. iPhone13下周三发布,提前看剧透:刘海缩小、120Hz高刷屏、Mini又续一年…
  2. Java的Socket通信(多Clients/Server模型)
  3. PMcaff-干货| 内容营销可不仅仅是点击量而已
  4. ACM北大暑期课培训第六天
  5. windows 系统nginx做反向代理实例
  6. java 认证和授权_SpringSecurity一:认证和授权
  7. java中menu用法_Android Menu用法全面讲解
  8. 光流(四)--Kanade-Lucas-Tomasi(KLT)目标跟踪
  9. html文本框能不能粘贴图片,[免费开源]wangEditor富文本框解决方案,粘贴自动上传图片(截图上传神器啊!),可嵌入视频,vue和jquery的BS框架都能用,不能用在cs哦!...
  10. “仿宋_GB2312、楷体_GB2312、方正小标宋简体”的下载和安装方式【实操】
  11. GBASE 8s DB-Access入门
  12. ice php 5.6.32,PHP通过ice调用python程序
  13. jQuery下载和安装详细教程
  14. 关于图片的多标签分类(1)
  15. 真子集的三种表示方法的区别(⊂与⫋ 与⊊)
  16. 香农编码的C++实现及求平均码长和编码效率
  17. ORA-ALL Oracle连接报错
  18. 祖国啊,心中最美的图腾
  19. 理论+实操:tomcat部署及优化————理论讲解
  20. Silverlight 4.0 Demo

热门文章

  1. 使用 VBScript 判断是否安装了雅虎助手的方法
  2. Windows cmd下载文件
  3. CSAPP,拆弹到一点!!!
  4. 003-电脑软件系统保护
  5. 利用eclipse自定义模板创建日志打印模板
  6. 电子商务B2C网店购物系统走势
  7. html5 右侧客服代码,js实现浮动在网页右侧的简洁QQ在线客服代码
  8. 幻想三国android官方版,幻想三国ol官方版
  9. kX3552 + HiFi级播放器 + wifi无线保真= 实战HiFi音乐娱乐欣赏
  10. 关于python变量使用下列说法中错误的是_关于Python中的全局变量和局部变量,以下描述中错误的是...