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