当前位置:   article > 正文

Java十天上手做一个自己的web商城笔记-新增收获地址(8)_收货地址如何使用java实现

收货地址如何使用java实现

 该系列博客主要记录笔者的开发过程,参考B站系列视频:【SpringBoot项目实战完整版】SpringBoot+MyBatis+MySQL电脑商城项目实战_哔哩哔哩_bilibili

所用的一些版本信息:

IDEA开发、JDK1.8版本以上、maven3.61版本以上,springboot,DataGrip管理数据库

新增收获地址:

0 前置准备

0.1 功能规划

当前收货地址功能模块:列表的展示、修改、删除、设置默认、新增地址。

开发顺序:新增收获地址,列表展示,设置默认收获地址、删除收获地址、修改收获地址。

0.2 创建实体类

在 store\src\main\java\com\cy\store\entity 目录下创建实体类:

  1. package com.cy.store.entity;
  2. import java.io.Serializable;
  3. /** 收货地址数据的实体类 */
  4. public class Address extends BaseEntity implements Serializable {
  5. private Integer aid;
  6. private Integer uid;
  7. private String name;
  8. private String provinceName;
  9. private String provinceCode;
  10. private String cityName;
  11. private String cityCode;
  12. private String areaName;
  13. private String areaCode;
  14. private String zip;
  15. private String address;
  16. private String phone;
  17. private String tel;
  18. private String tag;
  19. private Integer isDefault;
  20. public Integer getAid() {
  21. return aid;
  22. }
  23. public void setAid(Integer aid) {
  24. this.aid = aid;
  25. }
  26. public Integer getUid() {
  27. return uid;
  28. }
  29. public void setUid(Integer uid) {
  30. this.uid = uid;
  31. }
  32. public String getName() {
  33. return name;
  34. }
  35. public void setName(String name) {
  36. this.name = name;
  37. }
  38. public String getProvinceName() {
  39. return provinceName;
  40. }
  41. public void setProvinceName(String provinceName) {
  42. this.provinceName = provinceName;
  43. }
  44. public String getProvinceCode() {
  45. return provinceCode;
  46. }
  47. public void setProvinceCode(String provinceCode) {
  48. this.provinceCode = provinceCode;
  49. }
  50. public String getCityName() {
  51. return cityName;
  52. }
  53. public void setCityName(String cityName) {
  54. this.cityName = cityName;
  55. }
  56. public String getCityCode() {
  57. return cityCode;
  58. }
  59. public void setCityCode(String cityCode) {
  60. this.cityCode = cityCode;
  61. }
  62. public String getAreaName() {
  63. return areaName;
  64. }
  65. public void setAreaName(String areaName) {
  66. this.areaName = areaName;
  67. }
  68. public String getAreaCode() {
  69. return areaCode;
  70. }
  71. public void setAreaCode(String areaCode) {
  72. this.areaCode = areaCode;
  73. }
  74. public String getZip() {
  75. return zip;
  76. }
  77. public void setZip(String zip) {
  78. this.zip = zip;
  79. }
  80. public String getAddress() {
  81. return address;
  82. }
  83. public void setAddress(String address) {
  84. this.address = address;
  85. }
  86. public String getPhone() {
  87. return phone;
  88. }
  89. public void setPhone(String phone) {
  90. this.phone = phone;
  91. }
  92. public String getTel() {
  93. return tel;
  94. }
  95. public void setTel(String tel) {
  96. this.tel = tel;
  97. }
  98. public String getTag() {
  99. return tag;
  100. }
  101. public void setTag(String tag) {
  102. this.tag = tag;
  103. }
  104. public Integer getIsDefault() {
  105. return isDefault;
  106. }
  107. public void setIsDefault(Integer isDefault) {
  108. this.isDefault = isDefault;
  109. }
  110. @Override
  111. public boolean equals(Object o) {
  112. if (this == o) return true;
  113. if (!(o instanceof Address)) return false;
  114. Address address1 = (Address) o;
  115. if (getAid() != null ? !getAid().equals(address1.getAid()) : address1.getAid() != null) return false;
  116. if (getUid() != null ? !getUid().equals(address1.getUid()) : address1.getUid() != null) return false;
  117. if (getName() != null ? !getName().equals(address1.getName()) : address1.getName() != null) return false;
  118. if (getProvinceName() != null ? !getProvinceName().equals(address1.getProvinceName()) : address1.getProvinceName() != null)
  119. return false;
  120. if (getProvinceCode() != null ? !getProvinceCode().equals(address1.getProvinceCode()) : address1.getProvinceCode() != null)
  121. return false;
  122. if (getCityName() != null ? !getCityName().equals(address1.getCityName()) : address1.getCityName() != null)
  123. return false;
  124. if (getCityCode() != null ? !getCityCode().equals(address1.getCityCode()) : address1.getCityCode() != null)
  125. return false;
  126. if (getAreaName() != null ? !getAreaName().equals(address1.getAreaName()) : address1.getAreaName() != null)
  127. return false;
  128. if (getAreaCode() != null ? !getAreaCode().equals(address1.getAreaCode()) : address1.getAreaCode() != null)
  129. return false;
  130. if (getZip() != null ? !getZip().equals(address1.getZip()) : address1.getZip() != null) return false;
  131. if (getAddress() != null ? !getAddress().equals(address1.getAddress()) : address1.getAddress() != null)
  132. return false;
  133. if (getPhone() != null ? !getPhone().equals(address1.getPhone()) : address1.getPhone() != null) return false;
  134. if (getTel() != null ? !getTel().equals(address1.getTel()) : address1.getTel() != null) return false;
  135. if (getTag() != null ? !getTag().equals(address1.getTag()) : address1.getTag() != null) return false;
  136. return getIsDefault() != null ? getIsDefault().equals(address1.getIsDefault()) : address1.getIsDefault() == null;
  137. }
  138. @Override
  139. public int hashCode() {
  140. int result = getAid() != null ? getAid().hashCode() : 0;
  141. result = 31 * result + (getUid() != null ? getUid().hashCode() : 0);
  142. result = 31 * result + (getName() != null ? getName().hashCode() : 0);
  143. result = 31 * result + (getProvinceName() != null ? getProvinceName().hashCode() : 0);
  144. result = 31 * result + (getProvinceCode() != null ? getProvinceCode().hashCode() : 0);
  145. result = 31 * result + (getCityName() != null ? getCityName().hashCode() : 0);
  146. result = 31 * result + (getCityCode() != null ? getCityCode().hashCode() : 0);
  147. result = 31 * result + (getAreaName() != null ? getAreaName().hashCode() : 0);
  148. result = 31 * result + (getAreaCode() != null ? getAreaCode().hashCode() : 0);
  149. result = 31 * result + (getZip() != null ? getZip().hashCode() : 0);
  150. result = 31 * result + (getAddress() != null ? getAddress().hashCode() : 0);
  151. result = 31 * result + (getPhone() != null ? getPhone().hashCode() : 0);
  152. result = 31 * result + (getTel() != null ? getTel().hashCode() : 0);
  153. result = 31 * result + (getTag() != null ? getTag().hashCode() : 0);
  154. result = 31 * result + (getIsDefault() != null ? getIsDefault().hashCode() : 0);
  155. return result;
  156. }
  157. @Override
  158. public String toString() {
  159. return "Address{" +
  160. "aid=" + aid +
  161. ", uid=" + uid +
  162. ", name='" + name + '\'' +
  163. ", provinceName='" + provinceName + '\'' +
  164. ", provinceCode='" + provinceCode + '\'' +
  165. ", cityName='" + cityName + '\'' +
  166. ", cityCode='" + cityCode + '\'' +
  167. ", areaName='" + areaName + '\'' +
  168. ", areaCode='" + areaCode + '\'' +
  169. ", zip='" + zip + '\'' +
  170. ", address='" + address + '\'' +
  171. ", phone='" + phone + '\'' +
  172. ", tel='" + tel + '\'' +
  173. ", tag='" + tag + '\'' +
  174. ", isDefault=" + isDefault +
  175. "} " + super.toString();
  176. }
  177. }

