Commit 132c1cc828334fa303ba53df5bc34ea82d8e5995
1 parent
9fac998a
【优化】增强访问日志,支持是否记录、脱敏、操作信息等功能
Showing
20 changed files
with
484 additions
and
297 deletions
sql/mysql/ruoyi-vue-pro.sql
| @@ -11,7 +11,7 @@ | @@ -11,7 +11,7 @@ | ||
| 11 | Target Server Version : 80200 (8.2.0) | 11 | Target Server Version : 80200 (8.2.0) |
| 12 | File Encoding : 65001 | 12 | File Encoding : 65001 |
| 13 | 13 | ||
| 14 | - Date: 30/03/2024 20:42:06 | 14 | + Date: 03/04/2024 19:07:31 |
| 15 | */ | 15 | */ |
| 16 | 16 | ||
| 17 | SET NAMES utf8mb4; | 17 | SET NAMES utf8mb4; |
| @@ -327,9 +327,13 @@ CREATE TABLE `infra_api_access_log` ( | @@ -327,9 +327,13 @@ CREATE TABLE `infra_api_access_log` ( | ||
| 327 | `application_name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '应用名', | 327 | `application_name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '应用名', |
| 328 | `request_method` varchar(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '请求方法名', | 328 | `request_method` varchar(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '请求方法名', |
| 329 | `request_url` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '请求地址', | 329 | `request_url` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '请求地址', |
| 330 | - `request_params` varchar(8000) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '请求参数', | 330 | + `request_params` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL COMMENT '请求参数', |
| 331 | + `response_body` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL COMMENT '响应结果', | ||
| 331 | `user_ip` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '用户 IP', | 332 | `user_ip` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '用户 IP', |
| 332 | `user_agent` varchar(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '浏览器 UA', | 333 | `user_agent` varchar(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '浏览器 UA', |
| 334 | + `operate_module` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '操作模块', | ||
| 335 | + `operate_name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '操作名', | ||
| 336 | + `operate_type` tinyint NULL DEFAULT 0 COMMENT '操作分类', | ||
| 333 | `begin_time` datetime NOT NULL COMMENT '开始请求时间', | 337 | `begin_time` datetime NOT NULL COMMENT '开始请求时间', |
| 334 | `end_time` datetime NOT NULL COMMENT '结束请求时间', | 338 | `end_time` datetime NOT NULL COMMENT '结束请求时间', |
| 335 | `duration` int NOT NULL COMMENT '执行时长', | 339 | `duration` int NOT NULL COMMENT '执行时长', |
| @@ -343,7 +347,7 @@ CREATE TABLE `infra_api_access_log` ( | @@ -343,7 +347,7 @@ CREATE TABLE `infra_api_access_log` ( | ||
| 343 | `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', | 347 | `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', |
| 344 | PRIMARY KEY (`id`) USING BTREE, | 348 | PRIMARY KEY (`id`) USING BTREE, |
| 345 | INDEX `idx_create_time`(`create_time` ASC) USING BTREE | 349 | INDEX `idx_create_time`(`create_time` ASC) USING BTREE |
| 346 | -) ENGINE = InnoDB AUTO_INCREMENT = 35832 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'API 访问日志表'; | 350 | +) ENGINE = InnoDB AUTO_INCREMENT = 35920 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'API 访问日志表'; |
| 347 | 351 | ||
| 348 | -- ---------------------------- | 352 | -- ---------------------------- |
| 349 | -- Records of infra_api_access_log | 353 | -- Records of infra_api_access_log |
| @@ -385,7 +389,7 @@ CREATE TABLE `infra_api_error_log` ( | @@ -385,7 +389,7 @@ CREATE TABLE `infra_api_error_log` ( | ||
| 385 | `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', | 389 | `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', |
| 386 | `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', | 390 | `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', |
| 387 | PRIMARY KEY (`id`) USING BTREE | 391 | PRIMARY KEY (`id`) USING BTREE |
| 388 | -) ENGINE = InnoDB AUTO_INCREMENT = 16429 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '系统异常日志'; | 392 | +) ENGINE = InnoDB AUTO_INCREMENT = 16462 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '系统异常日志'; |
| 389 | 393 | ||
| 390 | -- ---------------------------- | 394 | -- ---------------------------- |
| 391 | -- Records of infra_api_error_log | 395 | -- Records of infra_api_error_log |
| @@ -494,7 +498,7 @@ CREATE TABLE `infra_config` ( | @@ -494,7 +498,7 @@ CREATE TABLE `infra_config` ( | ||
| 494 | -- Records of infra_config | 498 | -- Records of infra_config |
| 495 | -- ---------------------------- | 499 | -- ---------------------------- |
| 496 | BEGIN; | 500 | BEGIN; |
| 497 | -INSERT INTO `infra_config` (`id`, `category`, `type`, `name`, `config_key`, `value`, `visible`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2, 'biz', 1, '用户管理-账号初始密码', 'sys.user.init-password', '123456', b'0', '初始化密码 123456', 'admin', '2021-01-05 17:03:48', '1', '2024-02-28 22:54:14', b'0'); | 501 | +INSERT INTO `infra_config` (`id`, `category`, `type`, `name`, `config_key`, `value`, `visible`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2, 'biz', 1, '用户管理-账号初始密码', 'sys.user.init-password', '123456', b'0', '初始化密码 123456', 'admin', '2021-01-05 17:03:48', '1', '2024-04-03 17:22:28', b'0'); |
| 498 | INSERT INTO `infra_config` (`id`, `category`, `type`, `name`, `config_key`, `value`, `visible`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (7, 'url', 2, 'MySQL 监控的地址', 'url.druid', '', b'1', '', '1', '2023-04-07 13:41:16', '1', '2023-04-07 14:33:38', b'0'); | 502 | INSERT INTO `infra_config` (`id`, `category`, `type`, `name`, `config_key`, `value`, `visible`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (7, 'url', 2, 'MySQL 监控的地址', 'url.druid', '', b'1', '', '1', '2023-04-07 13:41:16', '1', '2023-04-07 14:33:38', b'0'); |
| 499 | INSERT INTO `infra_config` (`id`, `category`, `type`, `name`, `config_key`, `value`, `visible`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (8, 'url', 2, 'SkyWalking 监控的地址', 'url.skywalking', '', b'1', '', '1', '2023-04-07 13:41:16', '1', '2023-04-07 14:57:03', b'0'); | 503 | INSERT INTO `infra_config` (`id`, `category`, `type`, `name`, `config_key`, `value`, `visible`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (8, 'url', 2, 'SkyWalking 监控的地址', 'url.skywalking', '', b'1', '', '1', '2023-04-07 13:41:16', '1', '2023-04-07 14:57:03', b'0'); |
| 500 | INSERT INTO `infra_config` (`id`, `category`, `type`, `name`, `config_key`, `value`, `visible`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (9, 'url', 2, 'Spring Boot Admin 监控的地址', 'url.spring-boot-admin', '', b'1', '', '1', '2023-04-07 13:41:16', '1', '2023-04-07 14:52:07', b'0'); | 504 | INSERT INTO `infra_config` (`id`, `category`, `type`, `name`, `config_key`, `value`, `visible`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (9, 'url', 2, 'Spring Boot Admin 监控的地址', 'url.spring-boot-admin', '', b'1', '', '1', '2023-04-07 13:41:16', '1', '2023-04-07 14:52:07', b'0'); |
| @@ -690,7 +694,7 @@ CREATE TABLE `infra_file` ( | @@ -690,7 +694,7 @@ CREATE TABLE `infra_file` ( | ||
| 690 | `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', | 694 | `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', |
| 691 | `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', | 695 | `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', |
| 692 | PRIMARY KEY (`id`) USING BTREE | 696 | PRIMARY KEY (`id`) USING BTREE |
| 693 | -) ENGINE = InnoDB AUTO_INCREMENT = 1301 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '文件表'; | 697 | +) ENGINE = InnoDB AUTO_INCREMENT = 1302 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '文件表'; |
| 694 | 698 | ||
| 695 | -- ---------------------------- | 699 | -- ---------------------------- |
| 696 | -- Records of infra_file | 700 | -- Records of infra_file |
| @@ -1416,7 +1420,7 @@ CREATE TABLE `system_login_log` ( | @@ -1416,7 +1420,7 @@ CREATE TABLE `system_login_log` ( | ||
| 1416 | `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', | 1420 | `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', |
| 1417 | `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', | 1421 | `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', |
| 1418 | PRIMARY KEY (`id`) USING BTREE | 1422 | PRIMARY KEY (`id`) USING BTREE |
| 1419 | -) ENGINE = InnoDB AUTO_INCREMENT = 3054 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '系统访问记录'; | 1423 | +) ENGINE = InnoDB AUTO_INCREMENT = 3066 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '系统访问记录'; |
| 1420 | 1424 | ||
| 1421 | -- ---------------------------- | 1425 | -- ---------------------------- |
| 1422 | -- Records of system_login_log | 1426 | -- Records of system_login_log |
| @@ -2453,7 +2457,7 @@ CREATE TABLE `system_oauth2_access_token` ( | @@ -2453,7 +2457,7 @@ CREATE TABLE `system_oauth2_access_token` ( | ||
| 2453 | PRIMARY KEY (`id`) USING BTREE, | 2457 | PRIMARY KEY (`id`) USING BTREE, |
| 2454 | INDEX `idx_access_token`(`access_token` ASC) USING BTREE, | 2458 | INDEX `idx_access_token`(`access_token` ASC) USING BTREE, |
| 2455 | INDEX `idx_refresh_token`(`refresh_token` ASC) USING BTREE | 2459 | INDEX `idx_refresh_token`(`refresh_token` ASC) USING BTREE |
| 2456 | -) ENGINE = InnoDB AUTO_INCREMENT = 6332 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'OAuth2 访问令牌'; | 2460 | +) ENGINE = InnoDB AUTO_INCREMENT = 6366 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'OAuth2 访问令牌'; |
| 2457 | 2461 | ||
| 2458 | -- ---------------------------- | 2462 | -- ---------------------------- |
| 2459 | -- Records of system_oauth2_access_token | 2463 | -- Records of system_oauth2_access_token |
| @@ -2575,7 +2579,7 @@ CREATE TABLE `system_oauth2_refresh_token` ( | @@ -2575,7 +2579,7 @@ CREATE TABLE `system_oauth2_refresh_token` ( | ||
| 2575 | `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', | 2579 | `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', |
| 2576 | `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', | 2580 | `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', |
| 2577 | PRIMARY KEY (`id`) USING BTREE | 2581 | PRIMARY KEY (`id`) USING BTREE |
| 2578 | -) ENGINE = InnoDB AUTO_INCREMENT = 1430 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'OAuth2 刷新令牌'; | 2582 | +) ENGINE = InnoDB AUTO_INCREMENT = 1441 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'OAuth2 刷新令牌'; |
| 2579 | 2583 | ||
| 2580 | -- ---------------------------- | 2584 | -- ---------------------------- |
| 2581 | -- Records of system_oauth2_refresh_token | 2585 | -- Records of system_oauth2_refresh_token |
| @@ -2615,7 +2619,7 @@ CREATE TABLE `system_operate_log` ( | @@ -2615,7 +2619,7 @@ CREATE TABLE `system_operate_log` ( | ||
| 2615 | `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', | 2619 | `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', |
| 2616 | `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', | 2620 | `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', |
| 2617 | PRIMARY KEY (`id`) USING BTREE | 2621 | PRIMARY KEY (`id`) USING BTREE |
| 2618 | -) ENGINE = InnoDB AUTO_INCREMENT = 11964 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '操作日志记录'; | 2622 | +) ENGINE = InnoDB AUTO_INCREMENT = 12000 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '操作日志记录'; |
| 2619 | 2623 | ||
| 2620 | -- ---------------------------- | 2624 | -- ---------------------------- |
| 2621 | -- Records of system_operate_log | 2625 | -- Records of system_operate_log |
| @@ -5305,7 +5309,7 @@ CREATE TABLE `system_sms_log` ( | @@ -5305,7 +5309,7 @@ CREATE TABLE `system_sms_log` ( | ||
| 5305 | `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', | 5309 | `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', |
| 5306 | `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', | 5310 | `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', |
| 5307 | PRIMARY KEY (`id`) USING BTREE | 5311 | PRIMARY KEY (`id`) USING BTREE |
| 5308 | -) ENGINE = InnoDB AUTO_INCREMENT = 946 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '短信日志'; | 5312 | +) ENGINE = InnoDB AUTO_INCREMENT = 947 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '短信日志'; |
| 5309 | 5313 | ||
| 5310 | -- ---------------------------- | 5314 | -- ---------------------------- |
| 5311 | -- Records of system_sms_log | 5315 | -- Records of system_sms_log |
| @@ -5475,7 +5479,7 @@ INSERT INTO `system_tenant` (`id`, `name`, `contact_user_id`, `contact_name`, `c | @@ -5475,7 +5479,7 @@ INSERT INTO `system_tenant` (`id`, `name`, `contact_user_id`, `contact_name`, `c | ||
| 5475 | INSERT INTO `system_tenant` (`id`, `name`, `contact_user_id`, `contact_name`, `contact_mobile`, `status`, `website`, `package_id`, `expire_time`, `account_count`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (151, '大租户', 126, '土豆大', NULL, 0, 'https://tudou.iocoder.cn', 111, '2023-12-08 00:00:00', 10, '1', '2023-12-02 23:35:05', '1', '2023-12-08 23:39:56', b'0'); | 5479 | INSERT INTO `system_tenant` (`id`, `name`, `contact_user_id`, `contact_name`, `contact_mobile`, `status`, `website`, `package_id`, `expire_time`, `account_count`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (151, '大租户', 126, '土豆大', NULL, 0, 'https://tudou.iocoder.cn', 111, '2023-12-08 00:00:00', 10, '1', '2023-12-02 23:35:05', '1', '2023-12-08 23:39:56', b'0'); |
| 5476 | INSERT INTO `system_tenant` (`id`, `name`, `contact_user_id`, `contact_name`, `contact_mobile`, `status`, `website`, `package_id`, `expire_time`, `account_count`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (152, '新租户', 127, '土豆', NULL, 0, 'http://xx.iocoder.cn', 111, '2025-12-31 00:00:00', 50, '1', '2023-12-30 11:43:17', '1', '2023-12-30 11:43:17', b'0'); | 5480 | INSERT INTO `system_tenant` (`id`, `name`, `contact_user_id`, `contact_name`, `contact_mobile`, `status`, `website`, `package_id`, `expire_time`, `account_count`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (152, '新租户', 127, '土豆', NULL, 0, 'http://xx.iocoder.cn', 111, '2025-12-31 00:00:00', 50, '1', '2023-12-30 11:43:17', '1', '2023-12-30 11:43:17', b'0'); |
| 5477 | INSERT INTO `system_tenant` (`id`, `name`, `contact_user_id`, `contact_name`, `contact_mobile`, `status`, `website`, `package_id`, `expire_time`, `account_count`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (153, '小明的租户', 128, 'xiaoming', '15601691301', 0, 'xiaoming.iocoder.cn', 111, '2025-12-01 00:00:00', 100, '1', '2024-02-27 21:58:25', '1', '2024-02-28 22:53:54', b'0'); | 5481 | INSERT INTO `system_tenant` (`id`, `name`, `contact_user_id`, `contact_name`, `contact_mobile`, `status`, `website`, `package_id`, `expire_time`, `account_count`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (153, '小明的租户', 128, 'xiaoming', '15601691301', 0, 'xiaoming.iocoder.cn', 111, '2025-12-01 00:00:00', 100, '1', '2024-02-27 21:58:25', '1', '2024-02-28 22:53:54', b'0'); |
| 5478 | -INSERT INTO `system_tenant` (`id`, `name`, `contact_user_id`, `contact_name`, `contact_mobile`, `status`, `website`, `package_id`, `expire_time`, `account_count`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (154, 'hh', 129, 'hh', NULL, 0, 'http://hh.iocoder.cn', 111, '2024-04-30 00:00:00', 123, '1', '2024-03-30 17:52:59', '1', '2024-03-30 17:52:59', b'0'); | 5482 | +INSERT INTO `system_tenant` (`id`, `name`, `contact_user_id`, `contact_name`, `contact_mobile`, `status`, `website`, `package_id`, `expire_time`, `account_count`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (154, 'hh', 129, 'hh', NULL, 0, 'http://hh.iocoder.cn', 111, '2024-04-30 00:00:00', 123, '1', '2024-03-30 17:52:59', '1', '2024-04-03 15:06:42', b'0'); |
| 5479 | COMMIT; | 5483 | COMMIT; |
| 5480 | 5484 | ||
| 5481 | -- ---------------------------- | 5485 | -- ---------------------------- |
| @@ -5619,7 +5623,7 @@ CREATE TABLE `system_users` ( | @@ -5619,7 +5623,7 @@ CREATE TABLE `system_users` ( | ||
| 5619 | -- Records of system_users | 5623 | -- Records of system_users |
| 5620 | -- ---------------------------- | 5624 | -- ---------------------------- |
| 5621 | BEGIN; | 5625 | BEGIN; |
| 5622 | -INSERT INTO `system_users` (`id`, `username`, `password`, `nickname`, `remark`, `dept_id`, `post_ids`, `email`, `mobile`, `sex`, `avatar`, `status`, `login_ip`, `login_date`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1, 'admin', '$2a$10$mRMIYLDtRHlf6.9ipiqH1.Z.bh/R9dO9d5iHiGYPigi6r5KOoR2Wm', '芋道源码', '管理员', 103, '[1]', 'aoteman@126.com', '18818260277', 2, 'http://test.yudao.iocoder.cn/96c787a2ce88bf6d0ce3cd8b6cf5314e80e7703cd41bf4af8cd2e2909dbd6b6d.png', 0, '0:0:0:0:0:0:0:1', '2024-03-30 17:18:34', 'admin', '2021-01-05 17:03:47', NULL, '2024-03-30 17:18:34', b'0', 1); | 5626 | +INSERT INTO `system_users` (`id`, `username`, `password`, `nickname`, `remark`, `dept_id`, `post_ids`, `email`, `mobile`, `sex`, `avatar`, `status`, `login_ip`, `login_date`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1, 'admin', '$2a$10$mRMIYLDtRHlf6.9ipiqH1.Z.bh/R9dO9d5iHiGYPigi6r5KOoR2Wm', '芋道源码', '管理员', 103, '[1]', 'aoteman@126.com', '18818260277', 2, 'http://test.yudao.iocoder.cn/96c787a2ce88bf6d0ce3cd8b6cf5314e80e7703cd41bf4af8cd2e2909dbd6b6d.png', 0, '127.0.0.1', '2024-04-03 17:31:00', 'admin', '2021-01-05 17:03:47', NULL, '2024-04-03 17:31:00', b'0', 1); |
| 5623 | INSERT INTO `system_users` (`id`, `username`, `password`, `nickname`, `remark`, `dept_id`, `post_ids`, `email`, `mobile`, `sex`, `avatar`, `status`, `login_ip`, `login_date`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (100, 'yudao', '$2a$10$11U48RhyJ5pSBYWSn12AD./ld671.ycSzJHbyrtpeoMeYiw31eo8a', '芋道', '不要吓我', 104, '[1]', 'yudao@iocoder.cn', '15601691300', 1, '', 1, '127.0.0.1', '2022-07-09 23:03:33', '', '2021-01-07 09:07:17', NULL, '2022-07-09 23:03:33', b'0', 1); | 5627 | INSERT INTO `system_users` (`id`, `username`, `password`, `nickname`, `remark`, `dept_id`, `post_ids`, `email`, `mobile`, `sex`, `avatar`, `status`, `login_ip`, `login_date`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (100, 'yudao', '$2a$10$11U48RhyJ5pSBYWSn12AD./ld671.ycSzJHbyrtpeoMeYiw31eo8a', '芋道', '不要吓我', 104, '[1]', 'yudao@iocoder.cn', '15601691300', 1, '', 1, '127.0.0.1', '2022-07-09 23:03:33', '', '2021-01-07 09:07:17', NULL, '2022-07-09 23:03:33', b'0', 1); |
| 5624 | INSERT INTO `system_users` (`id`, `username`, `password`, `nickname`, `remark`, `dept_id`, `post_ids`, `email`, `mobile`, `sex`, `avatar`, `status`, `login_ip`, `login_date`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (103, 'yuanma', '$2a$10$YMpimV4T6BtDhIaA8jSW.u8UTGBeGhc/qwXP4oxoMr4mOw9.qttt6', '源码', NULL, 106, NULL, 'yuanma@iocoder.cn', '15601701300', 0, '', 0, '0:0:0:0:0:0:0:1', '2024-03-18 21:09:04', '', '2021-01-13 23:50:35', NULL, '2024-03-18 21:09:04', b'0', 1); | 5628 | INSERT INTO `system_users` (`id`, `username`, `password`, `nickname`, `remark`, `dept_id`, `post_ids`, `email`, `mobile`, `sex`, `avatar`, `status`, `login_ip`, `login_date`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (103, 'yuanma', '$2a$10$YMpimV4T6BtDhIaA8jSW.u8UTGBeGhc/qwXP4oxoMr4mOw9.qttt6', '源码', NULL, 106, NULL, 'yuanma@iocoder.cn', '15601701300', 0, '', 0, '0:0:0:0:0:0:0:1', '2024-03-18 21:09:04', '', '2021-01-13 23:50:35', NULL, '2024-03-18 21:09:04', b'0', 1); |
| 5625 | INSERT INTO `system_users` (`id`, `username`, `password`, `nickname`, `remark`, `dept_id`, `post_ids`, `email`, `mobile`, `sex`, `avatar`, `status`, `login_ip`, `login_date`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (104, 'test', '$2a$04$KhExCYl7lx6eWWZYKsibKOZ8IBJRyuNuCcEOLQ11RYhJKgHmlSwK.', '测试号', NULL, 107, '[1,2]', '111@qq.com', '15601691200', 1, '', 0, '0:0:0:0:0:0:0:1', '2024-03-26 07:11:35', '', '2021-01-21 02:13:53', NULL, '2024-03-26 07:11:35', b'0', 1); | 5629 | INSERT INTO `system_users` (`id`, `username`, `password`, `nickname`, `remark`, `dept_id`, `post_ids`, `email`, `mobile`, `sex`, `avatar`, `status`, `login_ip`, `login_date`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (104, 'test', '$2a$04$KhExCYl7lx6eWWZYKsibKOZ8IBJRyuNuCcEOLQ11RYhJKgHmlSwK.', '测试号', NULL, 107, '[1,2]', '111@qq.com', '15601691200', 1, '', 0, '0:0:0:0:0:0:0:1', '2024-03-26 07:11:35', '', '2021-01-21 02:13:53', NULL, '2024-03-26 07:11:35', b'0', 1); |
yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/spring/SpringAopUtils.java deleted
| 1 | -package cn.iocoder.yudao.framework.common.util.spring; | ||
| 2 | - | ||
| 3 | -import cn.hutool.core.bean.BeanUtil; | ||
| 4 | -import org.springframework.aop.framework.AdvisedSupport; | ||
| 5 | -import org.springframework.aop.framework.AopProxy; | ||
| 6 | -import org.springframework.aop.support.AopUtils; | ||
| 7 | - | ||
| 8 | -/** | ||
| 9 | - * Spring AOP 工具类 | ||
| 10 | - * | ||
| 11 | - * 参考波克尔 http://www.bubuko.com/infodetail-3471885.html 实现 | ||
| 12 | - */ | ||
| 13 | -public class SpringAopUtils { | ||
| 14 | - | ||
| 15 | - /** | ||
| 16 | - * 获取代理的目标对象 | ||
| 17 | - * | ||
| 18 | - * @param proxy 代理对象 | ||
| 19 | - * @return 目标对象 | ||
| 20 | - */ | ||
| 21 | - public static Object getTarget(Object proxy) throws Exception { | ||
| 22 | - // 不是代理对象 | ||
| 23 | - if (!AopUtils.isAopProxy(proxy)) { | ||
| 24 | - return proxy; | ||
| 25 | - } | ||
| 26 | - // Jdk 代理 | ||
| 27 | - if (AopUtils.isJdkDynamicProxy(proxy)) { | ||
| 28 | - return getJdkDynamicProxyTargetObject(proxy); | ||
| 29 | - } | ||
| 30 | - // Cglib 代理 | ||
| 31 | - return getCglibProxyTargetObject(proxy); | ||
| 32 | - } | ||
| 33 | - | ||
| 34 | - private static Object getCglibProxyTargetObject(Object proxy) throws Exception { | ||
| 35 | - Object dynamicAdvisedInterceptor = BeanUtil.getFieldValue(proxy, "CGLIB$CALLBACK_0"); | ||
| 36 | - AdvisedSupport advisedSupport = (AdvisedSupport) BeanUtil.getFieldValue(dynamicAdvisedInterceptor, "advised"); | ||
| 37 | - return advisedSupport.getTargetSource().getTarget(); | ||
| 38 | - } | ||
| 39 | - | ||
| 40 | - private static Object getJdkDynamicProxyTargetObject(Object proxy) throws Exception { | ||
| 41 | - AopProxy aopProxy = (AopProxy) BeanUtil.getFieldValue(proxy, "h"); | ||
| 42 | - AdvisedSupport advisedSupport = (AdvisedSupport) BeanUtil.getFieldValue(aopProxy, "advised"); | ||
| 43 | - return advisedSupport.getTargetSource().getTarget(); | ||
| 44 | - } | ||
| 45 | - | ||
| 46 | -} |
yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/spring/SpringUtils.java
0 → 100644
| 1 | +package cn.iocoder.yudao.framework.common.util.spring; | ||
| 2 | + | ||
| 3 | +import cn.hutool.extra.spring.SpringUtil; | ||
| 4 | + | ||
| 5 | +import java.util.Objects; | ||
| 6 | + | ||
| 7 | +/** | ||
| 8 | + * Spring 工具类 | ||
| 9 | + * | ||
| 10 | + * @author 芋道源码 | ||
| 11 | + */ | ||
| 12 | +public class SpringUtils extends SpringUtil { | ||
| 13 | + | ||
| 14 | + /** | ||
| 15 | + * 是否为生产环境 | ||
| 16 | + * | ||
| 17 | + * @return 是否生产环境 | ||
| 18 | + */ | ||
| 19 | + public static boolean isProd() { | ||
| 20 | + String activeProfile = getActiveProfile(); | ||
| 21 | + return Objects.equals("prod", activeProfile); | ||
| 22 | + } | ||
| 23 | + | ||
| 24 | +} |
yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/config/YudaoApiLogAutoConfiguration.java
| 1 | package cn.iocoder.yudao.framework.apilog.config; | 1 | package cn.iocoder.yudao.framework.apilog.config; |
| 2 | 2 | ||
| 3 | import cn.iocoder.yudao.framework.apilog.core.filter.ApiAccessLogFilter; | 3 | import cn.iocoder.yudao.framework.apilog.core.filter.ApiAccessLogFilter; |
| 4 | +import cn.iocoder.yudao.framework.apilog.core.interceptor.ApiAccessLogInterceptor; | ||
| 4 | import cn.iocoder.yudao.framework.apilog.core.service.ApiAccessLogFrameworkService; | 5 | import cn.iocoder.yudao.framework.apilog.core.service.ApiAccessLogFrameworkService; |
| 5 | import cn.iocoder.yudao.framework.apilog.core.service.ApiAccessLogFrameworkServiceImpl; | 6 | import cn.iocoder.yudao.framework.apilog.core.service.ApiAccessLogFrameworkServiceImpl; |
| 6 | import cn.iocoder.yudao.framework.apilog.core.service.ApiErrorLogFrameworkService; | 7 | import cn.iocoder.yudao.framework.apilog.core.service.ApiErrorLogFrameworkService; |
| @@ -10,23 +11,26 @@ import cn.iocoder.yudao.framework.web.config.WebProperties; | @@ -10,23 +11,26 @@ import cn.iocoder.yudao.framework.web.config.WebProperties; | ||
| 10 | import cn.iocoder.yudao.framework.web.config.YudaoWebAutoConfiguration; | 11 | import cn.iocoder.yudao.framework.web.config.YudaoWebAutoConfiguration; |
| 11 | import cn.iocoder.yudao.module.infra.api.logger.ApiAccessLogApi; | 12 | import cn.iocoder.yudao.module.infra.api.logger.ApiAccessLogApi; |
| 12 | import cn.iocoder.yudao.module.infra.api.logger.ApiErrorLogApi; | 13 | import cn.iocoder.yudao.module.infra.api.logger.ApiErrorLogApi; |
| 14 | +import jakarta.servlet.Filter; | ||
| 13 | import org.springframework.beans.factory.annotation.Value; | 15 | import org.springframework.beans.factory.annotation.Value; |
| 14 | import org.springframework.boot.autoconfigure.AutoConfiguration; | 16 | import org.springframework.boot.autoconfigure.AutoConfiguration; |
| 15 | import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; | 17 | import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; |
| 16 | import org.springframework.boot.web.servlet.FilterRegistrationBean; | 18 | import org.springframework.boot.web.servlet.FilterRegistrationBean; |
| 17 | import org.springframework.context.annotation.Bean; | 19 | import org.springframework.context.annotation.Bean; |
| 18 | - | ||
| 19 | -import jakarta.servlet.Filter; | 20 | +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; |
| 21 | +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; | ||
| 20 | 22 | ||
| 21 | @AutoConfiguration(after = YudaoWebAutoConfiguration.class) | 23 | @AutoConfiguration(after = YudaoWebAutoConfiguration.class) |
| 22 | -public class YudaoApiLogAutoConfiguration { | 24 | +public class YudaoApiLogAutoConfiguration implements WebMvcConfigurer { |
| 23 | 25 | ||
| 24 | @Bean | 26 | @Bean |
| 27 | + @SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection") | ||
| 25 | public ApiAccessLogFrameworkService apiAccessLogFrameworkService(ApiAccessLogApi apiAccessLogApi) { | 28 | public ApiAccessLogFrameworkService apiAccessLogFrameworkService(ApiAccessLogApi apiAccessLogApi) { |
| 26 | return new ApiAccessLogFrameworkServiceImpl(apiAccessLogApi); | 29 | return new ApiAccessLogFrameworkServiceImpl(apiAccessLogApi); |
| 27 | } | 30 | } |
| 28 | 31 | ||
| 29 | @Bean | 32 | @Bean |
| 33 | + @SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection") | ||
| 30 | public ApiErrorLogFrameworkService apiErrorLogFrameworkService(ApiErrorLogApi apiErrorLogApi) { | 34 | public ApiErrorLogFrameworkService apiErrorLogFrameworkService(ApiErrorLogApi apiErrorLogApi) { |
| 31 | return new ApiErrorLogFrameworkServiceImpl(apiErrorLogApi); | 35 | return new ApiErrorLogFrameworkServiceImpl(apiErrorLogApi); |
| 32 | } | 36 | } |
| @@ -49,4 +53,9 @@ public class YudaoApiLogAutoConfiguration { | @@ -49,4 +53,9 @@ public class YudaoApiLogAutoConfiguration { | ||
| 49 | return bean; | 53 | return bean; |
| 50 | } | 54 | } |
| 51 | 55 | ||
| 56 | + @Override | ||
| 57 | + public void addInterceptors(InterceptorRegistry registry) { | ||
| 58 | + registry.addInterceptor(new ApiAccessLogInterceptor()); | ||
| 59 | + } | ||
| 60 | + | ||
| 52 | } | 61 | } |
yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/annotations/ApiAccessLog.java
0 → 100644
| 1 | +package cn.iocoder.yudao.framework.apilog.core.annotations; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum; | ||
| 4 | + | ||
| 5 | +import java.lang.annotation.ElementType; | ||
| 6 | +import java.lang.annotation.Retention; | ||
| 7 | +import java.lang.annotation.RetentionPolicy; | ||
| 8 | +import java.lang.annotation.Target; | ||
| 9 | + | ||
| 10 | +/** | ||
| 11 | + * 访问日志注解 | ||
| 12 | + * | ||
| 13 | + * @author 芋道源码 | ||
| 14 | + */ | ||
| 15 | +@Target({ElementType.METHOD}) | ||
| 16 | +@Retention(RetentionPolicy.RUNTIME) | ||
| 17 | +public @interface ApiAccessLog { | ||
| 18 | + | ||
| 19 | + // ========== 开关字段 ========== | ||
| 20 | + | ||
| 21 | + /** | ||
| 22 | + * 是否记录访问日志 | ||
| 23 | + */ | ||
| 24 | + boolean enable() default true; | ||
| 25 | + /** | ||
| 26 | + * 是否记录请求参数 | ||
| 27 | + * | ||
| 28 | + * 默认记录,主要考虑请求数据一般不大。可手动设置为 false 进行关闭 | ||
| 29 | + */ | ||
| 30 | + boolean requestEnable() default true; | ||
| 31 | + /** | ||
| 32 | + * 是否记录响应结果 | ||
| 33 | + * | ||
| 34 | + * 默认不记录,主要考虑响应数据可能比较大。可手动设置为 true 进行打开 | ||
| 35 | + */ | ||
| 36 | + boolean responseEnable() default false; | ||
| 37 | + /** | ||
| 38 | + * 敏感参数数组 | ||
| 39 | + * | ||
| 40 | + * 添加后,请求参数、响应结果不会记录该参数 | ||
| 41 | + */ | ||
| 42 | + String[] sanitizeKeys() default {}; | ||
| 43 | + | ||
| 44 | + // ========== 模块字段 ========== | ||
| 45 | + | ||
| 46 | + /** | ||
| 47 | + * 操作模块 | ||
| 48 | + * | ||
| 49 | + * 为空时,会尝试读取 {@link io.swagger.v3.oas.annotations.tags.Tag#name()} 属性 | ||
| 50 | + */ | ||
| 51 | + String operateModule() default ""; | ||
| 52 | + /** | ||
| 53 | + * 操作名 | ||
| 54 | + * | ||
| 55 | + * 为空时,会尝试读取 {@link io.swagger.v3.oas.annotations.Operation#summary()} 属性 | ||
| 56 | + */ | ||
| 57 | + String operateName() default ""; | ||
| 58 | + /** | ||
| 59 | + * 操作分类 | ||
| 60 | + * | ||
| 61 | + * 实际并不是数组,因为枚举不能设置 null 作为默认值 | ||
| 62 | + */ | ||
| 63 | + OperateTypeEnum[] operateType() default {}; | ||
| 64 | + | ||
| 65 | +} |
yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/enums/OperateTypeEnum.java
0 → 100644
| 1 | +package cn.iocoder.yudao.framework.apilog.core.enums; | ||
| 2 | + | ||
| 3 | +import lombok.AllArgsConstructor; | ||
| 4 | +import lombok.Getter; | ||
| 5 | + | ||
| 6 | +/** | ||
| 7 | + * 操作日志的操作类型 | ||
| 8 | + * | ||
| 9 | + * @author ruoyi | ||
| 10 | + */ | ||
| 11 | +@Getter | ||
| 12 | +@AllArgsConstructor | ||
| 13 | +public enum OperateTypeEnum { | ||
| 14 | + | ||
| 15 | + /** | ||
| 16 | + * 查询 | ||
| 17 | + */ | ||
| 18 | + GET(1), | ||
| 19 | + /** | ||
| 20 | + * 新增 | ||
| 21 | + */ | ||
| 22 | + CREATE(2), | ||
| 23 | + /** | ||
| 24 | + * 修改 | ||
| 25 | + */ | ||
| 26 | + UPDATE(3), | ||
| 27 | + /** | ||
| 28 | + * 删除 | ||
| 29 | + */ | ||
| 30 | + DELETE(4), | ||
| 31 | + /** | ||
| 32 | + * 导出 | ||
| 33 | + */ | ||
| 34 | + EXPORT(5), | ||
| 35 | + /** | ||
| 36 | + * 导入 | ||
| 37 | + */ | ||
| 38 | + IMPORT(6), | ||
| 39 | + /** | ||
| 40 | + * 其它 | ||
| 41 | + * | ||
| 42 | + * 在无法归类时,可以选择使用其它。因为还有操作名可以进一步标识 | ||
| 43 | + */ | ||
| 44 | + OTHER(0); | ||
| 45 | + | ||
| 46 | + /** | ||
| 47 | + * 类型 | ||
| 48 | + */ | ||
| 49 | + private final Integer type; | ||
| 50 | + | ||
| 51 | +} |
yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/filter/ApiAccessLogFilter.java
| 1 | package cn.iocoder.yudao.framework.apilog.core.filter; | 1 | package cn.iocoder.yudao.framework.apilog.core.filter; |
| 2 | 2 | ||
| 3 | +import cn.hutool.core.collection.CollUtil; | ||
| 3 | import cn.hutool.core.date.LocalDateTimeUtil; | 4 | import cn.hutool.core.date.LocalDateTimeUtil; |
| 4 | import cn.hutool.core.exceptions.ExceptionUtil; | 5 | import cn.hutool.core.exceptions.ExceptionUtil; |
| 5 | import cn.hutool.core.map.MapUtil; | 6 | import cn.hutool.core.map.MapUtil; |
| 6 | -import cn.iocoder.yudao.framework.apilog.core.service.ApiAccessLog; | 7 | +import cn.hutool.core.util.ArrayUtil; |
| 8 | +import cn.hutool.core.util.BooleanUtil; | ||
| 9 | +import cn.hutool.core.util.StrUtil; | ||
| 10 | +import cn.iocoder.yudao.framework.apilog.core.annotations.ApiAccessLog; | ||
| 11 | +import cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum; | ||
| 7 | import cn.iocoder.yudao.framework.apilog.core.service.ApiAccessLogFrameworkService; | 12 | import cn.iocoder.yudao.framework.apilog.core.service.ApiAccessLogFrameworkService; |
| 8 | import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants; | 13 | import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants; |
| 9 | import cn.iocoder.yudao.framework.common.pojo.CommonResult; | 14 | import cn.iocoder.yudao.framework.common.pojo.CommonResult; |
| 15 | +import cn.iocoder.yudao.framework.common.util.json.JsonUtils; | ||
| 10 | import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils; | 16 | import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils; |
| 11 | import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils; | 17 | import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils; |
| 12 | import cn.iocoder.yudao.framework.web.config.WebProperties; | 18 | import cn.iocoder.yudao.framework.web.config.WebProperties; |
| 13 | import cn.iocoder.yudao.framework.web.core.filter.ApiRequestFilter; | 19 | import cn.iocoder.yudao.framework.web.core.filter.ApiRequestFilter; |
| 14 | import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils; | 20 | import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils; |
| 15 | -import lombok.extern.slf4j.Slf4j; | ||
| 16 | - | 21 | +import cn.iocoder.yudao.module.infra.api.logger.dto.ApiAccessLogCreateReqDTO; |
| 22 | +import com.fasterxml.jackson.databind.JsonNode; | ||
| 23 | +import io.swagger.v3.oas.annotations.Operation; | ||
| 24 | +import io.swagger.v3.oas.annotations.tags.Tag; | ||
| 17 | import jakarta.servlet.FilterChain; | 25 | import jakarta.servlet.FilterChain; |
| 18 | import jakarta.servlet.ServletException; | 26 | import jakarta.servlet.ServletException; |
| 19 | import jakarta.servlet.http.HttpServletRequest; | 27 | import jakarta.servlet.http.HttpServletRequest; |
| 20 | import jakarta.servlet.http.HttpServletResponse; | 28 | import jakarta.servlet.http.HttpServletResponse; |
| 29 | +import lombok.extern.slf4j.Slf4j; | ||
| 30 | +import org.springframework.web.bind.annotation.RequestMethod; | ||
| 31 | +import org.springframework.web.method.HandlerMethod; | ||
| 32 | + | ||
| 21 | import java.io.IOException; | 33 | import java.io.IOException; |
| 22 | import java.time.LocalDateTime; | 34 | import java.time.LocalDateTime; |
| 23 | import java.time.temporal.ChronoUnit; | 35 | import java.time.temporal.ChronoUnit; |
| 36 | +import java.util.Iterator; | ||
| 24 | import java.util.Map; | 37 | import java.util.Map; |
| 25 | 38 | ||
| 39 | +import static cn.iocoder.yudao.framework.apilog.core.interceptor.ApiAccessLogInterceptor.*; | ||
| 26 | import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString; | 40 | import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString; |
| 27 | 41 | ||
| 28 | /** | 42 | /** |
| 29 | * API 访问日志 Filter | 43 | * API 访问日志 Filter |
| 30 | * | 44 | * |
| 45 | + * 目的:记录 API 访问日志到数据库中 | ||
| 46 | + * | ||
| 31 | * @author 芋道源码 | 47 | * @author 芋道源码 |
| 32 | */ | 48 | */ |
| 33 | @Slf4j | 49 | @Slf4j |
| 34 | public class ApiAccessLogFilter extends ApiRequestFilter { | 50 | public class ApiAccessLogFilter extends ApiRequestFilter { |
| 35 | 51 | ||
| 52 | + private static final String[] SANITIZE_KEYS = new String[]{"password", "token", "accessToken", "refreshToken"}; | ||
| 53 | + | ||
| 36 | private final String applicationName; | 54 | private final String applicationName; |
| 37 | 55 | ||
| 38 | private final ApiAccessLogFrameworkService apiAccessLogFrameworkService; | 56 | private final ApiAccessLogFrameworkService apiAccessLogFrameworkService; |
| @@ -44,6 +62,7 @@ public class ApiAccessLogFilter extends ApiRequestFilter { | @@ -44,6 +62,7 @@ public class ApiAccessLogFilter extends ApiRequestFilter { | ||
| 44 | } | 62 | } |
| 45 | 63 | ||
| 46 | @Override | 64 | @Override |
| 65 | + @SuppressWarnings("NullableProblems") | ||
| 47 | protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) | 66 | protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) |
| 48 | throws ServletException, IOException { | 67 | throws ServletException, IOException { |
| 49 | // 获得开始时间 | 68 | // 获得开始时间 |
| @@ -66,45 +85,166 @@ public class ApiAccessLogFilter extends ApiRequestFilter { | @@ -66,45 +85,166 @@ public class ApiAccessLogFilter extends ApiRequestFilter { | ||
| 66 | 85 | ||
| 67 | private void createApiAccessLog(HttpServletRequest request, LocalDateTime beginTime, | 86 | private void createApiAccessLog(HttpServletRequest request, LocalDateTime beginTime, |
| 68 | Map<String, String> queryString, String requestBody, Exception ex) { | 87 | Map<String, String> queryString, String requestBody, Exception ex) { |
| 69 | - ApiAccessLog accessLog = new ApiAccessLog(); | 88 | + ApiAccessLogCreateReqDTO accessLog = new ApiAccessLogCreateReqDTO(); |
| 70 | try { | 89 | try { |
| 71 | - this.buildApiAccessLogDTO(accessLog, request, beginTime, queryString, requestBody, ex); | 90 | + boolean enable = buildApiAccessLog(accessLog, request, beginTime, queryString, requestBody, ex); |
| 91 | + if (!enable) { | ||
| 92 | + return; | ||
| 93 | + } | ||
| 72 | apiAccessLogFrameworkService.createApiAccessLog(accessLog); | 94 | apiAccessLogFrameworkService.createApiAccessLog(accessLog); |
| 73 | } catch (Throwable th) { | 95 | } catch (Throwable th) { |
| 74 | log.error("[createApiAccessLog][url({}) log({}) 发生异常]", request.getRequestURI(), toJsonString(accessLog), th); | 96 | log.error("[createApiAccessLog][url({}) log({}) 发生异常]", request.getRequestURI(), toJsonString(accessLog), th); |
| 75 | } | 97 | } |
| 76 | } | 98 | } |
| 77 | 99 | ||
| 78 | - private void buildApiAccessLogDTO(ApiAccessLog accessLog, HttpServletRequest request, LocalDateTime beginTime, | 100 | + private boolean buildApiAccessLog(ApiAccessLogCreateReqDTO accessLog, HttpServletRequest request, LocalDateTime beginTime, |
| 79 | Map<String, String> queryString, String requestBody, Exception ex) { | 101 | Map<String, String> queryString, String requestBody, Exception ex) { |
| 102 | + // 判断:是否要记录操作日志 | ||
| 103 | + HandlerMethod handlerMethod = (HandlerMethod) request.getAttribute(ATTRIBUTE_HANDLER_METHOD); | ||
| 104 | + ApiAccessLog accessLogAnnotation = null; | ||
| 105 | + if (handlerMethod != null) { | ||
| 106 | + accessLogAnnotation = handlerMethod.getMethodAnnotation(ApiAccessLog.class); | ||
| 107 | + if (accessLogAnnotation != null && BooleanUtil.isFalse(accessLogAnnotation.enable())) { | ||
| 108 | + return false; | ||
| 109 | + } | ||
| 110 | + } | ||
| 111 | + | ||
| 80 | // 处理用户信息 | 112 | // 处理用户信息 |
| 81 | - accessLog.setUserId(WebFrameworkUtils.getLoginUserId(request)); | ||
| 82 | - accessLog.setUserType(WebFrameworkUtils.getLoginUserType(request)); | 113 | + accessLog.setUserId(WebFrameworkUtils.getLoginUserId(request)) |
| 114 | + .setUserType(WebFrameworkUtils.getLoginUserType(request)); | ||
| 83 | // 设置访问结果 | 115 | // 设置访问结果 |
| 84 | CommonResult<?> result = WebFrameworkUtils.getCommonResult(request); | 116 | CommonResult<?> result = WebFrameworkUtils.getCommonResult(request); |
| 85 | if (result != null) { | 117 | if (result != null) { |
| 86 | - accessLog.setResultCode(result.getCode()); | ||
| 87 | - accessLog.setResultMsg(result.getMsg()); | 118 | + accessLog.setResultCode(result.getCode()).setResultMsg(result.getMsg()); |
| 88 | } else if (ex != null) { | 119 | } else if (ex != null) { |
| 89 | - accessLog.setResultCode(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode()); | ||
| 90 | - accessLog.setResultMsg(ExceptionUtil.getRootCauseMessage(ex)); | 120 | + accessLog.setResultCode(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode()) |
| 121 | + .setResultMsg(ExceptionUtil.getRootCauseMessage(ex)); | ||
| 91 | } else { | 122 | } else { |
| 92 | - accessLog.setResultCode(0); | ||
| 93 | - accessLog.setResultMsg(""); | ||
| 94 | - } | ||
| 95 | - // 设置其它字段 | ||
| 96 | - accessLog.setTraceId(TracerUtils.getTraceId()); | ||
| 97 | - accessLog.setApplicationName(applicationName); | ||
| 98 | - accessLog.setRequestUrl(request.getRequestURI()); | ||
| 99 | - Map<String, Object> requestParams = MapUtil.<String, Object>builder().put("query", queryString).put("body", requestBody).build(); | ||
| 100 | - accessLog.setRequestParams(toJsonString(requestParams)); | ||
| 101 | - accessLog.setRequestMethod(request.getMethod()); | ||
| 102 | - accessLog.setUserAgent(ServletUtils.getUserAgent(request)); | ||
| 103 | - accessLog.setUserIp(ServletUtils.getClientIP(request)); | 123 | + accessLog.setResultCode(GlobalErrorCodeConstants.SUCCESS.getCode()).setResultMsg(""); |
| 124 | + } | ||
| 125 | + // 设置请求字段 | ||
| 126 | + accessLog.setTraceId(TracerUtils.getTraceId()).setApplicationName(applicationName) | ||
| 127 | + .setRequestUrl(request.getRequestURI()).setRequestMethod(request.getMethod()) | ||
| 128 | + .setUserAgent(ServletUtils.getUserAgent(request)).setUserIp(ServletUtils.getClientIP(request)); | ||
| 129 | + String[] sanitizeKeys = accessLogAnnotation != null ? accessLogAnnotation.sanitizeKeys() : null; | ||
| 130 | + Boolean requestEnable = accessLogAnnotation != null ? accessLogAnnotation.requestEnable() : Boolean.TRUE; | ||
| 131 | + if (!BooleanUtil.isFalse(requestEnable)) { // 默认记录,所以判断 !false | ||
| 132 | + Map<String, Object> requestParams = MapUtil.<String, Object>builder() | ||
| 133 | + .put("query", sanitizeMap(queryString, sanitizeKeys)) | ||
| 134 | + .put("body", sanitizeJson(requestBody, sanitizeKeys)).build(); | ||
| 135 | + accessLog.setRequestParams(toJsonString(requestParams)); | ||
| 136 | + } | ||
| 137 | + Boolean responseEnable = accessLogAnnotation != null ? accessLogAnnotation.responseEnable() : Boolean.FALSE; | ||
| 138 | + if (BooleanUtil.isTrue(responseEnable)) { // 默认不记录,默认强制要求 true | ||
| 139 | + accessLog.setResponseBody(sanitizeJson(result, sanitizeKeys)); | ||
| 140 | + } | ||
| 104 | // 持续时间 | 141 | // 持续时间 |
| 105 | - accessLog.setBeginTime(beginTime); | ||
| 106 | - accessLog.setEndTime(LocalDateTime.now()); | ||
| 107 | - accessLog.setDuration((int) LocalDateTimeUtil.between(accessLog.getBeginTime(), accessLog.getEndTime(), ChronoUnit.MILLIS)); | 142 | + accessLog.setBeginTime(beginTime).setEndTime(LocalDateTime.now()) |
| 143 | + .setDuration((int) LocalDateTimeUtil.between(accessLog.getBeginTime(), accessLog.getEndTime(), ChronoUnit.MILLIS)); | ||
| 144 | + | ||
| 145 | + // 操作模块 | ||
| 146 | + if (handlerMethod != null) { | ||
| 147 | + Tag tagAnnotation = handlerMethod.getBeanType().getAnnotation(Tag.class); | ||
| 148 | + Operation operationAnnotation = handlerMethod.getMethodAnnotation(Operation.class); | ||
| 149 | + String operateModule = accessLogAnnotation != null ? accessLogAnnotation.operateModule() : | ||
| 150 | + tagAnnotation != null ? StrUtil.nullToDefault(tagAnnotation.name(), tagAnnotation.description()) : null; | ||
| 151 | + String operateName = accessLogAnnotation != null ? accessLogAnnotation.operateName() : | ||
| 152 | + operationAnnotation != null ? operationAnnotation.summary() : null; | ||
| 153 | + OperateTypeEnum operateType = accessLogAnnotation != null && accessLogAnnotation.operateType().length > 0 ? | ||
| 154 | + accessLogAnnotation.operateType()[0] : parseOperateLogType(request); | ||
| 155 | + accessLog.setOperateModule(operateModule).setOperateName(operateName).setOperateType(operateType.getType()); | ||
| 156 | + } | ||
| 157 | + return true; | ||
| 158 | + } | ||
| 159 | + | ||
| 160 | + // ========== 解析 @ApiAccessLog、@Swagger 注解 ========== | ||
| 161 | + | ||
| 162 | + private static OperateTypeEnum parseOperateLogType(HttpServletRequest request) { | ||
| 163 | + RequestMethod requestMethod = RequestMethod.resolve(request.getMethod()); | ||
| 164 | + if (requestMethod == null) { | ||
| 165 | + return OperateTypeEnum.OTHER; | ||
| 166 | + } | ||
| 167 | + switch (requestMethod) { | ||
| 168 | + case GET: | ||
| 169 | + return OperateTypeEnum.GET; | ||
| 170 | + case POST: | ||
| 171 | + return OperateTypeEnum.CREATE; | ||
| 172 | + case PUT: | ||
| 173 | + return OperateTypeEnum.UPDATE; | ||
| 174 | + case DELETE: | ||
| 175 | + return OperateTypeEnum.DELETE; | ||
| 176 | + default: | ||
| 177 | + return OperateTypeEnum.OTHER; | ||
| 178 | + } | ||
| 179 | + } | ||
| 180 | + | ||
| 181 | + // ========== 请求和响应的脱敏逻辑,移除类似 password、token 等敏感字段 ========== | ||
| 182 | + | ||
| 183 | + private static String sanitizeMap(Map<String, ?> map, String[] sanitizeKeys) { | ||
| 184 | + if (CollUtil.isNotEmpty(map)) { | ||
| 185 | + return null; | ||
| 186 | + } | ||
| 187 | + if (sanitizeKeys != null) { | ||
| 188 | + MapUtil.removeAny(map, sanitizeKeys); | ||
| 189 | + } | ||
| 190 | + MapUtil.removeAny(map, SANITIZE_KEYS); | ||
| 191 | + return JsonUtils.toJsonString(map); | ||
| 192 | + } | ||
| 193 | + | ||
| 194 | + private static String sanitizeJson(String jsonString, String[] sanitizeKeys) { | ||
| 195 | + if (StrUtil.isEmpty(jsonString)) { | ||
| 196 | + return null; | ||
| 197 | + } | ||
| 198 | + try { | ||
| 199 | + JsonNode rootNode = JsonUtils.parseTree(jsonString); | ||
| 200 | + sanitizeJson(rootNode, sanitizeKeys); | ||
| 201 | + return JsonUtils.toJsonString(rootNode); | ||
| 202 | + } catch (Exception e) { | ||
| 203 | + // 脱敏失败的情况下,直接忽略异常,避免影响用户请求 | ||
| 204 | + log.error("[sanitizeJson][脱敏({}) 发生异常]", jsonString, e); | ||
| 205 | + return jsonString; | ||
| 206 | + } | ||
| 207 | + } | ||
| 208 | + | ||
| 209 | + private static String sanitizeJson(CommonResult<?> commonResult, String[] sanitizeKeys) { | ||
| 210 | + if (commonResult == null) { | ||
| 211 | + return null; | ||
| 212 | + } | ||
| 213 | + String jsonString = toJsonString(commonResult); | ||
| 214 | + try { | ||
| 215 | + JsonNode rootNode = JsonUtils.parseTree(jsonString); | ||
| 216 | + sanitizeJson(rootNode.get("data"), sanitizeKeys); // 只处理 data 字段,不处理 code、msg 字段,避免错误被脱敏掉 | ||
| 217 | + return JsonUtils.toJsonString(rootNode); | ||
| 218 | + } catch (Exception e) { | ||
| 219 | + // 脱敏失败的情况下,直接忽略异常,避免影响用户请求 | ||
| 220 | + log.error("[sanitizeJson][脱敏({}) 发生异常]", jsonString, e); | ||
| 221 | + return jsonString; | ||
| 222 | + } | ||
| 223 | + } | ||
| 224 | + | ||
| 225 | + private static void sanitizeJson(JsonNode node, String[] sanitizeKeys) { | ||
| 226 | + // 情况一:数组,遍历处理 | ||
| 227 | + if (node.isArray()) { | ||
| 228 | + for (JsonNode childNode : node) { | ||
| 229 | + sanitizeJson(childNode, sanitizeKeys); | ||
| 230 | + } | ||
| 231 | + return; | ||
| 232 | + } | ||
| 233 | + // 情况二:非 Object,只是某个值,直接返回 | ||
| 234 | + if (!node.isObject()) { | ||
| 235 | + return; | ||
| 236 | + } | ||
| 237 | + // 情况三:Object,遍历处理 | ||
| 238 | + Iterator<Map.Entry<String, JsonNode>> iterator = node.properties().iterator(); | ||
| 239 | + while (iterator.hasNext()) { | ||
| 240 | + Map.Entry<String, JsonNode> entry = iterator.next(); | ||
| 241 | + if (ArrayUtil.contains(sanitizeKeys, entry.getKey()) | ||
| 242 | + || ArrayUtil.contains(SANITIZE_KEYS, entry.getKey())) { | ||
| 243 | + iterator.remove(); | ||
| 244 | + continue; | ||
| 245 | + } | ||
| 246 | + sanitizeJson(entry.getValue(), sanitizeKeys); | ||
| 247 | + } | ||
| 108 | } | 248 | } |
| 109 | 249 | ||
| 110 | } | 250 | } |
yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/interceptor/ApiAccessLogInterceptor.java
0 → 100644
| 1 | +package cn.iocoder.yudao.framework.apilog.core.interceptor; | ||
| 2 | + | ||
| 3 | +import cn.hutool.core.collection.CollUtil; | ||
| 4 | +import cn.hutool.core.util.StrUtil; | ||
| 5 | +import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils; | ||
| 6 | +import cn.iocoder.yudao.framework.common.util.spring.SpringUtils; | ||
| 7 | +import jakarta.servlet.http.HttpServletRequest; | ||
| 8 | +import jakarta.servlet.http.HttpServletResponse; | ||
| 9 | +import lombok.extern.slf4j.Slf4j; | ||
| 10 | +import org.springframework.util.StopWatch; | ||
| 11 | +import org.springframework.web.method.HandlerMethod; | ||
| 12 | +import org.springframework.web.servlet.HandlerInterceptor; | ||
| 13 | + | ||
| 14 | +import java.util.Map; | ||
| 15 | + | ||
| 16 | +/** | ||
| 17 | + * API 访问日志 Interceptor | ||
| 18 | + * | ||
| 19 | + * 目的:在非 prod 环境时,打印 request 和 response 两条日志到日志文件(控制台)中。 | ||
| 20 | + * | ||
| 21 | + * @author 芋道源码 | ||
| 22 | + */ | ||
| 23 | +@Slf4j | ||
| 24 | +public class ApiAccessLogInterceptor implements HandlerInterceptor { | ||
| 25 | + | ||
| 26 | + public static String ATTRIBUTE_HANDLER_METHOD = "HANDLER_METHOD"; | ||
| 27 | + | ||
| 28 | + private static String ATTRIBUTE_STOP_WATCH = "ApiAccessLogInterceptor.StopWatch"; | ||
| 29 | + | ||
| 30 | + @Override | ||
| 31 | + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { | ||
| 32 | + // 记录 HandlerMethod,提供给 ApiAccessLogFilter 使用 | ||
| 33 | + HandlerMethod handlerMethod = handler instanceof HandlerMethod ? (HandlerMethod) handler : null; | ||
| 34 | + if (handlerMethod != null) { | ||
| 35 | + request.setAttribute(ATTRIBUTE_HANDLER_METHOD, handlerMethod); | ||
| 36 | + } | ||
| 37 | + | ||
| 38 | + // 打印 request 日志 | ||
| 39 | + if (!SpringUtils.isProd()) { | ||
| 40 | + Map<String, String> queryString = ServletUtils.getParamMap(request); | ||
| 41 | + String requestBody = ServletUtils.isJsonRequest(request) ? ServletUtils.getBody(request) : null; | ||
| 42 | + if (CollUtil.isEmpty(queryString) && StrUtil.isEmpty(requestBody)) { | ||
| 43 | + log.info("[preHandle][开始请求 URL({}) 无参数]", request.getRequestURI()); | ||
| 44 | + } else { | ||
| 45 | + log.info("[preHandle][开始请求 URL({}) 参数({})]", request.getRequestURI(), | ||
| 46 | + StrUtil.nullToDefault(requestBody, queryString.toString())); | ||
| 47 | + } | ||
| 48 | + // 计时 | ||
| 49 | + StopWatch stopWatch = new StopWatch(); | ||
| 50 | + stopWatch.start(); | ||
| 51 | + request.setAttribute(ATTRIBUTE_STOP_WATCH, stopWatch); | ||
| 52 | + } | ||
| 53 | + return true; | ||
| 54 | + } | ||
| 55 | + | ||
| 56 | + @Override | ||
| 57 | + public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { | ||
| 58 | + // 打印 response 日志 | ||
| 59 | + if (!SpringUtils.isProd()) { | ||
| 60 | + StopWatch stopWatch = (StopWatch) request.getAttribute(ATTRIBUTE_STOP_WATCH); | ||
| 61 | + stopWatch.stop(); | ||
| 62 | + log.info("[afterCompletion][完成请求 URL({}) 耗时({} ms)]", | ||
| 63 | + request.getRequestURI(), stopWatch.getTotalTimeMillis()); | ||
| 64 | + } | ||
| 65 | + } | ||
| 66 | + | ||
| 67 | +} |
yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/service/ApiAccessLog.java deleted
| 1 | -package cn.iocoder.yudao.framework.apilog.core.service; | ||
| 2 | - | ||
| 3 | -import lombok.Data; | ||
| 4 | - | ||
| 5 | -import jakarta.validation.constraints.NotNull; | ||
| 6 | -import java.time.LocalDateTime; | ||
| 7 | - | ||
| 8 | -/** | ||
| 9 | - * API 访问日志 | ||
| 10 | - * | ||
| 11 | - * @author 芋道源码 | ||
| 12 | - */ | ||
| 13 | -@Data | ||
| 14 | -public class ApiAccessLog { | ||
| 15 | - | ||
| 16 | - /** | ||
| 17 | - * 链路追踪编号 | ||
| 18 | - */ | ||
| 19 | - private String traceId; | ||
| 20 | - /** | ||
| 21 | - * 用户编号 | ||
| 22 | - */ | ||
| 23 | - private Long userId; | ||
| 24 | - /** | ||
| 25 | - * 用户类型 | ||
| 26 | - */ | ||
| 27 | - private Integer userType; | ||
| 28 | - /** | ||
| 29 | - * 应用名 | ||
| 30 | - */ | ||
| 31 | - @NotNull(message = "应用名不能为空") | ||
| 32 | - private String applicationName; | ||
| 33 | - | ||
| 34 | - /** | ||
| 35 | - * 请求方法名 | ||
| 36 | - */ | ||
| 37 | - @NotNull(message = "http 请求方法不能为空") | ||
| 38 | - private String requestMethod; | ||
| 39 | - /** | ||
| 40 | - * 访问地址 | ||
| 41 | - */ | ||
| 42 | - @NotNull(message = "访问地址不能为空") | ||
| 43 | - private String requestUrl; | ||
| 44 | - /** | ||
| 45 | - * 请求参数 | ||
| 46 | - */ | ||
| 47 | - @NotNull(message = "请求参数不能为空") | ||
| 48 | - private String requestParams; | ||
| 49 | - /** | ||
| 50 | - * 用户 IP | ||
| 51 | - */ | ||
| 52 | - @NotNull(message = "ip 不能为空") | ||
| 53 | - private String userIp; | ||
| 54 | - /** | ||
| 55 | - * 浏览器 UA | ||
| 56 | - */ | ||
| 57 | - @NotNull(message = "User-Agent 不能为空") | ||
| 58 | - private String userAgent; | ||
| 59 | - | ||
| 60 | - /** | ||
| 61 | - * 开始请求时间 | ||
| 62 | - */ | ||
| 63 | - @NotNull(message = "开始请求时间不能为空") | ||
| 64 | - private LocalDateTime beginTime; | ||
| 65 | - /** | ||
| 66 | - * 结束请求时间 | ||
| 67 | - */ | ||
| 68 | - @NotNull(message = "结束请求时间不能为空") | ||
| 69 | - private LocalDateTime endTime; | ||
| 70 | - /** | ||
| 71 | - * 执行时长,单位:毫秒 | ||
| 72 | - */ | ||
| 73 | - @NotNull(message = "执行时长不能为空") | ||
| 74 | - private Integer duration; | ||
| 75 | - /** | ||
| 76 | - * 结果码 | ||
| 77 | - */ | ||
| 78 | - @NotNull(message = "错误码不能为空") | ||
| 79 | - private Integer resultCode; | ||
| 80 | - /** | ||
| 81 | - * 结果提示 | ||
| 82 | - */ | ||
| 83 | - private String resultMsg; | ||
| 84 | - | ||
| 85 | -} |
yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/service/ApiAccessLogFrameworkService.java
| 1 | package cn.iocoder.yudao.framework.apilog.core.service; | 1 | package cn.iocoder.yudao.framework.apilog.core.service; |
| 2 | 2 | ||
| 3 | +import cn.iocoder.yudao.module.infra.api.logger.dto.ApiAccessLogCreateReqDTO; | ||
| 4 | + | ||
| 3 | /** | 5 | /** |
| 4 | * API 访问日志 Framework Service 接口 | 6 | * API 访问日志 Framework Service 接口 |
| 5 | * | 7 | * |
| @@ -10,7 +12,8 @@ public interface ApiAccessLogFrameworkService { | @@ -10,7 +12,8 @@ public interface ApiAccessLogFrameworkService { | ||
| 10 | /** | 12 | /** |
| 11 | * 创建 API 访问日志 | 13 | * 创建 API 访问日志 |
| 12 | * | 14 | * |
| 13 | - * @param apiAccessLog API 访问日志 | 15 | + * @param reqDTO API 访问日志 |
| 14 | */ | 16 | */ |
| 15 | - void createApiAccessLog(ApiAccessLog apiAccessLog); | 17 | + void createApiAccessLog(ApiAccessLogCreateReqDTO reqDTO); |
| 18 | + | ||
| 16 | } | 19 | } |
yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/service/ApiAccessLogFrameworkServiceImpl.java
| 1 | package cn.iocoder.yudao.framework.apilog.core.service; | 1 | package cn.iocoder.yudao.framework.apilog.core.service; |
| 2 | 2 | ||
| 3 | -import cn.hutool.core.bean.BeanUtil; | ||
| 4 | import cn.iocoder.yudao.module.infra.api.logger.ApiAccessLogApi; | 3 | import cn.iocoder.yudao.module.infra.api.logger.ApiAccessLogApi; |
| 5 | import cn.iocoder.yudao.module.infra.api.logger.dto.ApiAccessLogCreateReqDTO; | 4 | import cn.iocoder.yudao.module.infra.api.logger.dto.ApiAccessLogCreateReqDTO; |
| 6 | import lombok.RequiredArgsConstructor; | 5 | import lombok.RequiredArgsConstructor; |
| @@ -20,8 +19,7 @@ public class ApiAccessLogFrameworkServiceImpl implements ApiAccessLogFrameworkSe | @@ -20,8 +19,7 @@ public class ApiAccessLogFrameworkServiceImpl implements ApiAccessLogFrameworkSe | ||
| 20 | 19 | ||
| 21 | @Override | 20 | @Override |
| 22 | @Async | 21 | @Async |
| 23 | - public void createApiAccessLog(ApiAccessLog apiAccessLog) { | ||
| 24 | - ApiAccessLogCreateReqDTO reqDTO = BeanUtil.copyProperties(apiAccessLog, ApiAccessLogCreateReqDTO.class); | 22 | + public void createApiAccessLog(ApiAccessLogCreateReqDTO reqDTO) { |
| 25 | apiAccessLogApi.createApiAccessLog(reqDTO); | 23 | apiAccessLogApi.createApiAccessLog(reqDTO); |
| 26 | } | 24 | } |
| 27 | 25 |
yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/service/ApiErrorLog.java deleted
| 1 | -package cn.iocoder.yudao.framework.apilog.core.service; | ||
| 2 | - | ||
| 3 | -import lombok.Data; | ||
| 4 | - | ||
| 5 | -import jakarta.validation.constraints.NotNull; | ||
| 6 | -import java.time.LocalDateTime; | ||
| 7 | - | ||
| 8 | -/** | ||
| 9 | - * API 错误日志 | ||
| 10 | - * | ||
| 11 | - * @author 芋道源码 | ||
| 12 | - */ | ||
| 13 | -@Data | ||
| 14 | -public class ApiErrorLog { | ||
| 15 | - | ||
| 16 | - /** | ||
| 17 | - * 链路编号 | ||
| 18 | - */ | ||
| 19 | - private String traceId; | ||
| 20 | - /** | ||
| 21 | - * 账号编号 | ||
| 22 | - */ | ||
| 23 | - private Long userId; | ||
| 24 | - /** | ||
| 25 | - * 用户类型 | ||
| 26 | - */ | ||
| 27 | - private Integer userType; | ||
| 28 | - /** | ||
| 29 | - * 应用名 | ||
| 30 | - */ | ||
| 31 | - @NotNull(message = "应用名不能为空") | ||
| 32 | - private String applicationName; | ||
| 33 | - | ||
| 34 | - /** | ||
| 35 | - * 请求方法名 | ||
| 36 | - */ | ||
| 37 | - @NotNull(message = "http 请求方法不能为空") | ||
| 38 | - private String requestMethod; | ||
| 39 | - /** | ||
| 40 | - * 访问地址 | ||
| 41 | - */ | ||
| 42 | - @NotNull(message = "访问地址不能为空") | ||
| 43 | - private String requestUrl; | ||
| 44 | - /** | ||
| 45 | - * 请求参数 | ||
| 46 | - */ | ||
| 47 | - @NotNull(message = "请求参数不能为空") | ||
| 48 | - private String requestParams; | ||
| 49 | - /** | ||
| 50 | - * 用户 IP | ||
| 51 | - */ | ||
| 52 | - @NotNull(message = "ip 不能为空") | ||
| 53 | - private String userIp; | ||
| 54 | - /** | ||
| 55 | - * 浏览器 UA | ||
| 56 | - */ | ||
| 57 | - @NotNull(message = "User-Agent 不能为空") | ||
| 58 | - private String userAgent; | ||
| 59 | - | ||
| 60 | - /** | ||
| 61 | - * 异常时间 | ||
| 62 | - */ | ||
| 63 | - @NotNull(message = "异常时间不能为空") | ||
| 64 | - private LocalDateTime exceptionTime; | ||
| 65 | - /** | ||
| 66 | - * 异常名 | ||
| 67 | - */ | ||
| 68 | - @NotNull(message = "异常名不能为空") | ||
| 69 | - private String exceptionName; | ||
| 70 | - /** | ||
| 71 | - * 异常发生的类全名 | ||
| 72 | - */ | ||
| 73 | - @NotNull(message = "异常发生的类全名不能为空") | ||
| 74 | - private String exceptionClassName; | ||
| 75 | - /** | ||
| 76 | - * 异常发生的类文件 | ||
| 77 | - */ | ||
| 78 | - @NotNull(message = "异常发生的类文件不能为空") | ||
| 79 | - private String exceptionFileName; | ||
| 80 | - /** | ||
| 81 | - * 异常发生的方法名 | ||
| 82 | - */ | ||
| 83 | - @NotNull(message = "异常发生的方法名不能为空") | ||
| 84 | - private String exceptionMethodName; | ||
| 85 | - /** | ||
| 86 | - * 异常发生的方法所在行 | ||
| 87 | - */ | ||
| 88 | - @NotNull(message = "异常发生的方法所在行不能为空") | ||
| 89 | - private Integer exceptionLineNumber; | ||
| 90 | - /** | ||
| 91 | - * 异常的栈轨迹异常的栈轨迹 | ||
| 92 | - */ | ||
| 93 | - @NotNull(message = "异常的栈轨迹不能为空") | ||
| 94 | - private String exceptionStackTrace; | ||
| 95 | - /** | ||
| 96 | - * 异常导致的根消息 | ||
| 97 | - */ | ||
| 98 | - @NotNull(message = "异常导致的根消息不能为空") | ||
| 99 | - private String exceptionRootCauseMessage; | ||
| 100 | - /** | ||
| 101 | - * 异常导致的消息 | ||
| 102 | - */ | ||
| 103 | - @NotNull(message = "异常导致的消息不能为空") | ||
| 104 | - private String exceptionMessage; | ||
| 105 | - | ||
| 106 | - | ||
| 107 | -} |
yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/service/ApiErrorLogFrameworkService.java
| 1 | package cn.iocoder.yudao.framework.apilog.core.service; | 1 | package cn.iocoder.yudao.framework.apilog.core.service; |
| 2 | 2 | ||
| 3 | +import cn.iocoder.yudao.module.infra.api.logger.dto.ApiErrorLogCreateReqDTO; | ||
| 4 | + | ||
| 3 | /** | 5 | /** |
| 4 | * API 错误日志 Framework Service 接口 | 6 | * API 错误日志 Framework Service 接口 |
| 5 | * | 7 | * |
| @@ -10,7 +12,8 @@ public interface ApiErrorLogFrameworkService { | @@ -10,7 +12,8 @@ public interface ApiErrorLogFrameworkService { | ||
| 10 | /** | 12 | /** |
| 11 | * 创建 API 错误日志 | 13 | * 创建 API 错误日志 |
| 12 | * | 14 | * |
| 13 | - * @param apiErrorLog API 错误日志 | 15 | + * @param reqDTO API 错误日志 |
| 14 | */ | 16 | */ |
| 15 | - void createApiErrorLog(ApiErrorLog apiErrorLog); | 17 | + void createApiErrorLog(ApiErrorLogCreateReqDTO reqDTO); |
| 18 | + | ||
| 16 | } | 19 | } |
yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/service/ApiErrorLogFrameworkServiceImpl.java
| 1 | package cn.iocoder.yudao.framework.apilog.core.service; | 1 | package cn.iocoder.yudao.framework.apilog.core.service; |
| 2 | 2 | ||
| 3 | -import cn.hutool.core.bean.BeanUtil; | ||
| 4 | import cn.iocoder.yudao.module.infra.api.logger.ApiErrorLogApi; | 3 | import cn.iocoder.yudao.module.infra.api.logger.ApiErrorLogApi; |
| 5 | import cn.iocoder.yudao.module.infra.api.logger.dto.ApiErrorLogCreateReqDTO; | 4 | import cn.iocoder.yudao.module.infra.api.logger.dto.ApiErrorLogCreateReqDTO; |
| 6 | import lombok.RequiredArgsConstructor; | 5 | import lombok.RequiredArgsConstructor; |
| @@ -20,8 +19,7 @@ public class ApiErrorLogFrameworkServiceImpl implements ApiErrorLogFrameworkServ | @@ -20,8 +19,7 @@ public class ApiErrorLogFrameworkServiceImpl implements ApiErrorLogFrameworkServ | ||
| 20 | 19 | ||
| 21 | @Override | 20 | @Override |
| 22 | @Async | 21 | @Async |
| 23 | - public void createApiErrorLog(ApiErrorLog apiErrorLog) { | ||
| 24 | - ApiErrorLogCreateReqDTO reqDTO = BeanUtil.copyProperties(apiErrorLog, ApiErrorLogCreateReqDTO.class); | 22 | + public void createApiErrorLog(ApiErrorLogCreateReqDTO reqDTO) { |
| 25 | apiErrorLogApi.createApiErrorLog(reqDTO); | 23 | apiErrorLogApi.createApiErrorLog(reqDTO); |
| 26 | } | 24 | } |
| 27 | 25 |
yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/handler/GlobalExceptionHandler.java
| @@ -3,7 +3,6 @@ package cn.iocoder.yudao.framework.web.core.handler; | @@ -3,7 +3,6 @@ package cn.iocoder.yudao.framework.web.core.handler; | ||
| 3 | import cn.hutool.core.exceptions.ExceptionUtil; | 3 | import cn.hutool.core.exceptions.ExceptionUtil; |
| 4 | import cn.hutool.core.map.MapUtil; | 4 | import cn.hutool.core.map.MapUtil; |
| 5 | import cn.hutool.core.util.StrUtil; | 5 | import cn.hutool.core.util.StrUtil; |
| 6 | -import cn.iocoder.yudao.framework.apilog.core.service.ApiErrorLog; | ||
| 7 | import cn.iocoder.yudao.framework.apilog.core.service.ApiErrorLogFrameworkService; | 6 | import cn.iocoder.yudao.framework.apilog.core.service.ApiErrorLogFrameworkService; |
| 8 | import cn.iocoder.yudao.framework.common.exception.ServiceException; | 7 | import cn.iocoder.yudao.framework.common.exception.ServiceException; |
| 9 | import cn.iocoder.yudao.framework.common.pojo.CommonResult; | 8 | import cn.iocoder.yudao.framework.common.pojo.CommonResult; |
| @@ -11,6 +10,7 @@ import cn.iocoder.yudao.framework.common.util.json.JsonUtils; | @@ -11,6 +10,7 @@ import cn.iocoder.yudao.framework.common.util.json.JsonUtils; | ||
| 11 | import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils; | 10 | import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils; |
| 12 | import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils; | 11 | import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils; |
| 13 | import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils; | 12 | import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils; |
| 13 | +import cn.iocoder.yudao.module.infra.api.logger.dto.ApiErrorLogCreateReqDTO; | ||
| 14 | import lombok.AllArgsConstructor; | 14 | import lombok.AllArgsConstructor; |
| 15 | import lombok.extern.slf4j.Slf4j; | 15 | import lombok.extern.slf4j.Slf4j; |
| 16 | import org.apache.commons.lang3.exception.ExceptionUtils; | 16 | import org.apache.commons.lang3.exception.ExceptionUtils; |
| @@ -46,6 +46,7 @@ import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeC | @@ -46,6 +46,7 @@ import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeC | ||
| 46 | @Slf4j | 46 | @Slf4j |
| 47 | public class GlobalExceptionHandler { | 47 | public class GlobalExceptionHandler { |
| 48 | 48 | ||
| 49 | + @SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection") | ||
| 49 | private final String applicationName; | 50 | private final String applicationName; |
| 50 | 51 | ||
| 51 | private final ApiErrorLogFrameworkService apiErrorLogFrameworkService; | 52 | private final ApiErrorLogFrameworkService apiErrorLogFrameworkService; |
| @@ -237,10 +238,10 @@ public class GlobalExceptionHandler { | @@ -237,10 +238,10 @@ public class GlobalExceptionHandler { | ||
| 237 | 238 | ||
| 238 | private void createExceptionLog(HttpServletRequest req, Throwable e) { | 239 | private void createExceptionLog(HttpServletRequest req, Throwable e) { |
| 239 | // 插入错误日志 | 240 | // 插入错误日志 |
| 240 | - ApiErrorLog errorLog = new ApiErrorLog(); | 241 | + ApiErrorLogCreateReqDTO errorLog = new ApiErrorLogCreateReqDTO(); |
| 241 | try { | 242 | try { |
| 242 | // 初始化 errorLog | 243 | // 初始化 errorLog |
| 243 | - initExceptionLog(errorLog, req, e); | 244 | + buildExceptionLog(errorLog, req, e); |
| 244 | // 执行插入 errorLog | 245 | // 执行插入 errorLog |
| 245 | apiErrorLogFrameworkService.createApiErrorLog(errorLog); | 246 | apiErrorLogFrameworkService.createApiErrorLog(errorLog); |
| 246 | } catch (Throwable th) { | 247 | } catch (Throwable th) { |
| @@ -248,7 +249,7 @@ public class GlobalExceptionHandler { | @@ -248,7 +249,7 @@ public class GlobalExceptionHandler { | ||
| 248 | } | 249 | } |
| 249 | } | 250 | } |
| 250 | 251 | ||
| 251 | - private void initExceptionLog(ApiErrorLog errorLog, HttpServletRequest request, Throwable e) { | 252 | + private void buildExceptionLog(ApiErrorLogCreateReqDTO errorLog, HttpServletRequest request, Throwable e) { |
| 252 | // 处理用户信息 | 253 | // 处理用户信息 |
| 253 | errorLog.setUserId(WebFrameworkUtils.getLoginUserId(request)); | 254 | errorLog.setUserId(WebFrameworkUtils.getLoginUserId(request)); |
| 254 | errorLog.setUserType(WebFrameworkUtils.getLoginUserType(request)); | 255 | errorLog.setUserType(WebFrameworkUtils.getLoginUserType(request)); |
yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/api/logger/dto/ApiAccessLogCreateReqDTO.java
| @@ -44,9 +44,12 @@ public class ApiAccessLogCreateReqDTO { | @@ -44,9 +44,12 @@ public class ApiAccessLogCreateReqDTO { | ||
| 44 | /** | 44 | /** |
| 45 | * 请求参数 | 45 | * 请求参数 |
| 46 | */ | 46 | */ |
| 47 | - @NotNull(message = "请求参数不能为空") | ||
| 48 | private String requestParams; | 47 | private String requestParams; |
| 49 | /** | 48 | /** |
| 49 | + * 响应结果 | ||
| 50 | + */ | ||
| 51 | + private String responseBody; | ||
| 52 | + /** | ||
| 50 | * 用户 IP | 53 | * 用户 IP |
| 51 | */ | 54 | */ |
| 52 | @NotNull(message = "ip 不能为空") | 55 | @NotNull(message = "ip 不能为空") |
| @@ -58,6 +61,21 @@ public class ApiAccessLogCreateReqDTO { | @@ -58,6 +61,21 @@ public class ApiAccessLogCreateReqDTO { | ||
| 58 | private String userAgent; | 61 | private String userAgent; |
| 59 | 62 | ||
| 60 | /** | 63 | /** |
| 64 | + * 操作模块 | ||
| 65 | + */ | ||
| 66 | + private String operateModule; | ||
| 67 | + /** | ||
| 68 | + * 操作名 | ||
| 69 | + */ | ||
| 70 | + private String operateName; | ||
| 71 | + /** | ||
| 72 | + * 操作分类 | ||
| 73 | + * | ||
| 74 | + * 枚举,参见 OperateTypeEnum 类 | ||
| 75 | + */ | ||
| 76 | + private Integer operateType; | ||
| 77 | + | ||
| 78 | + /** | ||
| 61 | * 开始请求时间 | 79 | * 开始请求时间 |
| 62 | */ | 80 | */ |
| 63 | @NotNull(message = "开始请求时间不能为空") | 81 | @NotNull(message = "开始请求时间不能为空") |
yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apiaccesslog/ApiAccessLogRespVO.java
| @@ -48,6 +48,10 @@ public class ApiAccessLogRespVO { | @@ -48,6 +48,10 @@ public class ApiAccessLogRespVO { | ||
| 48 | @ExcelProperty("请求参数") | 48 | @ExcelProperty("请求参数") |
| 49 | private String requestParams; | 49 | private String requestParams; |
| 50 | 50 | ||
| 51 | + @Schema(description = "响应结果") | ||
| 52 | + @ExcelProperty("响应结果") | ||
| 53 | + private String responseBody; | ||
| 54 | + | ||
| 51 | @Schema(description = "用户 IP", requiredMode = Schema.RequiredMode.REQUIRED, example = "127.0.0.1") | 55 | @Schema(description = "用户 IP", requiredMode = Schema.RequiredMode.REQUIRED, example = "127.0.0.1") |
| 52 | @ExcelProperty("用户 IP") | 56 | @ExcelProperty("用户 IP") |
| 53 | private String userIp; | 57 | private String userIp; |
| @@ -56,6 +60,19 @@ public class ApiAccessLogRespVO { | @@ -56,6 +60,19 @@ public class ApiAccessLogRespVO { | ||
| 56 | @ExcelProperty("浏览器 UA") | 60 | @ExcelProperty("浏览器 UA") |
| 57 | private String userAgent; | 61 | private String userAgent; |
| 58 | 62 | ||
| 63 | + @Schema(description = "操作模块", requiredMode = Schema.RequiredMode.REQUIRED, example = "商品模块") | ||
| 64 | + @ExcelProperty("操作模块") | ||
| 65 | + private String operateModule; | ||
| 66 | + | ||
| 67 | + @Schema(description = "操作名", requiredMode = Schema.RequiredMode.REQUIRED, example = "创建商品") | ||
| 68 | + @ExcelProperty("操作名") | ||
| 69 | + private String operateName; | ||
| 70 | + | ||
| 71 | + @Schema(description = "操作分类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | ||
| 72 | + @ExcelProperty(value = "操作分类", converter = DictConvert.class) | ||
| 73 | + @DictFormat(DictTypeConstants.OPERATE_TYPE) | ||
| 74 | + private Integer operateType; | ||
| 75 | + | ||
| 59 | @Schema(description = "开始请求时间", requiredMode = Schema.RequiredMode.REQUIRED) | 76 | @Schema(description = "开始请求时间", requiredMode = Schema.RequiredMode.REQUIRED) |
| 60 | @ExcelProperty("开始请求时间") | 77 | @ExcelProperty("开始请求时间") |
| 61 | private LocalDateTime beginTime; | 78 | private LocalDateTime beginTime; |
yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/logger/ApiAccessLogDO.java
| 1 | package cn.iocoder.yudao.module.infra.dal.dataobject.logger; | 1 | package cn.iocoder.yudao.module.infra.dal.dataobject.logger; |
| 2 | 2 | ||
| 3 | +import cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum; | ||
| 3 | import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; | 4 | import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; |
| 4 | import cn.iocoder.yudao.framework.common.pojo.CommonResult; | 5 | import cn.iocoder.yudao.framework.common.pojo.CommonResult; |
| 5 | import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; | 6 | import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; |
| @@ -71,6 +72,10 @@ public class ApiAccessLogDO extends BaseDO { | @@ -71,6 +72,10 @@ public class ApiAccessLogDO extends BaseDO { | ||
| 71 | */ | 72 | */ |
| 72 | private String requestParams; | 73 | private String requestParams; |
| 73 | /** | 74 | /** |
| 75 | + * 响应结果 | ||
| 76 | + */ | ||
| 77 | + private String responseBody; | ||
| 78 | + /** | ||
| 74 | * 用户 IP | 79 | * 用户 IP |
| 75 | */ | 80 | */ |
| 76 | private String userIp; | 81 | private String userIp; |
| @@ -82,6 +87,21 @@ public class ApiAccessLogDO extends BaseDO { | @@ -82,6 +87,21 @@ public class ApiAccessLogDO extends BaseDO { | ||
| 82 | // ========== 执行相关字段 ========== | 87 | // ========== 执行相关字段 ========== |
| 83 | 88 | ||
| 84 | /** | 89 | /** |
| 90 | + * 操作模块 | ||
| 91 | + */ | ||
| 92 | + private String operateModule; | ||
| 93 | + /** | ||
| 94 | + * 操作名 | ||
| 95 | + */ | ||
| 96 | + private String operateName; | ||
| 97 | + /** | ||
| 98 | + * 操作分类 | ||
| 99 | + * | ||
| 100 | + * 枚举 {@link OperateTypeEnum} | ||
| 101 | + */ | ||
| 102 | + private Integer operateType; | ||
| 103 | + | ||
| 104 | + /** | ||
| 85 | * 开始请求时间 | 105 | * 开始请求时间 |
| 86 | */ | 106 | */ |
| 87 | private LocalDateTime beginTime; | 107 | private LocalDateTime beginTime; |
| @@ -93,6 +113,7 @@ public class ApiAccessLogDO extends BaseDO { | @@ -93,6 +113,7 @@ public class ApiAccessLogDO extends BaseDO { | ||
| 93 | * 执行时长,单位:毫秒 | 113 | * 执行时长,单位:毫秒 |
| 94 | */ | 114 | */ |
| 95 | private Integer duration; | 115 | private Integer duration; |
| 116 | + | ||
| 96 | /** | 117 | /** |
| 97 | * 结果码 | 118 | * 结果码 |
| 98 | * | 119 | * |
yudao-module-infra/yudao-module-infra-biz/src/test/resources/sql/create_tables.sql
| @@ -94,8 +94,12 @@ CREATE TABLE IF NOT EXISTS "infra_api_access_log" ( | @@ -94,8 +94,12 @@ CREATE TABLE IF NOT EXISTS "infra_api_access_log" ( | ||
| 94 | "request_method" varchar(16) not null default '', | 94 | "request_method" varchar(16) not null default '', |
| 95 | "request_url" varchar(255) not null default '', | 95 | "request_url" varchar(255) not null default '', |
| 96 | "request_params" varchar(8000) not null default '', | 96 | "request_params" varchar(8000) not null default '', |
| 97 | + "response_body" varchar(8000) not null default '', | ||
| 97 | "user_ip" varchar(50) not null, | 98 | "user_ip" varchar(50) not null, |
| 98 | "user_agent" varchar(512) not null, | 99 | "user_agent" varchar(512) not null, |
| 100 | + `operate_module` varchar(50) NOT NULL, | ||
| 101 | + `operate_name` varchar(50) NOT NULL, | ||
| 102 | + `operate_type` bigint(4) NOT NULL DEFAULT '0', | ||
| 99 | "begin_time" timestamp not null, | 103 | "begin_time" timestamp not null, |
| 100 | "end_time" timestamp not null, | 104 | "end_time" timestamp not null, |
| 101 | "duration" integer not null, | 105 | "duration" integer not null, |
| @@ -108,7 +112,7 @@ CREATE TABLE IF NOT EXISTS "infra_api_access_log" ( | @@ -108,7 +112,7 @@ CREATE TABLE IF NOT EXISTS "infra_api_access_log" ( | ||
| 108 | "deleted" bit not null default false, | 112 | "deleted" bit not null default false, |
| 109 | "tenant_id" bigint not null default '0', | 113 | "tenant_id" bigint not null default '0', |
| 110 | primary key ("id") | 114 | primary key ("id") |
| 111 | - ) COMMENT 'API 访问日志表'; | 115 | +) COMMENT 'API 访问日志表'; |
| 112 | 116 | ||
| 113 | CREATE TABLE IF NOT EXISTS "infra_api_error_log" ( | 117 | CREATE TABLE IF NOT EXISTS "infra_api_error_log" ( |
| 114 | "id" bigint not null GENERATED BY DEFAULT AS IDENTITY, | 118 | "id" bigint not null GENERATED BY DEFAULT AS IDENTITY, |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notify/NotifyMessageController.java
| 1 | package cn.iocoder.yudao.module.system.controller.admin.notify; | 1 | package cn.iocoder.yudao.module.system.controller.admin.notify; |
| 2 | 2 | ||
| 3 | +import cn.iocoder.yudao.framework.apilog.core.annotations.ApiAccessLog; | ||
| 3 | import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; | 4 | import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; |
| 4 | import cn.iocoder.yudao.framework.common.pojo.CommonResult; | 5 | import cn.iocoder.yudao.framework.common.pojo.CommonResult; |
| 5 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 6 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| @@ -88,6 +89,7 @@ public class NotifyMessageController { | @@ -88,6 +89,7 @@ public class NotifyMessageController { | ||
| 88 | 89 | ||
| 89 | @GetMapping("/get-unread-count") | 90 | @GetMapping("/get-unread-count") |
| 90 | @Operation(summary = "获得当前用户的未读站内信数量") | 91 | @Operation(summary = "获得当前用户的未读站内信数量") |
| 92 | + @ApiAccessLog(enable = false) // 由于前端会不断轮询该接口,记录日志没有意义 | ||
| 91 | public CommonResult<Long> getUnreadNotifyMessageCount() { | 93 | public CommonResult<Long> getUnreadNotifyMessageCount() { |
| 92 | return success(notifyMessageService.getUnreadNotifyMessageCount( | 94 | return success(notifyMessageService.getUnreadNotifyMessageCount( |
| 93 | getLoginUserId(), UserTypeEnum.ADMIN.getValue())); | 95 | getLoginUserId(), UserTypeEnum.ADMIN.getValue())); |