效果展示

自定义日志格式和日志管理,使用 Spring 切面注解来对用户操作轨迹的记录。
整合 Logback 日志框架
日志是追溯系统使用记录、跟踪问题的的依据,是系统不可缺少的重要组成部分。在 Spring Boot 中,默认使用的是 Logback 日志。如果创建一个项目没有引用其他的日志框架的话,默认使用 Logback 打印日志

默认的日志格式
目前我们还没有对日志信息做任何设置,直接运行 Spring Boot 项目后,在控制台中就会生成 Logback 默认的日志格式

默认格式内容如下。
时间日期:日志打印时间,精确到毫秒。
日志级别:ERROR,WARN,INFO,DEBUG,TRACE。
进程 ID:进程 ID 指的是当前应用对应的 PID。
分隔符:–标识实际日志的开始。
线程名:方括号括起来(可能会阶段控制台输出)。
Logger 名:通常使用源代码的类名。
日志内容:日志正文。

配置日志文件

日志都是打印到控制台的,如果关闭项目或者系统,日志就会消失,这样不便于后期对问题的分析。所以除了将日志打印在控制台便于实时查看外,也需要将日志做定期归档,便于以后查找问题。针对这些问题, Spring Boot 默认支持使用 xml 自定义日志格式,只需要在 upms/src/main/resources 目录下新建 logback-spring.xml。

<?xml version="1.0" encoding="UTF-8"?>
<configuration  scan="true" scanPeriod="60 seconds" debug="false"><contextName>logback</contextName><!-- 输出到控制台 --><appender name="console" class="ch.qos.logback.core.ConsoleAppender"><encoder><pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36}-[%line] - %msg%n</pattern><charset>UTF-8</charset></encoder></appender><!-- 按天生成日志 --><appender name="logFile"  class="ch.qos.logback.core.rolling.RollingFileAppender"><Prudent>true</Prudent><rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><!-- 日志文件命名 --><FileNamePattern>/IdeaProjects/applog/%d{yyyy-MM-dd}/common-all-%d{yyyy-MM-dd}-%i.log</FileNamePattern><!-- 保存最近 10 天的日志,防止磁盘被占满 --><maxHistory>10</maxHistory><timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"><!-- 设置最大日志文件大小 --><maxFileSize>100MB</maxFileSize></timeBasedFileNamingAndTriggeringPolicy></rollingPolicy><layout class="ch.qos.logback.classic.PatternLayout"><Pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %logger{20}-[%line] - %msg%n</Pattern></layout></appender><!-- 输出指定包文件的日志 --><logger name="com.ming.bms" additivity="false"><appender-ref ref="console"/><appender-ref ref="logFile" /></logger><!-- Spring 日志级别控制  --><logger name="org.springframework" level="warn" /><!-- 日志处理级别 --><root level="info"><appender-ref ref="console"/><appender-ref ref="logFile" /></root></configuration>

logback-spring.xml 配置完成后,重新启动项目,此时可以看到自定义的控制台日志格式如下。

通过 logback-spring.xml 配置文件的设置,我们主要对控制台输出和打印到日志文件做了如下调整。
1、控制台输出中,输出格式为 时:分:秒.毫秒 [线程名] 日志级别 类名-日志信息。
2、打印到日志文件,日志文件的根目录为 D:\IdeaProjects\applog 日志按天进行归档,且单个日志文件最大为 100M,如果超过将生产两个文件。

用户操作行为记录

日志可以让作为开发人员排除问题的工具,但是对于系统的管理员,他们根本不会如何查看日志文件。如何才能让他们在页面上就可以看到用户的操作历史呢。此时就需要将用户的操作行为线性地记录在日志表中。记录下用户所访问的方法内容。

新增用户操作日志表

package com.example.bms.system.dao;import com.example.bms.system.domain.BmsLog;import java.util.List;
import java.util.Map;public interface BmsLogMapper {int deleteByPrimaryKey(Integer logId);int insert(BmsLog record);int insertSelective(BmsLog record);BmsLog selectByPrimaryKey(Integer logId);int updateByPrimaryKeySelective(BmsLog record);int updateByPrimaryKeyWithBLOBs(BmsLog record);int updateByPrimaryKey(BmsLog record);/*** 分页查询*/List<BmsLog> list(Map<String,Object> map);/*** 总数*/int count(Map<String,Object> map);
}

