從零開始的SpringBoot前後端分離入門級專案(二)

2020-09-22 11:00:36

正文

上回我們已經將專案建立好並且引入了本次專案所需要用到的依賴,這次我們就正式進入專案的編寫

編寫啟動類及組態檔

啟動類

在java資料夾下新建兩級目錄並建立MainApplication.class
目錄

啟動類
按照上述步驟建立並編寫完啟動類後就可以開始組態檔的建立了。

組態檔

在resources目錄下建立application.yml作為SpringBoot的組態檔

server:
  port: 8090 #監聽埠為8090
spring:
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource #設定資料庫連線池為Druid
    driver-class-name: com.mysql.cj.jdbc.Driver  #設定資料庫
    username: 資料庫使用者名稱
    password: 資料庫登入密碼
    url: jdbc:mysql://127.0.0.1:3306/資料庫名?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai

請注意對齊,以免發生錯誤。

啟動測試

完成上述兩個步驟後一個最簡易的SpringBoot專案就搭建完成了!這時我們右鍵主啟動類直接啟動專案看見如下圖所示,就已經成功在8090埠啟動了我們的SpringBoot專案了
在這裡插入圖片描述

搭建專案的基本框架

在完成啟動測試之後我們將整個專案停止,並繼續完善我們專案的骨架,熟悉JavaEE的同學都知道在一個JavaWeb專案中主要有下圖所示的幾個包
項目骨架
注意:請將這些包與主啟動類平級建立,以免後面SpringBoot無法掃描到相應的包。
不同包的作用就不在此贅述,接下來我們將從統一請求返回體開始進行專案的編寫。

統一請求返回體(統一請求響應體)

目前Web專案一般是採用前後端分離的架構,使用Json格式資料作為前後端溝通的橋樑,那麼我們在每次響應請求時都需要返回一個Json格式的資料給前端,如果每次手動拼接資料會產生很多冗餘程式碼於是我們利用一個統一的返回物件對返回格式進行統一。在model包下新建bean包並建立CommonResult類,類中的程式碼如下

CommonResult

/**
 * @author Alfalfa99
 * @Date 2020/9/13 14:00
 * @Version 1.0
 * 統一請求返回體
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
public class CommonResult<T> {
    private Integer code;
    private String message;
    private T data;
}

為了減少重複的get/set方法,我們使用了Lombok中的 @Data @AllArgsConstructor @NoArgsConstructor三個註解幫助我們自動生成get/set方法以及全參/無參構造方法。
注意:如果適用的舊版的idea請注意升級到較新版本的idea,以免idea中的Lombok外掛過久出錯,如果是第一次使用Lombok請前往idea中的外掛市場搜尋並下載Lombok外掛,以免執行時出錯。
那麼我們的統一請求返回體就已經編寫完畢了,類中有三個欄位

  1. Code:用於向前端返回約定好的狀態碼
  2. message:用於向前端返回一個訊息
  3. data:用於向前端返回真正需要的資料

接下來我們需要做兩件事情,一件事情是約定好狀態碼,另一件事情是編寫分頁結果類。

約定狀態碼

通常而言HTTP請求有常用狀態碼如200 OK,404 Not Found 等錯誤,但是這在開發中常常不足以滿足我們的全部需求,於是我們需要自定義所需的狀態碼

  1. 20000:表示一切正常
  2. 40000-4xxxx:表示程式出現如使用者未登入等問題
  3. 50000:表示程式出現預料外的錯誤,這時候應該記錄到伺服器紀錄檔
    這部分內容將會在後面的全域性例外處理類中詳細講述。

分頁結果類

在上文中我們說到了統一請求返回體CommonResult ,但是在實際編寫程式碼時我們會遇到一些問題,比如說對搜尋結果進行分頁,前端就要求我們返回結果總數和分頁的數量以及當前頁的結果,那這個時候我們只使用一個data欄位是無法完成這樣的需求的,所以我們需要將其封裝成一個分頁結果類PageResult。在bean包中新建PageResult類,類中程式碼如下

/**
 * @Author Alfalfa99
 * @Date 2020/9/17 11:02
 * @Version 1.0
 * 分頁返回類
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
public class PageResult <T> {
    private long pages;
    private long total;
    private List<T> rows;
}

在分頁結果類中我們同樣使用了Lombok,在這裡就不在贅述了,我們將分頁數,結果總數以及當前頁的資料作為欄位在查詢出結果之後先包裝到PageResult中再將PageResult包裝到上文所述的CommonResult中,由此我們的分頁結果類就完成了。

全域性例外處理類

在一個Web專案執行時總會出現各種各樣的異常,出現異常時我們應該根據異常的等級對其進行紀錄檔記錄,常用的工具有log4j,slf4j等,在本專案中就不對紀錄檔記錄進行詳細的講解也不去進行錯誤的記錄,僅將其丟擲到前端並由前端對使用者進行展示。
言歸正傳,在初學JavaSE時出現了異常我們常常將其列印到控制檯,但是在Web專案中如果直接將錯誤資訊輸出到使用者瀏覽器將是非常不明智且不美觀的,由此我們利用Spring框架中自帶的一個註解@RestControllerAdvice進行全域性異常的處理。

GlobalException

首先我們在與主啟動類同級的目錄下建立一個新的包exception,並在包中建立一個名為GlobalException的全域性例外處理類。
在這裡插入圖片描述
類中的內容為:

/**
 * @Author Alfalfa99
 * @Date 2020/9/13 13:59
 * @Version 1.0
 * 全域性例外處理類
 */