1 持久层

1.0 构建数据表

在利用dataGrip新建一个底层的数据表:

  1. CREATE TABLE t_address (
  2. aid INT AUTO_INCREMENT COMMENT '收货地址id',
  3. uid INT COMMENT '归属的用户id',
  4. name VARCHAR(20) COMMENT '收货人姓名',
  5. province_name VARCHAR(15) COMMENT '省-名称',
  6. province_code CHAR(6) COMMENT '省-行政代号',
  7. city_name VARCHAR(15) COMMENT '市-名称',
  8. city_code CHAR(6) COMMENT '市-行政代号',
  9. area_name VARCHAR(15) COMMENT '区-名称',
  10. area_code CHAR(6) COMMENT '区-行政代号',
  11. zip CHAR(6) COMMENT '邮政编码',
  12. address VARCHAR(50) COMMENT '详细地址',
  13. phone VARCHAR(20) COMMENT '手机',
  14. tel VARCHAR(20) COMMENT '固话',
  15. tag VARCHAR(6) COMMENT '标签',
  16. is_default INT COMMENT '是否默认:0-不默认,1-默认',
  17. created_user VARCHAR(20) COMMENT '创建人',
  18. created_time DATETIME COMMENT '创建时间',
  19. modified_user VARCHAR(20) COMMENT '修改人',
  20. modified_time DATETIME COMMENT '修改时间',
  21. PRIMARY KEY (aid)
  22. ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

1.1 规划SQL语句

1.插入数据语句。

2.用户收获地址最多20条数据相应,在插入用户数据前做查询操作。存在一个逻辑控制的异常

1.2 接口与抽象方法

在store\src\main\java\com\cy\store\mapper下创建AddressMapper

  1. package com.cy.store.mapper;
  2. import com.cy.store.entity.Address;
  3. public interface AddressMapper {
  4. /**
  5. * 插入地址数据
  6. * @param address 地址
  7. * @return 影响行数
  8. */
  9. Integer insert(Address address);
  10. /**
  11. * 根据用户ID统计收获地址数量
  12. * @param uid 用户id
  13. * @return 数量
  14. */
  15. Integer countByUid(Integer uid);
  16. }

1.3 配置SQL映射

在 store\src\main\resources\mapper 下新建地址的映射文件AddressMapper:

  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <!DOCTYPE mapper
  3. PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  4. "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  5. <!--namespace需要映射到java中的接口,指定路径-->
  6. <mapper namespace="com.cy.store.mapper.AddressMapper">
  7. <resultMap id="AddressEntityMap" type="com.cy.store.entity.Address">
  8. <id column="aid" property="aid"/>
  9. <result column="province_code" property="provinceCode"/>
  10. <result column="province_name" property="provinceName"/>
  11. <result column="city_code" property="cityCode"/>
  12. <result column="city_name" property="cityName"/>
  13. <result column="area_code" property="areaCode"/>
  14. <result column="area_name" property="areaName"/>
  15. <result column="is_default" property="isDefault"/>
  16. <result column="created_user" property="createdUser"/>
  17. <result column="created_time" property="createdTime"/>
  18. <result column="modified_user" property="modifiedUser"/>
  19. <result column="modified_time" property="modifiedTime"/>
  20. </resultMap>
  21. <insert id="insert" useGeneratedKeys="true" keyProperty="aid">
  22. INSERT INTO t_address(
  23. uid, name, province_name, province_code, city_name, city_code, area_name, area_code, zip,
  24. address, phone, tel, tag, is_default, created_user, created_time, modified_user, modified_time
  25. )VALUE (
  26. #{uid}, #{name}, #{provinceName}, #{provinceCode}, #{cityName}, #{cityCode}, #{areaName},
  27. #{areaCode}, #{zip}, #{address}, #{phone}, #{tel}, #{tag}, #{isDefault}, #{createdUser},
  28. #{createdTime}, #{modifiedUser}, #{modifiedTime}
  29. )
  30. </insert>
  31. <select id="countByUid" resultMap="java.lang.Integer">
  32. SELECT count(*) FROM t_address WHERE uid = #{uid}
  33. </select>
  34. </mapper>

1.4 单元测试

新建:store\src\test\java\com\cy\store\mapper\AddressMapperTests.java

编写测试函数:

  1. package com.cy.store.mapper;
  2. import com.cy.store.entity.Address;
  3. import com.cy.store.entity.User;
  4. import org.junit.Test;
  5. import org.junit.runner.RunWith;
  6. import org.springframework.boot.test.context.SpringBootTest;
  7. import org.springframework.test.context.junit4.SpringRunner;
  8. import javax.annotation.Resource;
  9. import java.util.Date;
  10. //@SpringBootTest:该注解表示标注当前类是个测试类,测试类不会随着项目一块打包发送
  11. @SpringBootTest
  12. //@RunWith:表示启动这个单元测试类(单元测试类时不能够运行的),需传递一个参数,必须是SpringRunner的实例类型
  13. @RunWith(SpringRunner.class)
  14. public class AddressMapperTests {
  15. //接口不能创建bean对象,但是mybatis创建了动态代理实现类帮我们进行解决
  16. @Resource
  17. private AddressMapper addressMapper;
  18. /**
  19. * 单元测试方法(可以独立运行,不启动整个项目):
  20. * 1.必须被@Test修饰
  21. * 2.返回值类型必须是void
  22. * 3.方法的参数列表不能指定任何类型
  23. * 4.方法的访问修饰符必须是public
  24. */
  25. @Test
  26. public void insert(){
  27. Address address = new Address();
  28. address.setUid(12);
  29. address.setPhone("123123412");
  30. address.setName("女朋友");
  31. Integer rows = addressMapper.insert(address);
  32. System.out.println(rows);
  33. }
  34. @Test
  35. public void contByUid(){
  36. System.out.println(addressMapper.countByUid(12));
  37. }
  38. }

2 业务层

2.0 规划业务:

1.首次插入,需要将该地址作为默认收获地址。

2.1 规划异常

1.查询结果大于等于20了,抛出AddressCountLimitException

新建:store\src\main\java\com\cy\store\service\ex\AddressCountLimitException.java

  1. package com.cy.store.service.ex;
  2. /** 收获地址超出限制 */
  3. public class AddressCountLimitException extends ServiceException{
  4. public AddressCountLimitException() {
  5. super();
  6. }
  7. public AddressCountLimitException(String message) {
  8. super(message);
  9. }
  10. public AddressCountLimitException(String message, Throwable cause) {
  11. super(message, cause);
  12. }
  13. public AddressCountLimitException(Throwable cause) {
  14. super(cause);
  15. }
  16. protected AddressCountLimitException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
  17. super(message, cause, enableSuppression, writableStackTrace);
  18. }
  19. }

