JAVA实现通用日志记录方法
程序员文章站
2024-02-12 09:35:40
前言:
之前想在filter层直接过滤httpserverletrequest请求进行日志处理,但是之后再getwriter()的 时候报already been...
前言:
之前想在filter层直接过滤httpserverletrequest请求进行日志处理,但是之后再getwriter()的 时候报already been call异常。查了下,才发现原来流形式的只能读取一次。。就好像食物,吃了就没了。。 所以在filter和inteceptor里面是没法通过获取request的流来进行日志记录的。
于是还是准备用通用的方法:controller层aop进行切面记录日志。
使用aop记录操作日志
第一步:添加aop
/** * 统一日志处理handler * @author mingchenchen * */ public class logaophandler { @autowired private auditlogdao auditlogdao; /** * controller层面记录操作日志 * 注意此处是aop:around的 因为需要得到请求前的参数以及请求后接口返回的结果 * @throws throwable */ public object dosavelog(proceedingjoinpoint joinpoint) throws throwable { methodsignature method = (methodsignature) joinpoint.getsignature(); string methodname = method.getname(); object[] objects = joinpoint.getargs(); string requestbody = null; if (objects!=null && objects.length>0) { for (object object : objects) { if (object == null) { requestbody = null;//post接口参数为空 比如删除xxx }else if (object instanceof string) { requestbody = (string) object;//有些接口直接把参数转换成对象了 }else { requestbody = jsonobject.tojsonstring(object); } } } //只记录post方法的日志 boolean isneedsavelog = false; //此处不能用getannotationbytype 是java8的特性,因为注解能够重名,所以得到的是数组 requestmapping annotation = method.getmethod().getannotation(requestmapping.class); for (requestmethod requestmethod : annotation.method()) { if (requestmethod==requestmethod.post) { isneedsavelog = true; } } jsonobject requestbodyjson = null; try { requestbodyjson = jsonobject.parseobject(requestbody); } catch (exception e) { //do nothing 即post请求没传body } httpservletrequest request = requestcontextutil.getrequestbycurrentcontext(); string username = requestcontextutil.getusernamebycurrentcontext(); if (stringutil.isempty(username)) { try { username = dmscache.get(requestbodyjson.getstring("username")).getname(); } catch (exception e) { username = requestcontextutil.getasynuserinfobyautodeploy().getname(); } } //得到request的参数后让方法执行它 //注意around的情况下需要返回result 否则将不会返回值给请求者 object result = joinpoint.proceed(objects); try { jsonobject resultjson = jsonobject.parseobject(result.tostring()); if (isneedsavelog) {//如果是post请求 则记录日志 logtypeenum logtypeenum = logtypeenum.getdesbymethodname(methodname); if (logtypeenum != null) { auditlogentity auditlogentity = new auditlogentity(); auditlogentity.setuuid(stringutil.createrandomuuid()); auditlogentity.setoperator(username); auditlogentity.setrequestip(request.getremoteaddr()); auditlogentity.setrequesturl(request.getrequesturi().replace("/cloud-master", "")); auditlogentity.seteventtype(logtypeenum.getkey()); auditlogentity.seteventdesc(logtypeenum.getdescription()); auditlogentity.setrequest(requestbody); int issuccess = "200".equals(resultjson.getstring("code")) ? 1 : 0; auditlogentity.setsuccessflag(issuccess); auditlogentity.setresponse(result.tostring()); auditlogentity.setcreatetime(new date()); auditlogdao.insert(auditlogentity); } } } catch (exception e) { e.printstacktrace(); } return result; } }
第二步:在spring的xml中声明
<!-- 记录操作日志 --> <bean id="operationlogaop" class="com.ming.learn.core.aop.logaophandler"/> <aop:config> <aop:aspect id="logaop" ref="operationlogaop"> <aop:pointcut id="target" expression="execution(* com.ming.learn..*controller.*(..))"/> <aop:around method="dosavelog" pointcut-ref="target"/> </aop:aspect> </aop:config>
如此一来,核心步骤就完成了,剩下的就是自己组装需要记录的东西了。
第三步:写dao、entity、mapper
import java.util.date; import javax.persistence.column; import javax.persistence.id; import javax.persistence.table; /** * 日志审计 * @author mingchenchen * */ @table(name="audit_log") public class auditlogentity { @id private string uuid; @column(name="event_type") private string eventtype;//事件类型 @column(name="event_desc") private string eventdesc;//事件中文描述 @column(name="operator") private string operator;//操作者 @column(name="request_ip") private string requestip;//客户端地址 @column(name="request_url") private string requesturl;//请求地址 @column(name="request") private string request;//请求body @column(name="response") private string response;//请求返回值 @column(name="create_time") private date createtime; public string getuuid() { return uuid; } public void setuuid(string uuid) { this.uuid = uuid; } public string geteventtype() { return eventtype; } public void seteventtype(string eventtype) { this.eventtype = eventtype; } public string geteventdesc() { return eventdesc; } public void seteventdesc(string eventdesc) { this.eventdesc = eventdesc; } public string getoperator() { return operator; } public void setoperator(string operator) { this.operator = operator; } public string getrequestip() { return requestip; } public void setrequestip(string requestip) { this.requestip = requestip; } public string getrequesturl() { return requesturl; } public void setrequesturl(string requesturl) { this.requesturl = requesturl; } public string getrequest() { return request; } public void setrequest(string request) { this.request = request; } public string getresponse() { return response; } public void setresponse(string response) { this.response = response; } public date getcreatetime() { return createtime; } public void setcreatetime(date createtime) { this.createtime = createtime; } }
第四步:根据controller的方法名称定制响应的事件类型
import java.util.map; import java.util.concurrent.concurrenthashmap; /** * 操作日志类型 * @author mingchenchen * */ public enum logtypeenum { //用户 common_login("login","login","登录"); //其他 private string methodname;//方法名称与controller一致 private string key;//保存到数据库的事件类型 private string description;//保存到数据库的描述 private logtypeenum(string methodname,string key,string description){ this.methodname = methodname; this.key = key; this.description = description; } public string getmethodname() { return methodname; } public void setmethodname(string methodname) { this.methodname = methodname; } public string getkey() { return key; } public void setkey(string key) { this.key = key; } public string getdescription() { return description; } public void setdescription(string description) { this.description = description; } /** * 根据方法名返回 * @param methodname * @return */ public static logtypeenum getdesbymethodname(string methodname){ return innermap.map.get(methodname); } /** * 内部类 用户保存所有的enum 无须通过enum.values()每次遍历 * @author mingchenchen * */ private static class innermap{ private static map<string, logtypeenum> map = new concurrenthashmap<>(128); static{ //初始化整个枚举类到map for (logtypeenum logtypeenum : logtypeenum.values()) { map.put(logtypeenum.getmethodname(), logtypeenum); } } } }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
上一篇: 宝宝发烧怎么办,教你在家物理降温!
下一篇: 孕妇可以吃羊肉吗,吃羊肉的禁忌有哪些!