Springboot学习教程(四)使用AOP处理全局捕获异常和添加日志

目录

1.Spring的AOP特性

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

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


 

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.浏览器访问时出现错误信息


Springboot学习教程(四)使用AOP处理全局捕获异常和添加日志_第1张图片


 

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

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

Springboot学习教程(四)使用AOP处理全局捕获异常和添加日志_第2张图片

 

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 errorResult(){
        Map errorResultMap = new HashMap<>();
        errorResultMap.put("errorCode","500");
        errorResultMap.put("errorMsg","全局捕获异常错误!");
        return errorResultMap;
    }
}
  • @ControllerAdvice 是 controller 的一个辅助类,最常用的就是作为全局异常处理的切面类。
  • @ControllerAdvice 可以指定扫描范围,我们可以捕获controller包的异常@ExceptionHandler 表示拦截异常
  • @ExceptionHandler 是拦截异常注解,需要声明拦截异常类型
  • @ResponseBody表示返回json格式

 

浏览器请求:


Springboot学习教程(四)使用AOP处理全局捕获异常和添加日志_第3张图片


 

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 errorResult(){
        Map 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" %>

系统错误啦!!!

 

浏览器请求:


Springboot学习教程(四)使用AOP处理全局捕获异常和添加日志_第4张图片


 

 

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.添加依赖



    org.springframework.boot
    spring-boot-starter-log4j
    1.3.8.RELEASE



    org.springframework.boot
    spring-boot-starter-aop

 

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 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.浏览器访问


Springboot学习教程(四)使用AOP处理全局捕获异常和添加日志_第5张图片


 

6.控制台打印日志

 

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

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

你可能感兴趣的:(分布式)