1. 创建一个日志记录表
CREATE TABLE `t_log` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '日志编号',
`operator` varchar(50) DEFAULT NULL COMMENT '操作人(工号表示)',
`operate_type` varchar(50) DEFAULT NULL COMMENT '日志类型',
`operate_object` varchar(100) DEFAULT NULL COMMENT '操作对象',
`cost_time` int(11) DEFAULT NULL COMMENT '耗时',
`method` varchar(100) DEFAULT NULL COMMENT '操作的方法',
`params` text COMMENT '方法的参数',
`created_time` datetime DEFAULT NULL COMMENT '操作时间',
`created_by` varchar(50) DEFAULT NULL COMMENT '创建人',
`is_deleted` tinyint(1) DEFAULT NULL COMMENT '是否删除:0未删除,1已删除',
`remark` text COMMENT '备注',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=571 DEFAULT CHARSET=utf8;
对应实体类:
@Data
@EqualsAndHashCode(callSuper = false)
@TableName("t_log")
@ApiModel(value="Log对象", description="")
public class LogEntity implements Serializable {
private static final long serialVersionUID=1L;
@ApiModelProperty(value = "日志编号")
@TableId(value = "id", type = IdType.AUTO)
private Integer id;
@ApiModelProperty(value = "操作人(工号表示)")
@TableField("operator")
private String operator;
@ApiModelProperty(value = "日志类型")
@TableField("operate_type")
private String operateType;
@ApiModelProperty(value = "操作对象")
@TableField("operate_object")
private String operateObject;
@ApiModelProperty(value = "操作的方法")
@TableField("method")
private String method;
@ApiModelProperty(value = "方法的参数")
@TableField("params")
private String params;
@ApiModelProperty(value = "花费时间")
@TableField("cost_time")
private Long costTime;
@ApiModelProperty(value = "备注")
@TableField("remark")
private String remark;
@ApiModelProperty(value = "创建人")
@TableField("created_by")
private String createdBy;
@ApiModelProperty(value = "创建人")
@TableField("created_time")
private Date createdTime;
@ApiModelProperty(value = "是否删除")
@TableField(value = "is_deleted")
private Integer isDeleted;
}
2. 创建一个数据库操作类
public interface LogMapper extends BaseMapper<LogEntity> {
/**
* @Description 分页查询
* @param
* @return
*/
List<LogVo> selectLogPage(LogDto logDto);
/**
* @Description 详情查询
* @param
* @return
*/
LogVo selectLog(@Param("id")Integer id);
/**
* @Description 增加记录
* @param
* @return
*/
int insertLog(LogEntity entity);
/**
* @Description 通过主键修改记录
* @param
* @return
*/
int updateLogByPrimaryKey(LogEntity entity);
/**
* @Description 通过主键删除记录
* @param
* @return
*/
int deleteLogByPrimaryKey(LogEntity entity);
/**
*
* @Description: 清理日志(当前日期6个月之前的数据)
* @param: @return
* @return: int
* @throws
*/
int cleanLog();
/**
*
* @Description: 查询待清理的日志记录
* @param: @return
* @return: List<LogEntity>
* @throws
*/
List<LogEntity> getCleanLog();
}
3. 创建一个常量类
public class Constant {
/**
* 有效
*/
public static final Integer IS_DELETED_VALID = 0;
/**
* 无效
*/
public static final Integer IS_DELETED_INVALID = 1;
public static final String LOG_OPERATE_TYPE_ADD = "新增";
public static final String LOG_OPERATE_TYPE_EDIT = "编辑";
public static final String LOG_OPERATE_OBJECT_COLLECT_TASK = "采集任务";
}
4.创建一个自定义注解类
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface RequiredLog {
/**
* 日志内容
*
* @return
*/
String value() default "";
/**
* 日志操作对象
*
*/
String operateObject() default "";
/**
* 日志操作类型
*
*/
String operateType() default "";
}
5. 创建一个aop拦截类
/**
* 系统日志,切面处理类
*
*/
@Aspect
@Component
public class LogAspect {
// 数据库操作类LogMapper
@Autowired
private LogMapper logMapper;
@Pointcut("@annotation(com.luox.web.annotation.RequiredLog)")
public void logPointCut() {
}
@Around("logPointCut()")
public Object around(ProceedingJoinPoint point) throws Throwable {
long beginTime = System.currentTimeMillis();
//执行方法
Object result = point.proceed();
//执行时长(毫秒)
long time = System.currentTimeMillis() - beginTime;
//保存日志
saveSysLog(point, time);
return result;
}
private void saveSysLog(ProceedingJoinPoint joinPoint, long time) {
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
LogEntity sysLog = new LogEntity();
RequiredLog syslog = method.getAnnotation(RequiredLog.class);
if (syslog != null) {
//注解上的描述,操作日志内容
sysLog.setOperateObject(syslog.operateObject());
sysLog.setOperateType(syslog.operateType());
}
//请求的方法名
String className = joinPoint.getTarget().getClass().getName();
String methodName = signature.getName();
sysLog.setMethod(className + "." + methodName + "()");
// 获取方法的参数
Object[] args = joinPoint.getArgs();
LocalVariableTableParameterNameDiscoverer parameter = new LocalVariableTableParameterNameDiscoverer();
String[] parameterNames = parameter.getParameterNames(method);
if (args != null && parameterNames != null) {
StringBuilder param = new StringBuilder();
for (int i = 0; i < args.length; i++) {
param.append(" ").append(parameterNames[i]).append(":").append(args[i]);
}
sysLog.setParams(param.toString());
}
//获取登录用户信息(这里为了测试给固定值,根据自己系统可动态获取)
String userId = "luox1111";
if (StringUtils.isNotBlank(userId)) {
sysLog.setOperator(userId);
sysLog.setCreatedBy(userId);
}
//耗时
sysLog.setCostTime(time);
sysLog.setCreatedTime(new Date());
sysLog.setIsDeleted(Constant.IS_DELETED_VALID);
//保存系统日志
logMapper.insert(sysLog);
}
@AfterThrowing(pointcut = "logPointCut()", throwing = "ex")
public void afterThrowing(JoinPoint joinPoint, Throwable ex) {
// 获取登录用户信息
String userId = "luox1111";
// 如果获取登录用户信息失败则不用记录日志,否则才记录
if (StringUtils.isNotBlank(userId)) {
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
LogEntity sysLog = new LogEntity();
StackTraceElement[] stackTraceElements = ex.getStackTrace();
String rootExceptionName = ex.getClass().getName();
StringBuilder resultContent = new StringBuilder("异常类:" + rootExceptionName);
int count = 0;
int maxTrace = 3;
for (StackTraceElement stackTraceElement : stackTraceElements) {
if (stackTraceElement.getClassName().contains("com.zt") && count < maxTrace) {
resultContent.append("\n出现于").append(stackTraceElement.getClassName())
.append("类中的").append(stackTraceElement.getMethodName())
.append("方法中 位于该类文件的第").append(stackTraceElement.getLineNumber())
.append("行)");
count++;
if (count == maxTrace) {
break;
}
}
}
// sysLog.setExceptionContent(resultContent.toString());
RequiredLog syslog = method.getAnnotation(RequiredLog.class);
if (syslog != null) {
//注解上的描述,操作日志内容
sysLog.setRemark(ex.getMessage());
sysLog.setOperateObject(syslog.operateObject());
sysLog.setOperateType(syslog.operateType());
}
//请求的方法名
String className = joinPoint.getTarget().getClass().getName();
String methodName = signature.getName();
sysLog.setMethod(className + "." + methodName + "()");
// 获取方法的参数
Object[] args = joinPoint.getArgs();
LocalVariableTableParameterNameDiscoverer parameter = new LocalVariableTableParameterNameDiscoverer();
String[] parameterNames = parameter.getParameterNames(method);
if (args != null && parameterNames != null) {
StringBuilder param = new StringBuilder();
for (int i = 0; i < args.length; i++) {
param.append(" ").append(parameterNames[i]).append(":").append(args[i]);
}
sysLog.setParams(param.toString());
}
if (StringUtils.isNotBlank(userId)) {
sysLog.setOperator(userId);
sysLog.setCreatedBy(userId);
}
sysLog.setIsDeleted(Constant.IS_DELETED_VALID);
sysLog.setCreatedTime(new Date());
//保存系统日志
logMapper.insert(sysLog);
}
}
}
4. 创建一个控制器类,通过注解进行日志收集,通过@RequiredLog注解就可以实现日志记录操作
@Api(tags = "任务管理")
@RestController
@RequestMapping("/web/task")
public class TaskController {
@RequiredLog(value = "创建任务", operateType = Constant.LOG_OPERATE_TYPE_ADD, operateObject = Constant.LOG_OPERATE_OBJECT_COLLECT_TASK)
@ApiOperation(value = "创建任务", notes = "作者: luox 功能: 创建任务, 增加时不需要传主键id")
@RequestMapping(value = "/add", method = RequestMethod.POST)
public ResultVo<Boolean> addTask(@RequestBody @Valid CollectDto dto) {
Boolean result = collectTaskService.addTask(dto);
return ResultVo.success(result, "创建成功");
}
}
经过上面几部,在新增任务时就会往日志表了加入新增创建任务的日志记录,如果有新的其他方法也需要引入日志,只需要按照相同操作,在方法上加入@RequiredLog注解,分别对operateType和operateObject进行赋值即可。