通过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.为什么需要 声明式的分布式锁 编程式分布式锁每次实现都要单独实现,但业务量大功能复杂时,使用编程式分布式锁无疑 ...
随机推荐
- ASP.Net MVC OA项目笔记<五>
1.1.1 抽象工厂封装数据操作类实例创建,然后DBSession调用抽象工厂,修改DBSession CZBK.ItcastOA.DALFactory数据会话层调数据层不能直接new,要封装一下解 ...
- unity2D 船只型物体驱动的实现
船只向前行驶的驱动力 假设在水中没有摩擦阻力,船只有惯性,船只可以转弯,按下前进键时船只会在力的作用下使得自身的物理运动方向变化到自身的前方方向,从而向前行进. 上图中 V:船当前物理速度 V1,V2 ...
- 【转】「Chris Richardson 微服务系列」微服务架构的优势与不足
Posted on 2016年5月4日 编者的话|本文来自 Nginx 官方博客,是微服务系列文章的第一篇,主要探讨了传统的单体式应用的不足,以及微服务架构的优势与挑战. 作者介绍:Chris Ric ...
- 解决linux下source /etc/profile关闭终端失效问题
本来想配置环境变量的,看网上和博客上很多说改/etc/profile,然后source /etc/profile之后就可以永久保存使环境变量生效,但是终端一关闭,就环境变量就失效了,其他终端也用不了. ...
- Ubuntu 16.04下安装golang
手动安装 下载golang安装包 https://studygolang.com/dl 从上面的网站上下载适合自己机器的go版本,我这里选择的是go1.10.linux-386.tar.gz 解压安装 ...
- mybatis 控制台打印执行的SQL语句
1. Spring boot 集成 mybatis [转载]SpringBoot中Mybatis打印sql 1.1 如果使用的是application.properties文件,加入如下配置: log ...
- python线程死锁与递归锁
死锁现象 所谓死锁: 是指两个或两个以上的进程或线程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去. 此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待 ...
- WebDriver高级应用实例(4)
4.1操作web页面的滚动条 被测网页的网址: http://v.sogou.com Java语言版本的API实例代码 import org.testng.annotations.Test; impo ...
- POJ 2575
#include<iostream> #include<set> #include<stdio.h> using namespace std; int my_abs ...
- Python动态变量名定义与调用
动态变量名赋值 在使用tkinter时需要动态生成变量,如动态生成var1...var10变量 使用exec动态赋值 exec在python3中是内置函数,它支持python代码的动态执行. 示例: ...