1、简介
在SpringBoot项目中,由于我们项目中难免会出现各种异常,一个个处理并不一定能包括全部异常,这时候我们需要一个全局类来处理项目中所抛出的异常。
2、实现步骤
a、定义一个类
import com.ck.syscheck.utils.JsonResult;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.TypeMismatchException;import org.springframework.beans.ConversionNotSupportedException;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;/*** 定义全局异常类*/@ControllerAdvice@ResponseBodypublic class GlobalExceptionHandler {private static final String logExceptionFormat = "Capture Exception By GlobalExceptionHandler: Code: %s Detail: %s";private static Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class);/*** 运行时异常** @param ex* @return*/@ExceptionHandler(RuntimeException.class)public String runtimeExceptionHandler(RuntimeException ex) {return resultFormat(1, ex);}/*** 空指针异常** @param ex* @return*/@ExceptionHandler(NullPointerException.class)public String nullPointerExceptionHandler(NullPointerException ex) {System.err.println("NullPointerException:");return resultFormat(2, ex);}/*** 类型转换异常** @param ex* @return*/@ExceptionHandler(ClassCastException.class)public String classCastExceptionHandler(ClassCastException ex) {return resultFormat(3, ex);}/*** IO异常** @param ex* @return*/@ExceptionHandler(IOException.class)public String iOExceptionHandler(IOException ex) {return resultFormat(4, ex);}/*** 未知方法异常** @param ex* @return*/@ExceptionHandler(NoSuchMethodException.class)public String noSuchMethodExceptionHandler(NoSuchMethodException ex) {return resultFormat(5, ex);}/*** 数组越界异常** @param ex* @return*/@ExceptionHandler(IndexOutOfBoundsException.class)public String indexOutOfBoundsExceptionHandler(IndexOutOfBoundsException ex) {return resultFormat(6, ex);}/*** 400错误** @param ex* @return*/@ExceptionHandler({HttpMessageNotReadableException.class})public String requestNotReadable(HttpMessageNotReadableException ex) {System.out.println("400..requestNotReadable");return resultFormat(7, ex);}/*** 400错误** @param ex* @return*/@ExceptionHandler({TypeMismatchException.class})public String requestTypeMismatch(TypeMismatchException ex) {System.out.println("400..TypeMismatchException");return resultFormat(8, ex);}/*** 400错误** @param ex* @return*/@ExceptionHandler({MissingServletRequestParameterException.class})public String requestMissingServletRequest(MissingServletRequestParameterException ex) {System.out.println("400..MissingServletRequest");return resultFormat(9, ex);}/*** 405错误** @param ex* @return*/@ExceptionHandler({HttpRequestMethodNotSupportedException.class})public String request405(HttpRequestMethodNotSupportedException ex) {return resultFormat(10, ex);}/*** 406错误** @param ex* @return*/@ExceptionHandler({HttpMediaTypeNotAcceptableException.class})public String request406(HttpMediaTypeNotAcceptableException ex) {System.out.println("406...");return resultFormat(11, ex);}/*** 500错误** @param ex* @return*/@ExceptionHandler({ConversionNotSupportedException.class, HttpMessageNotWritableException.class})public String server500(RuntimeException ex) {System.out.println("500...");return resultFormat(12, ex);}/*** 栈溢出** @param ex* @return*/@ExceptionHandler({StackOverflowError.class})public String requestStackOverflow(StackOverflowError ex) {return resultFormat(13, ex);}/*** 除数不能为0** @param ex* @return*/@ExceptionHandler({ArithmeticException.class})public String arithmeticException(ArithmeticException ex) {return resultFormat(13, ex);}/*** 其他错误** @param ex* @return*/@ExceptionHandler({Exception.class})public String exception(Exception ex) {return resultFormat(14, ex);}/*** 格式化结构,将其转换为JSon格式* 这里使用alibaba的fastjson依赖** @param code* @param ex* @param <T>* @return*/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());}}
必要注解:@ControllerAdvice: 使用 @ControllerAdvice,不用任何的配置,只要把这个类放在项目中,Spring能扫描到的地方。就可以实现全局异常的回调。
把@ControllerAdvice注解内部使用@ExceptionHandler、@InitBinder、@ModelAttribute注解的方法应用到所有的 @RequestMapping注解的方法。
package org.springframework.web.bind.annotation;import java.lang.annotation.Annotation;import java.lang.annotation.Documented;import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;import org.springframework.core.annotation.AliasFor;import org.springframework.stereotype.Component;@Target({ElementType.TYPE})@Retention(RetentionPolicy.RUNTIME)@Documented@Componentpublic @interface ControllerAdvice {@AliasFor("basePackages")String[] value() default {};@AliasFor("value")String[] basePackages() default {};Class<?>[] basePackageClasses() default {};Class<?>[] assignableTypes() default {};Class<? extends Annotation>[] annotations() default {};}
@ExceptionHandler注解:标识异常类型对应的处理方法_
import java.lang.annotation.Documented;import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;@Target({ElementType.METHOD})@Retention(RetentionPolicy.RUNTIME)@Documentedpublic @interface ExceptionHandler {Class<? extends Throwable>[] value() default {};}
b、定义一个JSON格式化工具类
该类用来处理抛出的异常信息
import com.alibaba.fastjson.JSON;import lombok.Data;import java.io.Serializable;import java.util.HashMap;import java.util.Map;/*** json格式化数据*/@Datapublic class JsonResult implements Serializable {/*** 返回码 非0即失败*/private int code;/*** 消息提示*/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)));}}
注意:这里的JSON格式化工具使用的是阿里的fastjson依赖
<dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.58</version></dependency>
c、浏览器输入错误的URL测试
结果信息展示,当在浏览器访问抛出异常时,页面出现的信息(以下仅仅以一个案例为栗)。
实际需要POST请求,结果给了GET请求,导致出现以下错误。