Mapper 文件

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.bms.system.dao.BmsLogMapper"><resultMap id="BaseResultMap" type="com.example.bms.system.domain.BmsLog"><id column="log_id" jdbcType="INTEGER" property="logId" /><result column="description" jdbcType="VARCHAR" property="description" /><result column="username" jdbcType="VARCHAR" property="username" /><result column="permissions" jdbcType="VARCHAR" property="permissions" /><result column="start_time" jdbcType="TIMESTAMP" property="startTime" /><result column="spend_time" jdbcType="INTEGER" property="spendTime" /><result column="base_path" jdbcType="VARCHAR" property="basePath" /><result column="uri" jdbcType="VARCHAR" property="uri" /><result column="method" jdbcType="VARCHAR" property="method" /><result column="user_agent" jdbcType="VARCHAR" property="userAgent" /><result column="ip" jdbcType="VARCHAR" property="ip" /><result column="result" jdbcType="TINYINT" property="result" /></resultMap><resultMap extends="BaseResultMap" id="ResultMapWithBLOBs" type="com.example.bms.system.domain.BmsLog"><result column="parameter" jdbcType="LONGVARCHAR" property="parameter" /></resultMap><sql id="Base_Column_List">log_id, description, username, permissions, start_time, spend_time, base_path, uri, method, user_agent, ip, result</sql><sql id="Blob_Column_List">parameter</sql><select id="selectByPrimaryKey" parameterType="java.lang.Integer" resultMap="ResultMapWithBLOBs">select <include refid="Base_Column_List" />,<include refid="Blob_Column_List" />from bms_logwhere log_id = #{logId,jdbcType=INTEGER}</select><delete id="deleteByPrimaryKey" parameterType="java.lang.Integer">delete from bms_logwhere log_id = #{logId,jdbcType=INTEGER}</delete><insert id="insert" parameterType="com.example.bms.system.domain.BmsLog">insert into bms_log (log_id, description, username, permissions, start_time, spend_time, base_path, uri, method, user_agent, ip, result, parameter)values (#{logId,jdbcType=INTEGER}, #{description,jdbcType=VARCHAR}, #{username,jdbcType=VARCHAR}, #{permissions,jdbcType=VARCHAR}, #{startTime,jdbcType=TIMESTAMP}, #{spendTime,jdbcType=INTEGER}, #{basePath,jdbcType=VARCHAR}, #{uri,jdbcType=VARCHAR}, #{method,jdbcType=VARCHAR}, #{userAgent,jdbcType=VARCHAR}, #{ip,jdbcType=VARCHAR}, #{result,jdbcType=TINYINT}, #{parameter,jdbcType=LONGVARCHAR})</insert><insert id="insertSelective" parameterType="com.example.bms.system.domain.BmsLog">insert into bms_log<trim prefix="(" suffix=")" suffixOverrides=","><if test="logId != null">log_id,</if><if test="description != null">description,</if><if test="username != null">username,</if><if test="permissions != null">permissions,</if><if test="startTime != null">start_time,</if><if test="spendTime != null">spend_time,</if><if test="basePath != null">base_path,</if><if test="uri != null">uri,</if><if test="method != null">method,</if><if test="userAgent != null">user_agent,</if><if test="ip != null">ip,</if><if test="result != null">result,</if><if test="parameter != null">parameter,</if></trim><trim prefix="values (" suffix=")" suffixOverrides=","><if test="logId != null">#{logId,jdbcType=INTEGER},</if><if test="description != null">#{description,jdbcType=VARCHAR},</if><if test="username != null">#{username,jdbcType=VARCHAR},</if><if test="permissions != null">#{permissions,jdbcType=VARCHAR},</if><if test="startTime != null">#{startTime,jdbcType=TIMESTAMP},</if><if test="spendTime != null">#{spendTime,jdbcType=INTEGER},</if><if test="basePath != null">#{basePath,jdbcType=VARCHAR},</if><if test="uri != null">#{uri,jdbcType=VARCHAR},</if><if test="method != null">#{method,jdbcType=VARCHAR},</if><if test="userAgent != null">#{userAgent,jdbcType=VARCHAR},</if><if test="ip != null">#{ip,jdbcType=VARCHAR},</if><if test="result != null">#{result,jdbcType=TINYINT},</if><if test="parameter != null">#{parameter,jdbcType=LONGVARCHAR},</if></trim></insert><update id="updateByPrimaryKeySelective" parameterType="com.example.bms.system.domain.BmsLog">update bms_log<set><if test="description != null">description = #{description,jdbcType=VARCHAR},</if><if test="username != null">username = #{username,jdbcType=VARCHAR},</if><if test="permissions != null">permissions = #{permissions,jdbcType=VARCHAR},</if><if test="startTime != null">start_time = #{startTime,jdbcType=TIMESTAMP},</if><if test="spendTime != null">spend_time = #{spendTime,jdbcType=INTEGER},</if><if test="basePath != null">base_path = #{basePath,jdbcType=VARCHAR},</if><if test="uri != null">uri = #{uri,jdbcType=VARCHAR},</if><if test="method != null">method = #{method,jdbcType=VARCHAR},</if><if test="userAgent != null">user_agent = #{userAgent,jdbcType=VARCHAR},</if><if test="ip != null">ip = #{ip,jdbcType=VARCHAR},</if><if test="result != null">result = #{result,jdbcType=TINYINT},</if><if test="parameter != null">parameter = #{parameter,jdbcType=LONGVARCHAR},</if></set>where log_id = #{logId,jdbcType=INTEGER}</update><update id="updateByPrimaryKeyWithBLOBs" parameterType="com.example.bms.system.domain.BmsLog">update bms_logset description = #{description,jdbcType=VARCHAR},username = #{username,jdbcType=VARCHAR},permissions = #{permissions,jdbcType=VARCHAR},start_time = #{startTime,jdbcType=TIMESTAMP},spend_time = #{spendTime,jdbcType=INTEGER},base_path = #{basePath,jdbcType=VARCHAR},uri = #{uri,jdbcType=VARCHAR},method = #{method,jdbcType=VARCHAR},user_agent = #{userAgent,jdbcType=VARCHAR},ip = #{ip,jdbcType=VARCHAR},result = #{result,jdbcType=TINYINT},parameter = #{parameter,jdbcType=LONGVARCHAR}where log_id = #{logId,jdbcType=INTEGER}</update><update id="updateByPrimaryKey" parameterType="com.example.bms.system.domain.BmsLog">update bms_logset description = #{description,jdbcType=VARCHAR},username = #{username,jdbcType=VARCHAR},permissions = #{permissions,jdbcType=VARCHAR},start_time = #{startTime,jdbcType=TIMESTAMP},spend_time = #{spendTime,jdbcType=INTEGER},base_path = #{basePath,jdbcType=VARCHAR},uri = #{uri,jdbcType=VARCHAR},method = #{method,jdbcType=VARCHAR},user_agent = #{userAgent,jdbcType=VARCHAR},ip = #{ip,jdbcType=VARCHAR},result = #{result,jdbcType=TINYINT}where log_id = #{logId,jdbcType=INTEGER}</update><select id="list" resultType="com.example.bms.system.domain.BmsLog">select `log_id`,`description`,`username`,`start_time`,`spend_time`,`base_path`,`uri`,`method`,`parameter`,`user_agent`,`ip`,`result`,`permissions` from bms_log<where><if test="logId != null and logId != ''"> and log_id = #{logId} </if><if test="description != null and description != ''"> and description = #{description} </if><if test="username != null and username != ''"> and username = #{username} </if><if test="startTime != null and startTime != ''"> and start_time = #{startTime} </if><if test="spendTime != null and spendTime != ''"> and spend_time = #{spendTime} </if><if test="basePath != null and basePath != ''"> and base_path = #{basePath} </if><if test="uri != null and uri != ''"> and uri = #{uri} </if><if test="method != null and method != ''"> and method = #{method} </if><if test="parameter != null and parameter != ''"> and parameter = #{parameter} </if><if test="userAgent != null and userAgent != ''"> and user_agent = #{userAgent} </if><if test="ip != null and ip != ''"> and ip = #{ip} </if><if test="result != null and result != ''"> and result = #{result} </if><if test="permissions != null and permissions != ''"> and permissions = #{permissions} </if></where><choose><when test="sort != null and sort.trim() != ''">order by ${sort} ${order}</when><otherwise>order by log_id desc</otherwise></choose><if test="offset != null and limit != null">limit #{offset}, #{limit}</if></select><select id="count" resultType="int">select count(*) from bms_log<where><if test="logId != null and logId != ''"> and log_id = #{logId} </if><if test="description != null and description != ''"> and description = #{description} </if><if test="username != null and username != ''"> and username = #{username} </if><if test="startTime != null and startTime != ''"> and start_time = #{startTime} </if><if test="spendTime != null and spendTime != ''"> and spend_time = #{spendTime} </if><if test="basePath != null and basePath != ''"> and base_path = #{basePath} </if><if test="uri != null and uri != ''"> and uri = #{uri} </if><if test="method != null and method != ''"> and method = #{method} </if><if test="parameter != null and parameter != ''"> and parameter = #{parameter} </if><if test="userAgent != null and userAgent != ''"> and user_agent = #{userAgent} </if><if test="ip != null and ip != ''"> and ip = #{ip} </if><if test="result != null and result != ''"> and result = #{result} </if><if test="permissions != null and permissions != ''"> and permissions = #{permissions} </if></where></select>
</mapper>

