異常處理-異常處理的問題分析

1-異常處理-異常處理的問題分析

參考文檔:

https://blog.csdn.net/kinginblue/article/details/70186586

自定義異常:

1:
10001 非法參數
10002 參數缺失

2:
2001 數據庫異常
2003 網絡異常

從添加頁面的service方法中找問題:

//添加頁面
public CmsPageResult add(CmsPage cmsPage){
	//校驗頁面是否存在,根據頁面名稱、站點Id、頁面webpath查詢
	CmsPage cmsPage1 = cmsPageRepository.findByPageNameAndSiteIdAndPageWebPath(cmsPage.getPageName(), cmsPage.getSiteId(), cmsPage.getPageWebPath());
    
    if(cmsPage1==null){
        cmsPage.setPageId(null);//添加頁面主鍵由spring data 自動生成
        cmsPageRepository.save(cmsPage);
        //返回結果
        CmsPageResult cmsPageResult = new CmsPageResult(CommonCode.SUCCESS,cmsPage);
        return cmsPageResult;
    }
    return new CmsPageResult(CommonCode.FAIL,null);
}

問題:

1、上邊的代碼只要操作不成功僅向用戶返回“錯誤代碼:11111,失敗信息:操作失敗”,無法區別具體的錯誤信
息。
2、service方法在執行過程出現異常在哪捕獲?在service中需要都加try/catch,如果在controller也需要添加
try/catch,代碼冗餘嚴重且不易維護。

解決方案:

1、在Service方法中的編碼順序是先校驗判斷,有問題則拋出具體的異常信息,最後執行具體的業務操作,返回成
功信息。
2、在統一異常處理類中去捕獲異常,無需controller捕獲異常,向用戶返回統一規範的響應信息。

//添加頁面
public CmsPageResult add(CmsPage cmsPage){
    //校驗cmsPage是否爲空
    if(cmsPage == null){
    	//拋出異常,非法請求
    	//...
    }
    //根據頁面名稱查詢(頁面名稱已在mongodb創建了唯一索引)
    CmsPage cmsPage1 =
    cmsPageRepository.findByPageNameAndSiteIdAndPageWebPath(cmsPage.getPageName(),
    cmsPage.getSiteId(), cmsPage.getPageWebPath());
    
    //校驗頁面是否存在,已存在則拋出異常
    if(cmsPage1 !=null){
    	//拋出異常,已存在相同的頁面名稱
    	//...
    }
    
    cmsPage.setPageId(null);//添加頁面主鍵由spring data 自動生成
    CmsPage save = cmsPageRepository.save(cmsPage);
    //返回結果
    CmsPageResult cmsPageResult = new CmsPageResult(CommonCode.SUCCESS,save);
    return cmsPageResult;
}

2-異常處理-異常處理流程

系統對異常的處理使用統一的異常處理流程:

1、自定義異常類型。
2、自定義錯誤代碼及錯誤信息。
3、對於可預知的異常由程序員在代碼中主動拋出,由SpringMVC統一捕獲。
可預知異常是程序員在代碼中手動拋出本系統定義的特定異常類型,由於是程序員拋出的異常,通常異常信息比較
齊全,程序員在拋出時會指定錯誤代碼及錯誤信息,獲取異常信息也比較方便。
4、對於不可預知的異常(運行時異常)由SpringMVC統一捕獲Exception類型的異常。
不可預知異常通常是由於系統出現bug、或一些不要抗拒的錯誤(比如網絡中斷、服務器宕機等),異常類型爲
RuntimeException類型(運行時異常)。
5、可預知的異常及不可預知的運行時異常最終會採用統一的信息格式(錯誤代碼+錯誤信息)來表示,最終也會隨請求響應給客戶端。``

異常拋出及處理流程:

在這裏插入圖片描述

1、在controller、service、dao中程序員拋出自定義異常;springMVC框架拋出框架異常類型
2、統一由異常捕獲類捕獲異常,並進行處理
3、捕獲到自定義異常則直接取出錯誤代碼及錯誤信息,響應給用戶。
4、捕獲到非自定義異常類型首先從Map中找該異常類型是否對應具體的錯誤代碼,如果有則取出錯誤代碼和錯誤
信息並響應給用戶,如果從Map中找不到異常類型所對應的錯誤代碼則統一爲99999錯誤代碼並響應給用戶。
5、將錯誤代碼及錯誤信息以Json格式響應給用戶。

3-異常處理-可預知異常處理-自定義異常類型和拋出類

CustomException.java

/**
 * 自定義異常類
 */
public class CustomException extends RuntimeException {

    private ResultCode resultCode;

    public CustomException(ResultCode resultCode) {
        //異常信息爲錯誤代碼+異常信息
        super("錯誤代碼:" + resultCode.code() + "錯誤信息:" + resultCode.message());
        this.resultCode = resultCode;
    }

    public ResultCode getResultCode() {
        return this.resultCode;
    }
}

ExceptionCast.java

