SpringBoot2.0 基础案例(11):配置AOP切面编程,解决日志记录业务

本文源码
GitHub地址:知了一笑
https://github.com/cicadasmile/spring-boot-base

一、AOP切面编程

1、什么是AOP编程

在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。AOP是OOP(面向对象编程)的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。

2、AOP编程特点

1)AOP采取横向抽取机制,取代了传统纵向继承体系重复性代码
2)经典应用:事务管理、性能监视、安全检查、缓存 、日志等
3)aop底层将采用代理机制进行实现
4)接口 + 实现类 :spring采用 jdk 的动态代理Proxy
5)实现类:spring 采用 cglib字节码增强

3、AOP中术语和图解

1)target:目标类
   需要被代理的类。例如:UserService
2)Joinpoint:连接点
   所谓连接点是指那些可能被拦截到的方法。例如:所有的方法
3)PointCut:切入点
   已经被增强的连接点。例如:addUser()
4)advice:通知/增强
   增强代码。例如:after、before
5)Weaving:织入
   指把增强advice应用到目标对象target来创建新的代理对象proxy的过程.
6)proxy 代理类
7) Aspect(切面): 是切入点pointcut和通知advice的结合
    一个线是一个特殊的面。
    一个切入点和一个通知,组成成一个特殊的面。

二、与SpringBoot2.0整合

1、核心依赖

<!-- AOP依赖 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

2、编写日志记录注解

package com.boot.aop.config;
import java.lang.annotation.*;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface LogFilter {
    String value() default "" ;
}

3、编写日志记录的切面代码

这里分为两种情况处理,一种正常的请求日志,和系统异常的错误日志。
核心注解两个。@Aspect和@Component。

package com.boot.aop.config;
import com.alibaba.fastjson.JSONObject;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
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 LogAspect {

    private static final Logger LOGGER = LoggerFactory.getLogger(LogAspect.class) ;

    @Pointcut("@annotation(com.boot.aop.config.LogFilter)")
    public void logPointCut (){

    }
    @Around("logPointCut()")
    public Object around (ProceedingJoinPoint point) throws Throwable {
        Object result = null ;
        try{
            // 执行方法
            result = point.proceed();
            // 保存请求日志
            saveRequestLog(point);
        } catch (Exception e){
            // 保存异常日志
            saveExceptionLog(point,e.getMessage());
        }
        return result;
    }
    private void saveExceptionLog (ProceedingJoinPoint point,String exeMsg){
        LOGGER.info("捕获异常:"+exeMsg);
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        LOGGER.info("请求路径:"+request.getRequestURL());
        MethodSignature signature = (MethodSignature) point.getSignature();
        Method method = signature.getMethod();
        LOGGER.info("请求方法:"+method.getName());
        // 获取方法上LogFilter注解
        LogFilter logFilter = method.getAnnotation(LogFilter.class);
        String value = logFilter.value() ;
        LOGGER.info("模块描述:"+value);
        Object[] args = point.getArgs();
        LOGGER.info("请求参数:"+ JSONObject.toJSONString(args));
    }
    private void saveRequestLog (ProceedingJoinPoint point){
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        LOGGER.info("请求路径:"+request.getRequestURL());
        MethodSignature signature = (MethodSignature) point.getSignature();
        Method method = signature.getMethod();
        LOGGER.info("请求方法:"+method.getName());
        // 获取方法上LogFilter注解
        LogFilter logFilter = method.getAnnotation(LogFilter.class);
        String value = logFilter.value() ;
        LOGGER.info("模块描述:"+value);
        Object[] args = point.getArgs();
        LOGGER.info("请求参数:"+ JSONObject.toJSONString(args));
    }
}

4、请求日志测试

@LogFilter("保存请求日志")
@RequestMapping("/saveRequestLog")
public String saveRequestLog (@RequestParam("name") String name){
    return "success:"+name ;
}

切面类信息打印

/**
 * 请求路径:http://localhost:8011/saveRequestLog
 * 请求方法:saveRequestLog
 * 模块描述:保存请求日志
 * 请求参数:["cicada"]
 */

5、异常日志测试

@LogFilter("保存异常日志")
@RequestMapping("/saveExceptionLog")
public String saveExceptionLog (@RequestParam("name") String name){
    int error = 100 / 0 ;
    System.out.println(error);
    return "success:"+name ;
}

切面类信息打印

/**
 * 捕获异常:/ by zero
 * 请求路径:http://localhost:8011/saveExceptionLog
 * 请求方法:saveExceptionLog
 * 模块描述:保存异常日志
 * 请求参数:["cicada"]
 */

三、源代码地址

GitHub地址:知了一笑
https://github.com/cicadasmile
码云地址:知了一笑
https://gitee.com/cicadasmile

原文地址:https://blog.51cto.com/14439672/2430322

时间: 2024-10-10 05:12:10

SpringBoot2.0 基础案例(11):配置AOP切面编程,解决日志记录业务的相关文章

SpringBoot2.0 基础案例(07):集成Druid连接池,配置监控界面