@RestControllerAdvice
public class GlobalException {

    /**
     * 捕獲所有(Exception.class)中的異常並通過下面的方法返回
     *
     * @param e 錯誤型別
     * @return 給前端返回報錯資訊
     */
    @ExceptionHandler(value = Exception.class)
    public CommonResult<String> toHandlerException(Exception e) {
        //開發模式下將錯誤資訊列印到控制檯便與偵錯
        e.printStackTrace();
        if (e instanceof MethodArgumentNotValidException) {
            //引數驗證錯誤
            return new CommonResult<>(40001, "Error", "引數驗證錯誤");
        } else if (e instanceof HttpRequestMethodNotSupportedException) {
            //請求方法有誤
            return new CommonResult<>(40002, "ERROR", "錯誤的請求方法");
        } else if (e instanceof HttpMessageNotReadableException) {
            //請求體錯誤
            return new CommonResult<>(40003, "ERROR", "錯誤的請求體");
        } else if (e instanceof IllegalArgumentException) {
            //錯誤的引數
            return new CommonResult<>(40004, "ERROR", "錯誤的請求引數");
        } else if (e instanceof AccessDeniedException) {
            //使用者許可權不足
            return new CommonResult<>(40005, "Error", e.getMessage());
        } else if (e instanceof BadCredentialsException) {
            //Token令牌過期
            return new CommonResult<>(40010, "Error", e.getMessage());
        } else if (e instanceof InternalAuthenticationServiceException) {
            //使用者名稱或密碼錯誤
            return new CommonResult<>(40011, "Error", e.getMessage());
        } else if (e instanceof DisabledException) {
            //賬號被封禁
            return new CommonResult<>(40012, "Error", e.getMessage());
        } else if (e instanceof AuthenticationCredentialsNotFoundException) {
            //使用者未登入
            return new CommonResult<>(40013, "Error", e.getMessage());
        } else if (e instanceof DuplicateKeyException) {
            //使用者名稱重複
            return new CommonResult<>(40014, "ERROR", e.getMessage());
        } else {
            return new CommonResult<>(50000, "Error", "你觸發了一個未知錯誤!");
        }
    }
}

從程式碼可以看到我們利用了@RestControllerAdvice註解註冊了一個全域性異常類,使用@ExceptionHandler註解捕獲一個特定種類的錯誤,方便起見這裡直接捕獲的是Exception.class,在你的專案中你可以個性化的捕獲不同的異常執行不同的操作。該類的內容比較簡單易懂,不去囉嗦。那麼專案的基本框架我們已經搭建完成了,在下一篇部落格我們將會進入到model的編寫和利用jwt進行許可權的驗證。