一、首先自定义注解类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";
}
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。
发表评论