您当前的位置: 首页 >  spring

SpringBoot2 综合案例(08):配置AOP切面编程,解决日志记录业务

蔚1 发布时间:2019-09-08 23:30:29 ,浏览量:3

Spring Boot 2 基础案例篇

包含:入门、日志管理、定时器、事务、AOP、数据库、缓存、NoSQL、监控、打包。

Spring Boot 2 高级案例篇

包含:整合常用中间件:分库分表、权限管理、Redis 集群、Dubbo、消息队列、定时器、搜索引擎、文件管理、邮件等

什么是 AOP 编程

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

AOP 编程特点
1)AOP 采取横向抽取机制,取代了传统纵向继承体系重复性代码2)经典应用:事务管理、性能监视、安全检查、缓存 、日志等3)aop 底层将采用代理机制进行实现4)接口 + 实现类 :spring 采用 jdk 的动态代理 Proxy5)实现类:spring 采用 cglib 字节码增强
AOP 中术语和图解
1)target:目标类   需要被代理的类。例如:UserService2)Joinpoint:连接点   所谓连接点是指那些可能被拦截到的方法。例如:所有的方法3)PointCut:切入点   已经被增强的连接点。例如:addUser()4)advice:通知/增强   增强代码。例如:after、before5)Weaving:织入   指把增强 advice 应用到目标对象 target 来创建新的代理对象 proxy 的过程.6)proxy 代理类7) Aspect(切面): 是切入点 pointcut 和通知 advice 的结合    一个线是一个特殊的面。    一个切入点和一个通知,组成成一个特殊的面。

在这里插入图片描述

与 SpringBoot2.0 整合 核心依赖
    org.springframework.boot    spring-boot-starter-aop
编写日志记录注解
package com.boot.aop.config;import java.lang.annotation.*;@Target(ElementType.METHOD)@Retention(RetentionPolicy.RUNTIME)@Documentedpublic @interface LogFilter {    String value() default "" ;}
编写日志记录的切面代码

这里分为两种情况处理,一种正常的请求日志,和系统异常的错误日志。核心注解两个。@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@Componentpublic 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));    }}
请求日志测试
@LogFilter("保存请求日志")@RequestMapping("/saveRequestLog")public String saveRequestLog (@RequestParam("name") String name){    return "success:"+name ;}

切面类信息打印

/** * 请求路径:http://localhost:8011/saveRequestLog * 请求方法:saveRequestLog * 模块描述:保存请求日志 * 请求参数:["cicada"] */
异常日志测试
@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/spring-boot-baseGitEE·地址https://gitee.com/cicadasmile/spring-boot-base

本文首发于 GitChat,未经授权不得转载,转载需与 GitChat 联系。

阅读全文: http://gitbook.cn/gitchat/activity/5d75129b010cbc57d32dbac2

您还可以下载 CSDN 旗下精品原创内容社区 GitChat App ,阅读更多 GitChat 专享技术内容哦。

FtooAtPSkEJwnW-9xkCLqSTRpBKX

关注
打赏
1688896170
查看更多评论

蔚1

暂无认证

  • 3浏览

    0关注

    4645博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文
立即登录/注册

微信扫码登录

0.0530s