SpringBoot第二十五篇:SpringBoot与AOP
作者:追梦1819
原文:https://www.cnblogs.com/yanfei1819/p/11457867.html
版权声明:本文为博主原创文章,转载请附上博文链接!
引言
作者在实际项目中碰到一个问题,就是需要在系统中加入操作日志功能。但是目前系统开发已经接近尾声,功能接口达到一百几十个。
如果按照新手的思维(项目组中有人就这样提建议),但是这样的话,工作量之大、冗余代码之多,可想而知。对于这种需求,我们应该考虑到 Java 的面向切面编程思想,使用 Spring AOP。下面,阐述在 SpringBoot 中使用 AOP。
在项目中的使用
为了演示更加完整的功能,此处我将我在实际项目中的需求抽取出来:将整个系统中的操作记录(比例数据的增、删、改、登录、退出等)入库。
为了演示实际的应用场景,本处代码不做专门的 demo 处理。将本人在真实项目中的实际代码展示出来,以便读者做更好的理解。
以下是核心代码:
package com.sunwin.aspect;
import com.sunwin.common.ErrorCode;
import com.sunwin.db.dao.ActionLogDao;
import com.sunwin.db.dto.ActionLogDTO;
import com.sunwin.exception.BusinessException;
import com.sunwin.util.DateUtil;
import com.sunwin.util.IPUtil;
import com.sunwin.util.UserUtil;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
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.beans.factory.annotation.Autowired;
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.text.SimpleDateFormat;
import java.util.Date;
/**
* Created by 追梦1819 on 2019-07-08.
*/
@Aspect
@Component
public class LogAspect {
@Autowired
private ActionLogDao actionLogDao;
private final static Logger logger = LoggerFactory.getLogger(LogAspect.class);
// ..表示包及子包 该方法代表controller层的所有方法
@Pointcut(
"execution(public * com.sunwin.web.controller.*.add*(..)) || " +
"execution(public * com.sunwin.web.controller.*.insert*(..)) || " +
"execution(public * com.sunwin.web.controller.*.update*(..)) || " +
"execution(public * com.sunwin.web.controller.*.delete*(..))||" +
// "execution(public * com.sunwin.web.controller.*.login*(..))"+
"execution(public * com.sunwin.web.controller.*.logout*(..))"
)
public void controllerMethod() {
}
@Pointcut("execution(public * com.sunwin.web.controller.*.login*(..))")
public void afterController() {
}
@After("afterController()")
public void afterLogRequestInfo(JoinPoint joinPoint) throws Exception {
common(joinPoint);
}
@Before("controllerMethod()")
public void LogRequestInfo(JoinPoint joinPoint) throws Exception {
common(joinPoint);
}
// aop业务处理逻辑
private void common(JoinPoint joinPoint) throws BusinessException {
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
StringBuffer requestLog = new StringBuffer();
requestLog.append("请求信息:")
.append("URL = {" + request.getRequestURI() + "},\t")
.append("HTTP_METHOD = {" + request.getMethod() + "},\t")
.append("IP = {" + request.getRemoteAddr() + "},\t")
.append("CLASS_METHOD = {" + joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName() + "}\t");
ActionLogDTO actionLog = new ActionLogDTO();
actionLog.setContent("调用信息是:" + requestLog);
String ip = IPUtil.getLocalIPAddress();
actionLog.setIp(ip);
String user = UserUtil.getUser() == null ? "" : UserUtil.getUser();
actionLog.setOperator(user);
SimpleDateFormat format = new SimpleDateFormat(DateUtil.DateFormat_yyyyMMddHHmmss);
String now = format.format(new Date());
actionLog.setActionDate(now);
String name = joinPoint.getSignature().getName();
// 类型、操作时间、操作者、内容、ip
// 操作类型:1-登录;2-退出;3-新增;4-编辑;5-删除;99-未知
if (name.startsWith("delete")) { // 删
actionLog.setActionType(5);
} else if (name.startsWith("update")) { // 改
actionLog.setActionType(4);
} else if (name.startsWith("add") || name.startsWith("insert")) { // 增
actionLog.setActionType(3);
} else if (name.startsWith("login")) {
actionLog.setActionType(1);
} else if (name.startsWith("logout")) {
actionLog.setActionType(2);
} else {
actionLog.setActionType(99);
}
int count = actionLogDao.insert(actionLog);
if (count < 1) {
throw new BusinessException(ErrorCode.INSERT_ERROR);
}
}
}
以上是项目中的部门真实代码。读者需要关注的有以下几点:
- 注解:@Aspect、@Pointcut、@After、@Before;
- 拦截的方法命名规则要统一,比如新增时 addXXX 或者 insertXXX,更新是 updateXXX 或者 editXXX,查询是 queryXXX 或者 selectXXX ,删除是 deleteXXX 等;
- 处理相关的业务逻辑,比如,数据入库,导出日志文件等等;
- 需要理解 Spring aop 中的相关概念,比如切点、切面、增强/通知等。SpringBoot Aop 还是对 Spring Aop 的封装。
下面是本项目中的日志展示效果:

