1、简介

在SpringBoot项目中,由于我们项目中难免会出现各种异常,一个个处理并不一定能包括全部异常,这时候我们需要一个全局类来处理项目中所抛出的异常。

2、实现步骤

a、定义一个类

  1. import com.ck.syscheck.utils.JsonResult;
  2. import org.slf4j.Logger;
  3. import org.slf4j.LoggerFactory;
  4. import org.springframework.beans.TypeMismatchException;
  5. import org.springframework.beans.ConversionNotSupportedException;
  6. import org.springframework.http.converter.HttpMessageNotReadableException;
  7. import org.springframework.http.converter.HttpMessageNotWritableException;
  8. import org.springframework.web.HttpMediaTypeNotAcceptableException;
  9. import org.springframework.web.HttpRequestMethodNotSupportedException;
  10. import org.springframework.web.bind.MissingServletRequestParameterException;
  11. import org.springframework.web.bind.annotation.ControllerAdvice;
  12. import org.springframework.web.bind.annotation.ExceptionHandler;
  13. import org.springframework.web.bind.annotation.ResponseBody;
  14. import java.io.IOException;
  15. /**
  16. * 定义全局异常类
  17. */
  18. @ControllerAdvice
  19. @ResponseBody
  20. public class GlobalExceptionHandler {
  21. private static final String logExceptionFormat = "Capture Exception By GlobalExceptionHandler: Code: %s Detail: %s";
  22. private static Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class);
  23. /**
  24. * 运行时异常
  25. *
  26. * @param ex
  27. * @return
  28. */
  29. @ExceptionHandler(RuntimeException.class)
  30. public String runtimeExceptionHandler(RuntimeException ex) {
  31. return resultFormat(1, ex);
  32. }
  33. /**
  34. * 空指针异常
  35. *
  36. * @param ex
  37. * @return
  38. */
  39. @ExceptionHandler(NullPointerException.class)
  40. public String nullPointerExceptionHandler(NullPointerException ex) {
  41. System.err.println("NullPointerException:");
  42. return resultFormat(2, ex);
  43. }
  44. /**
  45. * 类型转换异常
  46. *
  47. * @param ex
  48. * @return
  49. */
  50. @ExceptionHandler(ClassCastException.class)
  51. public String classCastExceptionHandler(ClassCastException ex) {
  52. return resultFormat(3, ex);
  53. }
  54. /**
  55. * IO异常
  56. *
  57. * @param ex
  58. * @return
  59. */
  60. @ExceptionHandler(IOException.class)
  61. public String iOExceptionHandler(IOException ex) {
  62. return resultFormat(4, ex);
  63. }
  64. /**
  65. * 未知方法异常
  66. *
  67. * @param ex
  68. * @return
  69. */
  70. @ExceptionHandler(NoSuchMethodException.class)
  71. public String noSuchMethodExceptionHandler(NoSuchMethodException ex) {
  72. return resultFormat(5, ex);
  73. }
  74. /**
  75. * 数组越界异常
  76. *
  77. * @param ex
  78. * @return
  79. */
  80. @ExceptionHandler(IndexOutOfBoundsException.class)
  81. public String indexOutOfBoundsExceptionHandler(IndexOutOfBoundsException ex) {
  82. return resultFormat(6, ex);
  83. }
  84. /**
  85. * 400错误
  86. *
  87. * @param ex
  88. * @return
  89. */
  90. @ExceptionHandler({HttpMessageNotReadableException.class})
  91. public String requestNotReadable(HttpMessageNotReadableException ex) {
  92. System.out.println("400..requestNotReadable");
  93. return resultFormat(7, ex);
  94. }
  95. /**
  96. * 400错误
  97. *
  98. * @param ex
  99. * @return
  100. */
  101. @ExceptionHandler({TypeMismatchException.class})
  102. public String requestTypeMismatch(TypeMismatchException ex) {
  103. System.out.println("400..TypeMismatchException");
  104. return resultFormat(8, ex);
  105. }
  106. /**
  107. * 400错误
  108. *
  109. * @param ex
  110. * @return
  111. */
  112. @ExceptionHandler({MissingServletRequestParameterException.class})
  113. public String requestMissingServletRequest(MissingServletRequestParameterException ex) {
  114. System.out.println("400..MissingServletRequest");
  115. return resultFormat(9, ex);
  116. }
  117. /**
  118. * 405错误
  119. *
  120. * @param ex
  121. * @return
  122. */
  123. @ExceptionHandler({HttpRequestMethodNotSupportedException.class})
  124. public String request405(HttpRequestMethodNotSupportedException ex) {
  125. return resultFormat(10, ex);
  126. }
  127. /**
  128. * 406错误
  129. *
  130. * @param ex
  131. * @return
  132. */
  133. @ExceptionHandler({HttpMediaTypeNotAcceptableException.class})
  134. public String request406(HttpMediaTypeNotAcceptableException ex) {
  135. System.out.println("406...");
  136. return resultFormat(11, ex);
  137. }
  138. /**
  139. * 500错误
  140. *
  141. * @param ex
  142. * @return
  143. */
  144. @ExceptionHandler({ConversionNotSupportedException.class, HttpMessageNotWritableException.class})
  145. public String server500(RuntimeException ex) {
  146. System.out.println("500...");
  147. return resultFormat(12, ex);
  148. }
  149. /**
  150. * 栈溢出
  151. *
  152. * @param ex
  153. * @return
  154. */
  155. @ExceptionHandler({StackOverflowError.class})
  156. public String requestStackOverflow(StackOverflowError ex) {
  157. return resultFormat(13, ex);
  158. }
  159. /**
  160. * 除数不能为0
  161. *
  162. * @param ex
  163. * @return
  164. */
  165. @ExceptionHandler({ArithmeticException.class})
  166. public String arithmeticException(ArithmeticException ex) {
  167. return resultFormat(13, ex);
  168. }
  169. /**
  170. * 其他错误
  171. *
  172. * @param ex
  173. * @return
  174. */
  175. @ExceptionHandler({Exception.class})
  176. public String exception(Exception ex) {
  177. return resultFormat(14, ex);
  178. }
  179. /**
  180. * 格式化结构,将其转换为JSon格式
  181. * 这里使用alibaba的fastjson依赖
  182. *
  183. * @param code
  184. * @param ex
  185. * @param <T>
  186. * @return
  187. */
  188. private <T extends Throwable> String resultFormat(Integer code, T ex) {
  189. ex.printStackTrace();
  190. log.error(String.format(logExceptionFormat, code, ex.getMessage()));
  191. return JsonResult.failed(code, ex.getMessage());
  192. }
  193. }

