主要实现:
1 在接口上添加注解,记录访问日志,并存储到数据库中
1 定义元注解。ApiLog
package com.ec.safety.common.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 日志记录
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface ApiLog {
String module() default "";
}
2 编写切面代码
package com.ec.safety.query.handler;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.alibaba.fastjson.JSONObject;
import com.ec.safety.common.annotation.ApiLog;
import com.ec.safety.common.constant.CommonConstant;
import com.ec.safety.common.model.CurrentUser;
import com.ec.safety.common.utils.CurrentUserUtil;
import com.ec.safety.query.entity.SysLogs;
import com.ec.safety.query.mapper.SysLogsMapper;
import com.ec.safety.query.mapper.TableCommonMapper;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Objects;
@Slf4j
@Component
@Aspect
public class SysOperateLogAspect {
@Around("@annotation(com.ec.safety.common.annotation.ApiLog)")
public Object around(ProceedingJoinPoint pjp) throws Exception{
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = Objects.requireNonNull(attributes).getRequest();
// 异步执行操作数据
CurrentUser currentUser = CurrentUserUtil.getCurrentUserCommon();
return insertLog(pjp, currentUser, request.getRemoteAddr(), request.getMethod(), request.getRequestURI());
}
private Object insertLog(ProceedingJoinPoint pjp, CurrentUser currentUser, String ip, String method, String requestURI) {
SysLogsMapper logsMapper = SpringUtil.getBean(SysLogsMapper.class);
Signature signature = pjp.getSignature();
MethodSignature methodSignature = (MethodSignature) signature;
ApiLog operation = methodSignature.getMethod().getAnnotation(ApiLog.class);
// 参数
Object[] args = pjp.getArgs();
// 参数类型
Class<?>[] parameterTypes = methodSignature.getParameterTypes();
// 参数名称
String[] parameterNames = methodSignature.getParameterNames();
String requestParams = null;
if (ArrayUtil.isNotEmpty(parameterNames)) {
JSONObject paramJson = new JSONObject();
for (int i = 0; i < parameterNames.length; i++) {
Class<?> parameterType = parameterTypes[i];
if (!parameterType.isAssignableFrom(HttpServletRequest.class) && !parameterType.isAssignableFrom(HttpServletResponse.class)) {
paramJson.put(parameterNames[i], args[i]);
}
}
if (paramJson.size() > 0) {
requestParams = JSONObject.toJSONString(paramJson);
}
}
String operateState = "成功";
String exceptionMessage = requestParams;
try {
return pjp.proceed();
} catch (Throwable e) {
operateState = "失败";
exceptionMessage = e.getMessage();
throw new RuntimeException(exceptionMessage);
} finally {
try {
TableCommonMapper tableCommonMapper = SpringUtil.getBean(TableCommonMapper.class);
String tableName = CommonConstant.SYS_LOGS_TABLE + LocalDateTimeUtil.format(LocalDate.now(), DatePattern.SIMPLE_MONTH_PATTERN);
// 检查新表是否存在 如果不存在 则创建表
Integer tableNum = tableCommonMapper.isExistTable("public", tableName);
if (tableNum == 0) {
String newTable = CommonConstant.PUBLIC + "." + tableName;
logsMapper.copyTable(newTable, tableName + "_pkey");
}
SysLogs logs = new SysLogs();
if (currentUser != null) {
logs.setUserId(currentUser.getId()).setUserName(currentUser.getUsername()).setMobile(currentUser.getMobilePhone());
}
logs.setIpAddress(ip)
.setModule(operation.module())
.setTitle(operation.module())
.setReqPath(method + ":" + requestURI)
.setOperateStatus(operateState).setRequestParam(requestParams)
.setContent(exceptionMessage)
.setCreateTime(LocalDateTime.now());
logsMapper.insert(logs);
} catch (Exception e) {
log.error("保存操作日志失败:", e);
}
}
}
}
3 检查数据库表是否存在,代码如下
<select id="isExistTable" resultType="java.lang.Integer" parameterType="java.lang.String">
SELECT
COUNT(1)
FROM information_schema.tables
WHERE
table_schema = #{tableSchema}
AND table_name = #{tableName}
</select>
4 如果不存在,创建表,代码如下:
<update id="copyTable" parameterType="java.lang.String">
CREATE TABLE ${newTable} (
id varchar(50) NOT NULL,
user_id varchar(50) NULL,
"module" varchar(100) NULL,
title varchar(100) NULL,
ip_address varchar(100) NULL,
req_path varchar(100) NULL,
operate_status varchar(10) NULL,
"content" text NULL,
user_name varchar(100) NULL,
mobile varchar(20) NULL,
request_param text NULL,
create_time timestamp NULL,
CONSTRAINT ${tablepKey} PRIMARY KEY (id)
);
</update>
5 在需要的接口上增加注解,功能实现
完成,是不是很简单呢,我们下次见