目錄
例外處理
業務回傳
用戶登錄
登錄安全問題(token)
業務實作
業務需求檔案
用戶管理
用戶串列
串列分頁
商品管理
商品串列
串列分頁
商品分類
查詢商品等級分類資訊
洗掉商品等級分類資訊
權限管理
資料統計
例外處理
Spring為了整合全域例外的處理(不用在每個方法下捕獲或者拋出例外從而達到處理例外的機制),開發了如下注解:
- @RestControllerAdvice 定義全域例外的處理類 回傳值JSON串
- @ExceptionHandler 標識攔截的例外的型別,如果型別匹配,則執行方法
@RestControllerAdvice
public class MyExceptionAdvice {
//寫法:1.運行時例外(通用) 2.自定義例外資訊 3.攔截所有例外Exception
@ExceptionHandler(RuntimeException.class)
public Object exception(Exception e){
//需求: 如果遇到例外,應該提示用戶201/失敗資訊.
e.printStackTrace();
return SysResult.fail();
}
}
業務回傳
滿足不同業務需求的回傳不同結果,方便前端識別業務執行成功與否,以便執行不同的操作.
@Data
@Accessors(chain = true)
@NoArgsConstructor//無參構造
@AllArgsConstructor//全參構造
public class SysResult implements Serializable {//實作介面是一種規范性寫法
private Integer status;//狀態碼資訊200 201
private String msg;//服務器回傳的提示資訊
private Object data;//回傳的業務資料,不清楚是什么型別,就用object
//為了用戶使用VO物件更加的方便,多載一些方法,簡化程式的呼叫
public static SysResult fail(){
return new SysResult(201,"業務執行失敗",null);
}
//1.不帶引數的正確回傳
public static SysResult success(){
return new SysResult(200,"業務執行成功",null);
}
//2.帶回傳值的正確回傳 用戶傳遞什么/回傳值就是什么
public static SysResult success(Object data){
return new SysResult(200,"服務器處理成功",data);
}
//3.帶回傳值,帶提示資訊
public static SysResult success(String msg, Object data){
return new SysResult(200,msg,data);
}
}
用戶登錄
登錄安全問題(token)
為了防止直接跳轉網頁,用戶登錄成功后會回傳一個token標識,后續跳轉頁面時,會監測是否帶有token標識,有則可以跳轉,沒有則不能執行相關業務.若后續關閉系統則需要重新登錄并獲取token標識.
業務實作
業務需求檔案
- 需求:檢測用戶登錄操作
- URL: /login
- 請求型別: Post請求
- 接收引數: User物件
- 回傳值: Sysresult物件
Controller層:
//檢測用戶登錄操作
@PostMapping("/login")
public SysResult login(@RequestBody User user){
System.out.println(user);
//token用于用戶名和密碼的校驗,防止直接跳轉網頁
//token 有值則業務正確 null 業務操作失敗
String token = userService.login(user);
if (token == null){
return SysResult.fail();
}
return SysResult.success(token);
}
Service層:
public String login(User user) {
String password = user.getPassword();//明文密碼,需要加密,利用DigestUtils
//byte[] passByte = password.getBytes();
String md5Pass = DigestUtils.md5DigestAsHex(password.getBytes());
//根據用戶名和密文查詢資料庫
//根據物件中不為null的屬性充當where條件
user.setPassword(md5Pass);
QueryWrapper<User> qw = new QueryWrapper<>(user);
User userDB = userMapper.selectOne(qw);
//查詢結果是否有效
if (userDB == null){//用戶名密碼錯誤 回傳null
return null;
}
//用戶名密碼均正確 回傳一個獨一無二的token 利用UUID
return UUID.randomUUID().toString()
.replace("-", "");
}
用戶管理
用戶串列
串列分頁
- 需求:分頁查詢用戶串列資訊
- URL:/list?query,pagenum,pagesize
- 請求型別:get
- 接收引數:PageResult物件
- 回傳值:SysResult
Controller層:
/**
* 獲取用戶串列資訊
* 引數:PageResult物件進行接收 傳遞3個引數
* 回傳值:SysResult物件 引數(PageResult物件) 回傳5個引數
* 我們想要的資料封裝在sysResult物件的data屬性里,data屬性也即PageResult物件,
* 前端再根據需要,從data屬性里面抽取需要的資料
*/
@GetMapping("/list")
public SysResult getUserList(PageResult pageResult){
return SysResult.success(userService.getUserList(pageResult));
}
Service層:
public PageResult getUserList(PageResult pageResult){
//引數1: page分頁物件
Page page = new Page(pageResult.getPageNum(),pageResult.getPageSize());
//引數2:分頁的查詢條件 username模糊查詢 注意bug:如果用戶沒有傳遞query,模糊查詢一樣拼接,與理想不符
QueryWrapper<User> qw = new QueryWrapper<>();
boolean flag = StringUtils.hasLength(pageResult.getQuery());
qw.like(flag,"username",pageResult.getQuery());
//page 原本兩個引數 根據分頁查詢回傳 total/分頁后的記錄records 4個引數
page = userMapper.selectPage(page, qw);
List<User> userList = page.getRecords();
long total = page.getTotal();
System.out.println(total);
return pageResult.setTotal(total).setRows(userList);
}
商品管理
商品串列
串列分頁
- 需求:分頁查詢商品
- URL:/item/getItemList?query,pagenum,pagesize
- 請求型別:get
- 接收引數:PageResult物件
- 回傳值:Sysresult
Controller層:
@GetMapping("/getItemList")
public SysResult getItemList(PageResult pageResult){
pageResult = itemService.getItemList(pageResult);
return SysResult.success(pageResult);
}
Service層:
public PageResult getItemList(PageResult pageResult) {
Page<Item> page = new Page<>(pageResult.getPageNum(),pageResult.getPageSize());
QueryWrapper<Item> qw = new QueryWrapper<>();
//query有值才拼接
boolean flag = StringUtils.hasLength(pageResult.getQuery());
qw.like(flag, "title", pageResult.getQuery());
page = itemMapper.selectPage(page, qw);
return pageResult.setTotal(page.getTotal()).setRows(page.getRecords());
}
商品分類
查詢商品等級分類資訊
- 需求:按照商品的level等級,查詢出對應等級的商品分類資訊
- URL:/itemCat/findItemCatList/{level}
- 請求型別:get
- 接收引數:level
- 回傳值:SysResult物件
Controller層:
@GetMapping("/findItemCatList/{level}")
public SysResult findItemCatList(@PathVariable Integer level){
List<ItemCat> itemCatList = itemCatService.findItemCatList(level);
return SysResult.success(itemCatList);
}
Service層:
方式1:利用map集合封裝所有的父子級關系
public List<ItemCat> findItemCatList(Integer level) {
long start = System.currentTimeMillis();
//map集合封裝的是所有父子級關系
Map<Integer,List<ItemCat>> map = initMap();
//只獲取一級,即parend_id=0
if (level == 1) return map.get(0);
//獲取二級 1/2
if (level == 2) return getLevel2List(map);
//獲取1/2/3級
else return getLevel3List(map);
}
/**
* 1.封裝Map集合 Map<父級id,list<ItemCat>,value里的資料是key對應資料的子級,只有父子級關系(并不是一二級)
* 只查詢一次資料庫,作為輔助方法
* @return
*/
public Map<Integer, List<ItemCat>> initMap() {
Map<Integer,List<ItemCat>> map = new HashMap<>();
//1.查詢item_cat表中的所有記錄(1/2/3級選單)
List<ItemCat> itemCatList = itemCatMapper.selectList(null);
//2.實作資料封裝
/**
* 1.key不存在,準備一個新的list集合,直接追加到list集合
* 2.key存在,獲取原有list集合,再追加
*/
for (ItemCat itemCat: itemCatList){
//key存在,獲取原有list集合,再追加
if (map.containsKey(itemCat.getParentId()))
map.get(itemCat.getParentId()).add(itemCat);
//key不存在,準備一個新的list集合,直接追加到list集合
else {
List<ItemCat> list = new ArrayList<>();
list.add(itemCat);
map.put(itemCat.getParentId(), list);
}
}
return map;//將封裝的資料進行回傳
}
//查詢一級和二級資訊
public List<ItemCat> getLevel2List(Map<Integer, List<ItemCat>> map) {
//先遍歷一級,再封裝二級
//1.獲取一級
List<ItemCat> oneList = map.get(0);
for (ItemCat oneItemCat: oneList){
//查詢二級,通過一級的id
List<ItemCat> twoList = map.get(oneItemCat.getId());
oneItemCat.setChildren(twoList);
}
return oneList;
}
//查詢一級/二級/三級
public List<ItemCat> getLevel3List(Map<Integer, List<ItemCat>> map) {
List<ItemCat> oneList = getLevel2List(map);
//遍歷一級,獲取二級
for (ItemCat oneItemCat: oneList){
List<ItemCat> twoList = oneItemCat.getChildren();
//如果當前一級沒有二級,直接跳過當前回圈
if (twoList == null || twoList.size() == 0) continue;
//若一級下面有二級,則查詢三級
for (ItemCat twoItemCat: twoList){
List<ItemCat> threeList = map.get(twoItemCat.getId());//獲取以二級id為父級的子級
twoItemCat.setChildren(threeList);//封裝為二級的子級
}
}
return oneList;
}
方式2:利用多重for回圈
public List<ItemCat> findItemCatList(Integer level) {
//1.查詢一級商品分類資訊
QueryWrapper<ItemCat> qw = new QueryWrapper<>();
qw.eq("parent_id", 0);
List<ItemCat> oneLists = itemCatMapper.selectList(qw);
for (ItemCat oneItemCat: oneLists){
qw.clear();
qw.eq("parent_id", oneItemCat.getId());
List<ItemCat> twoLists = itemCatMapper.selectList(qw);
//不能再次將二級記錄封裝給一級,如果在這里封裝,則二級的children為null
//oneItemCat.setChildren(twoLists);
for (ItemCat twoItemCat: twoLists){
qw.clear();
qw.eq("parent_id", twoItemCat.getId());
List<ItemCat> threeLists = itemCatMapper.selectList(qw);
//將三級記錄封裝給二級
twoItemCat.setChildren(threeLists);
}
//將二級記錄封裝給一級
oneItemCat.setChildren(twoLists);
}
return oneLists;
}
常識:用戶第一次查詢資料庫,需要建立鏈接,相對耗時長,但是后續查詢是直接從鏈接池中動態獲取鏈接,速度明顯會加快.
for回圈操作性能低:查詢資料庫的次數與for回圈的層數和每層次數相關.
封裝map集合:只查詢一次資料庫,作為輔助集合,后續業務都是對map集合進行相關操作,就不需要建立鏈接了,性能大幅度提高.
洗掉商品等級分類資訊
- 需求:按照level商品等級資訊,洗掉對應id分類資訊
- URL:/itemCat/deleteItemCat + id/level
- 請求型別:delete
- 接收引數:ItemCat物件
- 回傳值:SysResult
Controller層:
@DeleteMapping("/deleteItemCat")
public SysResult deleteItemCat(ItemCat itemCat){
itemCatService.deleteItemCat(itemCat);
return SysResult.success();
}
Service層:
@Transactional//添加事務
public void deleteItemCat(ItemCat itemCat) {
if (itemCat.getLevel() == 3) itemCatMapper.deleteById(itemCat.getId());
if (itemCat.getLevel() == 2) {
/*方式1
QueryWrapper<ItemCat> qw = new QueryWrapper<>();
qw.eq("parent_id", itemCat.getId());//只是洗掉當前二級下的所有三級資料,不用遍歷所有的二級
List<ItemCat> threeList = itemCatMapper.selectList(qw);
//遍歷洗掉三級*/
//方式2
QueryWrapper<ItemCat> qw = new QueryWrapper<>();
qw.eq("parent_id",itemCat.getId());
itemCatMapper.delete(qw);//洗掉三級
itemCatMapper.deleteById(itemCat.getId());//直接洗掉二級
}
else {//先刪3,再刪2,再刪1
List<Integer> ids = new ArrayList<>();//用于存放要洗掉的二級id
//1.查詢當前一級下的所有二級
QueryWrapper<ItemCat> qw = new QueryWrapper<>();
qw.eq("parent_id", itemCat.getId());
List<ItemCat> twoList = itemCatMapper.selectList(qw);
//2.根據2級刪3級
for (ItemCat twoItemCat: twoList){
qw.clear();
qw.eq("parent_id", twoItemCat.getId());
itemCatMapper.delete(qw);
/*//3.洗掉當前2級,每次回圈都要連接資料庫,可以優化
itemCatMapper.deleteById(twoItemCat.getId());*/
ids.add(twoItemCat.getId());//將要洗掉的二級id存入集合
}
//3.一次性洗掉二級,不用在回圈里面一個一個洗掉二級了
itemCatMapper.deleteBatchIds(ids);
//4.洗掉1級
itemCatMapper.deleteById(itemCat.getId());
}
}
權限管理
資料統計
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/293202.html
標籤:其他
