Springboot使用AOP处理全局捕获异常和添加日志

Springboot使用AOP处理全局捕获异常和添加日志

2019-11-26 22:3:39发布 浏览数:5352
概述:Springboot使用AOP处理全局捕获异常和添加日志

1.Spring的AOP特性

Spring有两大特性,IOC(控制反转)和AOP(面向切面编程),

我们可以利用aop特性处理全局捕获异常,添加日志,添加事物等。

 

 

2.使用AOP统一处理全局捕获异常

如果访问项目时出现异常,那么浏览器则会显示500或者别的报错信息,这样很显然是不合适的,这个时候我们就需要全局捕获异常了,当出现错误信息时,返回我们自定义的错误信息。

 

1.创建一个Controller类

package com.example.springboot_jsp.controller;

 

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

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

 

@RestController

public class ErrorController {

 

    @RequestMapping("/getUser")

    public String getUser(){

        int i = 1/0;

        return "SUCCESS";

    }

}

 

2.浏览器访问时出现错误信息


 

3.这个时候,就需要我们springboot提供的全局捕获异常异常机制了

我们创建一个新的包下的全局捕获异常类

 

4.全局捕获异常主要分成两类:

一类捕获返回json格式,另一类捕获返回页面。

1)捕获返回json格式的代码:

package com.example.springboot_jsp.error;

 

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

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

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

 

import java.util.HashMap;

import java.util.Map;

 

@ControllerAdvice(basePackages = "com.example.springboot_jsp.controller")

public class GlobaExceptionHandler {

 

    @ExceptionHandler(Exception.class)

    @ResponseBody

    public Map<String,Object> errorResult(){

        Map<String,Object> errorResultMap = new HashMap<>();

        errorResultMap.put("errorCode","500");

        errorResultMap.put("errorMsg","全局捕获异常错误!");

        return errorResultMap;

    }

}
  • @ControllerAdvice 是 controller 的一个辅助类,最常用的就是作为全局异常处理的切面类。 @ControllerAdvice 可以指定扫描范围,我们可以捕获controller包的异常@ExceptionHandler 表示拦截异常 @ExceptionHandler 是拦截异常注解,需要声明拦截异常类型 @ResponseBody表示返回json格式

 

浏览器请求:


 

2)捕获返回ModelAndView(页面)的代码:

package com.example.springboot_jsp.error;

 

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

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

 

@ControllerAdvice(basePackages = "com.example.springboot_jsp.controller")

public class GlobaExceptionHandler {

 

    /*@ExceptionHandler(Exception.class)

    @ResponseBody

    public Map<String,Object> errorResult(){

        Map<String,Object> errorResultMap = new HashMap<>();

        errorResultMap.put("errorCode","500");

        errorResultMap.put("errorMsg","全局捕获异常错误!");

        return errorResultMap;

    }*/

 

 

    @ExceptionHandler(Exception.class)

    public String errorResult(){

        return "errorMsg";

    }

}

 

在jsp目录下创建一个errorMsg.jsp页面

<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8" %>

 

系统错误啦!!!

 

浏览器请求:


 

 

3.使用AOP统一处理Web请求日志

1.在resources目录下创建一个log4j.properties文件

#log4j.rootLogger=CONSOLE,info,error,DEBUG

log4j.rootLogger=info,error,CONSOLE,DEBUG

log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender     

log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout     

log4j.appender.CONSOLE.layout.ConversionPattern=%d{yyyy-MM-dd-HH-mm} [%t] [%c] [%p] - %m%n     

log4j.logger.info=info

log4j.appender.info=org.apache.log4j.DailyRollingFileAppender

log4j.appender.info.layout=org.apache.log4j.PatternLayout     

log4j.appender.info.layout.ConversionPattern=%d{yyyy-MM-dd-HH-mm} [%t] [%c] [%p] - %m%n  

log4j.appender.info.datePattern='.'yyyy-MM-dd

log4j.appender.info.Threshold = info   

log4j.appender.info.append=true   

