设置默认收货地址

点击设为默认按钮,当前地址设置为默认,后面的按钮隐藏,其他的地址全部显示该按钮

image-20230810231339259

持久层

规划执行的SQL语句

1.检测用户想设置为默认地址的数据在数据库中是否存在,本质是一条查询语句

1
select * from t_address where aid=?;

2.将用户选择的地址设为默认地址之前,先将该用户所有的收货地址全部设置为非默认

1
update t_address set is_default=0 where uid=?;

3.将用户选择的该条地址设置为默认

1
update t_address set is_default=1,modified_user=?,modified_time=? where aid=?;

接口和抽象方法

AddressMapper接口中申明对应的抽象方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/**
* 根据aid查询收货地址数据
* @param aid 地址aid
* @return 记录存在则返回对应地址数据,反之返回null
*/
Address findByAid(Integer aid);

/**
* 将某个用户所有地址均设置为非默认
* @param uid 用户id
* @return 受影响行数
*/
Integer updateNoneDefaulit(Integer uid);

/**
* 将用户某条地址设置为默认
* @param aid 地址aid
* @param modifiedUser 修改者名称
* @param modifiedTime 记录修改时间
* @return 受影响行数
*/
Integer updateDefaultByAid(Integer aid, String modifiedUser, Date modifiedTime);

配置SQL映射

AddressMapper.xml中编写对应的映射语句

1
2
3
4
5
6
7
8
9
10
11
<select id="findByAid" resultMap="addressPojoMap">
select * from t_address where aid=#{aid};
</select>

<update id="updateNoneDefaulit">
update t_address set is_default=0 where uid=#{uid};
</update>

<update id="updateDefaultByAid">
update t_address set is_default=1,modified_user=#{modifiedUser},modified_time=#{modifiedTime} where aid=#{aid};
</update>

单元测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@Test
public void findByAid(){
Address address = addressMapper.findByAid(1);
System.out.println(address);
}

@Test
public void updateNoneDefaulit(){
Integer rows = addressMapper.updateNoneDefaulit(2);
System.out.println(rows);
}

@Test
public void updateDefaultByAid(){
Integer rows = addressMapper.updateDefaultByAid(3, "管理员", new Date());
System.out.println(rows);
}

业务层

规划异常

1.数据更新过程中可能发生未知异常,UpdateException,此异常类在其他功能中已经定义过了

2.访问的收货地址不属于当前登录的用户,非法访问异常AccessDeniedException

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
package com.bang.store.service.ex;

/**
* 非法访问异常:
* 可能由于其他模块存在BUG,导致展示的数据不属于当前登录用户
*/
public class AccessDeniedException extends ServiceException{
public AccessDeniedException() {
super();
}

public AccessDeniedException(String message) {
super(message);
}

public AccessDeniedException(String message, Throwable cause) {
super(message, cause);
}

public AccessDeniedException(Throwable cause) {
super(cause);
}

protected AccessDeniedException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}
}

3.当前收货地址在数据库不存在所引发的异常,AddressNotFoundException

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
package com.bang.store.service.ex;

/**
* 当前地址数据在数据库中不存在所引发的异常
*/
public class AddressNotFoundException extends ServiceException{
public AddressNotFoundException() {
super();
}

public AddressNotFoundException(String message) {
super(message);
}

public AddressNotFoundException(String message, Throwable cause) {
super(message, cause);
}

public AddressNotFoundException(Throwable cause) {
super(cause);
}

protected AddressNotFoundException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}
}

接口和抽象方法

IAddressService接口中定义对应的抽象方法

业务逻辑:根据aid查询当前地址记录是否存在,不存在触发AddressNotFoundException;判断当前地址是否属于当前登录的用户,不属于触发AccessDeniedExcption;否则,首先将当前用户所有收获地址全部设为非默认,然后再将当前用户选择的地址设置为默认

1
2
3
4
5
6
7
/**
* 更改当前用户的默认地址
* @param aid 地址编号
* @param uid 用户编号
* @param username 操作者姓名
*/
void setDefault(Integer aid,Integer uid,String username);

