springboot全局异常处理

springboot全局异常处理

1、AOP日志和异常处理

  • pom.xml中添加
		<!--aop切面-->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-aop</artifactId>
		</dependency>
  • 切面类
package global_exception.global_exception.demo.config;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

/**
 * Aop请求打日志
 */
@Aspect
@Component
public class WebLogAspect {
    private static final Logger logger = LoggerFactory.getLogger(WebLogAspect.class);
    private static final ThreadLocal<Long> timeTreadLocal = new ThreadLocal<>();

        @Pointcut("execution(* global_exception.global_exception.demo..*.*(..)) && @annotation(org.springframework.web.bind.annotation.RequestMapping)")
//    @Pointcut("execution(* global_exception.global_exception.demo.timer..*(..))")
    public void log() {
    }

    @Before("log()")
    public void before(JoinPoint joinPoint) {
        timeTreadLocal.set(System.currentTimeMillis());
        // 接收到请求,记录请求内容
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        //获取请求的request
        HttpServletRequest request = attributes.getRequest();
        //获取所有请求的参数,封装为map对象
        // Map<String,Object> parameterMap = getParameterMap(request);
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        //获取被拦截的方法
        Method method = methodSignature.getMethod();
        //获取被拦截的方法名
        String methodName = method.getName();
        //被拦截的类
        String className = joinPoint.getTarget().getClass().getName();
        String[] classNames = className.split("\\.");
        className = classNames[classNames.length - 1];
        logger.info("请求方法:{}--开始", className + "-->" + methodName);
        //获取所有请求参数key和value
        String keyValue = getReqParameter(request);
        logger.info("请求url = {}", request.getRequestURL().toString());
        logger.info("请求方式 = {}", request.getMethod());
//        logger.info("请求资源uri = {}", request.getRequestURI());
//        logger.info("所有的请求参数 key:value = {}", keyValue);
    }


    @After("log()")
    public void after(JoinPoint joinPoint) {
//        logger.info("aop的after()方法");
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        //获取被拦截的方法
        Method method = methodSignature.getMethod();
        //获取被拦截的方法名
        String methodName = method.getName();
        //被拦截的类
        String className = joinPoint.getTarget().getClass().getName();
        String[] classNames = className.split("\\.");
        className = classNames[classNames.length - 1];
        long startTime = timeTreadLocal.get();
        double callTime = (System.currentTimeMillis() - startTime) / 1000.0;
        logger.info("请求方法:{}--结束;花费时间time = {}s", className + "-->" + methodName, callTime);
    }

    //controller请求结束返回时调用
    @AfterReturning(returning = "result", pointcut = "log()")
    public Object afterReturn(Object result) {
        logger.info("AOP afterReturn,返回值result = {}", result.toString());
        // System.out.println("返回值="+result.toString());
//        long startTime = timeTreadLocal.get();
//        double callTime = (System.currentTimeMillis() - startTime) / 1000.0;
//        logger.info("调用controller花费时间time = {}s", callTime);
        return result;
    }

    /**
     * 异常捕获
     *
     * @param joinPoint
     * @param e
     */
    @AfterThrowing(pointcut = "log()", throwing = "e")
//    @AfterThrowing(pointcut = "execution(* global_exception.global_exception.demo.timer..*(..))", throwing = "e")
    public void handleThrowing(JoinPoint joinPoint, Exception e) {//controller类抛出的异常在这边捕获
        String className = joinPoint.getTarget().getClass().getName();
        String methodName = joinPoint.getSignature().getName();
        String[] classNames = className.split("\\.");
        className = classNames[classNames.length - 1];
        //开始打log
        logger.info(className + "-->" + methodName + " 报错");
        logger.error(className + "-->" + methodName + " 报错", e);
    }

    /**
     * 获取所有请求参数,封装为map对象
     *
     * @return
     */
    public Map<String, Object> getParameterMap(HttpServletRequest request) {
        if (request == null) {
            return null;
        }
        Enumeration<String> enumeration = request.getParameterNames();
        Map<String, Object> parameterMap = new HashMap<String, Object>();
        StringBuilder stringBuilder = new StringBuilder();
        while (enumeration.hasMoreElements()) {
            String key = enumeration.nextElement();
            String value = request.getParameter(key);
            String keyValue = key + " : " + value + " ; ";
            stringBuilder.append(keyValue);
            parameterMap.put(key, value);
        }
        return parameterMap;
    }

    public String getReqParameter(HttpServletRequest request) {
        if (request == null) {
            return null;
        }
        Enumeration<String> enumeration = request.getParameterNames();
        //StringBuilder stringBuilder = new StringBuilder();
        JSONArray jsonArray = new JSONArray();
        while (enumeration.hasMoreElements()) {
            String key = enumeration.nextElement();
            String value = request.getParameter(key);
            JSONObject json = new JSONObject();
            //String keyValue = key+" : " +value+" ; ";
            json.put(key, value);
            //stringBuilder.append(keyValue);
            jsonArray.add(json);
        }
        //JSONObject jsonObject = new JSONObject();
        //jsonObject.put("请求参数为:",jsonArray.toString());
        return jsonArray.toString();
    }

}

