根据AOP写一个简单的日志拦截,即创建一个注解,再对应接口注释即可查看访问的ip等信息,可以进行一些比如拉黑,限流等操作
sql脚本如下
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for log
-- ----------------------------
DROP TABLE IF EXISTS `log`;
CREATE TABLE `log` (
`id` varchar(255) CHARACTER SET latin1 COLLATE latin1_swedish_ci NOT NULL COMMENT '主键',
`post_ip` varchar(255) CHARACTER SET latin1 COLLATE latin1_swedish_ci NULL DEFAULT NULL COMMENT '请求ip',
`request_time` varchar(255) CHARACTER SET latin1 COLLATE latin1_swedish_ci NULL DEFAULT NULL COMMENT '请求时间',
`request_name` varchar(255) CHARACTER SET latin1 COLLATE latin1_swedish_ci NULL DEFAULT NULL COMMENT '请求路径名称',
`respone_time` varchar(255) CHARACTER SET latin1 COLLATE latin1_swedish_ci NULL DEFAULT NULL COMMENT '响应时间',
`respone_json` varchar(255) CHARACTER SET latin1 COLLATE latin1_swedish_ci NULL DEFAULT NULL COMMENT '请求数据(过大返会提示)',
`exception` int(3) NULL DEFAULT NULL COMMENT '异常标识',
`exception_info` varchar(255) CHARACTER SET latin1 COLLATE latin1_swedish_ci NULL DEFAULT NULL COMMENT '异常数据(过大返会提示)',
`request_param` varchar(255) CHARACTER SET latin1 COLLATE latin1_swedish_ci NULL DEFAULT NULL COMMENT '请求参数',
`user_time` datetime NULL DEFAULT NULL COMMENT '当前时间',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = latin1 COLLATE = latin1_swedish_ci ROW_FORMAT = Compact;
-- ----------------------------
-- Records of log
-- ----------------------------
SET FOREIGN_KEY_CHECKS = 1;
先定义类
@Data
public class LogEntity {
private String id;
private String postIp;
private String requestType;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private String requestTime;
private String requestName;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private String responeTime;
private String responeJSon;
//是否有异常1--是2--否
private Integer exception;
private String exceptionInfo;
private String requestParam;
private Integer userTime;
}
在定义注解
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Log {
}
根据环绕写一个切面
@Slf4j
public class LogAspent {
@Resource
LogMapper logMapper;
//线程安全的日志对象
ThreadLocal<LogEntity> threadLocal = new ThreadLocal<>();
/**
* 定义一个切面
*/
@Pointcut("annotation(com.example.dabaimao.configuration.Log)")
public void logPontCut() {
}
/**
* 前置增强
*
* @param point
*/
@Before("logPontCut()")
public void logBefore(JoinPoint point) {
LogEntity logEntity = new LogEntity();
logEntity.setIp(UUID.randomUUID().toString());
ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
assert requestAttributes != null;
HttpServletRequest request = requestAttributes.getRequest();
logEntity.setRequestName(request.getServletPath());
logEntity.setRequestTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) + "." + LocalDateTime.now().getNano() / 1000000);
logEntity.setPostId(IpUtils.getIpAddress(request));
logEntity.setRequestType(request.getMethod());
threadLocal.set(logEntity);
}
/**
* 后置增强
*
* @param joinPoint
* @param jsonResult 返回JSON
*/
@AfterReturning(value = "logPontCut()", returning = "jsonResult")
public void logAfterReturning(JoinPoint joinPoint, Object jsonResult) {
LogEntity logEntity = threadLocal.get();
logEntity.setResponeTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) + "." + LocalDateTime.now().getNano() / 1000000);
ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
assert requestAttributes != null;
HttpServletResponse response = requestAttributes.getResponse();
StringBuilder param = new StringBuilder();
for (Object arg : joinPoint.getArgs()) {
param.append(arg.toString());
}
logEntity.setRequestParam(param.toString());
logEntity.setException(0);
logEntity.setUserTime(LocalDateTime.now().getNano() / 1000000 - Integer.parseInt(logEntity.getRequestTime().substring(logEntity.getRequestTime().indexOf(".") + 1)));
if (!Objects.isNull(jsonResult)) {
} else {
logEntity.setResponeJSon("无返回值");
}
//执行代码logMapper.insert(threadlocal.get())
//记得remove避免内存泄漏
threadLocal.remove();
log.info("接口响应成功");
}
/**
* 异常增强
*
* @param joinPoint
* @param e 异常
*/
@AfterThrowing(value = "logPontCut()", throwing = "e")
public void logAfterThrowing(JoinPoint joinPoint, Exception e) {
LogEntity logEntity = threadLocal.get();
if (Objects.isNull(logEntity)) {
try {
logEntity.setException(1);
if (!Objects.isNull(e) && !Objects.isNull(e.getMessage())) {
if (e.getMessage().length() > 2000) {
logEntity.setExceptionInfo("出现异常,异常过长请查看日志");
} else {
logEntity.setExceptionInfo(e.getMessage());
}
}
//执行代码logMapper.insert(threadlocal.get())
//记得remove避免内存泄漏
log.error("接口出现异常");
} catch (Exception exception) {
log.info("threadLocal出现异常:" + exception.getMessage());
}
} else {
log.error("threadLocal出现异常:threalLocal读取失败");
}
}
}
设计一个数据库log表
最后的话加上@Scheduled注解实现几天一清除处理就可以了(也可以实现异步)