Bootstrap

新增收货地址

新增收货地址


新增收货地址-数据表创建

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;

新增收货地址创建实体类

创建一个类Address类,在类中定义表的相关字段,采用驼峰命名法方式,最后再去继承BaseEntity类。
private Integer aid;
private Integer uid;
private 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;
...

新增收货地址-持久层

各功能的开发顺序

当前收货地址功能模块:列表的展示,修改,删除,设置默认地址,新增收货地址。开发顺序:新增收货地址-列表展示-设置默认收货地址-删除收货地址-修改收货地址。

规划需要执行的SQL

1.对应的是插入语句:

insert into t_address (除了aid外字段列表) values (字段值列表)

2.一个用户的收货地址规定最多只能有20条数据对应。在插入用户数据之前做查询操作。

select count(*) t_address where uid = ?

接口和抽象方法

创建一个接口ddress,在这个接口中定义上面两个SQL语句抽象方法定义。

/**
	 *  新增收货地址
	 * @param address 地址的实体类
	 * @return 受影响的行数
	 */
	Integer insert(Address address);
	
	/**
	 *  根据用户的id统计收货地址数量
	 * @param uid   用户的id
	 * @return  当前用户的收货地址总数
	 */
	Integer countByUid(Integer uid);

配置SQL映射

创建一个AddressMapper.xml映射文件,在这个文件中添加

  <resultMap id="AddressEntityMap" type="com.cy.store.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>

    <insert id="insert" 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="countByUid" result="java.lang.Integer">
        SELECT count(*) FROM t_address WHERE uid = #{uid}
    </select>

2.在test下的mapper文件夹下创建AddressMapperTests的测试类。

@Test
public void insert(){
    Address address = new Address();
    address.setUid(7);
    address.setPhone("133333333");
    address.setName("张三");
    addressMapper.insert(address);
}

@Test
public void acountByUid(){
    Integer rows = addressMapper.countByUid(7);
    System.out.println(rows);
}

新增收货地址-业务层

规划异常

如果用户是第一次插入用户的收货地址, 规则:当用户插入的地址是第一条时, 需要将当前地址作为默认的收货地址,如果查询到统计总数为0则将当前地址的is_default值设置为1。查询统计的结果为0不代表异常。

查询到的结果大于20了,这时候需要抛出业务控制的异常AddressCountLimitException异常。自行创建这个异常。

/** 收货地址超出总数限制的异常(最大20条)*/
public class AddressCountLimitException extends ServiceException {
...
}

插入数据时产生未知的异常InsertException,不需要再重复的创建。

接口和抽象方法

1.创建一个IAddressService接口, 在接口中定义业务的抽象方法。

package com.cy.store.service;
	
	import com.cy.store.entity.Address;
	
	/**收货地址业务层接口*/
	public interface IAddressService {
	
	    /**收货地址业务层接口*/
	    void addNewAddress(Integer uid, String name, Address address);
	}

2.创建一个AddressServiceImpl实现类,去实现接口中抽象方法。
在配置文件中定义数据

#Spring读取配文件中的数据 @Value("${user.address.max-count}")
	user.address.max-count=20

在实现类中实现业务控制

package com.cy.store.service.impl;
	
	import com.cy.store.entity.Address;
	import com.cy.store.mapper.AddressMapper;
	import com.cy.store.service.IAddressService;
	import com.cy.store.service.ex.AddressCountLimitException;
	import com.cy.store.service.ex.InsertException;
	import org.springframework.beans.factory.annotation.Autowired;
	import org.springframework.beans.factory.annotation.Value;
	
	import java.util.Date;
	
	/*新增地址的实现类*/
	@service
	public class AddressServiceImpl implements IAddressService {
	
	    @Autowired
	    private AddressMapper addressMapper;
	
	    @Value("${user.address.max-count}")
	    private Integer maxCount;
	
	    @Override
	    public void addNewAddress(Integer uid, String username, Address address) {
	        Integer rows = addressMapper.countByUid(uid);
	        if(rows >= maxCount){
	            throw new AddressCountLimitException("用户地址总数超过限制");
	        }
	
	        // 补全数据:将参数uid封装到参数address中
	        address.setUid(uid);
	        // 补全数据:根据以上统计的数量,得到正确的isDefault值(是否默认:0-不默认,1-默认),并封装
	        Integer 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);
	        //插入收货地址的方法
	        Integer rows1 = addressMapper.insert(address);
	        if(rows!=1){
	            throw new InsertException("插入数据时产生了未知的异常");
	        }
	
	    }
	}

3.测试业务层功能是否正常。AddressServiceTest测试类来测试业务功能。

@Test
public void insert() {
    Address address = new Address();
    address.setPhone("13333333333");
    address.setName("张四");
    addressService.addNewAddress(7,"管理员",address);
}

新增收货地址-控制层

处理异常

业务层抛出了收货地址总数超标的异常,在BaseController类中捕获。

else if(e instanceof AddressCountLimitException){
	        result.setstate(4003);
	        result.setMessage("用户地址超出限制");
	    }

设计请求

/addressses/add_new_address
post
Address address,HttpSession session
JsonResult

处理请求

在控制层新建AddressController来处理用户收货地址的请求和响应。
package com.cy.store.controller;

import com.cy.store.entity.Address;
import com.cy.store.service.IAddressService;
import com.cy.store.util.JsonResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpSession;

/*用户新增地址的业务层*/
@RequestMapping("/addresses")
@RestController
public class AddressController extends BaseController {

    @Autowired
    private IAddressService addressService;

    @RequestMapping("/add_new_address")
    public JsonResult<Void> addNewAddress(Address address,HttpSession session){
        Integer uid = getUidFromSession(session);
        String username = getUsernameFromSession(session);
        addressService.addNewAddress(uid,username,address);
        return new JsonResult<>(OK);
    }
}

先登录用户,然后在访问http://localhost:8080/addresses/add_new_address?name=tom&phone=17858802222进行测试。

新增收货地址-前端页面

<script type="text/javascript">
		$("#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>
;