springboot全局异常处理

我们经常写代码的时候会在controller中写大量的try{}catch(exception e){}来响应一些信息给用户以保证接口的完整性。这样在写接口的时候会存在大量重复的代码,即浪费时间,代码看起来又不美观,那么我们是不是可以定义一个异常信息,当出现这种情况的时候直接抛出异常,在异常中响应给用户一些信息。比如,我们写接口的时候,会接收参数,我们要判断参数是否为空,如果不为空的时候那就可以接下来的操作,如果为空的时候我们是不是可以抛出我们自定义的一个异常,在异常中给用户响应一些信息呢?接下来我们就一起看看代码如何实现。
一、使用@RestControllerAdvice和@ExceptionHandler统一处理异常。

  	/**
  	* 这是用来测试的接口
  	*/
  	@RequestMapping("/handle/{id}")
    public String demo(@PathVariable(name="id") String id)throws Exception{

        if(StringUtils.isBlank(id)){
            throw new MyException(false,"10001");
        }
        return "1";
    }
/**
* 这是我们自定义的一个异常,实现RuntimeException
*/
public class MyException extends RuntimeException {

    private boolean success;
    private String errorCode;

    public MyException(boolean success, String errorCode) {
        this.success = success;
        this.errorCode = errorCode;
    }

    public boolean isSuccess() {
        return success;
    }

    public void setSuccess(boolean success) {
        this.success = success;
    }

    public String getErrorCode() {
        return errorCode;
    }

    public void setErrorCode(String errorCode) {
        this.errorCode = errorCode;
    }
/**
* 这是封住的一个返回数据的格式
*/
public class ResultMessage {

	// 消息标记
	private boolean success;
	// 消息主体
	private Object data;
	// 消息代码
	private String errorCode;
	//错误信息
	private String msg;

	public ResultMessage() {
		super();
	}

	/**
     * 正确数据返回
     * @param
     */
	public ResultMessage(Object data) {
		super();
		this.success = true;
		this.data = data;
		this.errorCode = "00000";
	}
	/**
	 * 错误数据
	 * @param
	 * @param
	 */
	public ResultMessage(boolean success, String errorCode) {
		super();
		this.success = false;
		this.errorCode = errorCode
		;
		this.msg = ErrorCodeEnum.getName(errorCode);
	}

	public boolean isSuccess() {
		return success;
	}

	public void setSuccess(boolean success) {
		this.success = success;
	}

	public Object getData() {
		return data;
	}

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

	public String getErrorCode() {
		return errorCode;
	}

	public void setErrorCode(String errorCode) {
		this.errorCode = errorCode;
	}

	public String getMsg() {
		return msg;
	}

	public void setMsg(String msg) {
		this.msg = msg;
	}
}
/**
* @ClassName: MyControllerAdvice
* @Description: 异常捕获处理
* @Author: zhbin
* @CreateDate: 2019/5/14 14:55
* @Version: 1.0
*/
@RestControllerAdvice
@Slf4j
public class MyControllerAdvice {
    @ExceptionHandler(MyException.class)
    public String myExceptionHandle(MyException e, HttpServletRequest request){
        System.out.println(e);
        return JSON.toJSONString(new ResultMessage(e.isSuccess(),e.getErrorCode()));
    }

}

运行接口如图这样是不是特别方便呢,当参数为空的时候我们直接抛出我们自定义的异常,在异常中响应用户请求,使的我们程序能够走下去。但是有时侯可能即会有我们自定义的异常,也会有系统出错时抛出的异常。接下来我们看一下,该如何处理呢?首先我们改造一下代码。

/**
* @ClassName: MyControllerAdvice
* @Description: 异常捕获处理
* @Author: zhbin
* @CreateDate: 2019/5/14 14:55
* @Version: 1.0
*/
@RestControllerAdvice
@Slf4j
public class MyControllerAdvice {

    @ExceptionHandler(Exception.class)
    public String exceptionHand(Exception e, HttpServletRequest request){

        ResultMessage resultMessage = null;
        System.out.println(request.getMethod()+"----"+request.getServletPath()+"==="+request.getQueryString());
        System.out.println();

        if(e instanceof MyException){

            resultMessage = new ResultMessage(((MyException) e).isSuccess(),((MyException) e).getErrorCode());
        }else{
            resultMessage = new ResultMessage(false,"10002");
        }
        return JSON.toJSONString(resultMessage);
    }
}

我们只需要判断一下异常是不是属于我们自定义的异常(instanceof),如果是响应自定义内容,如果不是响应其他内容就可以。当然我们也可以自定义多种异常来处理我们的义务。这里就不进行演示了。
二、aop进行统一异常处理
我们平时会使用aop来记录日志,那么是否记得aop有一种通知是异常通知,当程序发生异常的时候会进入到异常通知,我们是不是可以在这里面进行全局异常处理呢,接下来我们来看看能否通过aop实现异常处理?
经过测试发现,在异常通知中得不到异常信息,那么是不是aop就处理不了异常呢,其实不然,在环绕通知@Around中可以捕获到异常信息,下面我们看看代码。

/**
* @ClassName: MyControllerAspect
* @Description: aop统一处理异常
* @Author: zhbin
* @CreateDate: 2019/5/16 20:09
* @Version: 1.0
*/
@Aspect
@Component
@Slf4j
public class MyControllerAspect {

    // 切点,定义横切的方法
    @Pointcut("execution(public * com.zhb.exception_handle.controller..*.*(..))")
    public void pcut(){}

    @Around("pcut()")
    public String exciption(ProceedingJoinPoint joinPoint){
        ResultMessage resultMessage = null;
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        log.info("url={}",request.getRequestURL());
        log.info("前置通知------------"+joinPoint);
        Object proceed="";
        try {
            proceed = joinPoint.proceed();
            log.info("后置通知-----------"+joinPoint);
        }catch (Throwable e){
            resultMessage = exceptionHandle(e);
            log.info(e+"===异常通知");
            // 异常的时候直接返回异常信息
            return JSON.toJSONString(resultMessage);
        }
       // 正常的时候返回程序中的响应内容即可。
       return JSON.toJSONString(proceed);
    }

    /**
     * 判断异常类型
     * @param e
     * @return
     */
    public ResultMessage exceptionHandle(Throwable e){

        ResultMessage resultMessage = null;
        if(e instanceof MyException){

            resultMessage = new ResultMessage(((MyException) e).isSuccess(),((MyException) e).getErrorCode());
        }else{
            resultMessage = new ResultMessage(false,"10002");
        }
        return resultMessage;
    }
}

是不是特别方便呢,在环绕通知中捕获到异常后,就可以进行全局异常处理了。和第一种方式一样,只需要判断异常类型后进行相应的操作就可以了。是不是没有想到aop还有这么强大的功能呢。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Java旅途

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值