1. 修改默认收货地址-持久层
1.1 规划sql语句
- 检测当前用户向设置为默认收货地址的这条数据是否存在
SELECT * FROM t_address WHERE aid=#{aid}
- 在修改用户的收获默认地址之前,先将所有的收货地址设置为非默认
UPDATE t_address SET is_default=0 WHERE uid=#{uid}
- 将用户当前选中的这条记录设置为默认收货地址
UPDATE t_address SET is_default=1,
modified_user=#{modifiedUser},
modified_time=#{modifiedTime}
WHERE aid=#{aid}
1.2 AddressMapper接口定义抽象方法
/*** 根据aid查询收货地址数据* @param aid 收货地址id* @return*/Address findByAid(Integer aid);/*** 根据aid修改收货地址数据为默认地址* @param uid 用户id* @return*/Integer updateNonDefault(Integer uid);/*** 根据aid修改收货地址数据* @param * @return*/Integer updateDefaultByAid(@Param("aid") Integer aid,@Param("modifiedUser") String modifiedUser,@Param("modifiedTime") Date modifiedTime);
1.3 编写xml文件的sql映射
<select id="findByAid" resultMap="AddressEntityMap">SELECT * FROM t_address WHERE aid=#{aid}</select>
<!-- 把用户的所有收货地址均设为0 --><update id="updateNonDefault">UPDATE t_address SET is_default=0 WHERE uid=#{uid}</update>
<!-- 将选中的地址设置为 1 --><update id="updateDefaultByAid">UPDATE t_address SET is_default=1,modified_user=#{modifiedUser},modified_time=#{modifiedTime}WHERE aid=#{aid}</update>
1.4 进行测试
在AddressMapperTest测试类中进行mapper接口测试
@Testvoid findByAid() {Address address = addressMapper.findByAid(7);System.out.println(address);}@Testvoid updateNonDefault() {Integer integer = addressMapper.updateNonDefault(1);System.out.println(integer);}@Testvoid updateDefaultByAid() {Integer integer = addressMapper.updateDefaultByAid(7, "admin", new Date());System.out.println(integer);}
2. 修改默认收货地址-业务层
2.1 异常规划
- 在执行更新时产生未知的UpdateException异常,这个异常之前已经创建过了,无需重新创建
- 访问的数据不是当前登录用户的收货地址数据,非法访问异常,AccessDeniedException异常
/**非法访问的异常*/
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);}
}
- 收货地址有可能不存在的异常,AddressNotFoundException异常
package com.cy.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);}
}
2.2 接口类编写抽象方法
/*** 设置默认收货地址* @param aid 收货地址id* @param uid 用户id* @param username 用户名*/void setDefault(Integer aid, Integer uid, String username);
2.3 实现类实现接口,重写抽象方法
/*** 设置默认收货地址* @param aid 收货地址id* @param uid 用户id* @param username 用户名*/@Overridepublic void setDefault(Integer aid, Integer uid, String username) {
// 获取当前收货地址数据Address address = addressMapper.findByAid(aid);
// 判断用户id与收货地址数据中的用户id是否相同if (!address.getUid().equals(uid)){
// 不同的话抛出异常throw new AccessDeniedException("非法数据访问");}
// 将用户的所有收货地址的is_default字段设置为0Integer rows = addressMapper.updateNonDefault(uid);
// 一个用户可能有多个收货地址,因此可能返回的行数小于1说明异常if (rows<1){throw new UpdateException("更新数据时产生未知的异常");}
// 修改当前收货地址的is_default字段设置为1Integer integer = addressMapper.updateDefaultByAid(aid, username, new Date());if (integer!=1){throw new UpdateException("更新数据时产生未知的异常");}}
2.4 AddressServiceTest测试类进行测试
@Testvoid updateDefault() {addressService.setDefault(6,9,"admin");}
数据库修改成功✌
3. 修改默认收货地址-控制层
3.1 在BaseController捕获异常
/*** 控制层基类*/
public class BaseController {//操作成功的状态码public static final int OK = 200;/*** 全局异常处理器,用于捕获并处理业务层抛出的异常。** @param e 捕获的异常对象* @return 返回封装后的 JsonResult 对象,包含状态码和错误信息*/
// 该项目中产生了异常,会被统一拦截到此方法中,这个方法此时就充当了请求处理方法,方法的返回值直接给前端浏览器,返回给前端的数据中,状态码,状态码对应信息,数据@ExceptionHandler({ServiceException.class, FileUploadException.class})public JsonResult<Void> handleException(Throwable e) {// 创建一个 JsonResult 实例,并初始化异常消息JsonResult<Void> result = new JsonResult<>(e);// 判断异常类型,设置对应的状态码和提示信息if (e instanceof UsernameDuplicatedException){// 用户名被占用时返回 400 状态码和相应提示result.setState(4000);result.setMessage("用户名被占用");} else if (e instanceof InsertException){// 插入数据失败时返回 500 状态码和相应提示result.setState(4000);result.setMessage("注册时产生未知的异常");}else if (e instanceof UsernameNotFoundException){result.setState(4001);result.setMessage("用户数据不存在");}else if (e instanceof PasswordNotMatchException){result.setState(4002);result.setMessage("用户密码错误");}else if (e instanceof AddressCountLimitException){result.setState(4003);result.setMessage("收货地址超出上限");}else if (e instanceof AccessDeniedException){result.setState(4004);result.setMessage("收货地址数据非法访问");}else if (e instanceof AddressNotFoundException){result.setState(4005);result.setMessage("收货地址数据不存在");}else if (e instanceof UpdateException){result.setState(5003);result.setMessage("更新数据时产生未知的异常");} else if (e instanceof FileEmptyException) {result.setState(6000);} else if (e instanceof FileSizeException) {result.setState(6001);} else if (e instanceof FileTypeException) {result.setState(6002);} else if (e instanceof FileStateException) {result.setState(6003);} else if (e instanceof FileUploadIOException) {result.setState(6004);}// 返回最终的响应结果return result;}/*** 从Session中获取当前登录用户的uid* * @param session HttpSession对象,用于获取会话中的用户ID* @return 当前登录用户的uid* * `protected` 表示该方法只能被同一个包内的类或子类访问。* `final` 表示该方法不能被子类重写。*/protected final Integer getUidFromSession(HttpSession session) {// 从Session中获取uid// 从会话中获取uid属性并转换为整数类型返回return Integer.valueOf(session.getAttribute("uid").toString());}/*** 从Session中获取当前登录用户的用户名* @param session HttpSession对象,用于获取会话中的用户名* @return 当前登录用户的用户名*/protected final String getUsernameFromSession(HttpSession session) {// 从Session中获取当前登录的用户名return session.getAttribute("username").toString();}}
3.2 设计请求
/addresses/setDefault/{aid}
@PathVariable("aid") Integer aid,HttpSession session
GET
JsonResult<Void>
3.3 AddressController类编写业务代码
/*** 设置默认收货地址* @param aid 收货地址id* @param session 当前登录的用户的会话* @return*/@RequestMapping("/setDefault/{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);}
3.4 测试
先登录,访问localhost:8080/addresses/setDefault/7查看返回状态码
数据库也修改成功✌
4. 修改默认收货地址-前端页面
41. address.html绑定点击事件
首先需要先将之前展示的收货地址列表清空 $("#address-list").empty();然后优化一下展示收货地址列表的函数,创建一个点击事件,将收货地址id封装到点击事件上
4.2 发送请求
function setDefault(aid) {$.ajax({url: "/addresses/default/"+ aid,type: "POST",dataType: "json",success: function (json) {if (json.state == 200) {alert("设置默认地址成功")// 重新调用获取列表的方法showAddressList();}else{alert("设置默认地址失败")}},error: function (xhr) {alert("设置默认地址失败"+xhr.message)}})}
完整代码
<script type="text/javascript">$(document).ready(function() {// 页面一加载就调用方法showAddressList();})function showAddressList() {// 展示之前将收货地址列表清空$("#address-list").empty();$.ajax({url: "/addresses",type: "GET",dataType: "json",success: function (json) {if (json.state == 200) {// 获取省列表,包括所哟省名称let list = json.data;// 遍历省列表for (let i = 0; i < list.length; i++) {// #{tag} 占位符let tr = '<tr>\n' +'<td>#{tag}</td>\n' +'<td>#{name}</td>\n' +'<td>#{address}</td>\n' +'<td>#{phone}</td>\n' +'<td><a class="btn btn-xs btn-info"><span class="fa fa-edit"></span> 修改</a></td>\n' +'<td><a class="btn btn-xs add-del btn-info"><span class="fa fa-trash-o"></span> 删除</a></td>\n' +'<td><a onclick="setDefault(#{aid})" class="btn btn-xs add-def btn-default">设为默认</a></td>\n' +'</tr>'// 将列表的tr清空,替代成新的tr// replace() 替换tr = tr.replace("#{tag}", list[i].tag)tr = tr.replace("#{name}", list[i].name)tr = tr.replace("#{address}", list[i].address)tr = tr.replace("#{phone}", list[i].phone)// 获取aidtr = tr.replace("#{aid}", list[i].aid)// 替换完成之后,将tr追加到address-list列表中$("#address-list").append(tr)}// 按照降序排列的话,第一项是设置的默认项,那么”设为默认地址“这个按钮应该隐藏// 将某个元素隐藏使用hide()方法$(".add-def:eq(0)").hide();}else{alert("用户收货地址列表加载失败")}}})}function setDefault(aid) {$.ajax({url: "/addresses/setDefault/"+ aid,type: "POST",dataType: "json",success: function (json) {if (json.state == 200) {alert("设置默认地址成功")// 将列表的tr清空,替代成新的tr// 重新调用获取列表的方法showAddressList();}else{alert("设置默认地址失败")}},error: function (xhr) {alert("设置默认地址失败"+xhr.message)}})}</script>