项目准备
数据库
CREATE TABLE `smbms_user` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`userCode` varchar(15) CHARACTER SET utf8mb3 COLLATE utf8mb3_unicode_ci NULL DEFAULT NULL COMMENT '用户编码',
`userName` varchar(15) CHARACTER SET utf8mb3 COLLATE utf8mb3_unicode_ci NULL DEFAULT NULL COMMENT '用户名称',
`userPassword` varchar(15) CHARACTER SET utf8mb3 COLLATE utf8mb3_unicode_ci NULL DEFAULT '0000000' COMMENT '用户密码',
`gender` int NULL DEFAULT NULL COMMENT '性别(1:女、 2:男)',
`birthday` datetime NULL DEFAULT NULL COMMENT '出生日期',
`phone` varchar(15) CHARACTER SET utf8mb3 COLLATE utf8mb3_unicode_ci NULL DEFAULT NULL COMMENT '手机',
`address` varchar(30) CHARACTER SET utf8mb3 COLLATE utf8mb3_unicode_ci NULL DEFAULT NULL COMMENT '地址',
`userRole` bigint NULL DEFAULT NULL COMMENT '用户角色(取自角色表-角色id)',
`createdBy` bigint NULL DEFAULT NULL COMMENT '创建者(userId)',
`creationDate` datetime NULL DEFAULT NULL COMMENT '创建时间',
`modifyBy` bigint NULL DEFAULT NULL COMMENT '更新者(userId)',
`modifyDate` datetime NULL DEFAULT NULL COMMENT '更新时间',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 129 CHARACTER SET = utf8mb3 COLLATE = utf8mb3_unicode_ci ROW_FORMAT = Dynamic;
INSERT INTO `smbms_user` VALUES (1, 'admin', '系统管理员', '1234567', 1, '1983-10-10 00:00:00', '13688889999', '北京市海淀区成府路207号', 1, 1, '2013-03-21 16:52:07', NULL, NULL);
INSERT INTO `smbms_user` VALUES (2, 'liming', '李明', '0000000', 2, '1983-12-10 00:00:00', '13688884457', '北京市东城区前门东大街9号', 3, 1, '2014-12-31 19:52:09', NULL, '2025-09-04 15:57:03');
INSERT INTO `smbms_user` VALUES (5, 'hanlubiao', '韩路彪', '0000000', 2, '1984-06-05 00:00:00', '18567542321', '北京市朝阳区北辰中心12号', 2, 1, '2014-12-31 19:52:09', NULL, NULL);
INSERT INTO `smbms_user` VALUES (6, 'zhanghua', '张华1', '0000000', 1, '1983-06-15 00:00:00', '13544561111', '北京市海淀区学院路61号', 3, 1, '2013-02-11 10:51:17', NULL, '2025-08-19 16:45:43');
INSERT INTO `smbms_user` VALUES (7, 'wangyang', '王洋', '0000000', 2, '1982-12-31 00:00:00', '13444561124', '北京市海淀区西二旗辉煌国际16层', 3, 1, '2014-06-11 19:09:07', NULL, NULL);
INSERT INTO `smbms_user` VALUES (8, 'zhaoyan', '赵燕', '0000000', 1, '1986-03-07 00:00:00', '18098764545', '北京市海淀区回龙观小区10号楼', 3, 1, '2016-04-21 13:54:07', NULL, NULL);
INSERT INTO `smbms_user` VALUES (10, 'sunlei', '孙磊', '0000000', 2, '1981-01-04 00:00:00', '13387676765', '北京市朝阳区管庄新月小区12楼', 3, 1, '2015-05-06 10:52:07', NULL, NULL);
INSERT INTO `smbms_user` VALUES (11, 'sunxing', '孙兴', '0000000', 2, '1978-03-12 00:00:00', '13367890900', '北京市朝阳区建国门南大街10号', 3, 1, '2016-11-09 16:51:17', NULL, NULL);
INSERT INTO `smbms_user` VALUES (12, 'zhangchen', '张晨', '0000000', 1, '1986-03-28 00:00:00', '18098765434', '朝阳区管庄路口北柏林爱乐三期13号楼', 3, 1, '2016-08-09 05:52:37', 1, '2016-04-14 14:15:36');
INSERT INTO `smbms_user` VALUES (13, 'dengchao', '邓超', '0000000', 2, '1981-11-04 00:00:00', '13689674534', '北京市海淀区北航家属院10号楼', 3, 1, '2016-07-11 08:02:47', NULL, NULL);
INSERT INTO `smbms_user` VALUES (14, 'yangguo', '杨过', '0000000', 2, '1980-01-01 00:00:00', '13388886623', '北京市朝阳区北苑家园茉莉园20号楼', 3, 1, '2015-02-01 03:52:07', NULL, NULL);
INSERT INTO `smbms_user` VALUES (15, 'zhaomin', '赵敏1', '0000000', 1, '1992-01-01 00:00:00', '18099897657', '北京市昌平区天通苑3区12号楼', 2, 1, '2015-09-12 12:02:12', NULL, NULL);
INSERT INTO `smbms_user` VALUES (103, '1', '1', '1', 1, '2025-07-17 16:34:35', '1', '1', 1, 1, '2025-07-17 16:34:35', 1, '2025-07-17 16:34:35');
INSERT INTO `smbms_user` VALUES (112, '80', '惠静怡', 'BSu9Y5mIKEZ2C8H', NULL, NULL, NULL, NULL, 1, NULL, '2025-09-03 11:09:07', NULL, NULL);
INSERT INTO `smbms_user` VALUES (113, '山东', '是的是的', '0000000', 2, '2025-09-07 08:00:00', '15457854567', '山东', 2, NULL, '2025-09-03 11:12:28', NULL, '2025-09-04 15:07:54');
INSERT INTO `smbms_user` VALUES (114, '你好', '山东', '0000000', 2, '2025-09-09 08:00:00', '15456874569', '山东', 1, NULL, '2025-09-03 11:18:27', NULL, '2025-09-03 11:30:45');
INSERT INTO `smbms_user` VALUES (115, '山东', '山东', '0000000', 2, '2025-09-01 08:00:00', '14575674578', ' 但是', 1, NULL, '2025-09-03 11:19:43', NULL, NULL);
INSERT INTO `smbms_user` VALUES (116, '山东', '山东', '0000000', 2, '2025-09-09 08:00:00', '18466559854', '山东', 1, NULL, '2025-09-03 11:21:01', NULL, NULL);
INSERT INTO `smbms_user` VALUES (117, '山东', '山东', '0000000', 2, '2025-09-01 08:00:00', '14567854569', '45', 1, NULL, '2025-09-03 11:22:15', NULL, NULL);
INSERT INTO `smbms_user` VALUES (119, NULL, '李四', '0000000', NULL, NULL, NULL, NULL, 1, NULL, NULL, NULL, NULL);
INSERT INTO `smbms_user` VALUES (120, NULL, '李四', '0000000', NULL, NULL, NULL, NULL, 1, NULL, NULL, NULL, NULL);
新建项目并选择模块安装
创建一个空的 Spring Boot 工程
文件–>新建项目
选择模块
SpringBoot
版本选择2.7.6
- 在
DeveloperTools
中选择Lombok
- 在
Web
中选择SpringWeb
- 在
SQL
中选择MySQLDriver
添加依赖
<!-- mybatis-plus依赖 -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.1</version>
<!--sql性能分析插件使用版本-->
<!-- <version>3.1.2</version> -->
</dependency>
添加application.yml
我们删除application.properties
在resources文件下新建application.yml
.
在 application.yml
中配置文件中添加mysql 数据库相关配置:
server:
port: 8080
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/smbms?useUnicode=true&characterEncoding=utf-8&useSSL=false&allowPublicKeyRetrieval=true
username: root
password: root
# mybatis-plus 相关配置
mybatis-plus:
type-aliases-package: com.hsh.pojo #类型别名所在的包
#控制台打印sql语句
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
map-underscore-to-camel-case: false #关闭驼峰映射
注意你要写你的
数据库端口号
,账号
,密码
,你要简化的包名
这些一定要看一下。
删除demos.web包
编写pojo层
user
com/hsh/pojo/user
package com.hsh.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.LocalDateTime;
@Data
@NoArgsConstructor
@AllArgsConstructor
@TableName("smbms_user")
public class User {
private Long id;// 主键ID
private String userCode;// 用户编码
private String userName;// 用户名称
private String userPassword;// 用户密码
private Integer gender;// 性别(1:女、 2:男)
private LocalDateTime birthday;// 出生日期
private String phone;// 手机
private String address;// 地址
private Long userRole;// 用户角色(取自角色表-角色id)
private Long createdBy;// 创建者(userId)
private LocalDateTime creationDate;// 创建时间
private Long modifyBy; // 更新者(userId)
private LocalDateTime modifyDate; // 更新时间
}
dto/ResultJson
package com.hsh.pojo.tdo;
import java.io.Serializable;
@Data
public class ResultJSON<T> implements Serializable {
private Integer code;
private String msg;
private T data;
public ResultJSON(Integer code, String msg, T data) {
this.code = code;
this.msg = msg;
this.data = data;
}
/**
* 操作成功或者失败
* @param c 受影响行数
* @return 当前传入的受影响行数>0则返回成功,否则返回失败
*/
public static ResultJSON successORerror(int c){
return c>0?new ResultJSON(200,"操作成功",c)
:new ResultJSON(400,"操作失败",c);
}
public static ResultJSON success(){
return new ResultJSON(200,"操作成功",null);
}
public static ResultJSON success(String msg){
return new ResultJSON(200,msg,null);
}
public static <T> ResultJSON success(T data){
return new ResultJSON(200,"操作成功",data);
}
public static ResultJSON success(Integer code,String msg){
return new ResultJSON(code,msg,null);
}
public static <T> ResultJSON success(String msg,T data){
return new ResultJSON(200,msg,data);
}
public static <T> ResultJSON success(Integer code,String msg,T data){
return new ResultJSON(code,msg,data);
}
public static ResultJSON error(){
return new ResultJSON(500,"操作失败",null);
}
public static ResultJSON error(String msg){
return new ResultJSON(500,msg,null);
}
public static ResultJSON error(Integer code,String msg){
return new ResultJSON(code,msg,null);
}
}
编写mapper层
UserMapper
package com.hsh.mapper;
public interface UserMapper extends BaseMapper<User> {
}
编写service层
UserService
// 接口
package com.hsh.service;
public interface UserService {
ResultJSON<User> getUserById(Long id);
ResultJSON<User> editUser(User user);
ResultJSON<User> deleteUser(Long id);
ResultJSON<User> addUser(User user);
}
// 实现类
package com.hsh.service.impl;
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
@Autowired
private UserMapper userMapper;
@Override
public ResultJSON<User> getUserById(Long id) {
User user = userMapper.selectById(id);
return ResultJSON.success(user);
}
@Override
public ResultJSON<User> editUser(User user) {
int i = userMapper.updateById(user);
return ResultJSON.successORerror(i);
}
@Override
public ResultJSON<User> deleteUser(Long id) {
int i = userMapper.deleteById(id);
return ResultJSON.successORerror(i);
}
@Override
public ResultJSON<User> addUser(User user) {
int i = userMapper.insert(user);
return ResultJSON.successORerror(i);
}
}
编写controller层
UserContoller
package com.hsh.controller;
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService;
@RequestMapping("/getUserById")
public ResultJSON getUserById(Long id){
return ResultJSON.success(userService.getUserById(id));
}
@RequestMapping("/addUser")
public ResultJSON addUser(@RequestBody User user){
return userService.addUser(user);
}
@RequestMapping("/deleteUser")
public ResultJSON deleteUser(Long id){
return userService.deleteUser(id);
}
@RequestMapping("/editUser")
public ResultJSON editUser(@RequestBody User user){
return userService.editUser(user);
}
}
编写配置类
MybatisPlusConfig
package com.hsh.config;
@Configuration
@MapperScan("com.hsh.mapper")
public class MybatisPlusConfig {
}
编写测试类
package com.hsh;
import com.hsh.mapper.UserMapper;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class MybatisPlus01ApplicationTests {
@Autowired
private UserMapper userMapper;
@Test
void contextLoads() {
System.out.println(userMapper.selectById(1));
}
}
概述
日志处理分两种
- 异常日志:当程序报异常进行记录。
- 使用技术:log4j,logback,slf4j,
- 操作日志:当用户进行修改,更新,删除,操作时需要记录。查询不需要记录。
- 使用技术:AOP。使用AOP需要自定义注解进行使用。当我在方法上写这个自定义注解,我就去捕获这方法进行操作日志记录。
我们这些日志如何存贮呢?
- 数据库:当数据库满了需要手动备份然后清空数据库。(若依框架就是使用的这一套)
- Redis:虽然redis能持久化,但是一次要拿很多数据,只能用stream流过滤,当数据过大会出问题。
- 记事本:数据量过大会卡顿。
- 搜索引擎:solr(单体式项目),ES(分布式项目)。
记录操作日志
我们使用数据库存储,因为若依使用的就是这一套。
我们的记录日志操作是对某些方法进行操作,所以aop就可以对某些方法进行操作。
使用AOP对日志注解增强
引入aop依赖
<!-- aop依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
编写@Log注解
在com/hsh
文件夹下新建aop文件夹,并在com/hsh/aop
下新建Log类
package com.hsh.aop;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
// @Target 用来说明该注解可以被声明在那些元素之前
// ElementType.METHOD说明该注解只能被声明在一个类的方法前
@Target(ElementType.METHOD)
// @Retention 用来说明注解的声明周期
// RetentionPolicy.RUNTIME注解保留在程序运行期间,
// 此时可以通过反射获得定义在某个类上的所有注解。
@Retention(RetentionPolicy.RUNTIME)
public @interface Log {// @interface 注解类,自定义注解
String value() default "";
}
编写LogAspect增强类与增强方法
编写LogAspect增强类与增强方法(我们使用环绕增强around)
在com/hsh
文件夹下新建aop文件夹,并在com/hsh/aop
下新建LogAspect类
package com.hsh.aop;
@Aspect
@Component
public class LogAspect {
//切入点,指定当使用Log注解时进入环绕增强
@Pointcut("@annotation(com.hsh.aop.Log)")
public void pointcut() {
}
@Around("pointcut()")
public Object around(ProceedingJoinPoint point) {
try {
System.out.println("执行环绕增强..............开始");
Object result = point.proceed();//执行方法
System.out.println("结束..........");
return result;
} catch (Throwable throwable) {
throwable.printStackTrace();
}
return null;
}
}
在controller进行测试
package com.hsh.controller;
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService;
// 加入@Log注解测试
@RequestMapping("/getUserById")
@Log("获取所有用户集合")
public ResultJSON getUserById(Long id){
return ResultJSON.success(userService.getUserById(id));
}
}
浏览器输入http://localhost:8080/user/getUserById?id=1
查看idea控制台说明对注解的增强生效。
使用操作日志
创建数据库sys_log记录操作
创建日志记录表sys_log
DROP TABLE IF EXISTS `sys_log`;
CREATE TABLE `sys_log` (
`ID` bigint(20) NOT NULL AUTO_INCREMENT,
`USERNAME` varchar(50) DEFAULT NULL COMMENT '用户名',
`OPERATION` varchar(50) DEFAULT NULL COMMENT '用户操作',
`TIME` int(11) DEFAULT NULL COMMENT '响应时间',
`METHOD` varchar(200) DEFAULT NULL COMMENT '请求方法',
`PARAMS` varchar(500) DEFAULT NULL COMMENT '请求参数',
`IP` varchar(64) DEFAULT NULL COMMENT 'IP地址',
`CREATE_TIME` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
PRIMARY KEY (`ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
创建实体类
package com.hsh.pojo;
@TableName("sys_log")
@Data
public class SysLog {
// 设置自动递增
@TableId(value = "id", type = IdType.AUTO)
private Long id;
private String username;
private String operation;
private Integer time;
private String method;
private String params;
private String ip;
private Date createTime;
}
创建操作方法的实现
编写DAO层接口与实现,向表中插入数据
package com.hsh.mapper;
public interface SysLogMapper extends BaseMapper<SysLog> {
}
创建获取request的工具类
在com/hsh
文件夹下新建utils文件夹,并在com/hsh/utils
下新建HttpContextUtils 类
package com.hsh.utils;
public class HttpContextUtils {
public static HttpServletRequest getHttpServletRequest() {
return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
}
}
创建获取用户IP的工具类
在com/hsh/utils
下新建IPUtils 类
package com.hsh.utils;
public class IPUtils {
public static String getIpAddr(HttpServletRequest request){
String ip = request.getHeader("x-forwarded-for");
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("WL-Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getRemoteAddr();
}
return "0:0:0:0:0:0:0:1".equals(ip) ? "127.0.0.1" : ip;
}
}
修改LogAspect增强类与增强方法
package com.hsh.aop;
import com.hsh.mapper.SysLogMapper;
import com.hsh.pojo.SysLog;
import com.hsh.utils.HttpContextUtils;
import com.hsh.utils.IPUtils;
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.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
@Aspect
@Component
public class LogAspect {
@Autowired
private SysLogMapper sysLogMapper;
//切入点,指定当使用Log注解时进入环绕增强
@Pointcut("@annotation(com.hsh.aop.Log)")
public void pointcut() {
}
@Around("pointcut()")
public Object around(ProceedingJoinPoint point) {
try {
//实例化日志类
SysLog sysLog = new SysLog();
sysLog.setUsername("xrkhy");//模拟一个用户名 实际可以从session中获取
//开始执行时间
long beginTime = System.currentTimeMillis();
//执行方法
Object result = point.proceed();
// 执行时长(毫秒)
long time = System.currentTimeMillis() - beginTime;
//执行时长(毫秒)
sysLog.setTime((int) time);
// 获取request
HttpServletRequest request = HttpContextUtils.getHttpServletRequest();
// 设置IP地址
sysLog.setIp(IPUtils.getIpAddr(request));
// 通过反射获取方法名
MethodSignature signature = (MethodSignature) point.getSignature();
Method method = signature.getMethod();
// 获取操作名称
Log logAnnotation = method.getAnnotation(Log.class);
if (logAnnotation != null) {
// 注解上的描述
sysLog.setOperation(logAnnotation.value());
}
// 请求的方法名
String className = point.getTarget().getClass().getName();
String methodName = signature.getName();
sysLog.setMethod(className + "." + methodName + "()");
// 请求的方法参数值
Object[] args = point.getArgs();
// 请求的方法参数名称
LocalVariableTableParameterNameDiscoverer u = new LocalVariableTableParameterNameDiscoverer();
String[] paramNames = u.getParameterNames(method);
if (args != null && paramNames != null) {
String params = "";
for (int i = 0; i < args.length; i++) {
params += " " + paramNames[i] + ": " + args[i];
}
sysLog.setParams(params);
}
// 保存系统日志
sysLogMapper.insert(sysLog);
return result;
} catch (Throwable throwable) {
throwable.printStackTrace();
}
return null;
}
}
在service的增删改上面添加@Log注解
package com.hsh.controller;
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService;
@RequestMapping("/getUserById")
public ResultJSON getUserById(Long id){
return ResultJSON.success(userService.getUserById(id));
}
@RequestMapping("/addUser")
@Log("添加用户")
public ResultJSON addUser(User user){
return userService.addUser(user);
}
@RequestMapping("/deleteUser")
@Log("删除用户")
public ResultJSON deleteUser(Long id){
return userService.deleteUser(id);
}
@RequestMapping("/editUser")
@Log("修改用户")
public ResultJSON editUser(User user){
return userService.editUser(user);
}
}
测试
打开接口测试工具
apifox或者postman进行测试。
检查sys_log数据库。
记录异常日志
1. 创建logback-spring.xml
创建logback-spring.xml文件放入resource下,并复制内容到该文件
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<property name="LOG_CONTEXT_NAME" value="log"/>
<!--定义日志文件的存储地址 勿在 LogBack 的配置中使用相对路径-->
<property name="LOG_HOME" value="D:/logs"/>
<!-- 定义日志上下文的名称 -->
<contextName>${LOG_CONTEXT_NAME}</contextName>
<!-- 控制台输出 -->
<!--<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">-->
<!-- <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">-->
<!-- <!–格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个-->
<!-- 字符宽度%msg:日志消息,%n是换行符–>-->
<!-- <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %highlight(%-5level)-->
<!-- %cyan(%logger{50}:%L) - %msg%n</pattern>-->
<!-- <charset>utf-8</charset>-->
<!-- </encoder>-->
<!-- <filter class="ch.qos.logback.classic.filter.ThresholdFilter">-->
<!-- <level>INFO</level>-->
<!-- </filter>-->
<!--</appender>-->
<!-- 彩色日志依赖的渲染类 -->
<conversionRule conversionWord="clr"
converterClass="org.springframework.boot.logging.logback.ColorConverter"/>
<conversionRule conversionWord="wex"
converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter"/>
<conversionRule conversionWord="wEx"
converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter"/>
<!-- 彩色日志格式 -->
<property name="CONSOLE_LOG_PATTERN" value="${CONSOLE_LOG_PATTERN:-
%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p})
%clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint}
%clr(%-40.40logger{39}){cyan} %clr(:){faint}
%m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/>
<!--1. 输出到控制台-->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<!--此日志appender是为开发使用,只配置最底级别,控制台输出的日志级别是大于或等于此级
别的日志信息-->
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>INFO</level>
</filter>
<encoder>
<Pattern>${CONSOLE_LOG_PATTERN}</Pattern>
<!-- 设置字符集 -->
<charset>UTF-8</charset>
</encoder>
</appender>
<!--info日志统一输出到这里-->
<appender name="file.info" class="ch.qos.logback.core.rolling.RollingFileAppender">
<Prudent>true</Prudent>
<rollingPolicy
class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!--日志文件输出的文件名,按小时生成-->
<FileNamePattern>${LOG_HOME}/%d{yyyy-MM-dd}/info/info.%d{yyyy-MM-dd-HH}.%i.log</FileNamePattern>
<!--日志文件保留天数-->
<MaxHistory>30</MaxHistory>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<!-- 除按日志记录之外,还配置了日志文件不能超过10M(默认),若超过10M,日志
文件会以索引0开始, -->
<maxFileSize>10MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符
宽度 %method 方法名 %L 行数 %msg:日志消息,%n是换行符-->
<pattern> %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level
%logger{56}.%method:%L - %msg%n</pattern>
<charset>utf-8</charset>
</encoder>
<!-- 此日志文件只记录info级别的 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>INFO</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!--错误日志统一输出到这里-->
<appender name="file.error"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<Prudent>true</Prudent>
<rollingPolicy
class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!--日志文件输出的文件名,按天生成-->
<FileNamePattern>${LOG_HOME}/%d{yyyy-MM-dd}/error/error.%d{yyyy-MM-dd}.%i.log</FileNamePattern>
<!--日志文件保留天数-->
<MaxHistory>30</MaxHistory>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<!-- 除按日志记录之外,还配置了日志文件不能超过10M(默认),若超过10M,日志
文件会以索引0开始, -->
<maxFileSize>10MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符
宽度 %method 方法名 %L 行数 %msg:日志消息,%n是换行符-->
<pattern> %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level
%logger{56}.%method:%L - %msg%n</pattern>
<charset>utf-8</charset>
</encoder>
<!-- 此日志文件只记录error级别的 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>ERROR</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!--warn日志统一输出到这里-->
<appender name="file.warn"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<Prudent>true</Prudent>
<rollingPolicy
class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<FileNamePattern>${LOG_HOME}/%d{yyyy-MM-dd}/warn/warn.%d{yyyy-MM-dd}.%i.log</FileNamePattern>
<!--日志文件保留天数-->
<MaxHistory>30</MaxHistory>
<timeBasedFileNamingAndTriggeringPolicy
class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<!-- 除按日志记录之外,还配置了日志文件不能超过10M(默认),若超过10M,日志
文件会以索引0开始, -->
<maxFileSize>10MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符
宽度 %method 方法名 %L 行数 %msg:日志消息,%n是换行符-->
<pattern> %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level
%logger{56}.%method:%L - %msg%n</pattern>
<charset>utf-8</charset>
</encoder>
<!-- 此日志文件只记录warn级别的 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>WARN</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!-- 日志输出级别 -->
<root level="DEBUG">
<appender-ref ref="STDOUT" />
<appender-ref ref="file.error" />
<appender-ref ref="file.info" />
<appender-ref ref="file.warn" />
</root>
</configuration>
2. 配置application.properties文件
下面两种读取方式二选一
#读取配置文件
logging.config=classpath:logback-spring.xml
yml配置
#读取配置文件
logging:
config: classpath:logback-spring.xml
3. 编写controller测试
@Slf4j
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService;
@RequestMapping("/getUserById")
@Log("获取指定用户集合")
public ResultJSON getUserById(Long id){
log.info("获取指定用户集合");//输出信息
return ResultJSON.success(userService.getUserById(id));
}
}
等级可分为OFF、FATAL、ERROR、WARN、INFO、DEBUG、ALL,如果配置OFF则不打出任何信息,如果配置为INFO这样只显示INFO, WARN, ERROR的log信息,而DEBUG信息不会被显示