抽象方法实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
@Override
public void setDefault(Integer aid, Integer uid, String username) {
//1.查询当前地址记录是否存在
Address address = addressMapper.findByAid(aid);
if(address==null){
throw new AddressNotFoundException("当前地址不存在");
}
//2.判断当前地址是否属于该用户
if(!address.getUid().equals(uid)){
throw new AccessDeniedException("拒绝访问");
}
//3.将该用户所有地址设置为非默认
Integer rows = addressMapper.updateNoneDefaulit(uid);
if(rows==0){
throw new InsertException("数据更新发生未知错误");
}
//4.将用户选择的收货地址设置为默认
rows = addressMapper.updateDefaultByAid(aid, username, new Date());
if(rows!=1){
throw new InsertException("数据更新发生未知错误");
}
}

单元测试

1
2
3
4
5
6
7
@Test
public void setDefault(){
Integer aid = 3;
Integer uid = 2;
String username = "管理员";
addressService.setDefault(aid,uid,username);
}

控制层

异常处理

在控制层基类BaseController中增加新的异常处理逻辑

1
2
3
4
5
6
7
else if (e instanceof AddressNotFoundException){
result.setState(7001);
result.setMessage("收货地址不存在");
}else if (e instanceof AccessDeniedException){
result.setState(7002);
result.setMessage("非法数据访问");
}

设计请求

1
2
3
4
request url: /address/set_default/{aid}   //采用RestFul风格进行访问  
request method: GET
request params: @PathVariable("aid") Integer aid,HttpSession session
response data: new JsonResult<Void>()

处理请求

1
2
3
4
5
6
7
8
9
//采用restful风格进行数据传输
//采用注解 @PathVariable进行参数和数据之间的映射
@RequestMapping("/set_default/{aid}")
public JsonResult<Void> setDefault(@PathVariable("aid") Integer aid, HttpSession session){
Integer uid = getUidFromSession(session);
String username = getUsernameFromSession(session);
addressService.setDefault(aid,uid,username);
return new JsonResult<>(OK,"地址设置默认成功");
}

前端页面

用户点击Address.html页面中的设置默认按钮,会向后端服务器发送请求

给页面中的设置默认组件添加onclick()函数,然后绑定对应的事件处理函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
<script>
$(document).ready(function () {
showAddress()
})

function showAddress() {
$.ajax({
url: "/address/get_by_uid"
,type: "GET"
,data: null
,dataType: "JSON"
,success: function (data){
if(data.state == 200){
//后端传回数据是list列表
//清空原始内容
$("#address-list").empty();
let addressList = data.data;
for(let i=0;i<addressList.length;i++){
let trContent = "<tr>\n" +
"\t\t\t\t\t\t\t\t\t<td>"+addressList[i].tag+"</td>\n" +
"\t\t\t\t\t\t\t\t\t<td>"+addressList[i].name+"</td>\n" +
"\t\t\t\t\t\t\t\t\t<td>"+addressList[i].address+"</td>\n" +
"\t\t\t\t\t\t\t\t\t<td>"+addressList[i].phone+"</td>\n" +
"\t\t\t\t\t\t\t\t\t<td><a class=\"btn btn-xs btn-info\"><span class=\"fa fa-edit\"></span> 修改</a></td>\n" +
"\t\t\t\t\t\t\t\t\t<td><a class=\"btn btn-xs add-del btn-info\"><span class=\"fa fa-trash-o\"></span> 删除</a></td>\n" +
"\t\t\t\t\t\t\t\t\t<td><a onclick='setDefault(#{aid})' class=\"btn btn-xs add-def btn-default\">设为默认</a></td>\n" +
"\t\t\t\t\t\t\t\t</tr>";
trContent = trContent.replace("#{aid}",addressList[i].aid);
$("#address-list").append(trContent);
}
//第一个地址默认为默认地址,所以其所在的默认地址按钮需要隐藏
//某个元素隐藏,采用hide()方法
$(".add-def:eq(0)").hide();
}else{
alert("用户地址获取失败 "+data.message);
}
}
,error:function (xmh){
alert("用户地址获取过程中发生未知错误"+xmh.status);
}
});
}

//默认按钮点击事件响应函数
function setDefault(aid) {
$.ajax({
url: "/address/set_default/"+aid
,type: "GET"
,success: function (data){
if(data.state == 200){
alert("默认地址设置成功");
//刷新页面,展示地址列表
showAddress()
}else{
alert("默认地址设置失败 "+data.message);
}
}
,error:function (xmh){
alert("默认地址设置失败"+xmh.status);
}
});
}
</script>