Web層通用數據處理之統一異常處理@ExceptionHandler


  實際開發過程中會遇到對dao層、service層和controller層拋出的異常統一處理,對每個模塊的方法進行異常處理也能解決問題,但這樣是不合理的,並且代碼看起來也不雅觀,這時就可以使用@ExceptionHandler對Web層進行統一異常處理,讓異常由下往上(dao—>service—>controller)拋出。代碼如下:

import com.sand.base.core.common.BaseCommon;
import com.sand.base.core.entity.ResultEntity;
import com.sand.base.enums.ResultEnum;
import com.sand.base.exception.LsException;
import com.sand.base.util.ResultUtil;
import com.sand.base.util.editor.DateEditor;
import com.sand.base.util.editor.StringEditor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.ModelAttribute;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.util.Date;
import java.util.Objects;

/**
 * 功能說明:Web層通用數據處理
 * 開發人員:@author liusha
 * 開發日期:2019/8/26 21:43
 * 功能描述:定義所有控制器的父控制器,進行屬性綁定、數據轉換、異常處理
 */
@Slf4j
public class BaseController extends BaseCommon {
  protected HttpSession session;
  protected HttpServletRequest request;
  protected HttpServletResponse response;

  /**
   * 屬性訪問器
   *
   * @param session  session
   * @param request  request
   * @param response response
   */
  @ModelAttribute
  public void modelAttribute(HttpSession session, HttpServletRequest request, HttpServletResponse response) {
    this.session = session;
    this.request = request;
    this.response = response;
  }

  /**
   * 屬性編輯器
   *
   * @param binder 數據綁定
   */
  @InitBinder
  public void initBinder(WebDataBinder binder) {
    // Date類型轉換,幾乎支持所有的日期類型
    binder.registerCustomEditor(Date.class, new DateEditor());
    // String類型轉換,將所有傳遞進來的String進行HTML編碼,防止XSS攻擊
    binder.registerCustomEditor(String.class, new StringEditor());
  }

  /**
   * 頂級異常處理
   *
   * @param e 異常
   * @return 響應客戶端
   */
  @ExceptionHandler(Exception.class)
  public ResultEntity handleException(Exception e) {
    errorLog(e);
    return ResultUtil.error();
  }

  /**
   * 自定義異常處理
   *
   * @param e 異常
   * @return 響應客戶端
   */
  @ExceptionHandler(LsException.class)
  public ResultEntity handleLsException(LsException e) {
    errorLog(e);
    return ResultUtil.info(e.getCode(), e.getMessage());
  }

  /**
   * 參數缺失處理
   *
   * @param e 異常
   * @return 響應客戶端
   */
  @ExceptionHandler(MissingServletRequestParameterException.class)
  public ResultEntity handleMissingParamException(MissingServletRequestParameterException e) {
    errorLog(e);
    return ResultUtil.error(ResultEnum.PARAM_MISSING_ERROR);
  }

  /**
   * 讀取方法處理
   *
   * @param e 異常
   * @return 響應客戶端
   */
  @ExceptionHandler(HttpMessageNotReadableException.class)
  public ResultEntity handleMessageNotReadableException(HttpMessageNotReadableException e) {
    errorLog(e);
    return ResultUtil.error(ResultEnum.READ_METHOD_ERROR);
  }

  /**
   * 打印出錯log
   *
   * @param e 異常
   */
  private void errorLog(Exception e) {
    StackTraceElement element = e.getStackTrace()[0];
    if (e instanceof LsException) {
      log.info("異常位置:{}.{},第{}行,原因:{}", element.getClassName(), element.getMethodName(), element.getLineNumber(), e.getMessage());
      if (!Objects.isNull(e.getCause())) {
        StackTraceElement cause = e.getCause().getStackTrace()[0];
        log.info("起因:{}.{},第{}行,原因:{}", cause.getClassName(), cause.getMethodName(), cause.getLineNumber(), e.getCause().getMessage());
      }
    } else {
      log.error("錯誤位置:{}.{},第{}行,錯誤原因:{}", element.getClassName(), element.getMethodName(), element.getLineNumber(), e.getClass().getName());
    }
    log.error("錯誤信息:" + e);
  }

}

  需要注意的是,這種處理方式只對當前controller有效,也就是只有當controller繼承了BaseController才能捕獲到異常。如果希望沒有繼承BaseController的controller也能進行異常捕獲,就需要新建一個@ControllerAdvice切面類配合@ExceptionHandler進行全局異常處理(值得注意的是,其它所有的切面類需將異常拋出而不是捕獲處理,異常處理流程由統一異常處理類去完成,方便排查問題)。

  我這里只列出了其中幾種異常,異常種類遠遠不止這些,可以參考API文檔進行選擇自己需要的異常http://tool.oschina.net/apidocs/apidoc?api=Spring-3.1.1

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM