十:SpringBoot-配置AOP切面编程,解决日志记录业务
SpringBoot-配置AOP切面编程,解决日志记录业务
1、AOP切面编程
在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。AOP是OOP(面向对象编程)的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
1.1 AOP编程特点
- AOP采取横向抽取机制,取代了传统纵向继承体系重复性代码
- 经典应用:事务管理、性能监视、安全检查、缓存 、日志等
- aop底层将采用代理机制进行实现
- 接口 + 实现类 :spring采用 jdk 的动态代理Proxy
- 实现类:spring 采用 cglib字节码增强
1.2 AOP中术语和图解
- target:目标类
需要被代理的类。例如:UserService - Joinpoint:连接点
所谓连接点是指那些可能被拦截到的方法。例如:所有的方法 - PointCut:切入点
已经被增强的连接点。例如:addUser() - advice:通知/增强
增强代码。例如:after、before - Weaving:织入
指把增强advice应用到目标对象target来创建新的代理对象proxy的过程. - proxy 代理类
- Aspect(切面): 是切入点pointcut和通知advice的结合
一个线是一个特殊的面。
一个切入点和一个通知,组成成一个特殊的面。
2、SpringBoot整合AOP
2.1 核心依赖
<!-- AOP依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
2.2 编写日志记录注解
package com.boot.aop.config;
import java.lang.annotation.*;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface LogFilter {
String value() default "" ;
}
2.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));
}
}
2.4 请求日志测试
@LogFilter("保存请求日志")
@RequestMapping("/saveRequestLog")
public String saveRequestLog (@RequestParam("name") String name){
return "success:"+name ;
}
切面类信息打印
/**
* 请求路径:http://localhost:8011/saveRequestLog
* 请求方法:saveRequestLog
* 模块描述:保存请求日志
* 请求参数:["cicada"]
*/
2.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"]
*/
十:SpringBoot-配置AOP切面编程,解决日志记录业务的更多相关文章
- SpringBoot2.0 基础案例(11):配置AOP切面编程,解决日志记录业务
本文源码 GitHub地址:知了一笑 https://github.com/cicadasmile/spring-boot-base 一.AOP切面编程 1.什么是AOP编程 在软件业,AOP为Asp ...
- C# 面向切面编程--监控日志记录方案
背景:现在公司整体在做监控平台,要求把各个部分的细节都记录下来,在前台页面上有所显示,所以现在需要做的就是一个监控日志的记录工作,今天讲的就是渲染监控日志的例子. 现状:当前的渲染程序没有为监控日志记 ...
- 注解配置AOP切面编程
1.导入先关jar包 2.编写applicationContext.xml,配置开启注解扫描和切面注解扫描 <?xml version="1.0" encoding=&quo ...
- applicationContext.xml配置AOP切面编程
Computer.java package com.wh.aop2; public class Computer { public void play01(){ System.out.println( ...
- springboot整合aop实现网站访问日志记录
目的: 统一日志输出格式,统计访问网站的ip. 思路: 1.针对不同的调用场景定义不同的注解,目前想的是接口层和服务层. 2.我设想的接口层和服务层的区别在于: (1)接口层可以打印客户端IP,而服务 ...
- Spring MVC通过AOP切面编程 来拦截controller 实现日志的写入
首选需要参考的是:[参考]http://www.cnblogs.com/guokai870510826/p/5977948.html http://www.cnblogs.com/guokai8 ...
- Spring AOP 切面编程记录日志和接口执行时间
最近客户现在提出系统访问非常慢,需要优化提升访问速度,在排查了nginx.tomcat内存和服务器负载之后,判断是数据库查询速度慢,进一步排查发现是因为部分视图和表查询特别慢导致了整个系统的响应时间特 ...
- SpringBoot学习笔记(七):SpringBoot使用AOP统一处理请求日志、SpringBoot定时任务@Scheduled、SpringBoot异步调用Async、自定义参数
SpringBoot使用AOP统一处理请求日志 这里就提到了我们Spring当中的AOP,也就是面向切面编程,今天我们使用AOP去对我们的所有请求进行一个统一处理.首先在pom.xml中引入我们需要的 ...
- AOP切面编程在android上的应用
代码地址如下:http://www.demodashi.com/demo/12563.html 前言 切面编程一直是一个热点的话题,这篇文章讲讲一个第三方aop库在android上的应用.第三方AOP ...
随机推荐
- [每日一题]面试官问:Async/Await 如何通过同步的方式实现异步?
关注「松宝写代码」,精选好文,每日一题 时间永远是自己的 每分每秒也都是为自己的将来铺垫和增值 作者:saucxs | songEagle 一.前言 2020.12.23 日刚立的 flag,每日一 ...
- 园子的品牌专区上新:NoSQL 数据库佼佼者 Aerospike
品牌专区是园子去年推出的新楼盘,为优秀的科技企业在园子里提供一个地方,展示自己的品牌,分享自己的技术内容. 最近我们和国外领先的 NoSQL 数据库厂商 Aerospike 达成了合作,入驻了园子的品 ...
- 漫画|web的主要安全问题
在此主要说现在市面上存在的4个比较多的安全问题 一.钓鱼 钓鱼: 比较有诱惑性的标题 仿冒真实网站 骗取用户账号 骗取用户资料 二.篡改页面 有一大部分被黑的网站中会有关键字 (在被黑的网站中,用的最 ...
- OSTU大津法图像分割
OSTU图像分割 最大类间方差法,也成大津法OSTU,它是按图像的灰度特性,将图像分成背景和目标2部分.背景和目标之间的类间方差越大,说明构成图像的2部分的差别越大,当部分目标错分为背景或部分背景错分 ...
- 【SpringBoot1.x】SpringBoot1.x 入门
SpringBoot1.x 入门 文章源码 简介 传统的 JavaEE 开发,十分笨重且配置繁琐,开发效率很低,而且有很复杂的部署流程,对于第三方技术的集成也很困难. Sring 全家桶时代则解决了上 ...
- 【Oracle】查看哪些用户被授予了DBA权限
查看哪些用户被授予了DBA权限 select * from dba_role_privs where granted_role='DBA'; 回收权限: revoke dba from xxx;
- LeetCode671. 二叉树中第二小的节点
题目 纯暴力 1 class Solution { 2 public: 3 vector<int>ans; 4 int findSecondMinimumValue(TreeNode* r ...
- paramiko模块简单用法
最简单最基本的用法 1 #__*__coding:utf-8__*__ 2 import paramiko 3 hostname = '192.168.1.1' 4 username = 'root' ...
- 容器编排系统K8s之包管理器Helm基础使用
前文我们了解了k8s上的hpa资源的使用,回顾请参考:https://www.cnblogs.com/qiuhom-1874/p/14293237.html:今天我们来聊一下k8s包管理器helm的相 ...
- ALV中layout布局控制详解
参数的结构为SLIS_LAYOUT_ALV.结构中比较常用的字段如下: no_colhead 隐藏列标题 值为X或空 no_hotspot headings不作为热 ...