在添加相关的管理类,service controller

新增日志查询页面

添加log页面

使用 Spring 切面注解记录日志

1、添加依赖

需要在 pom.xml 中添加 aop 相关的依赖

<!-- Spring AOP 依赖 -->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId>
</dependency>
2、定义 @Log 注解
package com.example.bms.common.annotation;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;/*** @author pangxie* @data 2020/11/15 15:52** log 注解类*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Log {String value() default "";
}
3、添加 Spring 切面注解逻辑
package com.example.bms.common.aspect;import com.example.bms.common.annotation.Log;
import com.example.bms.common.utils.HttpContextUtils;
import com.example.bms.common.utils.IPUtils;
import com.example.bms.common.utils.JSONUtils;
import com.example.bms.common.utils.ShiroUtils;
import com.example.bms.system.domain.BmsLog;
import com.example.bms.system.domain.BmsUser;
import com.example.bms.system.service.BmsLogService;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Date;
import java.util.Map;
/*** @author pangxie* @data 2020/11/15 15:54** 切面注解*/
@Aspect
@Component
public class LogAspect {private static final Logger logger = LoggerFactory.getLogger(LogAspect.class);@AutowiredBmsLogService logService;@Pointcut("@annotation(com.example.bms.common.annotation.Log)")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;// 异步保存日志saveLog(point, time);return result;}void saveLog(ProceedingJoinPoint joinPoint, long time) throws InterruptedException {MethodSignature signature = (MethodSignature) joinPoint.getSignature();Method method = signature.getMethod();BmsLog sysLog = new BmsLog();Log syslog = method.getAnnotation(Log.class);if (syslog != null) {// 注解上的描述sysLog.setDescription(syslog.value());}// 获取requestHttpServletRequest request = HttpContextUtils.getHttpServletRequest();// 设置IP地址sysLog.setIp(IPUtils.getIpAddr(request));// 设置根路径String path = request.getContextPath();String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path;sysLog.setBasePath(basePath);// 获取urisysLog.setUri(request.getRequestURI());// 请求方式sysLog.setMethod(request.getMethod());// 获取用户设备信息sysLog.setUserAgent(request.getHeader("User-Agent"));// 用户名BmsUser currUser = ShiroUtils.getUser();// 请求的参数Map<String, String[]> paramMap = request.getParameterMap();try {if (paramMap != null) {String params = JSONUtils.beanToJson(paramMap);params = params.substring(0, params.length() < 1000 ? params.length(): 999);sysLog.setParameter(params);}} catch (Exception e) {logger.error("error: "+ e.getMessage(),e);}if (null == currUser) {if (null != sysLog.getParameter()) {sysLog.setUsername(sysLog.getParameter());} else {sysLog.setUsername("获取用户信息为空");}} else {sysLog.setUsername(ShiroUtils.getUser().getUsername());}sysLog.setSpendTime((int) time);// 系统当前时间Date date = new Date();sysLog.setStartTime(date);// 相应状态 0:成功, 1:失败sysLog.setResult(0);// 保存系统日志logService.insert(sysLog);}
}
4、使用注解

