SpringBoot的全域性異常處理
阿新 • • 發佈:2019-02-04
今天講解一下如何在SpringBoot實現全域性異常機制,在沒有用springboot大家要實現這一的功能基本上都是通過aop的思想,還是有點麻煩,而現在springboot中對它要進行了一次封裝,開發者使用起來更加的簡單,接下先通過程式碼演示效果,然後再分析一下原理,好了廢話不多說直接上程式碼,看程式碼結構:
看一下對應的Pom.xml檔案內容:
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <artifactId>spring_boot_exception</artifactId> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.2.RELEASE</version> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> </properties> <dependencies> <!-- --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.16.18</version> </dependency> <!-- https://mvnrepository.com/artifact/com.alibaba/fastjson --> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.44</version> </dependency> <!--支援web開發--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> </dependencies> </project>
定義一個封裝json的工具類,使用阿里巴巴的fastjson:
package com.springboot.exception.json; import com.alibaba.fastjson.JSON; import lombok.Data; import java.io.Serializable; import java.util.HashMap; import java.util.Map; /** * lombok格式化資料 */ @Data public class JsonResult implements Serializable{ private int code; //返回碼 非0即失敗 private String msg; //訊息提示 private Map<String, Object> data; //返回的資料 public JsonResult(){}; public JsonResult(int code, String msg, Map<String, Object> data) { this.code = code; this.msg = msg; this.data = data; } public static String success() { return success(new HashMap(0)); } public static String success(Map<String, Object> data) { return JSON.toJSONString(new JsonResult(0, "解析成功", data)); } public static String failed() { return failed("解析失敗"); } public static String failed(String msg) { return failed(-1, msg); } public static String failed(int code, String msg) { return JSON.toJSONString(new JsonResult(code, msg, new HashMap(0))); } }
接下來定義一個全域性異常處理類:
package com.springboot.exception.global_excep; import com.springboot.exception.json.JsonResult; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.ConversionNotSupportedException; 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.HttpRequestMethodNotSupportedException; 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; /** * @Author 18011618 * @Description 全域性異常攔截器 * @Date 16:38 2018/7/5 * @Modify By */ @ControllerAdvice @ResponseBody public class GlobalExceptionHandler { private static final String logExceptionFormat = "Capture Exception By GlobalExceptionHandler: Code: %s Detail: %s"; private static Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class); //執行時異常 @ExceptionHandler(RuntimeException.class) public String runtimeExceptionHandler(RuntimeException ex) { return resultFormat(1, ex); } //空指標異常 @ExceptionHandler(NullPointerException.class) public String nullPointerExceptionHandler(NullPointerException ex) { System.err.println("NullPointerException:"); return resultFormat(2, ex); } //型別轉換異常 @ExceptionHandler(ClassCastException.class) public String classCastExceptionHandler(ClassCastException ex) { return resultFormat(3, ex); } //IO異常 @ExceptionHandler(IOException.class) public String iOExceptionHandler(IOException ex) { return resultFormat(4, ex); } //未知方法異常 @ExceptionHandler(NoSuchMethodException.class) public String noSuchMethodExceptionHandler(NoSuchMethodException ex) { return resultFormat(5, ex); } //陣列越界異常 @ExceptionHandler(IndexOutOfBoundsException.class) public String indexOutOfBoundsExceptionHandler(IndexOutOfBoundsException ex) { return resultFormat(6, ex); } //400錯誤 @ExceptionHandler({HttpMessageNotReadableException.class}) public String requestNotReadable(HttpMessageNotReadableException ex) { System.out.println("400..requestNotReadable"); return resultFormat(7, ex); } //400錯誤 @ExceptionHandler({TypeMismatchException.class}) public String requestTypeMismatch(TypeMismatchException ex) { System.out.println("400..TypeMismatchException"); return resultFormat(8, ex); } //400錯誤 @ExceptionHandler({MissingServletRequestParameterException.class}) public String requestMissingServletRequest(MissingServletRequestParameterException ex) { System.out.println("400..MissingServletRequest"); return resultFormat(9, ex); } //405錯誤 @ExceptionHandler({HttpRequestMethodNotSupportedException.class}) public String request405(HttpRequestMethodNotSupportedException ex) { return resultFormat(10, ex); } //406錯誤 @ExceptionHandler({HttpMediaTypeNotAcceptableException.class}) public String request406(HttpMediaTypeNotAcceptableException ex) { System.out.println("406..."); return resultFormat(11, ex); } //500錯誤 @ExceptionHandler({ConversionNotSupportedException.class, HttpMessageNotWritableException.class}) public String server500(RuntimeException ex) { System.out.println("500..."); return resultFormat(12, ex); } //棧溢位 @ExceptionHandler({StackOverflowError.class}) public String requestStackOverflow(StackOverflowError ex) { return resultFormat(13, ex); } //除數不能為0 @ExceptionHandler({ArithmeticException.class}) public String arithmeticException(ArithmeticException ex) { return resultFormat(13, ex); } //其他錯誤 @ExceptionHandler({Exception.class}) public String exception(Exception ex) { return resultFormat(14, ex); } private <T extends Throwable> String resultFormat(Integer code, T ex) { ex.printStackTrace(); log.error(String.format(logExceptionFormat, code, ex.getMessage())); return JsonResult.failed(code, ex.getMessage()); } }
程式碼寫完了,講解一下幾個新的註解:
@ExceptionHandler:標識異常型別對應的處理方法
比如下面這個方法:就是處理當遇到了空指標異常對應的處理方法
@ExceptionHandler(NullPointerException.class) public String nullPointerExceptionHandler(NullPointerException ex) { System.err.println("NullPointerException:"); return resultFormat(2, ex); }
接下來寫一個測試的controller:
package com.springboot.exception.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @Author 18011618
* @Date 15:59 2018/7/13
* @Function 測試異常的controller
*/
@RestController
public class ExceptionController {
@RequestMapping("/exce")
public String showInfo(){
System.err.println("dddddddddddddd");
String info ="你好";
int a = 1/0;
return info;
}
}
最看看一下對應的application.yaml配置檔案
server:
port: 8888
最後寫一個啟動應用類:
package com.springboot.exception;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* @Author 18011618
* @Description
* @Date 16:00 2018/7/13
* @Modify By
*/
@SpringBootApplication
public class ExceptionApplication {
public static void main(String[] args) {
SpringApplication.run(ExceptionApplication.class,args);
}
}
這個返回的訊息就是全域性異常幫忙處理的。其它異常也可以去測試 都是可以攔截的,這裡要注意一下:
如果不想用@ResponseBody的話,可以使用@RestControllerAdvice代替@ControllerAdvice
OK 效果實現了,它主要是在Spring mvc 啟動時呼叫RequestMappingHandlerAdapter類的initControllerAdviceCache()方法進行初始化
到此為止,全域性異常處理就講解完了