原创

springboot全局异常捕捉

1.简介

springboot的全局异常处理,避免了程序中每个方法单独使用try-catch代码去捕获异常,也可以让程序统一的给客户端提供友好的返回信息

springboot 使用@ControllerAdvice、@ExceptionHandler、@ResponseBody实现全局异常处理
@ControllerAdvice 注解定义全局异常处理类,所有未捕获的异常都会执行到该注解声明的类
@ExceptionHandler 指定自定义错误处理方法拦截的异常类型

@ResponseBody  该注解说明返回的是数据,不是具体某一个页面 

下面咱们用一个简单的demo来了解一下@ControllerAdvice、@ExceptionHandler、@ResponseBody三个注解的使用

2.例子

项目采用springboot搭建,整体的结构如下图所示:

  

dto:定义了一个统一的返回实体

exception:ServiceException自定义的异常,GlobalExceptionHandler全局异常捕捉类

controller:用来测试的

2.1定一个统一的返回实体类 ResponseEntity.java

所有的接口统一返回该实体,抛出的异常也返回该实体,可以给前端提供一个统一的控制,代码如下:

package net.javain.springboot.exception.dto;

/**
* 定义接口统一返回数据
* Package : net.javain.springboot.exception.dto
*
* @author javain.net
* 2019年11月6日 下午7:29:57
*
*/
public class ResponseEntity<T extends Object> {

private String code="200";
private String message="ok";
private T data;

public String getCode() {
return code;
}

public void setCode(String code) {
this.code = code;
}

public String getMessage() {
return message;
}

public void setMessage(String message) {
this.message = message;
}

public T getData() {
return data;
}

public void setData(T data) {
this.data = data;
}


public ResponseEntity(){

}

public ResponseEntity(String _code,String _message){
code=_code;
message=_message;
}

public ResponseEntity(String _code,T _data){
code=_code;
data=_data;
}

public ResponseEntity(T _data){
data=_data;
}

public static ResponseEntity success(Object _data){
ResponseEntity responseEntity = new ResponseEntity();
responseEntity.setData(_data);
return responseEntity;
}
}

code表示返回的状态码,可以自定义错误类型的枚举值,message是具体的错误信息,data是接口返回的具体数据(如果接口请求成功的话)

2.2自定义异常类ServiceException.java

自定义的异常需要继承RuntimeException(运行时异常)或者Exception,具体代码实现如下:

package net.javain.springboot.exception.exception;

/**
* 自定义异常
* Package : net.javain.springboot.exception.exception
*
* @author javain.net
* 2019年11月6日 下午7:24:22
*
*/
public class ServiceException extends RuntimeException {

/**
* 无参数自定义业务异常构造方法.
*/
public ServiceException() {
}

/**
*
* @param message
* 异常消息.
*/
public ServiceException(String message) {
super(message);
}

/**
*
* @param cause
* 根异常.
*/
public ServiceException(Throwable cause) {
super(cause);
}

/**
*
* @param message
* 异常消息.
* @param cause
* 根异常.
*/
public ServiceException(String message, Throwable cause) {
super(message, cause);
}

/**
*
* @param message
* 异常消息.
* @param cause
* 根异常.
*/
public ServiceException(String message, String code) {
super(message);
}

}

super 方法调用父及的方法

2.3全局异常捕捉类GlobalExceptionHandler.java

该类使用@ControllerAdvice注解标注,标识所有的异常都会被该类捕捉,@ExceptionHandler的值标识捕捉的异常类,即捕捉什么样的异常,具体实现代码入下

package net.javain.springboot.exception.exception;

import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

import net.javain.springboot.exception.dto.ResponseEntity;

@ControllerAdvice
public class GlobalExceptionHandler {

/**
* 捕捉抛出的ServiceException异常
*
* @param ex
* @return
* @author javain.net
* 2019年11月6日 下午7:32:26
*/
@ResponseBody
@ExceptionHandler(value = ServiceException.class)
public ResponseEntity<String> ServiceExceptionHandler(ServiceException ex) {
//控制台打印错误日志
ex.printStackTrace();
ResponseEntity<String> responseEntity =new ResponseEntity<String>();
responseEntity.setCode("-1");//标识服务器端错误
responseEntity.setMessage(ex.getMessage());//错误信息
return responseEntity;
}

/**
* 抛出所有未捕获的异常
*
* @param ex
* @return
* @author chenlong12
* 2019年11月6日 下午7:32:59
*/
@ResponseBody
@ExceptionHandler(value = Exception.class)
public ResponseEntity<String> ExceptionHandler(Exception ex) {
//控制台打印错误日志
ex.printStackTrace();
ResponseEntity<String> responseEntity =new ResponseEntity<String>();
responseEntity.setCode("-2");
responseEntity.setMessage(ex.getMessage());

return responseEntity;
}
}


 @ResponseBody说明返回的是数据,不会具体的页面

@ExceptionHandler(value = ServiceException.class) 声明的方法标识捕捉抛出ServiceException的异常

GlobalExceptionHandler.java  会按照代码的先后顺序来进行异常的捕捉,如果没有匹配到 ServiceException,则进行Exception的匹配,直到匹配上,然后执行该方法

2.4异常测试类HomeController

写了两个接口,分别测试抛出自定义ServiceException异常与未捕获的异常

package net.javain.springboot.exception.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import net.javain.springboot.exception.exception.ServiceException;

@RestController
@RequestMapping("home")
public class HomeController {

@RequestMapping("serveExceptionTest")
public void serveExceptionTest(){
int i = 0;
if(i==0){
throw new ServiceException("测试Service异常");
}
}

@RequestMapping("exceptionTest")
public void ExceptionTest(){
int i = 1/0;
}
}

serveExceptionTest方法抛出了自定义的ServiceException

ExceptionTest方法抛出了未捕获的异常。

2.4测试

运行程序,在浏览器里访问http://localhost:8080/home/serveExceptionTest,返回数据:

{"code":"-1","message":"测试Service异常","data":null}

说明在全局异常类里捕捉到了自定义的异常

在浏览器里访问 http://localhost:8080/home/exceptionTest,返回数据:

{"code":"-2","message":"/ by zero","data":null}

说明在全局异常类里捕捉到了未捕获的异常

源码下载:链接: https://pan.baidu.com/s/1Dhcp2-CMBCnITtiwaEZ2Bw 提取码: d59v 

正文到此结束