一個基於Spring Boot的API、Restful API種子項目搭建

前言

參考博客一個基於Spring Boot的API、RESTful API項目種子(骨架)

最近使用Spring Boot 配合 MyBatis 、通用Mapper插件、PageHelper分頁插件 連做了幾個中小型API項目,做下來覺得這套框架、工具搭配起來開發這種項目確實非常舒服,團隊的反響也不錯。在項目搭建和開發的過程中也總結了一些小經驗,與大家分享一下。

在開發一個API項目之前,搭建項目、引入依賴、配置框架這些基礎活自然不用多說,通常爲了加快項目的開發進度(早點回家)還需要封裝一些常用的類和工具,比如統一的響應結果封裝、統一的異常處理、接口簽名認證、基礎的增刪改差方法封裝、基礎代碼生成工具等等,有了這些項目才能開工。

然而,下次再做類似的項目上述那些步驟可能還要搞一遍,雖然通常是拿過來改改,但是還是比較浪費時間。所以,可以利用面向對象抽象、封裝的思想,抽取這類項目的共同之處封裝成了一個種子項目(估計大部分公司都會有很多類似的種子項目),這樣的話下次再開發類似的項目直接在該種子項目上迭代就可以了,減少無意義的重複工作。

我在此基礎上自個兒再DIY了一些功能,把lenosp腳手架添加進來,爲了方便開發後臺管理系統而不只是編寫API接口。大部分應用都需要後臺管理系統的支持,而有一套通用的後臺管理系統模板會很方便,這裏使用lenosp腳手架,大家可以進入Gitee瞭解該項目:Gitee/一枚碼農/lenosp

因此我使用的種子項目是基於Maven多模塊開發的,整體骨架使用的是lenosp的設計,在上面擴展自己額外的功能。

特徵&提供

以下只對我自己新添加的一些特徵、配置進行簡要介紹。若要詳細理解種子項目,請移步我的另外一篇博客(製作中…)

  • 最佳實踐的項目結構、配置文件、精簡POM

  • 統一響應結果封裝及生成工具

因爲要給前端返回json格式的數據,這裏需要定義 統一返回碼、返回結果實體類。參考博客統一返回碼,返回結果實體類

  1. Result返回結果集封裝
@Data
@NoArgsConstructor
public class Result<T> implements Serializable{

    private boolean success;//是否成功
    private Integer code;// 返回碼
    private String message;//返回信息
    private T data;// 返回數據

    public Result(ResultCode code) {
        this.success = code.success;
        this.code = code.code;
        this.message = code.message;
    }

    public Result(ResultCode code,T data) {
        this.success = code.success;
        this.code = code.code;
        this.message = code.message;
        this.data = data;
    }

    public Result(Integer code,String message,boolean success) {
        this.code = code;
        this.message = message;
        this.success = success;
    }

    public static Result SUCCESS(){
        return new Result(ResultCode.SUCCESS);
    }

    public static Result ERROR(){
        return new Result(ResultCode.SERVER_ERROR);
    }

    public static Result FAIL(){
        return new Result(ResultCode.FAIL);
    }
}
  1. ResultCode狀態碼封裝
public enum ResultCode {

    SUCCESS(true,10000,"操作成功!"),
    //---系統錯誤返回碼-----
    FAIL(false,10001,"操作失敗"),
    UNAUTHENTICATED(false,10002,"您還未登錄"),
    UNAUTHORISE(false,10003,"權限不足"),
    SERVER_ERROR(false,99999,"抱歉,系統繁忙,請稍後重試!");

    //操作是否成功
    boolean success;
    //操作代碼
    int code;
    //提示信息
    String message;

    ResultCode(boolean success,int code, String message){
        this.success = success;
        this.code = code;
        this.message = message;
    }

    public boolean success() {
        return success;
    }

    public int code() {
        return code;
    }

    public String message() {
        return message;
    }
}
  • 統一異常處理
@RestControllerAdvice
public class GlobalExceptionHandler {

    private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);

    @ExceptionHandler(UnauthorizedException.class)
    public Result handleShiroException(Exception ex) {
        return new Result(10001,"無權訪問該資源",false);
    }

    @ExceptionHandler(AuthorizationException.class)
    public Result AuthorizationException(Exception ex) {
        return new Result(10001,"權限認證失敗",false);
    }
    /**
     * 默認統一異常處理方法
     * @ExceptionHandler 註解用來配置需要攔截的異常類型, 也可以是自定義異常
     */
    @ExceptionHandler(Exception.class)
    public Result runtimeExceptionHandler(Exception exception, HttpServletResponse response) {
        logger.error("請求出現未知異常,異常信息爲: {}", exception.getMessage());
        return new Result(10001,"請求出現未知異常,異常信息爲:"+exception.getMessage(),false);
    }

    @ExceptionHandler(MethodArgumentNotValidException.class)
    public Result handleBindException(MethodArgumentNotValidException ex) {
        /*
        // 返回所有參數效驗錯誤信息
        StringBuilder errMsg = new StringBuilder();
        List<ObjectError> allErrors = ex.getBindingResult().getAllErrors();
        for (ObjectError allError : allErrors) {
            errMsg.append(allError.getDefaultMessage()).append(",");
        }
        return ResponseMessage.newErrorInstance(errMsg.toString());
         */
        // 只返回一條參數校驗異常信息
        FieldError fieldError = ex.getBindingResult().getFieldError();
        assert fieldError != null;
        logger.info("參數校驗異常:{}({})", fieldError.getDefaultMessage(),fieldError.getField());
        return new Result(10001,fieldError.getDefaultMessage(),false);
    }

    @ExceptionHandler(BindException.class)
    public Result handleBindException(BindException ex) {
        logger.info("參數校驗異常:{}", ex.getMessage());
        return new Result(10001,ex.getMessage(),false);
    }

    @ExceptionHandler(ConstraintViolationException.class)
    public Result handleBindException(ConstraintViolationException ex) {
        logger.info("參數校驗異常:{}", ex.getMessage());
        return new Result(10001,ex.getMessage(),false);
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章