#log4j.appender.info.File=/home/admin/pms-api-services/logs/info/api_services_info

log4j.appender.info.File= D

log4j.logger.error=error  

log4j.appender.error=org.apache.log4j.DailyRollingFileAppender

log4j.appender.error.layout=org.apache.log4j.PatternLayout     

log4j.appender.error.layout.ConversionPattern=%d{yyyy-MM-dd-HH-mm} [%t] [%c] [%p] - %m%n  

log4j.appender.error.datePattern='.'yyyy-MM-dd

log4j.appender.error.Threshold = error   

log4j.appender.error.append=true   

#log4j.appender.error.File=/home/admin/pms-api-services/logs/error/api_services_error

log4j.appender.error.File=F:/log4j

log4j.logger.DEBUG=DEBUG

log4j.appender.DEBUG=org.apache.log4j.DailyRollingFileAppender

log4j.appender.DEBUG.layout=org.apache.log4j.PatternLayout     

log4j.appender.DEBUG.layout.ConversionPattern=%d{yyyy-MM-dd-HH-mm} [%t] [%c] [%p] - %m%n  

log4j.appender.DEBUG.datePattern='.'yyyy-MM-dd

log4j.appender.DEBUG.Threshold = DEBUG   

log4j.appender.DEBUG.append=true   

#log4j.appender.DEBUG.File=/home/admin/pms-api-services/logs/debug/api_services_debug

log4j.appender.DEBUG.File=F:/log4j

 

2.添加依赖

<!-- log4j 依赖-->

<dependency>

    <groupId>org.springframework.boot</groupId>

    <artifactId>spring-boot-starter-log4j</artifactId>

    <version>1.3.8.RELEASE</version>

</dependency>

<!-- aop 依赖-->

<dependency>

    <groupId>org.springframework.boot</groupId>

    <artifactId>spring-boot-starter-aop</artifactId>

</dependency>

 

3.新增一个aop包,定义一个切面类,打印日志

package com.example.springboot_jsp.aop;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
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.util.Enumeration;
@Aspect
@Component
public class WebLogAspect {
  private static final Logger logger = LoggerFactory.getLogger(WebLogAspect.class);
  // 切面
  @Pointcut("execution(public * com.example.springboot_jsp.controller.*.*(..))")
  public void webLog() {
  }
  // 前置通知
  @Before("webLog()")
  public void doBefore(JoinPoint joinPoint) throws Throwable {
    // 接收到请求,记录请求内容
    ServletRequestAttributes attributes = (ServletRequestAttributes)                       RequestContextHolder.getRequestAttributes();
    HttpServletRequest request = attributes.getRequest();
    // 记录下请求内容
    logger.info("URL : " + request.getRequestURL().toString());
    logger.info("HTTP_METHOD : " + request.getMethod());
    logger.info("IP : " + request.getRemoteAddr());
    Enumeration<String> enu = request.getParameterNames();
    while (enu.hasMoreElements()) {
      String name = (String) enu.nextElement();
      logger.info("name:{},value:{}", name, request.getParameter(name));
    }
  }
  // 后置通知
  @AfterReturning(returning = "ret", pointcut = "webLog()")
  public void doAfterReturning(Object ret) throws Throwable {
    // 处理完请求,返回内容
    logger.info("RESPONSE : " + ret);
  }
}

 

@Pointcut("execution(public * com.example.springboot_jsp.controller.*.*(..))")

定义拦截的切面是所有的controller包请求


 

4.在controller包下新增IndexController类

package com.example.springboot_jsp.controller;

 

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

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

 

@RestController

public class IndexController {

 

    @RequestMapping("/index")

    public String getUser(String name,Integer age){

        return "success";

    }

}

5.浏览器访问

6.控制台打印日志

7.我们也可以使用lombok组件的@Slf4j注解,简化每一个类中都要写这行代码,下一篇springboot集成lombok有详解。

private static final Logger logger = LoggerFactory.getLogger(XXXXXX.class);


请先
登录
后评论
0 条评论
暂时没有评论
最新文章
更多