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>