2.插入异常,已经存在

2.2 接口与抽象方法

创建接口:

F:\projects\store\src\main\java\com\cy\store\service\IAddressService.java

  1. package com.cy.store.service;
  2. import com.cy.store.entity.Address;
  3. /** 收获地址业务层接口 */
  4. public interface IAddressService {
  5. /**
  6. * 新增收获地址
  7. * @param uid
  8. * @param username
  9. * @param address
  10. */
  11. void addNewAddress(Integer uid, String username, Address address);
  12. }

2.3 实现抽象方法

在配置文件store\src\main\resources\application.yml中配置最大收获地址:

  1. # 自己的配置
  2. user:
  3. address:
  4. max-count = 20

实现方法store\src\main\java\com\cy\store\service\impl\AddressService.java:

  1. package com.cy.store.service.impl;
  2. import com.cy.store.entity.Address;
  3. import com.cy.store.mapper.AddressMapper;
  4. import com.cy.store.service.IAddressService;
  5. import com.cy.store.service.ex.AddressCountLimitException;
  6. import com.cy.store.service.ex.InsertException;
  7. import org.springframework.beans.factory.annotation.Autowired;
  8. import org.springframework.beans.factory.annotation.Value;
  9. import java.util.Date;
  10. /** 收获地址的实现类 */
  11. public class AddressService implements IAddressService {
  12. @Autowired
  13. private AddressMapper addressMapper;
  14. // 收获地址最大数量
  15. @Value("${user.address.max-count}")
  16. public Integer maxCount;
  17. @Override
  18. public void addNewAddress(Integer uid, String username, Address address) {
  19. //查看收获地址是否达到上限
  20. Integer count = addressMapper.countByUid(uid);
  21. if(count >= maxCount){
  22. throw new AddressCountLimitException("收获地址超出上限");
  23. }
  24. //补全字段
  25. address.setUid(uid);
  26. address.setIsDefault(count==0?1:0);
  27. //补全四项日志
  28. address.setCreatedTime(new Date());
  29. address.setCreatedUser(username);
  30. address.setModifiedTime(new Date());
  31. address.setModifiedUser(username);
  32. //插入
  33. Integer rows = addressMapper.insert(address);
  34. if(rows!=1){
  35. throw new InsertException("插入时异常");
  36. }
  37. }
  38. }

