6.3. 收货地址-设置默认收货地址
6.3.3. 收货地址-设置默认收货地址-控制器层
设计处理设置默认收货地址的请求:
请求路径:/address/set_default.do
请求类型:GET
请求参数:uid(HttpSession), id
响应方式:ResponseResult<Void>
是否拦截:是,登录拦截,但无须修改配置
则,在AddressController
中添加处理请求的方法:
@RequestMapping("/set_default")
@ResponseBody
public ResponseResult<Void> setDefault(
HttpSession session,
@RequestParam("id") Integer id) {
// 从session中获取uid
// 调用业务层对象的setDefaultAddress(uid, id)方法
// 创建返回值对象并返回
}
由于此次操作在业务层抛出的异常都是UpdateDataException
,此前在BaseController
中都已经处理过,则无须重复处理!
6.3.4. 收货地址-设置默认收货地址-前端页面
关于address.html
中的核心改动在于:
var html = '<div class="aim_content_one aim_active">'
+ '<span class="dzmc dzmc_active">#{tag}</span>'
+ '<span class="dzxm dzxm_normal">#{name}</span>'
+ '<span class="dzxq dzxq_normal">#{address}</span>'
+ '<span class="lxdh lxdh_normal">#{phone}</span>'
+ '<span class="operation operation_normal">'
+ ' <span class="aco_change">修改</span>|<span class="aco_delete">删除</span>'
+ '</span>'
+ '<span class="swmr swmr_normal">'
+ '<a href="javascript:setDefault(#{id});">#{default}</a>'
+ '</span>'
+ '</div>';
html = html.replace("#{id}", addresses[i].id);
function setDefault(id) {
// 发AJAX请求,并处理结果
var url = "../address/set_default.do";
var data = "id=" + id;
$.ajax({
"url": url,
"data": data,
"type": "GET",
"dataType": "json",
"success": function(json) {
if (json.state == 200) {
showList();
} else {
alert(json.message);
}
},
"error": function(xhr, textStatus, errorThrown) {
console.log("状态码:" + xhr.readyState);
console.log("响应码:" + xhr.status);
console.log("响应文本:" + xhr.responseText);
console.log("textStatus=" + textStatus);
console.log("errorThrown=" + errorThrown);
alert("您的登录信息已经过期,请重新登录!");
location.href = "../web/login.html";
}
});
}
6.4. 收货地址-删除
6.4.1 收货地址-删除-持久层
在持久层中,应该添加执行删除的功能,在该功能的设计上,可以通过id=?
作为删除条件,也可以使用id=? AND uid=?
作为删除条件:
使用 id=? 作为删除条件
优点:不局限于是谁操作某条数据,可以在业务中自由组织
缺点:必须在业务层判断id的有效性,是否是当前登录的用户的数据
使用 id=? AND uid=? 作为删除条件
优点:可以确保当前登录的用户操作的必然是他自己的数据
缺点:所有用户都只能删除自己的数据,包括管理员
小结
为了保证组织业务的自由,保证项目的可扩展性,推荐使用前者,所以,持久层只使用id=?
作为删除条件,最终会在业务层判断尝试删除的数据是不是当前登录的用户的数据,所以,还需要在持久层添加查询功能,根据尝试删除的数据id查出收货地址数据,后续根据登录的uid进行对比,所以,在持久层接口和映射中配置:
抽象方法
Integer delete(Integer id);
SQL语句
DELETE FROM t_address WHERE id=?
抽象方法
Address getAddressById(Integer id);
SQL语句
SELECT
id, uid,
recv_name AS recvName,
recv_district AS recvDistrict,
recv_address AS recvAddress,
recv_phone AS recvPhone,
recv_tel AS recvTel,
recv_zip AS recvZip,
recv_tag AS recvTag,
is_default AS isDefault
FROM
t_address
WHERE
id=#{id}
6.4.1 收货地址-删除-业务层
创建com.company.store.service.ex.AddressNotFoundException
和ArgumentException
这2个异常。
在业务层接口中添加抽象方法:
void deleteById(Integer uid, Integer id);
Address getAddressById(Integer id);
在实现类中:
public void deleteById(Integer uid, Integer id) {
// ** 组织业务,最终删除数据 **
// 判断数据是不是当前用户的,则根据参数id查询数据
// 判断是否查询到数据
// 是:数据存在,则判断参数uid和查询结果中封装的uid是否相同
// -- 是:删除的是自己的数据,执行删除
// -- 否:尝试删除的不是自己的数据:ArgumentException
// 否:数据不存在,AddressNotFoundException
}
private Integer delete(Integer id) {
Integer rows = addressMapper.delete(id);
if (rows != 1) {
throw new AddressNotFoundException();
}
}
在删除业务中,还需要考虑被删除的数据是否是默认收货地址,如果是,则还需要将另一条收货地址设置为默认!此项操作涉及2个功能:
判断删除的数据是否是默认收货地址:由于在现有的逻辑中,已经是先获取要删除的数据本身,然后执行的删除,所以,直接从获取的数据中判断
isDefault
属性即可,则无须添加新的持久层、业务层功能;将某条数据设置为默认收货地址:首先,设置规则为将最后添加的那条收货地址设置为默认,则需要获取最后一条添加的收货地址,则需要持久层开发新的功能:
抽象方法
Address getLatestAddress(Integer uid)
SQL语句
SELECT id FROM t_address WHERE uid=? ORDER BY id DESC LIMIT 0,1
然后,将原有逻辑调整为:
@Transactional
// ** 组织业务,最终删除数据 **
// 判断数据是不是当前用户的,则根据参数id查询数据
// 判断是否查询到数据
// 是:数据存在,则判断参数uid和查询结果中封装的uid是否相同
// -- 是:删除的是自己的数据,执行删除
// -- 判断删除的数据的isDefault是否为1
// -- -- 是:删除了默认收货地址,则查询最后添加的收货地址
// -- -- 判断是否查询到结果
// -- -- -- 是:获取数据id,调用setDefault(uid, id)
// -- -- -- 否:刚才删除的已经最后一条,则直接结束
// -- -- 否:结束
// -- 否:尝试删除的不是自己的数据:ArgumentException
// 否:数据不存在,AddressNotFoundException
由于调用了setDefault()
方法,还可能抛出UpdateDataException
,也应该在方法的声明中添加该异常!
6.4.3 收货地址-删除-控制器层
设计处理删除收货地址的请求:
请求路径:/address/delete.do
请求类型:GET
请求参数:uid(HttpSession), id
响应方式:ResponseResult<Void>
是否拦截:是,登录拦截,但无须修改配置
则,在AddressController
中添加处理请求的方法:
@RequestMapping("/delete.do")
@ResponseBody
public ResponseResult<Void> delete(
HttpSession session,
@RequestParam("id") Integer id) {
// 从session中获取uid
// 调用业务层对象的deleteById(uid, id)方法
// 创建返回值对象并返回
}
由于此次操作在业务层抛出的异常有AddressNotFoundException
、ArgumentException
、UpdateDataException
,此前在BaseController
中前2种尚未处理过,则应该添加对这2个异常的处理!
测试时,应该先登录,然后通过/address/delete.do?id=xx
此类的URL进行测试。