JAVA实现通用日志记录方法

网友投稿 414 2023-05-10


JAVA实现通用日志记录方法

前言:

之前想在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) joinPointhttp://.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的情况下需要返回rehttp://sult 否则将不会返回值给请求者

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中声明

如此一来,核心步骤就完成了,剩下的就是自己组装需要记录的东西了。

第三步:写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")

@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 map = new ConcurrentHashMap<>(128);

static{

//初始化整个枚举类到Map

for (LogTypeEnum logTypeEnum : LogTypeEnum.values()) {

map.put(logTypeEnum.getMethodName(), logTypeEnum);

}

}

}

}


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:springboot实现文件上传和下载功能
下一篇:Java concurrency之AtomicLongFieldUpdater原子类_动力节点Java学院整理
相关文章

 发表评论

暂时没有评论,来抢沙发吧~