2.4 单元测试

新建:store\src\test\java\com\cy\store\service\AddressServiceTests.java

  1. package com.cy.store.service;
  2. import com.cy.store.entity.Address;
  3. import com.cy.store.entity.User;
  4. import com.cy.store.service.ex.ServiceException;
  5. import org.junit.Test;
  6. import org.junit.runner.RunWith;
  7. import org.springframework.boot.test.context.SpringBootTest;
  8. import org.springframework.test.context.junit4.SpringRunner;
  9. import javax.annotation.Resource;
  10. //@SpringBootTest:该注解表示标注当前类是个测试类,测试类不会随着项目一块打包发送
  11. @SpringBootTest
  12. //@RunWith:表示启动这个单元测试类(单元测试类时不能够运行的),需传递一个参数,必须是SpringRunner的实例类型
  13. @RunWith(SpringRunner.class)
  14. public class AddressServiceImplTests {
  15. //接口不能创建bean对象,但是mybatis创建了动态代理实现类帮我们进行解决
  16. @Resource
  17. private IAddressService addressService;
  18. @Test
  19. public void addNewAddress(){
  20. Address address = new Address();
  21. address.setPhone("123123412");
  22. address.setName("男");
  23. addressService.addNewAddress(24, "管理员",address);
  24. }
  25. }