必要注解:
@ControllerAdvice使用 @ControllerAdvice,不用任何的配置,只要把这个类放在项目中,Spring能扫描到的地方。就可以实现全局异常的回调。
@ControllerAdvice注解内部使用@ExceptionHandler@InitBinder@ModelAttribute注解的方法应用到所有的 @RequestMapping注解的方法。

  1. package org.springframework.web.bind.annotation;
  2. import java.lang.annotation.Annotation;
  3. import java.lang.annotation.Documented;
  4. import java.lang.annotation.ElementType;
  5. import java.lang.annotation.Retention;
  6. import java.lang.annotation.RetentionPolicy;
  7. import java.lang.annotation.Target;
  8. import org.springframework.core.annotation.AliasFor;
  9. import org.springframework.stereotype.Component;
  10. @Target({ElementType.TYPE})
  11. @Retention(RetentionPolicy.RUNTIME)
  12. @Documented
  13. @Component
  14. public @interface ControllerAdvice {
  15. @AliasFor("basePackages")
  16. String[] value() default {};
  17. @AliasFor("value")
  18. String[] basePackages() default {};
  19. Class<?>[] basePackageClasses() default {};
  20. Class<?>[] assignableTypes() default {};
  21. Class<? extends Annotation>[] annotations() default {};
  22. }


@ExceptionHandler注解:
标识异常类型对应的处理方法_

  1. import java.lang.annotation.Documented;
  2. import java.lang.annotation.ElementType;
  3. import java.lang.annotation.Retention;
  4. import java.lang.annotation.RetentionPolicy;
  5. import java.lang.annotation.Target;
  6. @Target({ElementType.METHOD})
  7. @Retention(RetentionPolicy.RUNTIME)
  8. @Documented
  9. public @interface ExceptionHandler {
  10. Class<? extends Throwable>[] value() default {};
  11. }

b、定义一个JSON格式化工具类

该类用来处理抛出的异常信息

  1. import com.alibaba.fastjson.JSON;
  2. import lombok.Data;
  3. import java.io.Serializable;
  4. import java.util.HashMap;
  5. import java.util.Map;
  6. /**
  7. * json格式化数据
  8. */
  9. @Data
  10. public class JsonResult implements Serializable {
  11. /**
  12. * 返回码 非0即失败
  13. */
  14. private int code;
  15. /**
  16. * 消息提示
  17. */
  18. private String msg;
  19. /**
  20. * 返回的数据
  21. */
  22. private Map<String, Object> data;
  23. public JsonResult() {
  24. }
  25. public JsonResult(int code, String msg, Map<String, Object> data) {
  26. this.code = code;
  27. this.msg = msg;
  28. this.data = data;
  29. }
  30. public static String success() {
  31. return success(new HashMap(0));
  32. }
  33. public static String success(Map<String, Object> data) {
  34. return JSON.toJSONString(new JsonResult(0, "解析成功", data));
  35. }
  36. public static String failed() {
  37. return failed("解析失败");
  38. }
  39. public static String failed(String msg) {
  40. return failed(-1, msg);
  41. }
  42. public static String failed(int code, String msg) {
  43. return JSON.toJSONString(new JsonResult(code, msg, new HashMap(0)));
  44. }
  45. }

注意这里的JSON格式化工具使用的是阿里的fastjson依赖

  1. <dependency>
  2. <groupId>com.alibaba</groupId>
  3. <artifactId>fastjson</artifactId>
  4. <version>1.2.58</version>
  5. </dependency>

c、浏览器输入错误的URL测试

结果信息展示,当在浏览器访问抛出异常时,页面出现的信息(以下仅仅以一个案例为栗)。
实际需要POST请求,结果给了GET请求,导致出现以下错误。
image.png