Springboot接口项目如何使用AOP记录日志
程序员文章站
2022-04-09 16:20:56
一、 背景一直想给项目构建一个统一的日志收集系统,先迈出第一步,构建一个日志收集类,用aop实现无侵入日志收集二、 环境1.此随笔内容基于spring boot项目2.数据库为mysql 5.7.9版...
一、 背景
一直想给项目构建一个统一的日志收集系统,先迈出第一步,构建一个日志收集类,用aop实现无侵入日志收集
二、 环境
1.此随笔内容基于spring boot项目
2.数据库为mysql 5.7.9版本
3.jdk 版本为1.8
三、 说明
此版采用数据库存储,之后考虑使用elasticsearch等工具存储
四、 内容
1、构建日志采集实体类:baselogmessage
public class baselogmessage { private string serverip; private string appname; private string method; private string type; private string usercode; private string uri; private string operationname; private string operationstatus; private long starttime; private object parameter; private object result; private int spendtime; // 此处省略get、set }
2、构建一个配置文件读取类,用于读取配置文件中的系统名称:systempropetiesutil
@configuration public class systempropetiesutil { @value("${spring.application.name}") private string sysname;//系统名称<br> // 此处省略get、set<br>}
3、新建一个aop类,在控制器方法上作为切点,执行日志收集: logaspect
@aspect @component public class logaspect { @autowired private systempropetiesutil systempropetiesutil; //定义切点方法 @pointcut("execution(public * cq..campus.prevented.controller.*.*(..))") public void controllerlog() { } public static final logger logger = loggerfactory.getlogger(logaspect.class); @around("controllerlog()") public object doaround(proceedingjoinpoint joinpoint) throws throwable { long starttime = system.currenttimemillis(); //获取当前请求对象 servletrequestattributes attributes = (servletrequestattributes) requestcontextholder.getrequestattributes(); httpservletrequest request = attributes.getrequest(); //记录请求信息 baselogmessage baselogmessage = new baselogmessage(); //1.获取到所有的参数值的数组 object[] args = joinpoint.getargs(); signature signature = joinpoint.getsignature(); methodsignature methodsignature = (methodsignature) signature; //2.获取到方法的所有参数名称的字符串数组 string[] parameternames = methodsignature.getparameternames(); object result = joinpoint.proceed(); method method = methodsignature.getmethod(); if (method.isannotationpresent(apioperation.class)) { apioperation apioperation = method.getannotation(apioperation.class); baselogmessage.setoperationname(apioperation.value()); } long endtime = system.currenttimemillis(); string urlstr = request.getrequesturl().tostring(); baselogmessage.seturi(urlstr); baselogmessage.settype("操作日志"); baselogmessage.setserverip(getremoteip(request)); baselogmessage.setmethod(request.getmethod()); baselogmessage.setappname(systempropetiesutil.getsysname()); baselogmessage.setresult(result); baselogmessage.setparameter(getparameter(method, joinpoint.getargs())); baselogmessage.setspendtime((int) (endtime - starttime)); baselogmessage.setstarttime(endtime); logger.info("{}", jsonutils.objecttojson(baselogmessage)); // 数据库存储操作 return result; } /** * 异常返回通知,用于拦截异常日志信息 连接点抛出异常后执行 * * @param joinpoint 切入点 * @param e 异常信息 */ @afterthrowing(pointcut = "controllerlog()", throwing = "e") public void saveexceptionlog(joinpoint joinpoint, throwable e) { long starttime = system.currenttimemillis(); if(null==kafkaclient){ kafkaclient = kafkaproducerclient.getinstance(systempropetiesutil.getkafkahost()); // redisclient= redisclient.getinstance(systempropetiesutil.getreidshost(), integer.parseint(systempropetiesutil.getredisport()), ""); } // 获取requestattributes requestattributes requestattributes = requestcontextholder.getrequestattributes(); // 从获取requestattributes中获取httpservletrequest的信息 httpservletrequest request = (httpservletrequest) requestattributes .resolvereference(requestattributes.reference_request); string urlstr = request.getrequesturl().tostring(); baselogmessage baselogmessage = new baselogmessage(); signature signature = joinpoint.getsignature(); methodsignature methodsignature = (methodsignature) signature; method method = methodsignature.getmethod(); stringbuffer strbuff = new stringbuffer(); for (stacktraceelement stet : elements) { strbuff.append(stet + "\n"); } string message = exceptionname + ":" + exceptionmessage + strbuff.tostring(); try { object[] args = joinpoint.getargs(); string[] parameternames = methodsignature.getparameternames(); long endtime = system.currenttimemillis(); baselogmessage.seturi(urlstr); baselogmessage.settype("异常日志"); baselogmessage.setserverip(getremoteip(request)); baselogmessage.setmethod(request.getmethod()); baselogmessage.setappname(systempropetiesutil.getsysname()); baselogmessage.setresult(message); baselogmessage.setparameter(getparameter(method, joinpoint.getargs())); baselogmessage.setspendtime((int) (endtime - starttime)); baselogmessage.setstarttime(endtime); logger.info("{}", jsonutils.objecttojson(baselogmessage)); // 数据库存储操作 } catch (exception e2) { e2.printstacktrace(); } } /** * 根据方法和传入的参数获取请求参数 */ private object getparameter(method method, object[] args) { list<object> arglist = new arraylist<>(); parameter[] parameters = method.getparameters(); for (int i = 0; i < parameters.length; i++) { requestbody requestbody = parameters[i].getannotation(requestbody.class); if (requestbody != null) { arglist.add(args[i]); } requestparam requestparam = parameters[i].getannotation(requestparam.class); if (requestparam != null) { map<string, object> map = new hashmap<>(); string key = parameters[i].getname(); if (!stringutils.isempty(requestparam.value())) { key = requestparam.value(); } map.put(key, args[i]); arglist.add(map); } } if (arglist.size() == 0) { return null; } else if (arglist.size() == 1) { return arglist.get(0); } else { return arglist; } } /** * 获取请求ip */ public static string getremoteip(httpservletrequest request) { string ip =null; if (ip == null || ip.length() == 0 || "unknown".equalsignorecase(ip)) { ip = request.getheader("x-forwarded-for"); } if (ip == null || ip.length() == 0 || "unknown".equalsignorecase(ip)) { ip = request.getheader("proxy-client-ip"); } if (ip == null || ip.length() == 0 || "unknown".equalsignorecase(ip)) { ip = request.getheader("wl-proxy-client-ip"); } if (ip == null || ip.length() == 0 || "unknown".equalsignorecase(ip)) { ip = request.getremoteaddr(); } if (ip != null) { //对于通过多个代理的情况,最后ip为客户端真实ip,多个ip按照','分割 int position = ip.indexof(","); if (position > 0) { ip = ip.substring(0, position); } } return ip; } }
五、 问题
1、如果方法正常执行,不进入aop类,请检查aop的切点是否书写正确。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。