enter description here
设置切入点,前切、后切和异常切都已这个切点为入口
另外:方法内捕获了异常,全局就会再去捕获异常了
效果:
浏览器输入:http://localhost:8080/aopExceptionTest/test2

浏览器输入:http://localhost:8080/aopExceptionTest/test1

2、定时器AOP日志和异常

TimerLogAspect切面类

package global_exception.global_exception.demo.config;

import lombok.extern.log4j.Log4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;

/**
 * 定时器打日志
 */
@Aspect
@Component
public class TimerLogAspect {
    private static final Logger logger = LoggerFactory.getLogger(TimerLogAspect.class);
    private static final ThreadLocal<Long> timeTreadLocal = new ThreadLocal<>();

    /**
     * 切入点
     */
    @Pointcut("execution(* global_exception.global_exception.demo.timer..*(..))")
    public void log() {
    }

    /**
     * 前切
     * @param joinPoint
     */
    @Before("log()")
    public void before(JoinPoint joinPoint) {
        timeTreadLocal.set(System.currentTimeMillis());

        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        //获取被拦截的方法
        Method method = methodSignature.getMethod();
        //获取被拦截的方法名
        String methodName = method.getName();
        //被拦截的类
        String className = joinPoint.getTarget().getClass().getName();
        String[] classNames = className.split("\\.");
        className = classNames[classNames.length - 1];
        logger.info("定期器:{}--开始", className + "-->" + methodName);
    }

    /**
     * 后切
     * @param joinPoint
     */
    @After("log()")
    public void after(JoinPoint joinPoint) {
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        //获取被拦截的方法
        Method method = methodSignature.getMethod();
        //获取被拦截的方法名
        String methodName = method.getName();
        //被拦截的类
        String className = joinPoint.getTarget().getClass().getName();
        String[] classNames = className.split("\\.");
        className = classNames[classNames.length - 1];
        long startTime = timeTreadLocal.get();
        double callTime = (System.currentTimeMillis() - startTime) / 1000.0;
        logger.info("定时器:{}--结束;花费时间time = {}s", className + "-->" + methodName, callTime);
    }

    /**
     * 异常切面
     * @param joinPoint
     * @param e
     */
    @AfterThrowing(pointcut = "execution(* global_exception.global_exception.demo.timer..*(..))", throwing = "e")
    public void handleThrowing(JoinPoint joinPoint, Exception e) {//controller类抛出的异常在这边捕获
        String className = joinPoint.getTarget().getClass().getName();
        String methodName = joinPoint.getSignature().getName();
        String[] classNames = className.split("\\.");
        className = classNames[classNames.length - 1];
        //开始打log
        logger.info("定时器" + className + "-->" + methodName + " 报错");
        logger.error("定时器" + className + "-->" + methodName + " 报错", e);
    }
}

效果:
enter description here

3、请求页面异常捕获

两个页面404.html、500.html
404.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>404页面</h1>
</body>
</html>

500.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>500啦</h1>
</body>
</html>

两个类
NotFoundException.java

package global_exception.global_exception.demo.config;

import org.springframework.boot.web.servlet.error.ErrorController;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;

/**
 * 捕获404异常
 */
@Controller
public class NotFoundException implements ErrorController {

    @Override
    public String getErrorPath() {
        return "/error";
    }

    @RequestMapping(value = {"/error"})
//    @ResponseBody
    public String error(HttpServletRequest request) {
//        Map<String, Object> body = new HashMap<>();
//        body.put("error", "not found");
//        body.put("code", "404");
        return "/error/404.html";
    }
}

GlobalExceptionHandler.java

enter code herepackage global_exception.global_exception.demo.config;

import com.alibaba.fastjson.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;

/**
 * 统一异常处理
 */
@ControllerAdvice("global_exception.global_exception.demo")
public class GlobalExceptionHandler {
    private Logger logger = LoggerFactory.getLogger(getClass());

    @ExceptionHandler(RuntimeException.class)
//    @ResponseBody
    public String errorMsg(HttpServletRequest request,Exception ex) {
        //可以返回页面或json数据
//        logger.error("错误链接" + request.getRequestURL().toString());
//        Map<String, Object> errorMsgResult = new HashMap<>();
//        errorMsgResult.put("code", 500);
//        errorMsgResult.put("msg", "系统抛出异常");
        return "/error/500.html";
    }

}

效果:


项目地址:https://gitee.com/BestErwin/utils

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值