作者:追梦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);
}
}
}

  以上是项目中的部门真实代码。读者需要关注的有以下几点:

  1. 注解:@Aspect、@Pointcut、@After、@Before;
  2. 拦截的方法命名规则要统一,比如新增时 addXXX 或者 insertXXX,更新是 updateXXX 或者 editXXX,查询是 queryXXX 或者 selectXXX ,删除是 deleteXXX 等;
  3. 处理相关的业务逻辑,比如,数据入库,导出日志文件等等;
  4. 需要理解 Spring aop 中的相关概念,比如切点、切面、增强/通知等。SpringBoot Aop 还是对 Spring Aop 的封装。

下面是本项目中的日志展示效果:

总结

  本文希望传到的不仅仅是一个解决方案,更希望传达一种思想。在需求实现时,多思考,而不是在没有思考的前提下,就横冲直撞,胡写一通。正如方腾飞所说,聪明人的几个特质:

1、问题是什么?

2、解决方案有哪些?

3、哪一个方案是所有方案中的捷径?

![](https://img2018.cnblogs.com/blog/1183871/201910/1183871-20191015115013786-523924507.png)

SpringBoot第二十五篇:SpringBoot与AOP的更多相关文章

  1. SpringBoot第二十四篇:应用监控之Admin

    作者:追梦1819 原文:https://www.cnblogs.com/yanfei1819/p/11457867.html 版权声明:本文为博主原创文章,转载请附上博文链接! 引言   前一章(S ...

  2. 第二十五章 springboot + hystrixdashboard

    注意: hystrix基本使用:第十九章 springboot + hystrix(1) hystrix计数原理:附6 hystrix metrics and monitor 一.hystrixdas ...

  3. SpringBoot第十五篇:swagger构建优雅文档

    作者:追梦1819 原文:https://www.cnblogs.com/yanfei1819/p/11007470.html 版权声明:本文为博主原创文章,转载请附上博文链接! 引言   前面的十四 ...

  4. SpringBoot非官方教程 | 第二十五篇:2小时学会springboot

    转载请标明出处: http://blog.csdn.net/forezp/article/details/61472783 本文出自方志朋的博客 一.什么是spring boot Takes an o ...

  5. SpringBoot | 第二十五章:日志管理之自定义Appender

    前言 前面两章节我们介绍了一些日志框架的常见配置及使用实践.一般上,在开发过程中,像log4j2.logback日志框架都提供了很多Appender,基本上可以满足大部分的业务需求了.但在一些特殊需求 ...

  6. SpringBoot第二十二篇:应用监控之Actuator

    作者:追梦1819 原文:https://www.cnblogs.com/yanfei1819/p/11226397.html 版权声明:本文为博主原创文章,转载请附上博文链接! 引言   很多文章都 ...

  7. 第二十五篇:在SOUI中做事件分发处理

    不同的SOUI控件可以产生不同的事件.SOUI系统中提供了两种事件处理方式:事件订阅 + 事件处理映射表(参见第八篇:SOUI中控件事件的响应) 事件订阅由于直接将事件及事件处理函数连接,不存在事件分 ...

  8. Python之路(第二十五篇) 面向对象初级:反射、内置方法

    [TOC] 一.反射 反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问.检测和修改它本身状态或行为的一种能力(自省).这一概念的提出很快引发了计算机科学领域关于应用反射性的研究.它 ...

  9. flask第二十五篇——控制语句

    有兴趣的请加船长公众号:自动化测试实战 先和大家强调一个发邮件的问题 # coding: utf-8 import smtplib from email.mime.text import MIMETe ...

随机推荐

  1. cesium页面小控件的隐藏

    cesium页面小控件的隐藏 1   创建一个Viewer var viewer = new Cesium.Viewer('cesiumContainer');//cesiumContainer为di ...

  2. (六十五)c#Winform自定义控件-图标字体

    前提 入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章. GitHub:https://github.com/kwwwvagaa/NetWinformControl 码云:ht ...

  3. python爬虫-模拟微博登录

    微博模拟登录 这是本次爬取的网址:https://weibo.com/ 一.请求分析 找到登录的位置,填写用户名密码进行登录操作 看看这次请求响应的数据是什么 这是响应得到的数据,保存下来 exect ...

  4. JDK、Spring和Mybatis中使用到的设计模式

    一.JDK中的设计模式 (1)结构性模式 1.适配器模式 java.util.Arrays#asList() java.io.InputStreamReader(InputStream) java.i ...

  5. maven:Fatal error compiling: 无效的目标发行版: 1.8.0_45 -> [Help 1]

    使用mvn clean install命令的时候出现如下的错误: Failed to execute goal org.apache.maven.plugins:maven-compiler-plug ...

  6. VUE Node模式下,如何改变菜单的颜色,如何将超长文字缩略显示,在鼠标进入后展开全部显示,鼠标移出则恢复缩略显示

    VUE Node模式下,如何改变菜单的颜色,如何将超长文字缩略显示,在鼠标进入后展开全部显示,鼠标移出则恢复缩略显示: “事件”引起变量值的变化,系统引擎自动根据变量值的变化刷新页面 在VUE Nod ...

  7. Nancy获取Request.Form的所有参数

    Nancy是一个轻量级的webapi框架,在用Nancy框架的时候,我们经常要获取到接口的所有动态参数值, 但是Nancy的Request.Form不能够直接转成NameValueCollection ...

  8. 即时聊天APP(五) - 聊天界面

    设置界面没什么好说的,无非也就是加了个对话框来二次提醒用户,现在来讲讲聊天界面. 聊天界面初始化时会得到一个参数,就是对方的id,并设置在标题栏的位置,此界面也是使用RecyclerView来展示聊天 ...

  9. 1小时让你掌握响应式编程,并入门Reactor

    我看同步阻塞 “你知道什么是同步阻塞吗”,当然知道了.“那你怎么看它呢”,这个... 在同步阻塞的世界里,代码执行到哪里,数据就跟到哪里.如果数据很慢跟不上来,代码就停在那里等待数据的到来,然后再带着 ...

  10. php tp5 composer

    ## php tp5 composer安装tp5.1需要先去装个Apache或者Nginx,再装个php环境.一般Windows可以直接使用xmapp.然后tp5好像python的django啊... ...