打开 BmsUserController.java 类,在 /main 控制器的方法上添加注解。这样,所有用户访问 {。。。}/bms/user/main 时,系统都会记录下用户的操作信息。如下

可以在其他的请求页面中添加 @Log 注解,这样其他的方法也会纳入到我们的记录范围。这样我们就可以实现对用户的管理,可以起到对用户操作的监管追溯。也可以对系统执行效率进行分析,针对长请求可以做针对分析。

日志是追溯系统使用、问题跟踪的依据。日志的收集和归档对于开发者维护系统、BUG 定位起到至关重要的作用。

系统中 用户操作日志管理相关推荐

  1. mysql中用户操作日志_Mysql 纪录用户操作日志

    我们想追踪某个数据库操作记录,如想找出是谁操作了某个表(比如谁将字段名改了). 二进制日志记录了操作记录,线程号等信息,但是却没有记录用户信息,因此需要结合init-connect来实现追踪. ini ...

  2. Linux系统中用户的管理

    #####用户管理###### 1在Linux中,有三种用户: 1 root : 也成为超级用户,对系统有控制权限,超级用户可以不受限制的运行任何命令,root 用户可以看作是系统的管理员. 2 系统 ...

  3. linux 权限 x 表示,在Linux系统中,用户对目录拥有“x”权限,表示可以执行下列哪种操作?...

    在Linux系统中,用户对目录拥有"x"权限,表示可以执行下列哪种操作? 更多相关问题 通过花的中心只能作1个对称面称辐射对称花. 王叔和归纳了脉象( )种,规范了脉象名称. 车轮 ...

  4. 中操作日志文件记录的是什么_SpringBoot+AOP实现用户操作日志的记录

    前言: 任何一个项目都会有一个用户操作日志(也叫行为日志)的模块,它主要用来记录某个用户做了某个操作,当出现操作失败时,通过日志就可以快速的查找是哪个用户在哪个模块出现了错误,以便于开发人员快速定位问 ...

  5. 第17周翻译:SQL Server中的事务日志管理的阶梯:第5级:在完全恢复模式下管理日志...

    来源:http://www.sqlservercentral.com/articles/Stairway+Series/73785/ 作者:Tony Davis, 2012/01/27 翻译:刘琼滨. ...

  6. 查看历史操作记录_燕麦课堂丨操作日志管理,为企业数据安全保驾护航

    燕麦云的操作日志管理 燕麦云拥有详尽的操作日志,企业管理员可查阅所有账号对云盘文件的操作记录,追溯异常文件操作.能提供完善的跟踪.记录.监控管理机制,从登录开始到退出账号所有操作均可后台查阅.企业管理 ...

  7. 磁盘管理来安装linux,Linux_在CentOS系统中安装quota来管理磁盘配额,在网络管理的工作中,由于硬 - phpStudy...

    在CentOS系统中安装quota来管理磁盘配额 在网络管理的工作中,由于硬盘的资源是有限的,常常需要为多用户的服务器设定用户的linux磁盘配额.这个功能对公用的多用户服务器(免费的或者收费的)来说 ...

  8. IP记录Linux所有用户操作日志的方法(附脚本)

    按时按登录IP记录Linux所有用户操作日志的方法(附脚本) 标签: IP记录,Linux,总结,按时,方法,日志,用户操作,脚本.PS:Linux用户操作记录一般通过命令history来查看历史记录 ...

  9. 使用Spring AOP自定义注解方式实现用户操作日志记录

    1,开发环境 操作系统:Windows 7 JDK:1.8.0_161 Eclipse:Mars.2 Release (4.5.2) 2,自定义注解类UserLog @Target({ElementT ...

  10. Spring Boot + Aop 记录用户操作日志

    目录 一.前言 二.实战 1.设计用户操作日志表: sys_oper_log 2.引入依赖 3.自定义用户操作日志注解 4.自定义用户操作日志切面 5.MyLog注解的使用 6.最终效果 三.总结 一 ...

最新文章

  1. codeblocks使用指南
  2. mysql 连接超时 wait_timeout interactive_timeout 简介
  3. 怎么用numpy读取excel的数据画三维图_python初学者,如何快速匹配excel任务
  4. Java虚拟机(JVM)简介
  5. 将MongoDB.NET驱动程序与.NET Core WebAPI一起使用
  6. windows下编写dll
  7. 数模比赛经验分享(美赛分享)
  8. Python教学视频(六)关系及逻辑运算
  9. 压力测试流程及测试步骤
  10. mysql数据库误删后能恢复吗_浅谈数据库误删除恢复
  11. linux scl软件包下载,SCL项目:在Red Hat系列系统上安装同一软件的不同版本
  12. 电路基础里的等效电路
  13. JQuery制作手风琴效果
  14. Leetcode 460. LFU 缓存
  15. 按图搜索淘宝商品-item_search_img (拍立淘)
  16. 检查linux中nginx是否已安装成功,linux服务下安装nginx 系统版本Ubuntu 18.04.4
  17. 山西师范计算机科学与技术能转什么专业,太原师范学院可以转专业吗 太原师范学院新生转专业政策...
  18. 杨绛:越是难熬的时候,人越要体面
  19. gm220s路由器怎么设置_二级路由器怎么设置_二级路由器设置图解教程-192路由网...
  20. opencv 分水岭算法详细理论+实践

热门文章

  1. 2022年软考高级网络规划设计师备考指南
  2. 直击固定资产管理痛点,让企业轻松管理海量固定资产
  3. CAD弹窗拦截器/CAD字体自动替换工具
  4. 通过PyMuPDF编写增值税发票多PDF文件合并工具
  5. FastStone Capture(定时自动截图)
  6. 实现WEB打印的几种方法
  7. onpropertychange
  8. 如何解决“这台电脑上已经安装了更高版本的Bonjour”
  9. 卓有成效的管理者—第七章 有效的决定
  10. JAVAweb JSP飞机订票系统航空机票预订销售系统(机票预订系统)