public class ExceptionCast {

    //使用此靜態方法拋出自定義異常
    public static void cast(ResultCode resultCode){
        throw new CustomException(resultCode);
    }
}

ExceptionCatch.java

/**
 * 統一異常捕獲類
 *
 * 在spring 3.2中,新增了@ControllerAdvice 註解,
 * 可以用於定義@ExceptionHandler、@InitBinder、@ModelAttribute,並應用到所有@RequestMapping中。
 */
@ControllerAdvice // 控制器增強
public class ExceptionCatch {

    private static final Logger LOGGER = LoggerFactory.getLogger(ExceptionCatch.class);

    //捕獲 CustomException異常
    @ExceptionHandler(CustomException.class)
    @ResponseBody
    public ResponseResult customException(CustomException e) {
        // 記錄日誌
        LOGGER.error("catch exception : {} exception: ",e.getMessage(), e);
        ResultCode resultCode = e.getResultCode();
        ResponseResult responseResult = new ResponseResult(resultCode);
        return responseResult;
    }
}

在這裏插入圖片描述

4-異常處理-可預知異常處理-異常處理測試

PageService.java

在add()的代碼中加入異常處理:

//校驗cmsPage是否爲空
if(cmsPage1 != null){
	//拋出異常,非法請求
	ExceptionCast.cast(CmsCode.CMS_ADDPAGE_EXISTSNAME);
}

CmsCode.java

@ToString
public enum CmsCode implements ResultCode {
    CMS_ADDPAGE_EXISTSNAME(false,24001,"頁面名稱已存在!"),
    CMS_GENERATEHTML_DATAURLISNULL(false,24002,"從頁面信息中找不到獲取數據的url!"),
    CMS_GENERATEHTML_DATAISNULL(false,24003,"根據頁面的數據url獲取不到數據!"),
    CMS_GENERATEHTML_TEMPLATEISNULL(false,24004,"頁面模板爲空!"),
    CMS_GENERATEHTML_HTMLISNULL(false,24005,"生成的靜態html爲空!"),
    CMS_GENERATEHTML_SAVEHTMLERROR(false,24005,"保存靜態html出錯!"),
    CMS_COURSE_PERVIEWISNULL(false,24007,"預覽頁面爲空!");
    //操作代碼
    boolean success;
    //操作代碼
    int code;
    //提示信息
    String message;
    private CmsCode(boolean success, int code, String message){
        this.success = success;
        this.code = code;
        this.message = message;
    }

    @Override
    public boolean success() {
        return success;
    }

    @Override
    public int code() {
        return code;
    }

    @Override
    public String message() {
        return message;
    }
}

ManageCmsApplication.java

在覈心啓動類上加入包掃描,去掃描common項目的包

@SpringBootApplication
@EntityScan("com.yunke.framework.domain.cms")//掃描實體類
@ComponentScan(basePackages={"com.yunke.api"})//掃描接口
@ComponentScan(basePackages={"com.yunke.framework"})//掃描common包下的類
@ComponentScan(basePackages={"com.yunke.manage_cms"})//掃描本項目下的所有類
public class ManageCmsApplication {
    public static void main(String[] args) {
        SpringApplication.run(ManageCmsApplication.class,args);
    }
}

測試

當出現重複頁面的時候,無法進行保存,錯誤提示也是我們自己定義的了.

在這裏插入圖片描述

5-異常處理-不可預知異常處理

ExceptionCatch.java

//使用EXCEPTIONS存放異常類型和錯誤代碼的映射,ImmutableMap的特點的一旦創建不可改變,並且線程安全
private static ImmutableMap<Class<? extends Throwable>,ResultCode> EXCEPTIONS;

//使用builder來構建一個異常類型和錯誤代碼的異常
protected static ImmutableMap.Builder<Class<? extends Throwable>,ResultCode> builder = ImmutableMap.builder();

static{
    //在這裏加入一些基礎的異常類型判斷
    builder.put(HttpMessageNotReadableException.class,CommonCode.INVALID_PARAM);
}

//捕獲Exception異常
@ResponseBody
@ExceptionHandler(Exception.class)
public ResponseResult exception(Exception e) {
    LOGGER.error("catch exception : {} \r\n exception: ",e.getMessage(), e);
    if(EXCEPTIONS == null) {
        EXCEPTIONS = builder.build(); // EXCEPTIONS構建完畢
    }
    // 從EXCEPTIONS中尋找異常類型對應的錯誤代碼,如果找到了將錯誤代碼響應給用戶,如果找不到就返回給用戶9999
    final ResultCode resultCode = EXCEPTIONS.get(e.getClass());

    if (resultCode != null) {
        return new ResponseResult(resultCode);
    } else {
        return new ResponseResult(CommonCode.SERVER_ERROR);
    }
}		

CommonCode.java

@ToString
public enum CommonCode implements ResultCode{

    INVALID_PARAM(false,10003,"非法參數!"),
}

測試效果

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章