springboot aop添加日志方式
一、首先自定義注解類(lèi)SysLogAnnotation
/**
* @date 2019/2/1 操作日志注解
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface SysLogAnnotation {
/**
* 描述
* @return {String}
*/
String value();
}
二、添加切面類(lèi)SysLogAspect,實(shí)現(xiàn)同一的日志添加
1、使用@Aspect注解定義切面類(lèi)
@Component注冊(cè)bean
@Around(“@annotation(sysLogAnnotation)”)
實(shí)現(xiàn)切面環(huán)繞監(jiān)聽(tīng)添加了@sysLogAnnotation注解的方法,
通過(guò)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("[類(lèi)名]:{},[方法]:{}", strClassName, strMethodName);
SysLog logVo = SysLogUtils.getSysLog();
logVo.setTitle(sysLogAnnotation.value());
// 發(fā)送異步日志事件
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() {
//獲取請(qǐng)求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、通過(guò)繼承ApplicationEvent
自定義事件SysLogEvent
public class SysLogEvent extends ApplicationEvent {
public SysLogEvent(SysLog source) {
super(source);
}
}3、通過(guò)實(shí)現(xiàn)ApplicationContextAware接口
獲得自定義上下文管理器
調(diào)用applicationContext.publishEvent(event)方法發(fā)布事件
在切面監(jiān)聽(tīng)方法時(shí),調(diào)用事件發(fā)布方法發(fā)布事件
@Slf4j
@Service
@Lazy(false)
public class SpringContextHolder implements ApplicationContextAware, DisposableBean {
private static ApplicationContext applicationContext = null;
/**
* 取得存儲(chǔ)在靜態(tài)變量中的ApplicationContext.
*/
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
/**
* 實(shí)現(xiàn)ApplicationContextAware接口, 注入Context到靜態(tài)變量中.
*/
@Override
public void setApplicationContext(ApplicationContext applicationContext) {
SpringContextHolder.applicationContext = applicationContext;
}
/**
* 從靜態(tài)變量applicationContext中取得Bean, 自動(dòng)轉(zhuǎn)型為所賦值對(duì)象的類(lèi)型.
*/
@SuppressWarnings("unchecked")
public static <T> T getBean(String name) {
return (T) applicationContext.getBean(name);
}
/**
* 從靜態(tài)變量applicationContext中取得Bean, 自動(dòng)轉(zhuǎn)型為所賦值對(duì)象的類(lèi)型.
*/
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;
}
/**
* 發(fā)布事件
* @param event
*/
public static void publishEvent(ApplicationEvent event) {
if (applicationContext == null) {
return;
}
applicationContext.publishEvent(event);
}
/**
* 實(shí)現(xiàn)DisposableBean接口, 在Context關(guān)閉時(shí)清理靜態(tài)變量.
*/
@Override
@SneakyThrows
public void destroy() {
SpringContextHolder.clearHolder();
}
}
三、編寫(xiě)類(lèi)監(jiān)聽(tīng)事件
通過(guò)@EventListener(SysLogEvent.class)注解指定監(jiān)聽(tīng)的時(shí)間
@Async注解異步執(zhí)行事件
@RequiredArgsConstructor注解寫(xiě)在類(lèi)上可以代替@AutoWired注解
需要注意的是在注入時(shí)需要用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注解就可以實(shí)現(xiàn)通過(guò)aop切面的方式來(lái)添加日志
@SysLogAnnotation("導(dǎo)出日志")
@ApiOperation(value = "導(dǎo)出測(cè)試",notes = "導(dǎo)出測(cè)試")
@GetMapping("export")
public Object exportTest() {
exportService.testExport();
return "success";
}
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
SpringBoot使用AOP實(shí)現(xiàn)日志記錄功能詳解
這篇文章主要為大家介紹了SpringBoot使用AOP實(shí)現(xiàn)日志記錄功能詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-07-07
Java17和springboot3.0使用shiro報(bào)ClassNotFoundException的解決
本文主要介紹了Java17和springboot3.0使用shiro報(bào)ClassNotFoundException的解決,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2024-04-04
如何解決@SpringBootApplication報(bào)錯(cuò)問(wèn)題
這篇文章主要介紹了如何解決@SpringBootApplication報(bào)錯(cuò)問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-07-07
java讀寫(xiě)excel文件實(shí)現(xiàn)POI解析Excel的方法
在日常工作中,我們常常會(huì)進(jìn)行Excel文件讀寫(xiě)操作,這篇文章主要介紹了java讀寫(xiě)excel文件實(shí)現(xiàn)POI解析Excel的方法,實(shí)例分析了java讀寫(xiě)excel的技巧,非常具有實(shí)用價(jià)值,需要的朋友可以參考下2018-10-10
Java中DataInputStream和DataOutputStream的使用方法
這篇文章主要介紹了Java中DataInputStream和DataOutputStream的使用方法,通過(guò)創(chuàng)建對(duì)象展開(kāi)具體的內(nèi)容介紹,需要的小伙伴可以參考一下2022-05-05
SpringBoot服務(wù)監(jiān)控機(jī)制原理解析(面試官常問(wèn))
這篇文章主要介紹了SpringBoot服務(wù)監(jiān)控機(jī)制原理解析(面試官常問(wèn)),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-04-04
java char數(shù)據(jù)類(lèi)型原理解析
這篇文章主要介紹了java char數(shù)據(jù)類(lèi)型原理解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-02-02

