springboot aop添加日志方式

 更新时间:2024年05月11日 11:08:44   作者:当冬夜渐暖333  
这篇文章主要介绍了springboot aop添加日志方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

一、首先自定义注解类SysLogAnnotation

/**
 * @date 2019/2/1 操作日志注解
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface SysLogAnnotation {

	/**
	 * 描述
	 * @return {String}
	 */
	String value();
}

二、添加切面类SysLogAspect,实现同一的日志添加

1、使用@Aspect注解定义切面类

@Component注册bean

@Around(“@annotation(sysLogAnnotation)”)

实现切面环绕监听添加了@sysLogAnnotation注解的方法,

通过sysLogAnnotation.value()获取注解中的value值

@Aspect
@Slf4j
@Component
public class SysLogAspect {
	@Around("@annotation(sysLogAnnotation)")
	@SneakyThrows
	public Object around(ProceedingJoinPoint point, com.example.swaggerdemo.annotation.SysLogAnnotation sysLogAnnotation) {
		String strClassName = point.getTarget().getClass().getName();
		String strMethodName = point.getSignature().getName();
		log.debug("[类名]:{},[方法]:{}", strClassName, strMethodName);
		SysLog logVo = SysLogUtils.getSysLog();
		logVo.setTitle(sysLogAnnotation.value());

		// 发送异步日志事件
		Long startTime = System.currentTimeMillis();
		Object obj;

		try {
			obj = point.proceed();
		}
		catch (Exception e) {
			logVo.setType(LogTypeEnum.ERROR.getType());
			logVo.setException(e.getMessage());
			throw e;
		}
		finally {
			Long endTime = System.currentTimeMillis();
			logVo.setTime(String.valueOf(endTime - startTime));
			SpringContextHolder.publishEvent(new SysLogEvent(logVo));
		}

		return obj;
	}
}

  

@Slf4j
@UtilityClass
public class SysLogUtils {

	public SysLog getSysLog() {
		//获取请求url,ip,httpMethod
		HttpServletRequest request = ((ServletRequestAttributes) Objects
				.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
		SysLog sysLog = new SysLog();
		//sysLog.setCreateBy(Objects.requireNonNull(getUsername()));
		//sysLog.setUpdateBy(Objects.requireNonNull(getUsername()));
		sysLog.setType(LogTypeEnum.NORMAL.getType());
		sysLog.setRemoteAddr(ServletUtil.getClientIP(request));
		sysLog.setRequestUri(URLUtil.getPath(request.getRequestURI()));
		sysLog.setMethod(request.getMethod());
		sysLog.setUserAgent(request.getHeader(HttpHeaders.USER_AGENT));
		sysLog.setParams(HttpUtil.toParams(request.getParameterMap()));
		//sysLog.setServiceId(getClientId(request));
		return sysLog;
	}
}

2、通过继承ApplicationEvent

自定义事件SysLogEvent 

public class SysLogEvent extends ApplicationEvent {

	public SysLogEvent(SysLog source) {
		super(source);
	}
}

3、通过实现ApplicationContextAware接口

获得自定义上下文管理器

调用applicationContext.publishEvent(event)方法发布事件

在切面监听方法时,调用事件发布方法发布事件


@Slf4j
@Service
@Lazy(false)
public class SpringContextHolder implements ApplicationContextAware, DisposableBean {

	private static ApplicationContext applicationContext = null;

	/**
	 * 取得存储在静态变量中的ApplicationContext.
	 */
	public static ApplicationContext getApplicationContext() {
		return applicationContext;
	}

	/**
	 * 实现ApplicationContextAware接口, 注入Context到静态变量中.
	 */
	@Override
	public void setApplicationContext(ApplicationContext applicationContext) {
		SpringContextHolder.applicationContext = applicationContext;
	}

	/**
	 * 从静态变量applicationContext中取得Bean, 自动转型为所赋值对象的类型.
	 */
	@SuppressWarnings("unchecked")
	public static <T> T getBean(String name) {
		return (T) applicationContext.getBean(name);
	}

	/**
	 * 从静态变量applicationContext中取得Bean, 自动转型为所赋值对象的类型.
	 */
	public static <T> T getBean(Class<T> requiredType) {
		return applicationContext.getBean(requiredType);
	}