总结
本文希望传到的不仅仅是一个解决方案,更希望传达一种思想。在需求实现时,多思考,而不是在没有思考的前提下,就横冲直撞,胡写一通。正如方腾飞所说,聪明人的几个特质:
1、问题是什么?
2、解决方案有哪些?
3、哪一个方案是所有方案中的捷径?

SpringBoot第二十五篇:SpringBoot与AOP的更多相关文章
- SpringBoot第二十四篇:应用监控之Admin
作者:追梦1819 原文:https://www.cnblogs.com/yanfei1819/p/11457867.html 版权声明:本文为博主原创文章,转载请附上博文链接! 引言 前一章(S ...
- 第二十五章 springboot + hystrixdashboard
注意: hystrix基本使用:第十九章 springboot + hystrix(1) hystrix计数原理:附6 hystrix metrics and monitor 一.hystrixdas ...
- SpringBoot第十五篇:swagger构建优雅文档
作者:追梦1819 原文:https://www.cnblogs.com/yanfei1819/p/11007470.html 版权声明:本文为博主原创文章,转载请附上博文链接! 引言 前面的十四 ...
- SpringBoot非官方教程 | 第二十五篇:2小时学会springboot
转载请标明出处: http://blog.csdn.net/forezp/article/details/61472783 本文出自方志朋的博客 一.什么是spring boot Takes an o ...
- SpringBoot | 第二十五章:日志管理之自定义Appender
前言 前面两章节我们介绍了一些日志框架的常见配置及使用实践.一般上,在开发过程中,像log4j2.logback日志框架都提供了很多Appender,基本上可以满足大部分的业务需求了.但在一些特殊需求 ...
- SpringBoot第二十二篇:应用监控之Actuator
作者:追梦1819 原文:https://www.cnblogs.com/yanfei1819/p/11226397.html 版权声明:本文为博主原创文章,转载请附上博文链接! 引言 很多文章都 ...
- 第二十五篇:在SOUI中做事件分发处理
不同的SOUI控件可以产生不同的事件.SOUI系统中提供了两种事件处理方式:事件订阅 + 事件处理映射表(参见第八篇:SOUI中控件事件的响应) 事件订阅由于直接将事件及事件处理函数连接,不存在事件分 ...
- Python之路(第二十五篇) 面向对象初级:反射、内置方法
[TOC] 一.反射 反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问.检测和修改它本身状态或行为的一种能力(自省).这一概念的提出很快引发了计算机科学领域关于应用反射性的研究.它 ...
- flask第二十五篇——控制语句
有兴趣的请加船长公众号:自动化测试实战 先和大家强调一个发邮件的问题 # coding: utf-8 import smtplib from email.mime.text import MIMETe ...
随机推荐
- WebStorm调节控制台字体
File --> Settings --> Editor --> Colors & Fonts --> Console Font
- Java 编程语言中很少被人了解的特性-statement label
下面的语句会编译报错或者打印什么? System.out.print("baidu site :"); https://www.baidu.com; System.out.prin ...
- 在eclipse中引入mybatis和spring的约束文件
eclipse中引入mybatis约束文件步骤: 首先: config的key值 http://mybatis.org/dtd/mybatis-3-config.dtd mapper的key值 htt ...
- Newtonsoft.Json 序列化
当我们对一个json数组进行反序列化用Newtonsoft.Json.JsonConvert.DeserializeObject<T>() 通常会报此错误 Newtonsoft.Json. ...
- Android集成JPush极光推送
推送原理 参考网址:https://blog.csdn.net/huangli1466384630/article/details/79889473 SDK下载 https://docs.jiguan ...
- Python3-编码问题-解决为何我的python打印总是出现乱码??
#python3 编码问题: ############举个例子############################### import sys print(sys.getdefaultencodi ...
- 洛谷 P1219八皇后
把全部,在这251秒,赌上! ——<游戏人生zero> 题目:https://www.luogu.org/problem/P1219 八皇后是一道非常非常非常经典的深搜+回溯的题目. 这道 ...
- 宝锋UV-5R说明书下载
宝锋UV-5R说明书 百度网盘下载地址: 链接: https://pan.baidu.com/s/1QJXEJ2YyO7ovMAQG7Uur4A 提取码: j8d2 BI8EJM 73 ...
- Servlet重定向
重定向就是在访问一个Servlet时,没有得到资源,只能去找另外一个Servlet去获取资源.状态码为302. import javax.servlet.ServletException; impor ...
- response中文乱码问题
1.要确定I代码的编码格式为UTF-8 2.乱码原因:浏览器和服务器的编码格式不同: 服务器的默认编码为:ISO-8859-1,如果浏览器的编码不是ISO-8859-1,就会出现乱码: public ...