通过AOP自定义注解实现日志管理
前言:
通过自定义注解和AOP结合的方式,实现日志的记录功能
大致流程:项目运行->用户操作调用业务处理类->通过自定义的注解(我理解为一个切点)->进入到AOP切面类(在这里可以获得业务处理类的类名,方法名,通过request获取操作者ip,自定义的操作名,时间等)->把获取的信息记入数据库实现日志的记录->记录成功后返回业务处理类,下面是代码。
1.spring-mvc配置文件
<!-- 6.开启注解AOP (前提是引入aop命名空间和相关jar包) -->
<aop:aspectj-autoproxy expose-proxy="true" proxy-target-class="true"></aop:aspectj-autoproxy> <!-- 7.开启aop,对类代理强制使用cglib代理 -->
<aop:config proxy-target-class="true"></aop:config> <!-- 8.扫描 @Service @Component 注解-->
<context:component-scan base-package="com.bs" >
<!-- 不扫描 @Controller的类 -->
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller" />
</context:component-scan>
2.自定义注解类
package com.bs.annotation; import java.lang.annotation.*; @Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface SysLog { String value() default "";
}
3.AOP切面类
package com.bs.aop; import java.lang.reflect.Method;
import java.text.DateFormat;
import java.util.Date;
import java.util.Enumeration;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.lang.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
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 com.bs.annotation.SysLog;
import com.bs.basic.service.BsSysLogService; @Aspect
@Component
public class LogAspect { private static final String LOG_CONTENT = "[类名]:%s <br/>[方法]:%s <br>[参数]:%s <br/>[IP]:%s"; @Autowired
public BsSysLogService logService; @Around("@annotation(com.bs.annotation.SysLog)")
public Object saveLog(ProceedingJoinPoint joinPoint) throws Throwable{ DateFormat ddtf = DateFormat.getDateTimeInstance();
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
Object result = null;
String methodName = joinPoint.getSignature().getName();
Method method = currentMethod(joinPoint, methodName);
SysLog log = method.getAnnotation(SysLog.class);
String content =buildeContent(joinPoint, methodName, request); logService.insert(content,ddtf.format(new Date()),"-",log.value());
try{
result=joinPoint.proceed();
}catch(Exception exception){ }finally{
}
return result;
} /**
* 获取当前方法
* @param joinPoint
* @param methodName
* @return
*/
public Method currentMethod(ProceedingJoinPoint joinPoint,String methodName){
Method[] methods = joinPoint.getTarget().getClass().getMethods();
Method resultMethod = null;
for (Method method : methods) {
if (method.getName().equals(methodName)) {
resultMethod = method;
break;
}
}
return resultMethod;
} /**
* 日志内容
* @param joinPoint
* @param methodName
* @param request
* @return
*/
public String buildeContent(ProceedingJoinPoint joinPoint, String methodName, HttpServletRequest request) {
String className = joinPoint.getTarget().getClass().getName();
Object[] params = joinPoint.getArgs();
StringBuffer bf = new StringBuffer();
if (params != null && params.length > 0) {
Enumeration<String> paraNames = request.getParameterNames();
while (paraNames.hasMoreElements()) {
String key = paraNames.nextElement();
bf.append(key).append("=");
bf.append(request.getParameter(key)).append("&");
}
if (StringUtils.isBlank(bf.toString())) {
bf.append(request.getQueryString());
}
}
return String.format(LOG_CONTENT, className, methodName, bf.toString(),getRemoteAddress(request));
} /**
*
* 获取请求客户端ip
*
* @param request
*
* @return ip地址
*
*/
public static String getRemoteAddress(HttpServletRequest request) { String ip = request.getHeader("x-forwarded-for");
if (ip == null || ip.length() == 0 || ip.equalsIgnoreCase("unknown")) {
ip = request.getHeader("Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || ip.equalsIgnoreCase("unknown")) {
ip = request.getHeader("WL-Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || ip.equalsIgnoreCase("unknown")) {
ip = request.getRemoteAddr();
}
return ip;
}
}
4.自定义注解配置在需要记录的业务处理类
@SysLog("删除场景")
@Override
public String deleteScene(String cmdValues) {
//业务逻辑....
}
@SysLog("更新场景")
@Override
public String updateScene(String value) {
//业务处理...
}
...
记录的日志是这样的

通过AOP自定义注解实现日志管理的更多相关文章
- spring AOP自定义注解 实现日志管理
今天继续实现AOP,到这里我个人认为是最灵活,可扩展的方式了,就拿日志管理来说,用Spring AOP 自定义注解形式实现日志管理.废话不多说,直接开始!!! 关于配置我还是的再说一遍. 在appli ...
- 利用Spring AOP自定义注解解决日志和签名校验
转载:http://www.cnblogs.com/shipengzhi/articles/2716004.html 一.需解决的问题 部分API有签名参数(signature),Passport首先 ...
- (转)利用Spring AOP自定义注解解决日志和签名校验
一.需解决的问题 部分API有签名参数(signature),Passport首先对签名进行校验,校验通过才会执行实现方法. 第一种实现方式(Origin):在需要签名校验的接口里写校验的代码,例如: ...
- 【Spring】每个程序员都使用Spring(四)——Aop+自定义注解做日志拦截
一.前言 上一篇博客向大家介绍了Aop的概念,对切面=切点+通知 .连接点.织入.目标对象.代理(jdk动态代理和CGLIB代理)有所了解了.理论很强,实用就在这篇博客介绍. 这篇博客中,小编向大家介 ...
- spring boot aop 自定义注解 实现 日志检验 权限过滤
核心代码: package com.tran.demo.aspect; import java.lang.reflect.Method; import java.time.LocalDateTime; ...
- SpringBoot系列(十三)统一日志处理,logback+slf4j AOP+自定义注解,走起!
往期精彩推荐 SpringBoot系列(一)idea新建Springboot项目 SpringBoot系列(二)入门知识 springBoot系列(三)配置文件详解 SpringBoot系列(四)we ...
- spring AOP自定义注解方式实现日志管理
今天继续实现AOP,到这里我个人认为是最灵活,可扩展的方式了,就拿日志管理来说,用Spring AOP 自定义注解形式实现日志管理.废话不多说,直接开始!!! 关于配置我还是的再说一遍. 在appli ...
- Spring aop+自定义注解统一记录用户行为日志
写在前面 本文不涉及过多的Spring aop基本概念以及基本用法介绍,以实际场景使用为主. 场景 我们通常有这样一个需求:打印后台接口请求的具体参数,打印接口请求的最终响应结果,以及记录哪个用户在什 ...
- redis分布式锁-spring boot aop+自定义注解实现分布式锁
接这这一篇redis分布式锁-java实现末尾,实现aop+自定义注解 实现分布式锁 1.为什么需要 声明式的分布式锁 编程式分布式锁每次实现都要单独实现,但业务量大功能复杂时,使用编程式分布式锁无疑 ...
随机推荐
- JVM活学活用——GC算法 垃圾收集器
概述 垃圾收集 Garbage Collection 通常被称为“GC”,它诞生于1960年 MIT 的 Lisp 语言,经过半个多世纪,目前已经十分成熟了. jvm 中,程序计数器.虚拟机栈.本地方 ...
- HttpURLConnection与HttpClient随笔
目前在工作中遇到的需要各种对接接口的工作,需要用到HTTP的知识,工作完成后想要做一些笔记,本来知识打算把自己写的代码粘贴上来就好了,但是偶然发现一篇博文对这些知识的总结非常到位,自认无法写的这么好, ...
- MariaDB 数据库索引详解(9)
MariaDB数据库管理系统是MySQL的一个分支,主要由开源社区在维护,采用GPL授权许可MariaDB的目的是完全兼容MySQL,包括API和命令行,MySQL由于现在闭源了,而能轻松成为MySQ ...
- JS简单表单验证
这里我是写了一个简单的注册表单验证功能,亲测有效,一起来看看吧! 首先我的HTML代码是这样的: class大家可以忽略一下,这里我项目使用的是bootstrap的样式. 输入用户名和密码用的是正则表 ...
- JAVA动态代理和方法拦截(使用CGLib实现AOP、方法拦截、委托)
AOP用CGLib更简便.更可控. 动态代理的实现非常优雅. 实体类: public class SampleClass { public String MyFunction1(String inpu ...
- 创建python3虚拟环境指令和冻结所安装的包
mkvirtualenv file_name -p python3 去掉后面的 P 和python3 代表创建python2环境 其中p代表路径的意思 冻结所安装包命令 pip freeze > ...
- 【sping揭秘】2、关于spring配置文件
<import>标签 引入其他的配置文件,如果A.xml 中的<bean>定义可能依赖B.xml中的某些<bean>定义,那么可以再A.xml中使用这种方式< ...
- SQLServer——SQLServer链接外部数据源
学习链接:https://www.cnblogs.com/licin/p/6244169.html 一.新建ODBC数据源 1.打开控制面板→管理工具→ODBC数据源→系统DSN 2.添加新系统数据源 ...
- 性能优化中CPU、内存、磁盘IO、网络性能的依赖(转)
关于系统性能优化,推荐一篇不错的博客! 系统优化是一项复杂.繁琐.长期的工作,优化前需要监测.采集.测试.评估,优化后也需要测试.采集.评估.监测,而且是一个长期和持续的过程,不 是说现在优化了,测试 ...
- 线程中的读写锁ReadWriteLock
Lock锁还有两个非常强大的类 ReadWriteLock接口实现类ReentrantReadWriteLock(非常重要的锁) 想实现 读取的时候允许多线程并发访问,写入的时候不允许. 这种效果.. ...