SpringBoot 处理全局异常的策略和方法

1 定义一个异常处理类 加上@ControllerAdvice 

   @ControllerAdvice ,使Spring能加载该类,同时我们将所有捕获的异常统一返回结果Result这个实体。

package com.application.exception;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ui.Model;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.ResponseBody;

import com.application.response.StatusResult;

/**
 * controller增强器 处理异常
 * @class ExceptionControllerAdvice
 * @author Jason
 * @description
 * @date Apr 24, 2019 11:55:47 AM
 */
@ControllerAdvice
public class ExceptionControllerAdvice {
	
	private static Logger logger = LoggerFactory.getLogger(ExceptionControllerAdvice.class);
	
	/**
     * 应用到所有@RequestMapping注解方法,在其执行之前初始化数据绑定器
     * @param binder
     */
    @InitBinder
    public void initBinder(WebDataBinder binder) {}

    /**
     * 把值绑定到Model中,使全局@RequestMapping可以获取到该值
     * @param model
     */
    @ModelAttribute
    public void addAttributes(Model model) {
        model.addAttribute("author", "Jason");
    }

    /**
     * 全局异常捕捉处理
     * @param ex
     * @return
     */
    @ResponseBody
    @ExceptionHandler(value = Exception.class)
    public StatusResult errorHandler(Exception ex) {
    	logger.error("出错了 捕捉到异常:  "+ ex.getMessage());
    	StatusResult result = null;
    	
    	if(ex instanceof NotAuthException) {
    		result = StatusResult.error("token错误");
    	}else if (ex instanceof TokenExpirationException){
    		result = StatusResult.error("token过期");
    	}
    	
    	{
    		result = StatusResult.error("系统错误");
        }
        
        return result;
    }

}

2 定义一个切面类 加上@AfterThrowing(适合特定的业务点)

package com.zy.test.aspect;
 
import java.lang.reflect.Method;
 
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
 
import com.zy.test.annotation.ArchivesLog;
 
/**
 * web 异常切面
 * @author user
 *
 */
@Aspect
public class WebExceptionAspect {
    
    @Pointcut("@annotation(org.springframework.web.bind.annotation.RequestMapping)")//连接点是@RequestMapping注解的方法
    private void webPointcut() {}
    
    @AfterThrowing(pointcut = "webPointcut()", throwing = "e")//切点在webpointCut()
    public void handleThrowing(JoinPoint joinPoint, Exception e) {//controller类抛出的异常在这边捕获
        String className = joinPoint.getTarget().getClass().getName();
        String methodName = joinPoint.getSignature().getName();
        Object[] args = joinPoint.getArgs();
        //开始打log
        System.out.println("异常:" + e.getMessage());
        System.out.println("异常所在类:" + className);
        System.out.println("异常所在方法:" + methodName);
        System.out.println("异常中的参数:");
        System.out.println(methodName);
        for (int i = 0; i < args.length; i++) {
            System.out.println(args[i].toString());
        }
    }
    
 
    @Before("execution(* com.zy.test.controller.*.*(..))")
    public void beforeProcess(JoinPoint joinPoint) {
        String className = joinPoint.getTarget().getClass().getName();
        String methodName = joinPoint.getSignature().getName();
        Object[] args = joinPoint.getArgs();
        //在项目中最好记录当前操作的时间和用户
        System.out.println("操作所在类:" + className);
        System.out.println("操作所在方法:" + methodName);
        System.out.println("操作中的参数:");
        for (int i = 0; i < args.length; i++) {
            System.out.println(args[i].toString());
        }
    }
    
    @AfterReturning(value = "execution(* com.zy.test.controller.*.*(..)))", returning = "returnVal")
    public void returnProcess(JoinPoint joinPoint, Object returnVal) {
        String className = joinPoint.getTarget().getClass().getName();
        String methodName = joinPoint.getSignature().getName();
        Object[] args = joinPoint.getArgs();
        Class targetClass = null;
        String operationName = "";
        try {
            targetClass = Class.forName(className);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        Method[] methods = targetClass.getMethods();
        for (Method method : methods) {
            if (method.getName().equals(methodName)) {
                Class[] clazzs = method.getParameterTypes();
                if (clazzs != null && clazzs.length == args.length&&
                        method.getAnnotation(ArchivesLog.class)!=null) {//这块是取出我们注解ArchiveLog中的值,一遍在日志时明确这个操作的名称
                    operationName = method.getAnnotation(ArchivesLog.class).operationName();
                    break;
                }
            }
        }
        System.out.println("操作名称:" + operationName);
        System.out.println("方法正常返回的值:" + returnVal);
    }
    
}

3  实现接口 ThrowsAdvice

spring aop对异常的处理有良好的支持。spring 提供了一个接口 ThrowsAdvice,该接口里面没有任何方法,但是实现类里面必须的实现

afterThrowing(Method method, Object[] args, Object target, RuntimeException  throwable) 或者

afterThrowing(RuntimeException  throwable)

如果需要记录发生异常方法的详细信息,则实现第一个方法就行,如果只记录发生的异常,实现第二个方法就ok!

package com.beckham.aop;
import java.lang.reflect.Method;
import org.springframework.aop.ThrowsAdvice;
/**
 * @author Owner Jan 18, 2010 2:37:10 PM 处理DAO层的异常 struts2 com.beckham.aop
 *         ExceptionLog.java
 */
public class ExceptionLog implements ThrowsAdvice {
	/**
	 * Owner 
	 * 参数解释 Method method 执行的方法 
	 * Object[] args 方法参数
	 *  Object target 代理的目标对象
	 * Throwable throwable 产生的异常 
	 * Jan 18, 2010 3:21:46 PM
	 */
	public void afterThrowing(Method method, Object[] args, Object target,
			RuntimeException  throwable) {
		System.out.println("产生异常的方法名称:  " + method.getName());
		
		for(Object o:args){
			System.out.println("方法的参数:   " + o.toString());
		}
		
		System.out.println("代理对象:   " + target.getClass().getName());
		System.out.println("抛出的异常:    " + throwable.getMessage()+">>>>>>>"
				+ throwable.getCause());
		System.out.println("异常详细信息:   "+throwable.fillInStackTrace());
	}
}


 

你可能感兴趣的:(异常,springboot)