springboot 使用@ControllerAdvice註解全局處理系統異常
在日常的開發中,我們很多時候不停的使用try catch來處理異常,這樣的代碼重復性強,通過@controllerAdvice 註解來實現可以全局定義異常,大大減少代碼的try catch。
import com.vicrab.api.bean.OperateCode;
import com.vicrab.api.server.model.OperateResult;
import org.apache.shiro.authc.AuthenticationException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.TypeMismatchException;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.http.converter.HttpMessageNotWritableException;
import org.springframework.web.HttpMediaTypeNotAcceptableException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import java.io.IOException;
@ControllerAdvice
public class ControllerExceptionHandler {
private static final Logger logger = LoggerFactory.getLogger(ControllerExceptionHandler.class);
private static final String logExceptionFormat = "Capture Exception By GlobalExceptionHandler: Code: %s Detail: %s";
//運行時異常
@ExceptionHandler(RuntimeException.class)
@ResponseBody
public OperateResult runtimeExceptionHandler(RuntimeException ex) {
return exceptionFormat(OperateCode.EX_RUN, ex);
}
//空指針異常
@ExceptionHandler(NullPointerException.class)
@ResponseBody
public OperateResult nullPointerExceptionHandler(NullPointerException ex) {
return exceptionFormat(OperateCode.EX_NULL, ex);
}
//類型轉換異常
@ExceptionHandler(ClassCastException.class)
@ResponseBody
public OperateResult classCastExceptionHandler(ClassCastException ex) {
return exceptionFormat(OperateCode.EX_CAST, ex);
}
//IO異常
@ExceptionHandler(IOException.class)
@ResponseBody
public OperateResult iOExceptionHandler(IOException ex) {
return exceptionFormat(OperateCode.EX_IO, ex);
}
//未知方法異常
@ExceptionHandler(NoSuchMethodException.class)
@ResponseBody
public OperateResult noSuchMethodExceptionHandler(NoSuchMethodException ex) {
return exceptionFormat(OperateCode.EX_NO_SUCH_METHOD, ex);
}
//數組越界異常
@ExceptionHandler(IndexOutOfBoundsException.class)
@ResponseBody
public OperateResult indexOutOfBoundsExceptionHandler(IndexOutOfBoundsException ex) {
return exceptionFormat(OperateCode.EX_INDEX_OUT_OF_BOUNDNS, ex);
}
//400錯誤
@ExceptionHandler({HttpMessageNotReadableException.class})
@ResponseBody
public OperateResult requestNotReadable(HttpMessageNotReadableException ex) {
logger.error("400..requestNotReadable");
return exceptionFormat(OperateCode.BAD_REQUEST, ex);
}
//400錯誤
@ExceptionHandler({TypeMismatchException.class})
@ResponseBody
public OperateResult requestTypeMismatch(TypeMismatchException ex) {
logger.error("400..TypeMismatchException");
return exceptionFormat(OperateCode.BAD_REQUEST, ex);
}
//400錯誤
@ExceptionHandler({MissingServletRequestParameterException.class})
@ResponseBody
public OperateResult requestMissingServletRequest(MissingServletRequestParameterException ex) {
logger.error("400..MissingServletRequest");
return exceptionFormat(OperateCode.BAD_REQUEST, ex);
}
//405錯誤
@ExceptionHandler({AuthenticationException.class})
@ResponseBody
public OperateResult request401(AuthenticationException ex) {
return exceptionFormat(OperateCode.UNAUTHORIZED, ex);
}
//405錯誤
@ExceptionHandler({HttpRequestMethodNotSupportedException.class})
@ResponseBody
public OperateResult request405(HttpRequestMethodNotSupportedException ex) {
return exceptionFormat(OperateCode.METHOD_NOT_ALLOWED, ex);
}
//406錯誤
@ExceptionHandler({HttpMediaTypeNotAcceptableException.class})
@ResponseBody
public OperateResult request406(HttpMediaTypeNotAcceptableException ex) {
logger.error("406...");
return exceptionFormat(OperateCode.NOT_ACCEPTABLE, ex);
}
//500錯誤
@ExceptionHandler({ConversionNotSupportedException.class, HttpMessageNotWritableException.class})
@ResponseBody
public OperateResult server500(RuntimeException ex) {
logger.error("500...");
return exceptionFormat(OperateCode.INTERNAL_SERVER_ERROR, ex);
}
//棧溢出
@ExceptionHandler({StackOverflowError.class})
@ResponseBody
public OperateResult requestStackOverflow(StackOverflowError ex) {
return exceptionFormat(OperateCode.EX_STACK_OVER_FLOW, ex);
}
//其他錯誤
@ExceptionHandler({Exception.class})
@ResponseBody
public OperateResult exception(Exception ex) {
return exceptionFormat(OperateCode.EX_OTHER, ex);
}
private <T extends Throwable> OperateResult exceptionFormat(OperateCode operateCode, T ex) {
logger.error(String.format(logExceptionFormat, operateCode, ex));
return OperateResult.exception(operateCode, ex);
}
}
@ExceptionHandler 用來定義異常的類型,這裏面列舉了空指針異常等,其實還可以實現自定義異常,比如
public class MyException extends RuntimeException {
public MyException(String code, String msg) {
this.code = code;
this.msg = msg;
}
private String code;
private String msg;
// getter & setter
}
import org.springframework.ui.Model;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.*;
import java.util.HashMap;
import java.util.Map;
@ControllerAdvice
public class MyControllerAdvice {
/**
* 全局異常捕捉處理
* @param ex
* @return
*/
@ResponseBody
@ExceptionHandler(value = Exception.class)
public Map errorHandler(Exception ex) {
Map map = new HashMap();
map.put("code", 100);
map.put("msg", ex.getMessage());
return map;
}
@ResponseBody
@ExceptionHandler(value = MyException.class)
public Map myErrorHandler(MyException ex) {
Map map = new HashMap();
map.put("code", ex.getCode());
map.put("msg", ex.getMsg());
return map;
}
}
controller中拋出異常進行測試。
@RequestMapping("/home")
public String home() throws Exception {
// throw new Exception("Sam 錯誤");
throw new MyException("101", "Sam 錯誤");
}
啟動應用,訪問:http://localhost:8080/home
springboot 使用@ControllerAdvice註解全局處理系統異常