	/**
	 * 清除SpringContextHolder中的ApplicationContext为Null.
	 */
	public static void clearHolder() {
		if (log.isDebugEnabled()) {
			log.debug("清除SpringContextHolder中的ApplicationContext:" + applicationContext);
		}
		applicationContext = null;
	}

	/**
	 * 发布事件
	 * @param event
	 */
	public static void publishEvent(ApplicationEvent event) {
		if (applicationContext == null) {
			return;
		}
		applicationContext.publishEvent(event);
	}

	/**
	 * 实现DisposableBean接口, 在Context关闭时清理静态变量.
	 */
	@Override
	@SneakyThrows
	public void destroy() {
		SpringContextHolder.clearHolder();
	}

}

三、编写类监听事件

通过@EventListener(SysLogEvent.class)注解指定监听的时间

@Async注解异步执行事件

@RequiredArgsConstructor注解写在类上可以代替@AutoWired注解

需要注意的是在注入时需要用final定义,或者使用@notnull注解

@Slf4j
@RequiredArgsConstructor
@Component
public class SysLogListener {

	private final SysLogMapper sysLogMapper;

	@Async
	@Order
	@EventListener(SysLogEvent.class)
	public void saveSysLog(SysLogEvent event) {
		SysLog sysLog = (SysLog) event.getSource();
		sysLogMapper.insert(sysLog);
	}
}
 

四、在controller中的方法上

加上@SysLogAnnotation注解就可以实现通过aop切面的方式来添加日志

    @SysLogAnnotation("导出日志")
    @ApiOperation(value = "导出测试",notes = "导出测试")
    @GetMapping("export")
    public Object exportTest() {
        exportService.testExport();
        return "success";
    }

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • 聊聊Spring循环依赖三级缓存是否可以减少为二级缓存的情况

    聊聊Spring循环依赖三级缓存是否可以减少为二级缓存的情况

    这篇文章主要介绍了聊聊Spring循环依赖三级缓存是否可以减少为二级缓存的情况,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-02-02
  • java中的instanceof关键字详细解读

    java中的instanceof关键字详细解读

    这篇文章主要介绍了java中的instanceof关键字详细解读,instanceof 是 Java 的保留关键字,它的作用是测试它左边的对象是否是它右边的类的实例,返回 boolean 的数据类型,需要的朋友可以参考下
    2024-01-01
  • Java 新特性之Option示例详解

    Java 新特性之Option示例详解

    使用Optional开发时要注意正确使用Optional的“姿势”,特别注意不要使用3.2节提到的错误示范,谨慎使用isPresent()和get()方法,尽量多使用map()、filter()、orElse()等方法来发挥Optional的作用,对Java  Option相关知识感兴趣的朋友一起看看吧
    2024-02-02
  • Java中的final关键字和抽象类详解

    Java中的final关键字和抽象类详解

    这篇文章主要介绍了Java中的final关键字和抽象类详解,当不希望 类被继承时,可以用final修饰比如不希望子类重写父类时,当不希望某个局部变量被修改时,对参数进行修饰,需要的朋友可以参考下
    2023-07-07
  • java实现IP地址转换

    java实现IP地址转换

    这篇文章主要为大家详细介绍了java实现IP地址转换,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-11-11
  • 使用Java编写导出不确定行数列数数据的工具类

    使用Java编写导出不确定行数列数数据的工具类

    这篇文章主要为大家详细介绍了如何使用Java编写导出不确定行数列数数据的工具类,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下
    2024-03-03
  • Java对象Serializable接口实现详解

    Java对象Serializable接口实现详解

    这篇文章主要介绍了Java对象Serializable接口实现详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-12-12
  • Spring AOP操作的相关术语及环境准备

    Spring AOP操作的相关术语及环境准备

    这篇文章主要为大家介绍了Spring AOP操作的相关术语及环境准备学习,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-05-05
  • java如何获取map中value的最大值

    java如何获取map中value的最大值

    这篇文章主要介绍了java如何获取map中value的最大值问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-05-05
  • Intellij IDEA 2020.3 配置教程详解

    Intellij IDEA 2020.3 配置教程详解

    这篇文章主要介绍了Intellij IDEA 2020.3 配置教程详解,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-02-02

最新评论