3 控制层

3.1 处理异常

在store\src\main\java\com\cy\store\controller\BaseController.java中添加:

3.2 设计请求

  1. url:/addresses/add_new_address
  2. 请求方式:post
  3. 请求参数:Address address, HttpSession session
  4. 返回数据:JsonResult<Void>

3.3 处理请求

创建文件:store\src\main\java\com\cy\store\controller\AddressController.java

  1. package com.cy.store.controller;
  2. import com.cy.store.entity.Address;
  3. import com.cy.store.service.IAddressService;
  4. import com.cy.store.util.JsonResult;
  5. import org.springframework.web.bind.annotation.RequestMapping;
  6. import org.springframework.web.bind.annotation.RestController;
  7. import javax.annotation.Resource;
  8. import javax.servlet.http.HttpSession;
  9. //@Controller
  10. @RestController //该注解等于@Controller + 方法上的@ResponseBody
  11. @RequestMapping("addresses")
  12. public class AddressController extends BaseController{
  13. @Resource
  14. private IAddressService addressService;
  15. @RequestMapping("add_new_address")
  16. //@ResponseBody //此方法响应结果以json格式进行数据的响应给前端
  17. public JsonResult<Void> addNewAddress(Address address, HttpSession session){
  18. Integer uid = getuidFromSession(session);
  19. String username = getusernameFromSession(session);
  20. addressService.addNewAddress(uid, username, address);
  21. return new JsonResult<Void>(OK);
  22. }
  23. }

3.4 测试

登录后测试:

http://localhost:8081/addresses/add_new_address?name=tom

4 前端页面

在store\src\main\resources\static\web\address.html中添加ajax请求

  1. <script type="text/javascript">
  2. $("#btn-add-new-address").click(function(){
  3. $.ajax({
  4. url:"/addresses/add_new_address",
  5. type: "POST",
  6. data: $('#form-add-new-address').serialize(),
  7. dataType:"JSON",
  8. success:function (json){
  9. console.log(json)
  10. if(json.state == 200){
  11. alert("新增地址成功");
  12. }else{
  13. alert("新增地址失败" + json.message);
  14. }
  15. },
  16. error: function(xhr){
  17. alert("新增地址时产生未知异常" + xhr.message)
  18. }
  19. });
  20. });
  21. </script>

测试:

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/羊村懒王/article/detail/191646
推荐阅读
相关标签
  

闽ICP备14008679号