先创建注解 OperInfo

 @Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface OperInfo { public String description() default "";//操作说明 }

然后创建AOP的切面类 LogAspect

public class LogAspect {

	@Resource
private OperationLogService operService; public Object doAroundMethodForCtLog(ProceedingJoinPoint pjp)
throws Throwable{
Method method = getMethod(pjp);
if(method != null && method.isAnnotationPresent(OperInfo.class)){
OperInfo annotation = method.getAnnotation(OperInfo.class);
String descpTemp = annotation.description();
String description = executeTemplate(descpTemp, pjp);
HttpServletRequest request = HttpServletUtils.getRequest();
Users user = (Users) request.getSession().getAttribute("users");
OperationLog operation = new OperationLog();
operation.setChangetime(new Date());
operation.setChangeuserid(user.getUsersid());
operation.setOptid(UUIDUtils.getUUID());
operation.setDescription("用户:"+ user.getUsername() +",日志信息:【{"+description+"}】");
operService.insertService(operation);
}
return pjp.proceed();
}
//解析SPEL
private String executeTemplate(String template, ProceedingJoinPoint joinPoint){
         
LocalVariableTableParameterNameDiscoverer parameterNameDiscovere = new LocalVariableTableParameterNameDiscoverer();
Method method = getMethod(joinPoint);
String[] parameterNames = parameterNameDiscovere.getParameterNames(method); EvaluationContext context = new StandardEvaluationContext();
ExpressionParser parser = new SpelExpressionParser();
Object[] args = joinPoint.getArgs();
if(args.length == parameterNames.length){
for (int i = 0,len = args.length; i < len; i++) {
context.setVariable(parameterNames[i], args[i]);
}
}
return parser.parseExpression(template, new TemplateParserContext()).getValue(context, String.class);
} private Method getMethod(ProceedingJoinPoint joinPoint){
Object target = joinPoint.getTarget();
Method method = ((MethodSignature)joinPoint.getSignature()).getMethod();
try {
method = target.getClass().getMethod(method.getName(), method.getParameterTypes());
} catch (Exception e) {
e.printStackTrace();
}
return method;
} }

  spring-mvc.xml配置

<bean class="com.aop.LogAspect" id="logAspect" />
<aop:config expose-proxy="true">
<aop:pointcut expression="execution(* com.service.impl.*Impl.*(..))" id="txPointcut"/>
<aop:aspect ref="logAspect" >
<aop:around method="doAroundMethodForCtLog" pointcut-ref="txPointcut" />
</aop:aspect>
</aop:config>

  最后在需要拦截的service上加上注解就行了

@OperInfo(description="新增了名为#{#user.username}的用户")
public int insertUser(Users user){ }

  

使用AOP+Annotation实现操作日志记录的更多相关文章

  1. 微软企业库5.0 学习之路——第九步、使用PolicyInjection模块进行AOP—PART4——建立自定义Call Handler实现用户操作日志记录

    在前面的Part3中, 我介绍Policy Injection模块中内置的Call Handler的使用方法,今天则继续介绍Call Handler——Custom Call Handler,通过建立 ...

  2. 来一手 AOP 注解方式进行日志记录

    系统日志对于定位/排查问题的重要性不言而喻,相信许多开发和运维都深有体会. 通过日志追踪代码运行状况,模拟系统执行情况,并迅速定位代码/部署环境问题. 系统日志同样也是数据统计/建模的重要依据,通过分 ...

  3. Winform开发框架之权限管理系统改进的经验总结(4)-一行代码实现表操作日志记录

    在前面介绍了几篇关于我的权限系统改进的一些经验总结,本篇继续这一系列主体,介绍如何一行代码实现重要表的操作日志记录.我们知道,在很多业务系统里面,数据是很敏感的,特别对于一些增加.修改.删除等关键的操 ...

  4. 基于SqlSugar的开发框架循序渐进介绍(8)-- 在基类函数封装实现用户操作日志记录

    在我们对数据进行重要修改调整的时候,往往需要跟踪记录好用户操作日志.一般来说,如对重要表记录的插入.修改.删除都需要记录下来,由于用户操作日志会带来一定的额外消耗,因此我们通过配置的方式来决定记录那些 ...

  5. .NetCore中使用AspectCore、ExceptionLess 实现AOP操作日志记录

    结合前面封装的ExceptionLess,接下来使用 AspectCore 实现AOP日志处理 nuget导入AspectCore.Core .AspectCore.Extensions.Depend ...

  6. Spring Boot分布式系统实践【基础模块构建3.3】注解轻松实现操作日志记录

    日志注解 前言 spring切面的编程,spring中事物处理.日志记录常常与pointcut相结合 * * Pointcut 是指那些方法需要被执行"AOP",是由"P ...

  7. springAOP实现操作日志记录,并记录请求参数与编辑前后字段的具体改变

    本文为博主原创,未经允许不得转载: 在项目开发已经完成多半的情况下,需要开发进行操作日志功能的开发,由于操作的重要性,需要记录下操作前的参数和请求时的参数, 在网上找了很多,没找到可行的方法.由于操作 ...

  8. springboot—spring aop 实现系统操作日志记录存储到数据库

    原文:https://www.jianshu.com/p/d0bbdf1974bd 采用方案: 使用spring 的 aop 技术切到自定义注解上,针对不同注解标志进行参数解析,记录日志 缺点是要针对 ...

  9. 利用AOP与ToStringBuilder简化日志记录

    刚学spring的时候书上就强调spring的核心就是ioc和aop blablabla...... IOC到处都能看到...AOP么刚开始接触的时候使用在声明式事务上面..当时书上还提到一个用到ao ...

随机推荐

  1. madplay播放控制

    管理madplay的主程序,包括播放,暂停播放,恢复播放,停止播放system("madplay north.mp3 &");//利用system函数调用madplay播放 ...

  2. [ASP.NET MVC 小牛之路]06 - 使用 Entity Framework

    在家闲着也是闲着,继续写我的[ASP.NET MVC 小牛之路]系列吧.在该系列的上一篇博文中,在显示书本信息列表的时候,我们是在程序代码中手工造的数据.本文将演示如何在ASP.NET MVC中使用E ...

  3. Thrift架构~目录

    回到占占推荐博客索引 概念相关 thrift是一个软件框架,用来进行可扩展且跨语言的服务的开发.它结合了功能强大的软件堆栈和代码生成引擎,以构建在 C++, Java, Python, PHP, Ru ...

  4. iOS开发-闪退问题-解决之前上架的 App 在 iOS 9 会闪退问题

    最新更新:(2015.10.02) 开发环境: Delphi 10 Seattle OS X El Capitan v10.11 需使用下列 HotfixID: 30398, PAServer Hot ...

  5. Security1:Create Login

    Login 用于登陆SQL Server,语法是 -- Syntax for SQL Server CREATE LOGIN login_name { WITH <option_list1> ...

  6. 3、Redis 基础

    Redis的五大数据类型 String(字符串) string是redis最基本的类型,你可以理解成与Memcached一模一样的类型,一个key对应一个value.string类型是二进制安全的.意 ...

  7. IOS开发之自动布局显示网络请求内容

    在上一篇博客中详细的介绍了IOS开发中的相对布局和绝对布局,随着手机屏幕尺寸的改变,在App开发中为了适应不同尺寸的手机屏幕,用自动布局来完成我们想要实现的功能和效果显得尤为重要.本人更喜欢使用相对布 ...

  8. Objective-C中的单例模式

    ​    ​单例模式算是设计模式中比较简单的一种吧,设计模式不是只针对某种编程语言,在C++, Java, PHP等其他OOP语言也有设计模式,笔者初接触设计模式是通过<漫谈设计模式>了解 ...

  9. LTP随笔——本地调用ltp之ltp4j

    关于ltp本地调用的相关参考请见LTP的Git项目:https://github.com/HIT-SCIR 以下以/home/lion/Desktop路径为例下面教程中出现的具体路径以你实际配置的为准 ...

  10. PHP程序员如何理解IoC/DI

    思想是解决问题的根本 思想必须转换成习惯构建一套完整的思想体系是开发能力成熟的标志 详情请点击