feat: complete all post-refactor tasks (performance, monitoring, docs, CI/CD)
This commit is contained in:
@@ -0,0 +1,884 @@
|
||||
# 模块架构重构执行计划
|
||||
|
||||
> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
|
||||
|
||||
**Goal:** 重构项目模块架构,实现清晰的职责划分和依赖倒置
|
||||
|
||||
**Architecture:**
|
||||
- app模块:只包含启动类、应用级配置和flyway脚本
|
||||
- sys模块:包含所有业务代码(domain、service、handler等)和业务级配置
|
||||
- gateway模块:包含路由和限流配置
|
||||
- db模块:依赖sys模块,实现repository接口
|
||||
- common模块:提供通用工具类和基础配置
|
||||
|
||||
**Tech Stack:** Maven, Spring Boot, Spring WebFlux, Spring Security, R2DBC
|
||||
|
||||
---
|
||||
|
||||
## 重构目标
|
||||
|
||||
### 模块职责划分
|
||||
|
||||
| 模块 | 职责 | 内容 |
|
||||
|-------|--------|------|
|
||||
| manage-app | 应用启动和配置 | ManageApplication.java、application.yml、flyway脚本、应用级配置(WebFluxConfig、MultipartConfig、OpenApiConfig) |
|
||||
| manage-sys | 业务逻辑 | domain、repository接口、service接口和实现、handler、业务级配置(SecurityConfig、WebSocketConfig) |
|
||||
| manage-gateway | 网关路由和限流 | GatewayApplication.java、路由配置(SystemRouter)、限流配置(RateLimitConfig) |
|
||||
| manage-db | 数据访问实现 | entity、dao、repository实现、converter |
|
||||
| manage-common | 通用工具和配置 | 工具类、通用DTO、基础配置、全局异常处理(GlobalExceptionHandler) |
|
||||
|
||||
### 依赖关系
|
||||
|
||||
```
|
||||
manage-gateway → 无依赖(独立模块)
|
||||
manage-app → manage-sys + manage-db
|
||||
manage-sys → manage-common
|
||||
manage-db → manage-sys
|
||||
manage-common → 无依赖
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Task 1: 将RateLimitConfig从app模块移到gateway模块
|
||||
|
||||
**Files:**
|
||||
- Create: `manage-gateway/src/main/java/cn/novalon/manage/gateway/config/RateLimitConfig.java`
|
||||
- Delete: `manage-app/src/main/java/cn/novalon/manage/app/config/RateLimitConfig.java`
|
||||
|
||||
**Step 1: 创建gateway模块的config目录**
|
||||
|
||||
```bash
|
||||
mkdir -p manage-gateway/src/main/java/cn/novalon/manage/gateway/config
|
||||
```
|
||||
|
||||
**Step 2: 移动RateLimitConfig.java**
|
||||
|
||||
```bash
|
||||
mv manage-app/src/main/java/cn/novalon/manage/app/config/RateLimitConfig.java \
|
||||
manage-gateway/src/main/java/cn/novalon/manage/gateway/config/
|
||||
```
|
||||
|
||||
**Step 3: 更新RateLimitConfig.java的包声明**
|
||||
|
||||
```java
|
||||
// 将
|
||||
package cn.novalon.manage.sys.config;
|
||||
// 改为
|
||||
package cn.novalon.manage.gateway.config;
|
||||
```
|
||||
|
||||
**Step 4: 更新gateway模块的pom.xml,添加Resilience4j依赖**
|
||||
|
||||
```xml
|
||||
<dependency>
|
||||
<groupId>io.github.resilience4j</groupId>
|
||||
<artifactId>resilience4j-spring-boot3</artifactId>
|
||||
<version>2.2.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.github.resilience4j</groupId>
|
||||
<artifactId>resilience4j-reactor</artifactId>
|
||||
<version>2.2.0</version>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
**Step 5: 更新gateway模块的application.yml,添加限流配置**
|
||||
|
||||
```yaml
|
||||
rate:
|
||||
limit:
|
||||
limit-for-period: 100
|
||||
limit-refresh-period: 1s
|
||||
timeout-duration: 0
|
||||
```
|
||||
|
||||
**Step 6: 提交更改**
|
||||
|
||||
```bash
|
||||
git add manage-gateway/src/main/java/cn/novalon/manage/gateway/config/RateLimitConfig.java
|
||||
git add manage-gateway/pom.xml
|
||||
git add manage-gateway/src/main/resources/application.yml
|
||||
git rm manage-app/src/main/java/cn/novalon/manage/app/config/RateLimitConfig.java
|
||||
git commit -m "refactor: move RateLimitConfig to gateway module"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Task 2: 将SystemRouter从app模块移到gateway模块
|
||||
|
||||
**Files:**
|
||||
- Create: `manage-gateway/src/main/java/cn/novalon/manage/gateway/config/SystemRouter.java`
|
||||
- Delete: `manage-app/src/main/java/cn/novalon/manage/app/config/SystemRouter.java`
|
||||
|
||||
**Step 1: 移动SystemRouter.java**
|
||||
|
||||
```bash
|
||||
mv manage-app/src/main/java/cn/novalon/manage/app/config/SystemRouter.java \
|
||||
manage-gateway/src/main/java/cn/novalon/manage/gateway/config/
|
||||
```
|
||||
|
||||
**Step 2: 更新SystemRouter.java的包声明**
|
||||
|
||||
```java
|
||||
// 将
|
||||
package cn.novalon.manage.sys.config;
|
||||
// 改为
|
||||
package cn.novalon.manage.gateway.config;
|
||||
```
|
||||
|
||||
**Step 3: 更新GatewayApplication.java,集成SystemRouter**
|
||||
|
||||
```java
|
||||
package cn.novalon.manage.gateway;
|
||||
|
||||
import cn.novalon.manage.gateway.config.SystemRouter;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.cloud.gateway.route.RouteLocator;
|
||||
import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
|
||||
@SpringBootApplication
|
||||
public class GatewayApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(GatewayApplication.class, args);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public RouteLocator customRouteLocator(RouteLocatorBuilder builder, SystemRouter systemRouter) {
|
||||
return systemRouter.buildRoutes(builder);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Step 4: 更新SystemRouter.java,使用RouteLocatorBuilder**
|
||||
|
||||
```java
|
||||
package cn.novalon.manage.gateway.config;
|
||||
|
||||
import org.springframework.cloud.gateway.route.RouteLocator;
|
||||
import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* 系统路由配置
|
||||
*
|
||||
* 文件定义:配置Spring Cloud Gateway的路由规则
|
||||
* 涉及业务:API路由、负载均衡、服务发现
|
||||
* 算法:使用Spring Cloud Gateway的路由匹配和转发
|
||||
*
|
||||
* @author 张翔
|
||||
* @date 2026-03-13
|
||||
*/
|
||||
@Component
|
||||
public class SystemRouter {
|
||||
|
||||
public RouteLocator buildRoutes(RouteLocatorBuilder builder) {
|
||||
return builder.routes()
|
||||
.route("manage-app", r -> r
|
||||
.path("/api/**")
|
||||
.uri("http://manage-app:8081"))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Step 5: 提交更改**
|
||||
|
||||
```bash
|
||||
git add manage-gateway/src/main/java/cn/novalon/manage/gateway/config/SystemRouter.java
|
||||
git add manage-gateway/src/main/java/cn/novalon/manage/gateway/GatewayApplication.java
|
||||
git rm manage-app/src/main/java/cn/novalon/manage/app/config/SystemRouter.java
|
||||
git commit -m "refactor: move SystemRouter to gateway module"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Task 3: 将SecurityConfig从app模块移到sys模块
|
||||
|
||||
**Files:**
|
||||
- Create: `manage-sys/src/main/java/cn/novalon/manage/sys/config/SecurityConfig.java`
|
||||
- Delete: `manage-app/src/main/java/cn/novalon/manage/app/config/SecurityConfig.java`
|
||||
|
||||
**Step 1: 创建sys模块的config目录**
|
||||
|
||||
```bash
|
||||
mkdir -p manage-sys/src/main/java/cn/novalon/manage/sys/config
|
||||
```
|
||||
|
||||
**Step 2: 移动SecurityConfig.java**
|
||||
|
||||
```bash
|
||||
mv manage-app/src/main/java/cn/novalon/manage/app/config/SecurityConfig.java \
|
||||
manage-sys/src/main/java/cn/novalon/manage/sys/config/
|
||||
```
|
||||
|
||||
**Step 3: 更新SecurityConfig.java的包声明**
|
||||
|
||||
```java
|
||||
// 将
|
||||
package cn.novalon.manage.sys.config;
|
||||
// 改为
|
||||
package cn.novalon.manage.sys.config;
|
||||
```
|
||||
|
||||
**Step 4: 提交更改**
|
||||
|
||||
```bash
|
||||
git add manage-sys/src/main/java/cn/novalon/manage/sys/config/SecurityConfig.java
|
||||
git rm manage-app/src/main/java/cn/novalon/manage/app/config/SecurityConfig.java
|
||||
git commit -m "refactor: move SecurityConfig to sys module"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Task 4: 将WebSocketConfig从app模块移到sys模块
|
||||
|
||||
**Files:**
|
||||
- Create: `manage-sys/src/main/java/cn/novalon/manage/sys/config/WebSocketConfig.java`
|
||||
- Delete: `manage-app/src/main/java/cn/novalon/manage/app/config/WebSocketConfig.java`
|
||||
|
||||
**Step 1: 移动WebSocketConfig.java**
|
||||
|
||||
```bash
|
||||
mv manage-app/src/main/java/cn/novalon/manage/app/config/WebSocketConfig.java \
|
||||
manage-sys/src/main/java/cn/novalon/manage/sys/config/
|
||||
```
|
||||
|
||||
**Step 2: 更新WebSocketConfig.java的包声明**
|
||||
|
||||
```java
|
||||
// 将
|
||||
package cn.novalon.manage.sys.config;
|
||||
// 改为
|
||||
package cn.novalon.manage.sys.config;
|
||||
```
|
||||
|
||||
**Step 3: 提交更改**
|
||||
|
||||
```bash
|
||||
git add manage-sys/src/main/java/cn/novalon/manage/sys/config/WebSocketConfig.java
|
||||
git rm manage-app/src/main/java/cn/novalon/manage/app/config/WebSocketConfig.java
|
||||
git commit -m "refactor: move WebSocketConfig to sys module"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Task 5: 将GlobalExceptionHandler移到common模块并重构
|
||||
|
||||
**Files:**
|
||||
- Create: `manage-common/src/main/java/cn/novalon/manage/common/handler/GlobalExceptionHandler.java`
|
||||
- Create: `manage-common/src/main/java/cn/novalon/manage/common/handler/ExceptionLogService.java`
|
||||
- Delete: `manage-app/src/main/java/cn/novalon/manage/app/handler/GlobalExceptionHandler.java`
|
||||
|
||||
**Step 1: 创建common模块的handler目录**
|
||||
|
||||
```bash
|
||||
mkdir -p manage-common/src/main/java/cn/novalon/manage/common/handler
|
||||
```
|
||||
|
||||
**Step 2: 创建异常日志服务接口**
|
||||
|
||||
```java
|
||||
package cn.novalon.manage.common.handler;
|
||||
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
/**
|
||||
* 异常日志服务接口
|
||||
*
|
||||
* 文件定义:定义异常日志记录的抽象接口
|
||||
* 涉及业务:异常日志记录、错误追踪
|
||||
* 算法:使用响应式编程实现异步日志记录
|
||||
*
|
||||
* @author 张翔
|
||||
* @date 2026-03-13
|
||||
*/
|
||||
public interface ExceptionLogService {
|
||||
Mono<Void> logException(String title, String exceptionName, String exceptionMsg,
|
||||
String methodName, String ip, String stackTrace);
|
||||
}
|
||||
```
|
||||
|
||||
**Step 3: 重构GlobalExceptionHandler,移除对sys模块的依赖**
|
||||
|
||||
```java
|
||||
package cn.novalon.manage.common.handler;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.dao.DataIntegrityViolationException;
|
||||
import org.springframework.dao.DuplicateKeyException;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.validation.FieldError;
|
||||
import org.springframework.web.bind.MethodArgumentNotValidException;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
||||
import org.springframework.web.server.ResponseStatusException;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
import org.springframework.web.server.ServerWebInputException;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 全局异常处理器
|
||||
*
|
||||
* 文件定义:统一处理系统中抛出的各种异常,返回标准化的错误响应
|
||||
* 涉及业务:异常捕获、错误日志记录、错误响应格式化
|
||||
* 算法:使用@RestControllerAdvice注解实现全局异常拦截
|
||||
*
|
||||
* @author 张翔
|
||||
* @date 2026-03-13
|
||||
*/
|
||||
@RestControllerAdvice
|
||||
public class GlobalExceptionHandler {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);
|
||||
|
||||
private final ExceptionLogService exceptionLogService;
|
||||
|
||||
public GlobalExceptionHandler(ExceptionLogService exceptionLogService) {
|
||||
this.exceptionLogService = exceptionLogService;
|
||||
}
|
||||
|
||||
@ExceptionHandler(RuntimeException.class)
|
||||
public ResponseEntity<Map<String, Object>> handleRuntimeException(RuntimeException ex, ServerWebExchange exchange) {
|
||||
logger.warn("Runtime exception: ", ex);
|
||||
|
||||
Map<String, Object> response = new HashMap<>();
|
||||
if (ex.getMessage() != null && ex.getMessage().contains("not found")) {
|
||||
response.put("code", HttpStatus.NOT_FOUND.value());
|
||||
response.put("message", ex.getMessage());
|
||||
response.put("timestamp", LocalDateTime.now());
|
||||
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(response);
|
||||
}
|
||||
response.put("code", HttpStatus.BAD_REQUEST.value());
|
||||
response.put("message", ex.getMessage());
|
||||
response.put("timestamp", LocalDateTime.now());
|
||||
|
||||
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(response);
|
||||
}
|
||||
|
||||
@ExceptionHandler(Exception.class)
|
||||
public ResponseEntity<Map<String, Object>> handleException(Exception ex, ServerWebExchange exchange) {
|
||||
logger.error("Exception occurred: ", ex);
|
||||
|
||||
exceptionLogService.logException(
|
||||
"System Exception",
|
||||
ex.getClass().getSimpleName(),
|
||||
ex.getMessage(),
|
||||
exchange.getRequest().getPath().value(),
|
||||
getClientIp(exchange),
|
||||
getStackTrace(ex)
|
||||
).subscribe();
|
||||
|
||||
Map<String, Object> response = new HashMap<>();
|
||||
response.put("code", HttpStatus.INTERNAL_SERVER_ERROR.value());
|
||||
response.put("message", "Internal server error");
|
||||
response.put("timestamp", LocalDateTime.now());
|
||||
|
||||
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(response);
|
||||
}
|
||||
|
||||
@ExceptionHandler(IllegalArgumentException.class)
|
||||
public ResponseEntity<Map<String, Object>> handleIllegalArgumentException(IllegalArgumentException ex, ServerWebExchange exchange) {
|
||||
logger.warn("Illegal argument: ", ex);
|
||||
|
||||
Map<String, Object> response = new HashMap<>();
|
||||
response.put("code", HttpStatus.BAD_REQUEST.value());
|
||||
response.put("message", ex.getMessage());
|
||||
response.put("timestamp", LocalDateTime.now());
|
||||
|
||||
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(response);
|
||||
}
|
||||
|
||||
@ExceptionHandler(MethodArgumentNotValidException.class)
|
||||
public ResponseEntity<Map<String, Object>> handleMethodArgumentNotValidException(MethodArgumentNotValidException ex, ServerWebExchange exchange) {
|
||||
logger.warn("Validation failed: ", ex);
|
||||
|
||||
Map<String, Object> response = new HashMap<>();
|
||||
response.put("code", HttpStatus.BAD_REQUEST.value());
|
||||
response.put("message", "Validation failed");
|
||||
response.put("timestamp", LocalDateTime.now());
|
||||
|
||||
Map<String, String> fieldErrors = ex.getBindingResult()
|
||||
.getFieldErrors()
|
||||
.stream()
|
||||
.collect(Collectors.toMap(FieldError::getField, FieldError::getDefaultMessage, (e1, e2) -> e1));
|
||||
|
||||
response.put("errors", fieldErrors);
|
||||
|
||||
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(response);
|
||||
}
|
||||
|
||||
@ExceptionHandler(ServerWebInputException.class)
|
||||
public ResponseEntity<Map<String, Object>> handleServerWebInputException(ServerWebInputException ex, ServerWebExchange exchange) {
|
||||
logger.warn("Invalid input: ", ex);
|
||||
|
||||
Map<String, Object> response = new HashMap<>();
|
||||
response.put("code", HttpStatus.BAD_REQUEST.value());
|
||||
response.put("message", "Invalid input");
|
||||
response.put("timestamp", LocalDateTime.now());
|
||||
|
||||
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(response);
|
||||
}
|
||||
|
||||
@ExceptionHandler(ResponseStatusException.class)
|
||||
public ResponseEntity<Map<String, Object>> handleResponseStatusException(ResponseStatusException ex, ServerWebExchange exchange) {
|
||||
logger.warn("Response status exception: ", ex);
|
||||
|
||||
Map<String, Object> response = new HashMap<>();
|
||||
response.put("code", ex.getStatusCode().value());
|
||||
response.put("message", ex.getReason());
|
||||
response.put("timestamp", LocalDateTime.now());
|
||||
|
||||
return ResponseEntity.status(ex.getStatusCode()).body(response);
|
||||
}
|
||||
|
||||
@ExceptionHandler(DuplicateKeyException.class)
|
||||
public ResponseEntity<Map<String, Object>> handleDuplicateKeyException(DuplicateKeyException ex, ServerWebExchange exchange) {
|
||||
logger.warn("Duplicate key: ", ex);
|
||||
|
||||
Map<String, Object> response = new HashMap<>();
|
||||
response.put("code", HttpStatus.CONFLICT.value());
|
||||
response.put("message", "Duplicate key violation");
|
||||
response.put("timestamp", LocalDateTime.now());
|
||||
|
||||
return ResponseEntity.status(HttpStatus.CONFLICT).body(response);
|
||||
}
|
||||
|
||||
@ExceptionHandler(DataIntegrityViolationException.class)
|
||||
public ResponseEntity<Map<String, Object>> handleDataIntegrityViolationException(DataIntegrityViolationException ex, ServerWebExchange exchange) {
|
||||
logger.warn("Data integrity violation: ", ex);
|
||||
|
||||
Map<String, Object> response = new HashMap<>();
|
||||
response.put("code", HttpStatus.CONFLICT.value());
|
||||
response.put("message", "Data integrity violation");
|
||||
response.put("timestamp", LocalDateTime.now());
|
||||
|
||||
return ResponseEntity.status(HttpStatus.CONFLICT).body(response);
|
||||
}
|
||||
|
||||
private String getClientIp(ServerWebExchange exchange) {
|
||||
return exchange.getRequest().getHeaders().getFirst("X-Forwarded-For",
|
||||
exchange.getRequest().getRemoteAddress().getAddress().getHostAddress());
|
||||
}
|
||||
|
||||
private String getStackTrace(Exception ex) {
|
||||
StringBuilder stackTrace = new StringBuilder();
|
||||
for (StackTraceElement element : ex.getStackTrace()) {
|
||||
stackTrace.append(element.toString()).append("\n");
|
||||
}
|
||||
return stackTrace.toString();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Step 4: 移动GlobalExceptionHandler.java**
|
||||
|
||||
```bash
|
||||
mv manage-app/src/main/java/cn/novalon/manage/app/handler/GlobalExceptionHandler.java \
|
||||
manage-common/src/main/java/cn/novalon/manage/common/handler/
|
||||
```
|
||||
|
||||
**Step 5: 更新GlobalExceptionHandler.java的包声明**
|
||||
|
||||
```java
|
||||
// 将
|
||||
package cn.novalon.manage.sys.handler;
|
||||
// 改为
|
||||
package cn.novalon.manage.common.handler;
|
||||
```
|
||||
|
||||
**Step 6: 在sys模块实现ExceptionLogService接口**
|
||||
|
||||
```java
|
||||
package cn.novalon.manage.sys.handler;
|
||||
|
||||
import cn.novalon.manage.common.handler.ExceptionLogService;
|
||||
import cn.novalon.manage.sys.core.domain.SysExceptionLog;
|
||||
import cn.novalon.manage.sys.core.service.ISysExceptionLogService;
|
||||
import org.springframework.stereotype.Service;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
/**
|
||||
* 异常日志服务实现
|
||||
*
|
||||
* 文件定义:实现异常日志记录接口,使用sys模块的异常日志服务
|
||||
* 涉及业务:异常日志记录、错误追踪
|
||||
* 算法:使用响应式编程实现异步日志记录
|
||||
*
|
||||
* @author 张翔
|
||||
* @date 2026-03-13
|
||||
*/
|
||||
@Service
|
||||
public class ExceptionLogServiceImpl implements ExceptionLogService {
|
||||
|
||||
private final ISysExceptionLogService exceptionLogService;
|
||||
|
||||
public ExceptionLogServiceImpl(ISysExceptionLogService exceptionLogService) {
|
||||
this.exceptionLogService = exceptionLogService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<Void> logException(String title, String exceptionName, String exceptionMsg,
|
||||
String methodName, String ip, String stackTrace) {
|
||||
SysExceptionLog exceptionLog = new SysExceptionLog();
|
||||
exceptionLog.setTitle(title);
|
||||
exceptionLog.setExceptionName(exceptionName);
|
||||
exceptionLog.setExceptionMsg(exceptionMsg);
|
||||
exceptionLog.setMethodName(methodName);
|
||||
exceptionLog.setIp(ip);
|
||||
exceptionLog.setCreateTime(LocalDateTime.now());
|
||||
exceptionLog.setStackTrace(stackTrace);
|
||||
|
||||
return exceptionLogService.save(exceptionLog).then();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Step 7: 在sys模块的配置中注册ExceptionLogServiceImpl**
|
||||
|
||||
```java
|
||||
package cn.novalon.manage.sys.config;
|
||||
|
||||
import cn.novalon.manage.common.handler.ExceptionLogService;
|
||||
import cn.novalon.manage.sys.handler.ExceptionLogServiceImpl;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* 异常日志配置类
|
||||
*
|
||||
* 文件定义:配置异常日志服务的实现
|
||||
* 涉及业务:异常日志记录、错误追踪
|
||||
* 算法:使用Spring的依赖注入实现接口和实现的绑定
|
||||
*
|
||||
* @author 张翔
|
||||
* @date 2026-03-13
|
||||
*/
|
||||
@Configuration
|
||||
public class ExceptionLogConfig {
|
||||
|
||||
@Bean
|
||||
public ExceptionLogService exceptionLogService(ExceptionLogServiceImpl exceptionLogServiceImpl) {
|
||||
return exceptionLogServiceImpl;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Step 8: 提交更改**
|
||||
|
||||
```bash
|
||||
git add manage-common/src/main/java/cn/novalon/manage/common/handler/GlobalExceptionHandler.java
|
||||
git add manage-common/src/main/java/cn/novalon/manage/common/handler/ExceptionLogService.java
|
||||
git add manage-sys/src/main/java/cn/novalon/manage/sys/handler/ExceptionLogServiceImpl.java
|
||||
git add manage-sys/src/main/java/cn/novalon/manage/sys/config/ExceptionLogConfig.java
|
||||
git rm manage-app/src/main/java/cn/novalon/manage/app/handler/GlobalExceptionHandler.java
|
||||
git commit -m "refactor: move GlobalExceptionHandler to common module with dependency inversion"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Task 6: 更新app模块的ManageApplication.java
|
||||
|
||||
**Files:**
|
||||
- Modify: `manage-app/src/main/java/cn/novalon/manage/app/ManageApplication.java`
|
||||
|
||||
**Step 1: 更新ManageApplication.java的组件扫描配置**
|
||||
|
||||
```java
|
||||
package cn.novalon.manage.app;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.context.properties.ConfigurationPropertiesScan;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.data.r2dbc.repository.config.EnableR2dbcRepositories;
|
||||
|
||||
/**
|
||||
* 管理应用主类
|
||||
*
|
||||
* 文件定义:Spring Boot应用启动类,配置组件扫描和功能启用
|
||||
* 涉及业务:应用启动、组件扫描、功能配置
|
||||
* 算法:使用Spring Boot自动配置和注解驱动
|
||||
*
|
||||
* @author 张翔
|
||||
* @date 2026-03-13
|
||||
*/
|
||||
@SpringBootApplication
|
||||
@ConfigurationPropertiesScan(basePackages = "cn.novalon.manage")
|
||||
@ComponentScan(basePackages = {"cn.novalon.manage.sys", "cn.novalon.manage.db"})
|
||||
@EnableR2dbcRepositories(basePackages = "cn.novalon.manage.db.repository")
|
||||
public class ManageApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(ManageApplication.class, args);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Step 2: 提交更改**
|
||||
|
||||
```bash
|
||||
git add manage-app/src/main/java/cn/novalon/manage/app/ManageApplication.java
|
||||
git commit -m "refactor: update ManageApplication component scan configuration"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Task 7: 更新app模块的pom.xml
|
||||
|
||||
**Files:**
|
||||
- Modify: `manage-app/pom.xml`
|
||||
|
||||
**Step 1: 确保app模块依赖sys和db模块**
|
||||
|
||||
```xml
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>cn.novalon.manage</groupId>
|
||||
<artifactId>manage-sys</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.novalon.manage</groupId>
|
||||
<artifactId>manage-db</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-webflux</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-actuator</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.micrometer</groupId>
|
||||
<artifactId>micrometer-registry-prometheus</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.postgresql</groupId>
|
||||
<artifactId>r2dbc-postgresql</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.postgresql</groupId>
|
||||
<artifactId>postgresql</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.flywaydb</groupId>
|
||||
<artifactId>flyway-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.flywaydb</groupId>
|
||||
<artifactId>flyway-database-postgresql</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
```
|
||||
|
||||
**Step 2: 移除不需要的依赖**
|
||||
|
||||
```xml
|
||||
<!-- 移除以下依赖 -->
|
||||
<dependency>
|
||||
<groupId>io.github.resilience4j</groupId>
|
||||
<artifactId>resilience4j-spring-boot3</artifactId>
|
||||
<version>2.2.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.github.resilience4j</groupId>
|
||||
<artifactId>resilience4j-reactor</artifactId>
|
||||
<version>2.2.0</version>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
**Step 3: 提交更改**
|
||||
|
||||
```bash
|
||||
git add manage-app/pom.xml
|
||||
git commit -m "refactor: update app module dependencies"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Task 8: 编译和测试验证
|
||||
|
||||
**Files:**
|
||||
- Test: `manage-app`, `manage-sys`, `manage-db`, `manage-gateway`
|
||||
|
||||
**Step 1: 清理并编译所有模块**
|
||||
|
||||
```bash
|
||||
mvn clean compile -DskipTests
|
||||
```
|
||||
|
||||
**Expected:** 所有模块编译成功,无错误
|
||||
|
||||
**Step 2: 运行单元测试**
|
||||
|
||||
```bash
|
||||
mvn test
|
||||
```
|
||||
|
||||
**Expected:** 所有测试通过
|
||||
|
||||
**Step 3: 启动应用验证**
|
||||
|
||||
```bash
|
||||
cd manage-app
|
||||
mvn spring-boot:run
|
||||
```
|
||||
|
||||
**Expected:** 应用成功启动,无错误日志
|
||||
|
||||
**Step 4: 提交更改**
|
||||
|
||||
```bash
|
||||
git add .
|
||||
git commit -m "refactor: complete module architecture refactoring"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Task 9: 更新文档
|
||||
|
||||
**Files:**
|
||||
- Create: `docs/architecture/module-architecture.md`
|
||||
|
||||
**Step 1: 创建模块架构文档**
|
||||
|
||||
```markdown
|
||||
# 模块架构设计
|
||||
|
||||
## 模块职责划分
|
||||
|
||||
### manage-app
|
||||
应用启动和配置模块,包含:
|
||||
- ManageApplication.java:应用启动类
|
||||
- application.yml:应用配置文件
|
||||
- flyway脚本:数据库迁移脚本
|
||||
- 应用级配置:WebFluxConfig、MultipartConfig、OpenApiConfig、GlobalExceptionHandler
|
||||
|
||||
### manage-sys
|
||||
业务逻辑模块,包含:
|
||||
- domain:领域对象(SysUser、SysRole、SysMenu等)
|
||||
- repository:数据访问接口
|
||||
- service:业务逻辑接口和实现
|
||||
- handler:业务处理器(用户、角色、菜单等)
|
||||
- 业务级配置:SecurityConfig、WebSocketConfig
|
||||
- 其他:filter、security、websocket、primitive、command、dto
|
||||
|
||||
### manage-gateway
|
||||
网关模块,包含:
|
||||
- GatewayApplication.java:网关启动类
|
||||
- 路由配置:SystemRouter
|
||||
- 限流配置:RateLimitConfig
|
||||
|
||||
### manage-db
|
||||
数据访问实现模块,包含:
|
||||
- entity:数据库实体
|
||||
- dao:数据访问对象
|
||||
- repository:repository实现
|
||||
- converter:实体和领域对象转换器
|
||||
|
||||
### manage-common
|
||||
通用工具和配置模块,包含:
|
||||
- 工具类:SnowflakeId等
|
||||
- 通用DTO:PageRequest、PageResponse
|
||||
- 基础配置:JwtProperties、CacheConfig
|
||||
|
||||
## 依赖关系
|
||||
|
||||
```
|
||||
manage-gateway → 无依赖(独立模块)
|
||||
manage-app → manage-sys + manage-db
|
||||
manage-sys → manage-common
|
||||
manage-db → manage-sys
|
||||
manage-common → 无依赖
|
||||
```
|
||||
|
||||
## 依赖倒置实现
|
||||
|
||||
通过manage-app模块的依赖注入,实现依赖倒置:
|
||||
- sys模块定义repository接口
|
||||
- db模块实现repository接口
|
||||
- app模块通过@ComponentScan扫描db模块的repository实现
|
||||
- app模块通过@EnableR2dbcRepositories启用R2DBC repository
|
||||
- common模块定义ExceptionLogService接口
|
||||
- sys模块实现ExceptionLogService接口
|
||||
- app模块通过配置注册ExceptionLogService实现
|
||||
```
|
||||
|
||||
**Step 2: 提交文档**
|
||||
|
||||
```bash
|
||||
git add docs/architecture/module-architecture.md
|
||||
git commit -m "docs: add module architecture documentation"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 验证清单
|
||||
|
||||
### 编译验证
|
||||
- [ ] manage-common编译成功
|
||||
- [ ] manage-sys编译成功
|
||||
- [ ] manage-db编译成功
|
||||
- [ ] manage-app编译成功
|
||||
- [ ] manage-gateway编译成功
|
||||
|
||||
### 功能验证
|
||||
- [ ] 应用启动成功
|
||||
- [ ] 数据库连接正常
|
||||
- [ ] API访问正常
|
||||
- [ ] WebSocket连接正常
|
||||
- [ ] 安全认证正常
|
||||
- [ ] 限流功能正常
|
||||
|
||||
### 依赖验证
|
||||
- [ ] manage-sys不依赖manage-db
|
||||
- [ ] manage-db依赖manage-sys
|
||||
- [ ] manage-app依赖manage-sys和manage-db
|
||||
- [ ] manage-gateway无依赖
|
||||
|
||||
### 测试验证
|
||||
- [ ] 单元测试全部通过
|
||||
- [ ] 集成测试全部通过
|
||||
- [ ] E2E测试全部通过
|
||||
|
||||
---
|
||||
|
||||
## 回滚计划
|
||||
|
||||
如果重构过程中出现问题,可以使用以下命令回滚:
|
||||
|
||||
```bash
|
||||
# 回滚到重构前的状态
|
||||
git reset --hard <commit-hash-before-refactoring>
|
||||
|
||||
# 或者使用git reflog查找之前的提交
|
||||
git reflog
|
||||
git reset --hard HEAD@{n}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 注意事项
|
||||
|
||||
1. **循环依赖**:确保manage-sys不依赖manage-db
|
||||
2. **包声明**:移动文件后记得更新包声明
|
||||
3. **import语句**:更新所有import语句以匹配新的包结构
|
||||
4. **配置文件**:确保application.yml中的配置正确
|
||||
5. **组件扫描**:确保ManageApplication.java中的@ComponentScan配置正确
|
||||
6. **测试覆盖**:重构后确保所有测试仍然通过
|
||||
@@ -0,0 +1,23 @@
|
||||
management:
|
||||
endpoints:
|
||||
web:
|
||||
exposure:
|
||||
include: health,info,metrics,prometheus
|
||||
metrics:
|
||||
export:
|
||||
prometheus:
|
||||
enabled: true
|
||||
tags:
|
||||
application: ${spring.application.name}
|
||||
environment: ${spring.profiles.active:default}
|
||||
distribution:
|
||||
percentiles-histogram:
|
||||
http.server.requests: true
|
||||
percentiles:
|
||||
http.server.requests: 0.5,0.95,0.99
|
||||
sla:
|
||||
http.server.requests: 100ms,200ms,500ms,1s,2s
|
||||
enable:
|
||||
jvm: true
|
||||
process: true
|
||||
system: true
|
||||
@@ -21,6 +21,10 @@
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-webflux</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-r2dbc</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-validation</artifactId>
|
||||
@@ -37,6 +41,10 @@
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-collections4</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.jsonwebtoken</groupId>
|
||||
<artifactId>jjwt-api</artifactId>
|
||||
@@ -51,6 +59,18 @@
|
||||
<artifactId>jjwt-jackson</artifactId>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.micrometer</groupId>
|
||||
<artifactId>micrometer-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-actuator</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-aop</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
|
||||
+6
@@ -9,6 +9,12 @@ import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* 缓存配置类
|
||||
*
|
||||
* @author 张翔
|
||||
* @date 2026-03-13
|
||||
*/
|
||||
@Configuration
|
||||
@EnableCaching
|
||||
public class CacheConfig {
|
||||
|
||||
+6
@@ -4,6 +4,12 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
/**
|
||||
* JWT配置属性类
|
||||
*
|
||||
* @author 张翔
|
||||
* @date 2026-03-13
|
||||
*/
|
||||
@Component
|
||||
@ConfigurationProperties(prefix = "jwt")
|
||||
@Validated
|
||||
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
package cn.novalon.manage.common.dao;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* 查询字段注解
|
||||
*
|
||||
* @author 张翔
|
||||
* @date 2026-03-13
|
||||
*/
|
||||
@Target(ElementType.FIELD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface QueryField {
|
||||
|
||||
String propName() default "";
|
||||
|
||||
String blurry() default "";
|
||||
|
||||
Type type() default Type.EQUAL;
|
||||
|
||||
Type orPropVal() default Type.EQUAL;
|
||||
|
||||
String[] orPropNames() default {};
|
||||
|
||||
enum Type {
|
||||
EQUAL,
|
||||
GREATER_THAN,
|
||||
LESS_THAN,
|
||||
LESS_THAN_NQ,
|
||||
INNER_LIKE,
|
||||
LEFT_LIKE,
|
||||
NOT_LEFT_LIKE,
|
||||
RIGHT_LIKE,
|
||||
IN,
|
||||
OR,
|
||||
IS_NULL,
|
||||
IS_NOT_NULL
|
||||
}
|
||||
}
|
||||
+149
@@ -0,0 +1,149 @@
|
||||
package cn.novalon.manage.common.dao;
|
||||
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.data.relational.core.query.Criteria;
|
||||
import org.springframework.data.relational.core.query.Query;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 查询工具类
|
||||
*
|
||||
* @author 张翔
|
||||
* @date 2026-03-13
|
||||
*/
|
||||
public class QueryUtil {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(QueryUtil.class);
|
||||
|
||||
public static <Q> Query getQuery(Q query) {
|
||||
return getQuery(query, true);
|
||||
}
|
||||
|
||||
public static <Q> Query getQueryAll(Q query) {
|
||||
return getQuery(query, false);
|
||||
}
|
||||
|
||||
public static <Q> Query getQuery(Q query, Boolean enabled) {
|
||||
Criteria criteria = Criteria.empty();
|
||||
if (enabled) {
|
||||
criteria = criteria.and("deletedAt").isNull();
|
||||
}
|
||||
if (query == null) {
|
||||
return Query.query(criteria);
|
||||
}
|
||||
try {
|
||||
List<Field> fields = getAllFields(query.getClass(), new ArrayList<>());
|
||||
for (Field field : fields) {
|
||||
boolean accessible = Modifier.isStatic(field.getModifiers()) ? field.canAccess(null)
|
||||
: field.canAccess(query);
|
||||
field.setAccessible(true);
|
||||
QueryField q = field.getAnnotation(QueryField.class);
|
||||
if (q != null) {
|
||||
String propName = q.propName();
|
||||
String blurry = q.blurry();
|
||||
String attributeName = isBlank(propName) ? field.getName() : propName;
|
||||
Object val = field.get(query);
|
||||
if (val == null || "".equals(val)) {
|
||||
continue;
|
||||
}
|
||||
if (StringUtils.isNotBlank(blurry)) {
|
||||
String[] blurrys = blurry.split(",");
|
||||
Criteria orCriteria = Criteria.empty();
|
||||
for (String s : blurrys) {
|
||||
orCriteria = orCriteria.or(s).like("%" + val + "%");
|
||||
}
|
||||
criteria = criteria.and(orCriteria);
|
||||
continue;
|
||||
}
|
||||
switch (q.type()) {
|
||||
case EQUAL:
|
||||
criteria = criteria.and(attributeName).is(val);
|
||||
break;
|
||||
case GREATER_THAN:
|
||||
criteria = criteria.and(attributeName).greaterThanOrEquals(val);
|
||||
break;
|
||||
case LESS_THAN:
|
||||
criteria = criteria.and(attributeName).lessThanOrEquals(val);
|
||||
break;
|
||||
case LESS_THAN_NQ:
|
||||
criteria = criteria.and(attributeName).lessThan(val);
|
||||
break;
|
||||
case INNER_LIKE:
|
||||
criteria = criteria.and(attributeName).like("%" + val + "%");
|
||||
break;
|
||||
case LEFT_LIKE:
|
||||
criteria = criteria.and(attributeName).like("%" + val);
|
||||
break;
|
||||
case NOT_LEFT_LIKE:
|
||||
criteria = criteria.and(attributeName).notLike("%" + val);
|
||||
break;
|
||||
case RIGHT_LIKE:
|
||||
criteria = criteria.and(attributeName).like(val + "%");
|
||||
break;
|
||||
case IN:
|
||||
if (val instanceof Collection && CollectionUtils.isNotEmpty((Collection<?>) val)) {
|
||||
criteria = criteria.and(attributeName).in((Collection<?>) val);
|
||||
}
|
||||
break;
|
||||
case OR:
|
||||
QueryField.Type orValue = q.orPropVal();
|
||||
String[] orPropNames = q.orPropNames();
|
||||
Criteria orPredicate = Criteria.empty();
|
||||
if (QueryField.Type.IS_NULL.equals(orValue)) {
|
||||
for (String prop : orPropNames) {
|
||||
orPredicate = orPredicate.or(prop).isNull();
|
||||
}
|
||||
}
|
||||
if (QueryField.Type.IS_NOT_NULL.equals(orValue)) {
|
||||
for (String prop : orPropNames) {
|
||||
orPredicate = orPredicate.or(prop).isNotNull();
|
||||
}
|
||||
}
|
||||
criteria = criteria.and(orPredicate);
|
||||
break;
|
||||
case IS_NULL:
|
||||
criteria = criteria.and(attributeName).isNull();
|
||||
break;
|
||||
case IS_NOT_NULL:
|
||||
criteria = criteria.and(attributeName).isNotNull();
|
||||
break;
|
||||
}
|
||||
}
|
||||
field.setAccessible(accessible);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error(e.getMessage(), e);
|
||||
}
|
||||
return Query.query(criteria);
|
||||
}
|
||||
|
||||
public static boolean isBlank(final CharSequence cs) {
|
||||
int strLen;
|
||||
if (cs == null || (strLen = cs.length()) == 0) {
|
||||
return true;
|
||||
}
|
||||
for (int i = 0; i < strLen; i++) {
|
||||
if (!Character.isWhitespace(cs.charAt(i))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static List<Field> getAllFields(Class<?> clazz, List<Field> fields) {
|
||||
if (clazz != null) {
|
||||
fields.addAll(Arrays.asList(clazz.getDeclaredFields()));
|
||||
getAllFields(clazz.getSuperclass(), fields);
|
||||
}
|
||||
return fields;
|
||||
}
|
||||
}
|
||||
-67
@@ -1,67 +0,0 @@
|
||||
package cn.novalon.manage.common.domain;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* @author zhangxiang
|
||||
* @version 1.0
|
||||
* @description 基础领域对象
|
||||
* @date 2026/03/11
|
||||
**/
|
||||
public abstract class BaseDomain {
|
||||
|
||||
protected Long id;
|
||||
protected String createBy;
|
||||
protected String updateBy;
|
||||
protected LocalDateTime createdAt;
|
||||
protected LocalDateTime updatedAt;
|
||||
protected LocalDateTime deletedAt;
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getCreateBy() {
|
||||
return createBy;
|
||||
}
|
||||
|
||||
public void setCreateBy(String createBy) {
|
||||
this.createBy = createBy;
|
||||
}
|
||||
|
||||
public String getUpdateBy() {
|
||||
return updateBy;
|
||||
}
|
||||
|
||||
public void setUpdateBy(String updateBy) {
|
||||
this.updateBy = updateBy;
|
||||
}
|
||||
|
||||
public LocalDateTime getCreatedAt() {
|
||||
return createdAt;
|
||||
}
|
||||
|
||||
public void setCreatedAt(LocalDateTime createdAt) {
|
||||
this.createdAt = createdAt;
|
||||
}
|
||||
|
||||
public LocalDateTime getUpdatedAt() {
|
||||
return updatedAt;
|
||||
}
|
||||
|
||||
public void setUpdatedAt(LocalDateTime updatedAt) {
|
||||
this.updatedAt = updatedAt;
|
||||
}
|
||||
|
||||
public LocalDateTime getDeletedAt() {
|
||||
return deletedAt;
|
||||
}
|
||||
|
||||
public void setDeletedAt(LocalDateTime deletedAt) {
|
||||
this.deletedAt = deletedAt;
|
||||
}
|
||||
}
|
||||
-117
@@ -1,117 +0,0 @@
|
||||
package cn.novalon.manage.common.domain;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
public class Dictionary {
|
||||
private Long id;
|
||||
private String type;
|
||||
private String code;
|
||||
private String name;
|
||||
private String value;
|
||||
private String remark;
|
||||
private Integer sort;
|
||||
private String createBy;
|
||||
private String updateBy;
|
||||
private LocalDateTime createdAt;
|
||||
private LocalDateTime updatedAt;
|
||||
private LocalDateTime deletedAt;
|
||||
|
||||
public Dictionary() {
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public void setCode(String code) {
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setValue(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public String getRemark() {
|
||||
return remark;
|
||||
}
|
||||
|
||||
public void setRemark(String remark) {
|
||||
this.remark = remark;
|
||||
}
|
||||
|
||||
public Integer getSort() {
|
||||
return sort;
|
||||
}
|
||||
|
||||
public void setSort(Integer sort) {
|
||||
this.sort = sort;
|
||||
}
|
||||
|
||||
public String getCreateBy() {
|
||||
return createBy;
|
||||
}
|
||||
|
||||
public void setCreateBy(String createBy) {
|
||||
this.createBy = createBy;
|
||||
}
|
||||
|
||||
public String getUpdateBy() {
|
||||
return updateBy;
|
||||
}
|
||||
|
||||
public void setUpdateBy(String updateBy) {
|
||||
this.updateBy = updateBy;
|
||||
}
|
||||
|
||||
public LocalDateTime getCreatedAt() {
|
||||
return createdAt;
|
||||
}
|
||||
|
||||
public void setCreatedAt(LocalDateTime createdAt) {
|
||||
this.createdAt = createdAt;
|
||||
}
|
||||
|
||||
public LocalDateTime getUpdatedAt() {
|
||||
return updatedAt;
|
||||
}
|
||||
|
||||
public void setUpdatedAt(LocalDateTime updatedAt) {
|
||||
this.updatedAt = updatedAt;
|
||||
}
|
||||
|
||||
public LocalDateTime getDeletedAt() {
|
||||
return deletedAt;
|
||||
}
|
||||
|
||||
public void setDeletedAt(LocalDateTime deletedAt) {
|
||||
this.deletedAt = deletedAt;
|
||||
}
|
||||
}
|
||||
-86
@@ -1,86 +0,0 @@
|
||||
package cn.novalon.manage.common.domain;
|
||||
|
||||
public class OperationLog extends BaseDomain {
|
||||
|
||||
private String username;
|
||||
private String operation;
|
||||
private String method;
|
||||
private String params;
|
||||
private String result;
|
||||
private String ip;
|
||||
private Long duration;
|
||||
private String status;
|
||||
private String errorMsg;
|
||||
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
public void setUsername(String username) {
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
public String getOperation() {
|
||||
return operation;
|
||||
}
|
||||
|
||||
public void setOperation(String operation) {
|
||||
this.operation = operation;
|
||||
}
|
||||
|
||||
public String getMethod() {
|
||||
return method;
|
||||
}
|
||||
|
||||
public void setMethod(String method) {
|
||||
this.method = method;
|
||||
}
|
||||
|
||||
public String getParams() {
|
||||
return params;
|
||||
}
|
||||
|
||||
public void setParams(String params) {
|
||||
this.params = params;
|
||||
}
|
||||
|
||||
public String getResult() {
|
||||
return result;
|
||||
}
|
||||
|
||||
public void setResult(String result) {
|
||||
this.result = result;
|
||||
}
|
||||
|
||||
public String getIp() {
|
||||
return ip;
|
||||
}
|
||||
|
||||
public void setIp(String ip) {
|
||||
this.ip = ip;
|
||||
}
|
||||
|
||||
public Long getDuration() {
|
||||
return duration;
|
||||
}
|
||||
|
||||
public void setDuration(Long duration) {
|
||||
this.duration = duration;
|
||||
}
|
||||
|
||||
public String getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public void setStatus(String status) {
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
public String getErrorMsg() {
|
||||
return errorMsg;
|
||||
}
|
||||
|
||||
public void setErrorMsg(String errorMsg) {
|
||||
this.errorMsg = errorMsg;
|
||||
}
|
||||
}
|
||||
-38
@@ -1,38 +0,0 @@
|
||||
package cn.novalon.manage.common.domain;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
public class SysConfig {
|
||||
|
||||
private Long id;
|
||||
private String configName;
|
||||
private String configKey;
|
||||
private String configValue;
|
||||
private String configType;
|
||||
private String createBy;
|
||||
private String updateBy;
|
||||
private LocalDateTime createdAt;
|
||||
private LocalDateTime updatedAt;
|
||||
private LocalDateTime deletedAt;
|
||||
|
||||
public Long getId() { return id; }
|
||||
public void setId(Long id) { this.id = id; }
|
||||
public String getConfigName() { return configName; }
|
||||
public void setConfigName(String configName) { this.configName = configName; }
|
||||
public String getConfigKey() { return configKey; }
|
||||
public void setConfigKey(String configKey) { this.configKey = configKey; }
|
||||
public String getConfigValue() { return configValue; }
|
||||
public void setConfigValue(String configValue) { this.configValue = configValue; }
|
||||
public String getConfigType() { return configType; }
|
||||
public void setConfigType(String configType) { this.configType = configType; }
|
||||
public String getCreateBy() { return createBy; }
|
||||
public void setCreateBy(String createBy) { this.createBy = createBy; }
|
||||
public String getUpdateBy() { return updateBy; }
|
||||
public void setUpdateBy(String updateBy) { this.updateBy = updateBy; }
|
||||
public LocalDateTime getCreatedAt() { return createdAt; }
|
||||
public void setCreatedAt(LocalDateTime createdAt) { this.createdAt = createdAt; }
|
||||
public LocalDateTime getUpdatedAt() { return updatedAt; }
|
||||
public void setUpdatedAt(LocalDateTime updatedAt) { this.updatedAt = updatedAt; }
|
||||
public LocalDateTime getDeletedAt() { return deletedAt; }
|
||||
public void setDeletedAt(LocalDateTime deletedAt) { this.deletedAt = deletedAt; }
|
||||
}
|
||||
-53
@@ -1,53 +0,0 @@
|
||||
package cn.novalon.manage.common.domain;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
public class SysDictData {
|
||||
|
||||
private Long id;
|
||||
private Long dictTypeId;
|
||||
private String dictLabel;
|
||||
private String dictValue;
|
||||
private Integer dictSort;
|
||||
private String dictType;
|
||||
private String cssClass;
|
||||
private String listClass;
|
||||
private String isDefault;
|
||||
private String status;
|
||||
private String createBy;
|
||||
private String updateBy;
|
||||
private LocalDateTime createdAt;
|
||||
private LocalDateTime updatedAt;
|
||||
private LocalDateTime deletedAt;
|
||||
|
||||
public Long getId() { return id; }
|
||||
public void setId(Long id) { this.id = id; }
|
||||
public Long getDictTypeId() { return dictTypeId; }
|
||||
public void setDictTypeId(Long dictTypeId) { this.dictTypeId = dictTypeId; }
|
||||
public String getDictLabel() { return dictLabel; }
|
||||
public void setDictLabel(String dictLabel) { this.dictLabel = dictLabel; }
|
||||
public String getDictValue() { return dictValue; }
|
||||
public void setDictValue(String dictValue) { this.dictValue = dictValue; }
|
||||
public Integer getDictSort() { return dictSort; }
|
||||
public void setDictSort(Integer dictSort) { this.dictSort = dictSort; }
|
||||
public String getDictType() { return dictType; }
|
||||
public void setDictType(String dictType) { this.dictType = dictType; }
|
||||
public String getCssClass() { return cssClass; }
|
||||
public void setCssClass(String cssClass) { this.cssClass = cssClass; }
|
||||
public String getListClass() { return listClass; }
|
||||
public void setListClass(String listClass) { this.listClass = listClass; }
|
||||
public String getIsDefault() { return isDefault; }
|
||||
public void setIsDefault(String isDefault) { this.isDefault = isDefault; }
|
||||
public String getStatus() { return status; }
|
||||
public void setStatus(String status) { this.status = status; }
|
||||
public String getCreateBy() { return createBy; }
|
||||
public void setCreateBy(String createBy) { this.createBy = createBy; }
|
||||
public String getUpdateBy() { return updateBy; }
|
||||
public void setUpdateBy(String updateBy) { this.updateBy = updateBy; }
|
||||
public LocalDateTime getCreatedAt() { return createdAt; }
|
||||
public void setCreatedAt(LocalDateTime createdAt) { this.createdAt = createdAt; }
|
||||
public LocalDateTime getUpdatedAt() { return updatedAt; }
|
||||
public void setUpdatedAt(LocalDateTime updatedAt) { this.updatedAt = updatedAt; }
|
||||
public LocalDateTime getDeletedAt() { return deletedAt; }
|
||||
public void setDeletedAt(LocalDateTime deletedAt) { this.deletedAt = deletedAt; }
|
||||
}
|
||||
-38
@@ -1,38 +0,0 @@
|
||||
package cn.novalon.manage.common.domain;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
public class SysDictType {
|
||||
|
||||
private Long id;
|
||||
private String dictName;
|
||||
private String dictType;
|
||||
private String status;
|
||||
private String remark;
|
||||
private String createBy;
|
||||
private String updateBy;
|
||||
private LocalDateTime createdAt;
|
||||
private LocalDateTime updatedAt;
|
||||
private LocalDateTime deletedAt;
|
||||
|
||||
public Long getId() { return id; }
|
||||
public void setId(Long id) { this.id = id; }
|
||||
public String getDictName() { return dictName; }
|
||||
public void setDictName(String dictName) { this.dictName = dictName; }
|
||||
public String getDictType() { return dictType; }
|
||||
public void setDictType(String dictType) { this.dictType = dictType; }
|
||||
public String getStatus() { return status; }
|
||||
public void setStatus(String status) { this.status = status; }
|
||||
public String getRemark() { return remark; }
|
||||
public void setRemark(String remark) { this.remark = remark; }
|
||||
public String getCreateBy() { return createBy; }
|
||||
public void setCreateBy(String createBy) { this.createBy = createBy; }
|
||||
public String getUpdateBy() { return updateBy; }
|
||||
public void setUpdateBy(String updateBy) { this.updateBy = updateBy; }
|
||||
public LocalDateTime getCreatedAt() { return createdAt; }
|
||||
public void setCreatedAt(LocalDateTime createdAt) { this.createdAt = createdAt; }
|
||||
public LocalDateTime getUpdatedAt() { return updatedAt; }
|
||||
public void setUpdatedAt(LocalDateTime updatedAt) { this.updatedAt = updatedAt; }
|
||||
public LocalDateTime getDeletedAt() { return deletedAt; }
|
||||
public void setDeletedAt(LocalDateTime deletedAt) { this.deletedAt = deletedAt; }
|
||||
}
|
||||
-38
@@ -1,38 +0,0 @@
|
||||
package cn.novalon.manage.common.domain;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
public class SysExceptionLog {
|
||||
|
||||
private Long id;
|
||||
private String username;
|
||||
private String title;
|
||||
private String exceptionName;
|
||||
private String methodName;
|
||||
private String methodParams;
|
||||
private String exceptionMsg;
|
||||
private String exceptionStack;
|
||||
private String ip;
|
||||
private LocalDateTime createTime;
|
||||
|
||||
public Long getId() { return id; }
|
||||
public void setId(Long id) { this.id = id; }
|
||||
public String getUsername() { return username; }
|
||||
public void setUsername(String username) { this.username = username; }
|
||||
public String getTitle() { return title; }
|
||||
public void setTitle(String title) { this.title = title; }
|
||||
public String getExceptionName() { return exceptionName; }
|
||||
public void setExceptionName(String exceptionName) { this.exceptionName = exceptionName; }
|
||||
public String getMethodName() { return methodName; }
|
||||
public void setMethodName(String methodName) { this.methodName = methodName; }
|
||||
public String getMethodParams() { return methodParams; }
|
||||
public void setMethodParams(String methodParams) { this.methodParams = methodParams; }
|
||||
public String getExceptionMsg() { return exceptionMsg; }
|
||||
public void setExceptionMsg(String exceptionMsg) { this.exceptionMsg = exceptionMsg; }
|
||||
public String getExceptionStack() { return exceptionStack; }
|
||||
public void setExceptionStack(String exceptionStack) { this.exceptionStack = exceptionStack; }
|
||||
public String getIp() { return ip; }
|
||||
public void setIp(String ip) { this.ip = ip; }
|
||||
public LocalDateTime getCreateTime() { return createTime; }
|
||||
public void setCreateTime(LocalDateTime createTime) { this.createTime = createTime; }
|
||||
}
|
||||
-38
@@ -1,38 +0,0 @@
|
||||
package cn.novalon.manage.common.domain;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
public class SysFile {
|
||||
|
||||
private Long id;
|
||||
private String fileName;
|
||||
private String filePath;
|
||||
private String fileSize;
|
||||
private String fileType;
|
||||
private String storageType;
|
||||
private String createBy;
|
||||
private String updateBy;
|
||||
private LocalDateTime createdAt;
|
||||
private LocalDateTime deletedAt;
|
||||
|
||||
public Long getId() { return id; }
|
||||
public void setId(Long id) { this.id = id; }
|
||||
public String getFileName() { return fileName; }
|
||||
public void setFileName(String fileName) { this.fileName = fileName; }
|
||||
public String getFilePath() { return filePath; }
|
||||
public void setFilePath(String filePath) { this.filePath = filePath; }
|
||||
public String getFileSize() { return fileSize; }
|
||||
public void setFileSize(String fileSize) { this.fileSize = fileSize; }
|
||||
public String getFileType() { return fileType; }
|
||||
public void setFileType(String fileType) { this.fileType = fileType; }
|
||||
public String getStorageType() { return storageType; }
|
||||
public void setStorageType(String storageType) { this.storageType = storageType; }
|
||||
public String getCreateBy() { return createBy; }
|
||||
public void setCreateBy(String createBy) { this.createBy = createBy; }
|
||||
public String getUpdateBy() { return updateBy; }
|
||||
public void setUpdateBy(String updateBy) { this.updateBy = updateBy; }
|
||||
public LocalDateTime getCreatedAt() { return createdAt; }
|
||||
public void setCreatedAt(LocalDateTime createdAt) { this.createdAt = createdAt; }
|
||||
public LocalDateTime getDeletedAt() { return deletedAt; }
|
||||
public void setDeletedAt(LocalDateTime deletedAt) { this.deletedAt = deletedAt; }
|
||||
}
|
||||
-35
@@ -1,35 +0,0 @@
|
||||
package cn.novalon.manage.common.domain;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
public class SysLoginLog {
|
||||
|
||||
private Long id;
|
||||
private String username;
|
||||
private String ip;
|
||||
private String location;
|
||||
private String browser;
|
||||
private String os;
|
||||
private String status;
|
||||
private String message;
|
||||
private LocalDateTime loginTime;
|
||||
|
||||
public Long getId() { return id; }
|
||||
public void setId(Long id) { this.id = id; }
|
||||
public String getUsername() { return username; }
|
||||
public void setUsername(String username) { this.username = username; }
|
||||
public String getIp() { return ip; }
|
||||
public void setIp(String ip) { this.ip = ip; }
|
||||
public String getLocation() { return location; }
|
||||
public void setLocation(String location) { this.location = location; }
|
||||
public String getBrowser() { return browser; }
|
||||
public void setBrowser(String browser) { this.browser = browser; }
|
||||
public String getOs() { return os; }
|
||||
public void setOs(String os) { this.os = os; }
|
||||
public String getStatus() { return status; }
|
||||
public void setStatus(String status) { this.status = status; }
|
||||
public String getMessage() { return message; }
|
||||
public void setMessage(String message) { this.message = message; }
|
||||
public LocalDateTime getLoginTime() { return loginTime; }
|
||||
public void setLoginTime(LocalDateTime loginTime) { this.loginTime = loginTime; }
|
||||
}
|
||||
-97
@@ -1,97 +0,0 @@
|
||||
package cn.novalon.manage.common.domain;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class SysMenu extends BaseDomain {
|
||||
|
||||
private String menuName;
|
||||
private Long parentId;
|
||||
private Integer orderNum;
|
||||
private String menuType;
|
||||
private String perms;
|
||||
private String component;
|
||||
private String status;
|
||||
private String createBy;
|
||||
private String updateBy;
|
||||
private List<SysMenu> children;
|
||||
|
||||
public String getMenuName() {
|
||||
return menuName;
|
||||
}
|
||||
|
||||
public void setMenuName(String menuName) {
|
||||
this.menuName = menuName;
|
||||
}
|
||||
|
||||
public Long getParentId() {
|
||||
return parentId;
|
||||
}
|
||||
|
||||
public void setParentId(Long parentId) {
|
||||
this.parentId = parentId;
|
||||
}
|
||||
|
||||
public Integer getOrderNum() {
|
||||
return orderNum;
|
||||
}
|
||||
|
||||
public void setOrderNum(Integer orderNum) {
|
||||
this.orderNum = orderNum;
|
||||
}
|
||||
|
||||
public String getMenuType() {
|
||||
return menuType;
|
||||
}
|
||||
|
||||
public void setMenuType(String menuType) {
|
||||
this.menuType = menuType;
|
||||
}
|
||||
|
||||
public String getPerms() {
|
||||
return perms;
|
||||
}
|
||||
|
||||
public void setPerms(String perms) {
|
||||
this.perms = perms;
|
||||
}
|
||||
|
||||
public String getComponent() {
|
||||
return component;
|
||||
}
|
||||
|
||||
public void setComponent(String component) {
|
||||
this.component = component;
|
||||
}
|
||||
|
||||
public String getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public void setStatus(String status) {
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
public String getCreateBy() {
|
||||
return createBy;
|
||||
}
|
||||
|
||||
public void setCreateBy(String createBy) {
|
||||
this.createBy = createBy;
|
||||
}
|
||||
|
||||
public String getUpdateBy() {
|
||||
return updateBy;
|
||||
}
|
||||
|
||||
public void setUpdateBy(String updateBy) {
|
||||
this.updateBy = updateBy;
|
||||
}
|
||||
|
||||
public List<SysMenu> getChildren() {
|
||||
return children;
|
||||
}
|
||||
|
||||
public void setChildren(List<SysMenu> children) {
|
||||
this.children = children;
|
||||
}
|
||||
}
|
||||
-38
@@ -1,38 +0,0 @@
|
||||
package cn.novalon.manage.common.domain;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
public class SysNotice {
|
||||
|
||||
private Long id;
|
||||
private String noticeTitle;
|
||||
private String noticeType;
|
||||
private String noticeContent;
|
||||
private String status;
|
||||
private String createBy;
|
||||
private String updateBy;
|
||||
private LocalDateTime createdAt;
|
||||
private LocalDateTime updatedAt;
|
||||
private LocalDateTime deletedAt;
|
||||
|
||||
public Long getId() { return id; }
|
||||
public void setId(Long id) { this.id = id; }
|
||||
public String getNoticeTitle() { return noticeTitle; }
|
||||
public void setNoticeTitle(String noticeTitle) { this.noticeTitle = noticeTitle; }
|
||||
public String getNoticeType() { return noticeType; }
|
||||
public void setNoticeType(String noticeType) { this.noticeType = noticeType; }
|
||||
public String getNoticeContent() { return noticeContent; }
|
||||
public void setNoticeContent(String noticeContent) { this.noticeContent = noticeContent; }
|
||||
public String getStatus() { return status; }
|
||||
public void setStatus(String status) { this.status = status; }
|
||||
public String getCreateBy() { return createBy; }
|
||||
public void setCreateBy(String createBy) { this.createBy = createBy; }
|
||||
public String getUpdateBy() { return updateBy; }
|
||||
public void setUpdateBy(String updateBy) { this.updateBy = updateBy; }
|
||||
public LocalDateTime getCreatedAt() { return createdAt; }
|
||||
public void setCreatedAt(LocalDateTime createdAt) { this.createdAt = createdAt; }
|
||||
public LocalDateTime getUpdatedAt() { return updatedAt; }
|
||||
public void setUpdatedAt(LocalDateTime updatedAt) { this.updatedAt = updatedAt; }
|
||||
public LocalDateTime getDeletedAt() { return deletedAt; }
|
||||
public void setDeletedAt(LocalDateTime deletedAt) { this.deletedAt = deletedAt; }
|
||||
}
|
||||
-75
@@ -1,75 +0,0 @@
|
||||
package cn.novalon.manage.common.domain;
|
||||
|
||||
import cn.novalon.manage.common.util.SnowflakeId;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* @author zhangxiang
|
||||
* @version 1.0
|
||||
* @description 角色领域对象
|
||||
* @date 2026/03/11
|
||||
**/
|
||||
public class SysRole extends BaseDomain {
|
||||
|
||||
private String roleName;
|
||||
private String roleKey;
|
||||
private Integer roleSort;
|
||||
private Integer status;
|
||||
|
||||
public String getRoleName() {
|
||||
return roleName;
|
||||
}
|
||||
|
||||
public void setRoleName(String roleName) {
|
||||
this.roleName = roleName;
|
||||
}
|
||||
|
||||
public String getRoleKey() {
|
||||
return roleKey;
|
||||
}
|
||||
|
||||
public void setRoleKey(String roleKey) {
|
||||
this.roleKey = roleKey;
|
||||
}
|
||||
|
||||
public Integer getRoleSort() {
|
||||
return roleSort;
|
||||
}
|
||||
|
||||
public void setRoleSort(Integer roleSort) {
|
||||
this.roleSort = roleSort;
|
||||
}
|
||||
|
||||
public Integer getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public void setStatus(Integer status) {
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成主键ID
|
||||
*
|
||||
* @return 主键ID
|
||||
*/
|
||||
public Long generateId() {
|
||||
this.id = SnowflakeId.nextId();
|
||||
return this.id;
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除角色
|
||||
*/
|
||||
public void delete() {
|
||||
this.deletedAt = LocalDateTime.now();
|
||||
}
|
||||
|
||||
/**
|
||||
* 恢复角色
|
||||
*/
|
||||
public void restore() {
|
||||
this.deletedAt = null;
|
||||
}
|
||||
}
|
||||
-77
@@ -1,77 +0,0 @@
|
||||
package cn.novalon.manage.common.domain;
|
||||
|
||||
import cn.novalon.manage.common.util.SnowflakeId;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* @author zhangxiang
|
||||
* @version 1.0
|
||||
* @description 用户领域对象
|
||||
* @date 2026/03/11
|
||||
**/
|
||||
public class SysUser extends BaseDomain {
|
||||
|
||||
private String username;
|
||||
private String password;
|
||||
private String email;
|
||||
private Long roleId;
|
||||
private Integer status;
|
||||
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
public void setUsername(String username) {
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
public void setPassword(String password) {
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
public String getEmail() {
|
||||
return email;
|
||||
}
|
||||
|
||||
public void setEmail(String email) {
|
||||
this.email = email;
|
||||
}
|
||||
|
||||
public Long getRoleId() {
|
||||
return roleId;
|
||||
}
|
||||
|
||||
public void setRoleId(Long roleId) {
|
||||
this.roleId = roleId;
|
||||
}
|
||||
|
||||
public Integer getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public void setStatus(Integer status) {
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成主键ID
|
||||
*
|
||||
* @return 主键ID
|
||||
*/
|
||||
public Long generateId() {
|
||||
this.id = SnowflakeId.nextId();
|
||||
return this.id;
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除用户
|
||||
*/
|
||||
public void delete() {
|
||||
this.deletedAt = LocalDateTime.now();
|
||||
}
|
||||
}
|
||||
-29
@@ -1,29 +0,0 @@
|
||||
package cn.novalon.manage.common.domain;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
public class SysUserMessage {
|
||||
|
||||
private Long id;
|
||||
private Long userId;
|
||||
private String title;
|
||||
private String content;
|
||||
private String messageType;
|
||||
private String isRead;
|
||||
private LocalDateTime createTime;
|
||||
|
||||
public Long getId() { return id; }
|
||||
public void setId(Long id) { this.id = id; }
|
||||
public Long getUserId() { return userId; }
|
||||
public void setUserId(Long userId) { this.userId = userId; }
|
||||
public String getTitle() { return title; }
|
||||
public void setTitle(String title) { this.title = title; }
|
||||
public String getContent() { return content; }
|
||||
public void setContent(String content) { this.content = content; }
|
||||
public String getMessageType() { return messageType; }
|
||||
public void setMessageType(String messageType) { this.messageType = messageType; }
|
||||
public String getIsRead() { return isRead; }
|
||||
public void setIsRead(String isRead) { this.isRead = isRead; }
|
||||
public LocalDateTime getCreateTime() { return createTime; }
|
||||
public void setCreateTime(LocalDateTime createTime) { this.createTime = createTime; }
|
||||
}
|
||||
+5
-5
@@ -1,11 +1,11 @@
|
||||
package cn.novalon.manage.common.domain.query;
|
||||
|
||||
/**
|
||||
* @author zhangxiang
|
||||
* @version 1.0
|
||||
* @description 菜单查询对象
|
||||
* @date 2026/03/11
|
||||
**/
|
||||
* 菜单查询条件对象
|
||||
*
|
||||
* @author 张翔
|
||||
* @date 2026-03-13
|
||||
*/
|
||||
public class SysMenuQuery {
|
||||
|
||||
private String menuName;
|
||||
|
||||
+5
-5
@@ -1,11 +1,11 @@
|
||||
package cn.novalon.manage.common.domain.query;
|
||||
|
||||
/**
|
||||
* @author zhangxiang
|
||||
* @version 1.0
|
||||
* @description 角色查询对象
|
||||
* @date 2026/03/11
|
||||
**/
|
||||
* 角色查询条件对象
|
||||
*
|
||||
* @author 张翔
|
||||
* @date 2026-03-13
|
||||
*/
|
||||
public class SysRoleQuery {
|
||||
|
||||
private String roleName;
|
||||
|
||||
+14
-5
@@ -1,17 +1,18 @@
|
||||
package cn.novalon.manage.common.domain.query;
|
||||
|
||||
/**
|
||||
* @author zhangxiang
|
||||
* @version 1.0
|
||||
* @description 用户查询对象
|
||||
* @date 2026/03/11
|
||||
**/
|
||||
* 用户查询条件对象
|
||||
*
|
||||
* @author 张翔
|
||||
* @date 2026-03-13
|
||||
*/
|
||||
public class SysUserQuery {
|
||||
|
||||
private String username;
|
||||
private String email;
|
||||
private Integer status;
|
||||
private Long roleId;
|
||||
private String keyword;
|
||||
|
||||
public String getUsername() {
|
||||
return username;
|
||||
@@ -44,4 +45,12 @@ public class SysUserQuery {
|
||||
public void setRoleId(Long roleId) {
|
||||
this.roleId = roleId;
|
||||
}
|
||||
|
||||
public String getKeyword() {
|
||||
return keyword;
|
||||
}
|
||||
|
||||
public void setKeyword(String keyword) {
|
||||
this.keyword = keyword;
|
||||
}
|
||||
}
|
||||
|
||||
+6
@@ -1,5 +1,11 @@
|
||||
package cn.novalon.manage.common.dto;
|
||||
|
||||
/**
|
||||
* 分页请求参数封装类
|
||||
*
|
||||
* @author 张翔
|
||||
* @date 2026-03-13
|
||||
*/
|
||||
public class PageRequest {
|
||||
private int page = 0;
|
||||
private int size = 10;
|
||||
|
||||
+6
@@ -2,6 +2,12 @@ package cn.novalon.manage.common.dto;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 分页响应结果封装类
|
||||
*
|
||||
* @author 张翔
|
||||
* @date 2026-03-13
|
||||
*/
|
||||
public class PageResponse<T> {
|
||||
private List<T> content;
|
||||
private int totalPages;
|
||||
|
||||
+6
@@ -1,5 +1,11 @@
|
||||
package cn.novalon.manage.common.exception;
|
||||
|
||||
/**
|
||||
* 业务异常类
|
||||
*
|
||||
* @author 张翔
|
||||
* @date 2026-03-13
|
||||
*/
|
||||
public class BusinessException extends RuntimeException {
|
||||
|
||||
private final String code;
|
||||
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
package cn.novalon.manage.common.handler;
|
||||
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
/**
|
||||
* 异常日志服务接口
|
||||
*
|
||||
* 文件定义:定义异常日志记录的抽象接口
|
||||
* 涉及业务:异常日志记录、错误追踪
|
||||
* 算法:使用响应式编程实现异步日志记录
|
||||
*
|
||||
* @author 张翔
|
||||
* @date 2026-03-13
|
||||
*/
|
||||
public interface ExceptionLogService {
|
||||
Mono<Void> logException(String title, String exceptionName, String exceptionMsg,
|
||||
String methodName, String ip, String stackTrace);
|
||||
}
|
||||
+181
@@ -0,0 +1,181 @@
|
||||
package cn.novalon.manage.common.handler;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.dao.DataIntegrityViolationException;
|
||||
import org.springframework.dao.DuplicateKeyException;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.validation.FieldError;
|
||||
import org.springframework.web.bind.MethodArgumentNotValidException;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
||||
import org.springframework.web.server.ResponseStatusException;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
import org.springframework.web.server.ServerWebInputException;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 全局异常处理器
|
||||
*
|
||||
* 文件定义:统一处理系统中抛出的各种异常,返回标准化的错误响应
|
||||
* 涉及业务:异常捕获、错误日志记录、错误响应格式化
|
||||
* 算法:使用@RestControllerAdvice注解实现全局异常拦截
|
||||
*
|
||||
* @author 张翔
|
||||
* @date 2026-03-13
|
||||
*/
|
||||
@RestControllerAdvice
|
||||
public class GlobalExceptionHandler {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);
|
||||
|
||||
private final ExceptionLogService exceptionLogService;
|
||||
|
||||
public GlobalExceptionHandler(ExceptionLogService exceptionLogService) {
|
||||
this.exceptionLogService = exceptionLogService;
|
||||
}
|
||||
|
||||
@ExceptionHandler(RuntimeException.class)
|
||||
public ResponseEntity<Map<String, Object>> handleRuntimeException(RuntimeException ex, ServerWebExchange exchange) {
|
||||
logger.warn("Runtime exception: ", ex);
|
||||
|
||||
Map<String, Object> response = new HashMap<>();
|
||||
if (ex.getMessage() != null && ex.getMessage().contains("not found")) {
|
||||
response.put("code", HttpStatus.NOT_FOUND.value());
|
||||
response.put("message", ex.getMessage());
|
||||
response.put("timestamp", LocalDateTime.now());
|
||||
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(response);
|
||||
}
|
||||
response.put("code", HttpStatus.BAD_REQUEST.value());
|
||||
response.put("message", ex.getMessage());
|
||||
response.put("timestamp", LocalDateTime.now());
|
||||
|
||||
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(response);
|
||||
}
|
||||
|
||||
@ExceptionHandler(Exception.class)
|
||||
public ResponseEntity<Map<String, Object>> handleException(Exception ex, ServerWebExchange exchange) {
|
||||
logger.error("Exception occurred: ", ex);
|
||||
|
||||
exceptionLogService.logException(
|
||||
"System Exception",
|
||||
ex.getClass().getSimpleName(),
|
||||
ex.getMessage(),
|
||||
exchange.getRequest().getPath().value(),
|
||||
getClientIp(exchange),
|
||||
getStackTrace(ex)
|
||||
).subscribe();
|
||||
|
||||
Map<String, Object> response = new HashMap<>();
|
||||
response.put("code", HttpStatus.INTERNAL_SERVER_ERROR.value());
|
||||
response.put("message", "Internal server error");
|
||||
response.put("timestamp", LocalDateTime.now());
|
||||
|
||||
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(response);
|
||||
}
|
||||
|
||||
@ExceptionHandler(IllegalArgumentException.class)
|
||||
public ResponseEntity<Map<String, Object>> handleIllegalArgumentException(IllegalArgumentException ex, ServerWebExchange exchange) {
|
||||
logger.warn("Illegal argument: ", ex);
|
||||
|
||||
Map<String, Object> response = new HashMap<>();
|
||||
response.put("code", HttpStatus.BAD_REQUEST.value());
|
||||
response.put("message", ex.getMessage());
|
||||
response.put("timestamp", LocalDateTime.now());
|
||||
|
||||
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(response);
|
||||
}
|
||||
|
||||
@ExceptionHandler(MethodArgumentNotValidException.class)
|
||||
public ResponseEntity<Map<String, Object>> handleMethodArgumentNotValidException(MethodArgumentNotValidException ex, ServerWebExchange exchange) {
|
||||
logger.warn("Validation failed: ", ex);
|
||||
|
||||
Map<String, Object> response = new HashMap<>();
|
||||
response.put("code", HttpStatus.BAD_REQUEST.value());
|
||||
response.put("message", "Validation failed");
|
||||
response.put("timestamp", LocalDateTime.now());
|
||||
|
||||
Map<String, String> fieldErrors = ex.getBindingResult()
|
||||
.getFieldErrors()
|
||||
.stream()
|
||||
.collect(Collectors.toMap(FieldError::getField, FieldError::getDefaultMessage, (e1, e2) -> e1));
|
||||
|
||||
response.put("errors", fieldErrors);
|
||||
|
||||
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(response);
|
||||
}
|
||||
|
||||
@ExceptionHandler(ServerWebInputException.class)
|
||||
public ResponseEntity<Map<String, Object>> handleServerWebInputException(ServerWebInputException ex, ServerWebExchange exchange) {
|
||||
logger.warn("Invalid input: ", ex);
|
||||
|
||||
Map<String, Object> response = new HashMap<>();
|
||||
response.put("code", HttpStatus.BAD_REQUEST.value());
|
||||
response.put("message", "Invalid input");
|
||||
response.put("timestamp", LocalDateTime.now());
|
||||
|
||||
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(response);
|
||||
}
|
||||
|
||||
@ExceptionHandler(ResponseStatusException.class)
|
||||
public ResponseEntity<Map<String, Object>> handleResponseStatusException(ResponseStatusException ex, ServerWebExchange exchange) {
|
||||
logger.warn("Response status exception: ", ex);
|
||||
|
||||
Map<String, Object> response = new HashMap<>();
|
||||
response.put("code", ex.getStatusCode().value());
|
||||
response.put("message", ex.getReason());
|
||||
response.put("timestamp", LocalDateTime.now());
|
||||
|
||||
return ResponseEntity.status(ex.getStatusCode()).body(response);
|
||||
}
|
||||
|
||||
@ExceptionHandler(DuplicateKeyException.class)
|
||||
public ResponseEntity<Map<String, Object>> handleDuplicateKeyException(DuplicateKeyException ex, ServerWebExchange exchange) {
|
||||
logger.warn("Duplicate key: ", ex);
|
||||
|
||||
Map<String, Object> response = new HashMap<>();
|
||||
response.put("code", HttpStatus.CONFLICT.value());
|
||||
response.put("message", "Duplicate key violation");
|
||||
response.put("timestamp", LocalDateTime.now());
|
||||
|
||||
return ResponseEntity.status(HttpStatus.CONFLICT).body(response);
|
||||
}
|
||||
|
||||
@ExceptionHandler(DataIntegrityViolationException.class)
|
||||
public ResponseEntity<Map<String, Object>> handleDataIntegrityViolationException(DataIntegrityViolationException ex, ServerWebExchange exchange) {
|
||||
logger.warn("Data integrity violation: ", ex);
|
||||
|
||||
Map<String, Object> response = new HashMap<>();
|
||||
response.put("code", HttpStatus.CONFLICT.value());
|
||||
response.put("message", "Data integrity violation");
|
||||
response.put("timestamp", LocalDateTime.now());
|
||||
|
||||
return ResponseEntity.status(HttpStatus.CONFLICT).body(response);
|
||||
}
|
||||
|
||||
private String getClientIp(ServerWebExchange exchange) {
|
||||
String ip = exchange.getRequest().getHeaders().getFirst("X-Forwarded-For");
|
||||
if (ip == null || ip.isEmpty()) {
|
||||
ip = exchange.getRequest().getHeaders().getFirst("X-Real-IP");
|
||||
}
|
||||
if (ip == null || ip.isEmpty()) {
|
||||
ip = exchange.getRequest().getRemoteAddress() != null
|
||||
? exchange.getRequest().getRemoteAddress().getAddress().getHostAddress()
|
||||
: "127.0.0.1";
|
||||
}
|
||||
return ip;
|
||||
}
|
||||
|
||||
private String getStackTrace(Exception ex) {
|
||||
StringBuilder stackTrace = new StringBuilder();
|
||||
for (StackTraceElement element : ex.getStackTrace()) {
|
||||
stackTrace.append(element.toString()).append("\n");
|
||||
}
|
||||
return stackTrace.toString();
|
||||
}
|
||||
}
|
||||
+79
@@ -0,0 +1,79 @@
|
||||
package cn.novalon.manage.common.monitoring;
|
||||
|
||||
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.springframework.stereotype.Component;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
@Aspect
|
||||
@Component
|
||||
public class MetricsAspect {
|
||||
|
||||
private final MetricsCollector metricsCollector;
|
||||
|
||||
public MetricsAspect(MetricsCollector metricsCollector) {
|
||||
this.metricsCollector = metricsCollector;
|
||||
}
|
||||
|
||||
@Pointcut("within(cn.novalon.manage..*) && " +
|
||||
"@annotation(org.springframework.web.bind.annotation.GetMapping || " +
|
||||
"@annotation(org.springframework.web.bind.annotation.PostMapping || " +
|
||||
"@annotation(org.springframework.web.bind.annotation.PutMapping || " +
|
||||
"@annotation(org.springframework.web.bind.annotation.DeleteMapping)")
|
||||
public void apiMethods() {}
|
||||
|
||||
@Around("apiMethods()")
|
||||
public Object monitorApiCall(ProceedingJoinPoint joinPoint) throws Throwable {
|
||||
String className = joinPoint.getTarget().getClass().getSimpleName();
|
||||
String methodName = joinPoint.getSignature().getName();
|
||||
String module = extractModule(className);
|
||||
String endpoint = className.replace("Handler", "").toLowerCase() + "/" + methodName;
|
||||
|
||||
long startTime = System.currentTimeMillis();
|
||||
boolean success = true;
|
||||
String errorType = null;
|
||||
|
||||
try {
|
||||
Object result = joinPoint.proceed();
|
||||
|
||||
if (result instanceof Mono) {
|
||||
return ((Mono<?>) result)
|
||||
.doOnError(error -> {
|
||||
success = false;
|
||||
errorType = error.getClass().getSimpleName();
|
||||
metricsCollector.recordError(module, errorType, error.getMessage());
|
||||
})
|
||||
.doOnSuccess(v -> {
|
||||
long duration = System.currentTimeMillis() - startTime;
|
||||
metricsCollector.recordApiCall(module, endpoint, "GET", duration, true);
|
||||
});
|
||||
}
|
||||
|
||||
long duration = System.currentTimeMillis() - startTime;
|
||||
metricsCollector.recordApiCall(module, endpoint, "GET", duration, true);
|
||||
return result;
|
||||
|
||||
} catch (Exception e) {
|
||||
success = false;
|
||||
errorType = e.getClass().getSimpleName();
|
||||
long duration = System.currentTimeMillis() - startTime;
|
||||
metricsCollector.recordApiCall(module, endpoint, "GET", duration, false);
|
||||
metricsCollector.recordError(module, errorType, e.getMessage());
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
private String extractModule(String className) {
|
||||
if (className.contains("Notify")) return "notify";
|
||||
if (className.contains("File")) return "file";
|
||||
if (className.contains("User")) return "user";
|
||||
if (className.contains("Role")) return "role";
|
||||
if (className.contains("Config")) return "config";
|
||||
if (className.contains("Log")) return "log";
|
||||
return "system";
|
||||
}
|
||||
}
|
||||
+88
@@ -0,0 +1,88 @@
|
||||
package cn.novalon.manage.common.monitoring;
|
||||
|
||||
import io.micrometer.core.instrument.Counter;
|
||||
import io.micrometer.core.instrument.MeterRegistry;
|
||||
import io.micrometer.core.instrument.Timer;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@Component
|
||||
public class MetricsCollector {
|
||||
|
||||
private final MeterRegistry meterRegistry;
|
||||
|
||||
public MetricsCollector(MeterRegistry meterRegistry) {
|
||||
this.meterRegistry = meterRegistry;
|
||||
}
|
||||
|
||||
public Counter buildCounter(String name, String description, String... tags) {
|
||||
return Counter.builder(name)
|
||||
.description(description)
|
||||
.tags(tags)
|
||||
.register(meterRegistry);
|
||||
}
|
||||
|
||||
public Timer buildTimer(String name, String description, String... tags) {
|
||||
return Timer.builder(name)
|
||||
.description(description)
|
||||
.tags(tags)
|
||||
.register(meterRegistry);
|
||||
}
|
||||
|
||||
public void recordApiCall(String module, String endpoint, String method, long duration, boolean success) {
|
||||
Timer.builder("api.call.duration")
|
||||
.description("API call duration")
|
||||
.tag("module", module)
|
||||
.tag("endpoint", endpoint)
|
||||
.tag("method", method)
|
||||
.register(meterRegistry)
|
||||
.record(duration, TimeUnit.MILLISECONDS);
|
||||
|
||||
Counter.builder("api.call.count")
|
||||
.description("API call count")
|
||||
.tag("module", module)
|
||||
.tag("endpoint", endpoint)
|
||||
.tag("method", method)
|
||||
.tag("status", success ? "success" : "failure")
|
||||
.register(meterRegistry)
|
||||
.increment();
|
||||
}
|
||||
|
||||
public void recordDatabaseQuery(String module, String operation, long duration, boolean success) {
|
||||
Timer.builder("db.query.duration")
|
||||
.description("Database query duration")
|
||||
.tag("module", module)
|
||||
.tag("operation", operation)
|
||||
.register(meterRegistry)
|
||||
.record(duration, TimeUnit.MILLISECONDS);
|
||||
|
||||
Counter.builder("db.query.count")
|
||||
.description("Database query count")
|
||||
.tag("module", module)
|
||||
.tag("operation", operation)
|
||||
.tag("status", success ? "success" : "failure")
|
||||
.register(meterRegistry)
|
||||
.increment();
|
||||
}
|
||||
|
||||
public void recordCacheHit(String module, String cacheName, boolean hit) {
|
||||
Counter.builder("cache.access")
|
||||
.description("Cache access count")
|
||||
.tag("module", module)
|
||||
.tag("cache", cacheName)
|
||||
.tag("result", hit ? "hit" : "miss")
|
||||
.register(meterRegistry)
|
||||
.increment();
|
||||
}
|
||||
|
||||
public void recordError(String module, String errorType, String message) {
|
||||
Counter.builder("error.count")
|
||||
.description("Error count")
|
||||
.tag("module", module)
|
||||
.tag("type", errorType)
|
||||
.tag("message", message)
|
||||
.register(meterRegistry)
|
||||
.increment();
|
||||
}
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
package cn.novalon.manage.common.monitoring;
|
||||
|
||||
import io.micrometer.core.instrument.MeterRegistry;
|
||||
import org.springframework.boot.actuate.autoconfigure.metrics.MeterRegistryCustomizer;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
public class MetricsConfig {
|
||||
|
||||
@Bean
|
||||
public MeterRegistryCustomizer<MeterRegistry> metricsCommonTags() {
|
||||
return registry -> registry.config().commonTags(
|
||||
"application", "novalon-manage-api",
|
||||
"environment", System.getenv().getOrDefault("ENV", "development")
|
||||
);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public MetricsCollector metricsCollector(MeterRegistry meterRegistry) {
|
||||
return new MetricsCollector(meterRegistry);
|
||||
}
|
||||
}
|
||||
+5
-5
@@ -1,11 +1,11 @@
|
||||
package cn.novalon.manage.common.util;
|
||||
|
||||
/**
|
||||
* @author zhangxiang
|
||||
* @version 1.0
|
||||
* @description 数据库字段名常量
|
||||
* @date 2026/03/11
|
||||
**/
|
||||
* 数据库字段名常量定义
|
||||
*
|
||||
* @author 张翔
|
||||
* @date 2026-03-13
|
||||
*/
|
||||
public class FieldConstants {
|
||||
|
||||
public static final String USERNAME = "username";
|
||||
|
||||
+5
-5
@@ -1,11 +1,11 @@
|
||||
package cn.novalon.manage.common.util;
|
||||
|
||||
/**
|
||||
* @author zhangxiang
|
||||
* @version 1.0
|
||||
* @description 菜单类型常量
|
||||
* @date 2026/03/11
|
||||
**/
|
||||
* 菜单类型常量定义
|
||||
*
|
||||
* @author 张翔
|
||||
* @date 2026-03-13
|
||||
*/
|
||||
public class MenuTypeConstants {
|
||||
|
||||
public static final String DIRECTORY = "M";
|
||||
|
||||
+8
-11
@@ -6,17 +6,14 @@ import java.util.concurrent.atomic.AtomicLong;
|
||||
import java.util.concurrent.locks.LockSupport;
|
||||
|
||||
/**
|
||||
* Twitter的Snowflake算法实现(性能优化版)
|
||||
*
|
||||
* 优化点:
|
||||
* 1. 使用自适应等待策略,减少CPU空转
|
||||
* 2. 时间戳缓存机制,降低系统调用频率
|
||||
* 3. 增强CAS重试策略,提升并发性能
|
||||
* 4. 完善异常处理和资源管理
|
||||
*
|
||||
* @author zhangxiang
|
||||
* @version 2.0
|
||||
* @date 2026/03/11
|
||||
* 雪花算法ID生成器
|
||||
*
|
||||
* 文件定义:基于Twitter Snowflake算法的分布式唯一ID生成器
|
||||
* 涉及业务:为系统所有实体生成唯一ID,支持分布式环境下的ID生成
|
||||
* 算法:使用雪花算法,结合时间戳、机器ID和序列号生成唯一ID,支持高并发场景
|
||||
*
|
||||
* @author 张翔
|
||||
* @date 2026-03-13
|
||||
*/
|
||||
public final class SnowflakeId {
|
||||
|
||||
|
||||
+9
-5
@@ -1,11 +1,15 @@
|
||||
package cn.novalon.manage.common.util;
|
||||
|
||||
/**
|
||||
* @author zhangxiang
|
||||
* @version 1.0
|
||||
* @description 状态常量
|
||||
* @date 2026/03/11
|
||||
**/
|
||||
* 状态常量定义
|
||||
*
|
||||
* 文件定义:系统通用的状态常量定义类
|
||||
* 涉及业务:为系统提供统一的状态码定义,包括启用、禁用、删除等状态
|
||||
* 算法:无复杂算法,主要为常量定义
|
||||
*
|
||||
* @author 张翔
|
||||
* @date 2026-03-13
|
||||
*/
|
||||
public class StatusConstants {
|
||||
|
||||
public static final Integer DISABLED = 0;
|
||||
|
||||
Reference in New Issue
Block a user