一.Druid连接池 1.druid简介 Druid连接池是阿里巴巴开源的数据库连接池项目.Druid连接池为监控而生,内置强大的监控功能,监控特性不影响性能.功能强大,能防SQL注入,内置Loging能诊断Hack应用行为.Druid连接池是阿里巴巴内部唯一使用的连接池,在内部数据库相关中间件TDDL/DRDS 都内置使用强依赖了Druid连接池,经过阿里内部数千上万的系统大规模验证,经过历年双十一超大规模并发验证. 2.druid特点 1)稳定性特性,阿里巴巴的业务验证 2)完备的监控信息,

SpringBoot2.0 基础案例(03):配置系统全局异常映射处理

一.异常分类 这里的异常分类从系统处理异常的角度看,主要分类两类:业务异常和系统异常. 1.业务异常 业务异常主要是一些可预见性异常,处理业务异常,用来提示用户的操作,提高系统的可操作性.常见的业务异常提示:1)请输入xxx2)xxx不能为空3)xxx重复,请更换 2.系统异常 系统异常主要是一些不可预见性异常,处理系统异常,可以让展示出一个友好的用户界面,不易给用户造成反感.如果是一个金融类系统,在用户界面出现一个系统异常的崩溃界面,很有可能直接导致用户流失.常见的系统异常提示:1)页面丢失4

SpringBoot2.0 基础案例(15):配置MongoDB数据库,实现增删改查逻辑

一.NoSQL简介 1.NoSQL 概念 NoSQL( Not Only SQL ),意即"不仅仅是SQL".对不同于传统的关系型数据库的数据库管理系统的统称.NoSQL用于超大规模数据的存储.这些类型的数据存储不需要固定的模式,无需多余操作就可以横向扩展. 2.NoSQL的优点/缺点 --优点: 高可扩展性 分布式计算 低成本 架构的灵活性,半结构化数据 没有复杂的关系 --缺点: 没有标准化 有限的查询功能(到目前为止) 数据展现不直观 二.MongoDB数据库 1.MongoDB

SpringBoot2.0基础案例(01):环境搭建和RestFul风格接口

一.SpringBoot 框架的特点 1.SpringBoot2.0 特点 1)SpringBoot继承了Spring优秀的基因,上手难度小 2)简化配置,提供各种默认配置来简化项目配置 3)内嵌式容器简化Web项目,简化编码 Spring Boot 则会帮助开发着快速启动一个 web 容器,在 Spring Boot 中,只需要在 pom 文件中添加如下一个 starter-web 依赖即可. <dependency> <groupId>org.springframework.b

SpringBoot2.0 基础案例(10):整合Mybatis框架,集成分页助手插件

一.Mybatis框架 1.mybatis简介 MyBatis 是一款优秀的持久层框架,它支持定制化 SQL.存储过程以及高级映射.MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集.MyBatis 可以使用简单的 XML 或注解来配置和映射原生类型.接口和 Java 的 POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录. 2.mybatis特点 1)sql语句与代码分离,存放于xml配置文件中,方便管理 2)用逻辑标签

SpringBoot2.0 基础案例(13):基于Cache注解模式,管理Redis缓存

本文源码 GitHub地址:知了一笑 https://github.com/cicadasmile/spring-boot-base 一.Cache缓存简介 从Spring3开始定义Cache和CacheManager接口来统一不同的缓存技术:Cache接口为缓存的组件规范定义,包含缓存的各种操作集合:Cache接口下Spring提供了各种缓存的实现:如RedisCache,EhCacheCache ,ConcurrentMapCache等: 二.核心API 1.Cache缓存接口定义缓存操作.

SpringBoot2.0 基础案例(09):集成JPA持久层框架,简化数据库操作

一.JAP框架简介 JPA(Java Persistence API)意即Java持久化API,是Sun官方在JDK5.0后提出的Java持久化规范.主要是为了简化持久层开发以及整合ORM技术,结束Hibernate.TopLink.JDO等ORM框架各自为营的局面.JPA是在吸收现有ORM框架的基础上发展而来,易于使用,伸缩性强. 二.与SpringBoot2.0整合 1.核心依赖 <!-- JPA框架 --> <dependency> <groupId>org.sp

C# 面向切面编程--监控日志记录方案

背景:现在公司整体在做监控平台,要求把各个部分的细节都记录下来,在前台页面上有所显示,所以现在需要做的就是一个监控日志的记录工作,今天讲的就是渲染监控日志的例子. 现状:当前的渲染程序没有为监控日志记录预留代码接入口,因此要新增加监控日志势必要增加新的代码.但是如果只是单单在已有逻辑中新增日志记录的代码似乎不太合理:因为记录日志的代码很多都是一样的,直接插入代码有很多重复代码:原有代码已经上线并且运行良好,新增代码会破坏原有封装,甚至增加出错的可能:再者从设计的角度来说,记录日志不属于任何一个功

SpringBoot2.0 基础案例(06):引入JdbcTemplate,和多数据源配置

一.JdbcTemplate对象 1.JdbcTemplate简介 在Spring Boot2.0框架下配置数据源和通过JdbcTemplate访问数据库的案例.SpringBoot对数据库的操作在jdbc上面做了深层次的封装,使用spring的注入功能,可以把DataSource注册到JdbcTemplate之中. 2.JdbcTemplate核心方法 1)execute方法:可以用于执行任何SQL语句: 2)update方法batchUpdate方法:update方法用于执行新增.修改.删除