# Multi-Module Architecture Refactor Implementation Plan
> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
**Goal:** 将 novalon-manage-api 从单体模块重构为网关 + 单体多模块架构,实现模块化、统一认证授权、独立部署和性能优化。
**Architecture:** 采用网关(manage-gateway)+ 应用层(manage-app)+ 业务模块(manage-sys、manage-audit、manage-notify、manage-file)+ 公共模块(manage-common、manage-db)的分层架构。网关统一处理JWT认证、RBAC权限和限流熔断,应用层聚合所有业务模块,通过Caffeine缓存优化性能,使用Docker容器化部署。
**Tech Stack:** Java 21, Spring Boot 3.4.1, Spring WebFlux, Spring Security, R2DBC, PostgreSQL, JWT, Caffeine, Docker, Maven
---
## Phase 1: Preparation (1-2 days)
### Task 1: Create manage-gateway module structure
**Files:**
- Create: `novalon-manage-api/manage-gateway/pom.xml`
- Create: `novalon-manage-api/manage-gateway/src/main/java/cn/novalon/manage/gateway/GatewayApplication.java`
- Create: `novalon-manage-api/manage-gateway/src/main/resources/application.yml`
- Create: `novalon-manage-api/manage-gateway/src/main/resources/application-dev.yml`
- Create: `novalon-manage-api/manage-gateway/src/main/resources/application-prod.yml`
- Create: `novalon-manage-api/manage-gateway/Dockerfile`
**Step 1: Create manage-gateway pom.xml**
```xml
4.0.0
cn.novalon.manage
novalon-manage-api
1.0.0
manage-gateway
jar
Manage Gateway
Gateway module for Novalon Manage API
cn.novalon.manage
manage-common
${project.version}
org.springframework.boot
spring-boot-starter-webflux
org.springframework.boot
spring-boot-starter-actuator
org.springframework.cloud
spring-cloud-starter-gateway
4.1.0
io.micrometer
micrometer-registry-prometheus
org.springframework.boot
spring-boot-starter-test
test
org.springframework.boot
spring-boot-maven-plugin
cn.novalon.manage.gateway.GatewayApplication
```
**Step 2: Create GatewayApplication.java**
```java
package cn.novalon.manage.gateway;
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) {
return builder.routes()
.route("manage-app", r -> r
.path("/api/**")
.uri("http://manage-app:8081"))
.build();
}
}
```
**Step 3: Create application.yml**
```yaml
server:
port: 8080
spring:
application:
name: manage-gateway
cloud:
gateway:
routes:
- id: manage-app
uri: http://manage-app:8081
predicates:
- Path=/api/**
default-filters:
- name: Retry
args:
retries: 3
statuses: BAD_GATEWAY,SERVICE_UNAVAILABLE
methods: GET,POST
backoff:
firstBackoff: 10ms
maxBackoff: 50ms
factor: 2
basedOnPreviousValue: false
management:
endpoints:
web:
exposure:
include: health,info,metrics
base-path: /actuator
endpoint:
health:
show-details: always
metrics:
tags:
application: ${spring.application.name}
logging:
level:
cn.novalon.manage: DEBUG
org.springframework.cloud.gateway: DEBUG
```
**Step 4: Create Dockerfile**
```dockerfile
FROM openjdk:21-jdk-slim
WORKDIR /app
COPY manage-gateway/target/manage-gateway-1.0.0.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "app.jar"]
```
**Step 5: Compile and verify**
Run: `cd novalon-manage-api && mvn clean compile -pl manage-gateway -am`
Expected: BUILD SUCCESS
**Step 6: Commit**
```bash
git add novalon-manage-api/manage-gateway/
git commit -m "feat: create manage-gateway module structure"
```
---
### Task 2: Create manage-app module structure
**Files:**
- Create: `novalon-manage-api/manage-app/pom.xml`
- Create: `novalon-manage-api/manage-app/src/main/java/cn/novalon/manage/app/ManageApplication.java`
- Create: `novalon-manage-api/manage-app/src/main/resources/application.yml`
- Create: `novalon-manage-api/manage-app/src/main/resources/application-dev.yml`
- Create: `novalon-manage-api/manage-app/src/main/resources/application-prod.yml`
- Create: `novalon-manage-api/manage-app/Dockerfile`
**Step 1: Create manage-app pom.xml**
```xml
4.0.0
cn.novalon.manage
novalon-manage-api
1.0.0
manage-app
jar
Manage App
Application module for Novalon Manage API
cn.novalon.manage
manage-sys
${project.version}
cn.novalon.manage
manage-audit
${project.version}
cn.novalon.manage
manage-notify
${project.version}
cn.novalon.manage
manage-file
${project.version}
cn.novalon.manage
manage-db
${project.version}
cn.novalon.manage
manage-common
${project.version}
org.springframework.boot
spring-boot-starter-webflux
org.springframework.boot
spring-boot-starter-actuator
io.micrometer
micrometer-registry-prometheus
org.postgresql
r2dbc-postgresql
org.postgresql
postgresql
org.flywaydb
flyway-core
org.flywaydb
flyway-database-postgresql
org.springframework.boot
spring-boot-starter-test
test
org.springframework.boot
spring-boot-maven-plugin
cn.novalon.manage.app.ManageApplication
```
**Step 2: Create 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;
@SpringBootApplication
@ConfigurationPropertiesScan(basePackages = "cn.novalon.manage")
@ComponentScan(basePackages = "cn.novalon.manage")
public class ManageApplication {
public static void main(String[] args) {
SpringApplication.run(ManageApplication.class, args);
}
}
```
**Step 3: Create application.yml**
```yaml
server:
port: 8081
spring:
application:
name: manage-app
r2dbc:
url: r2dbc:postgresql://${DB_HOST:localhost}:${DB_PORT:5432}/${DB_NAME:novalon_manage}
username: ${DB_USERNAME:postgres}
password: ${DB_PASSWORD:postgres}
pool:
initial-size: 10
max-size: 50
max-idle-time: 30m
max-life-time: 1h
acquire-timeout: 5s
flyway:
enabled: true
locations: classpath:db/migration
management:
endpoints:
web:
exposure:
include: health,info,metrics,env,loggers
base-path: /actuator
endpoint:
health:
show-details: always
metrics:
tags:
application: ${spring.application.name}
environment: ${spring.profiles.active}
logging:
level:
cn.novalon.manage: DEBUG
org.springframework.r2dbc: DEBUG
```
**Step 4: Create Dockerfile**
```dockerfile
FROM openjdk:21-jdk-slim
WORKDIR /app
COPY manage-app/target/manage-app-1.0.0.jar app.jar
EXPOSE 8081
ENTRYPOINT ["java", "-jar", "app.jar"]
```
**Step 5: Compile and verify**
Run: `cd novalon-manage-api && mvn clean compile -pl manage-app -am`
Expected: BUILD SUCCESS
**Step 6: Commit**
```bash
git add novalon-manage-api/manage-app/
git commit -m "feat: create manage-app module structure"
```
---
### Task 3: Create manage-common module structure
**Files:**
- Create: `novalon-manage-api/manage-common/pom.xml`
- Create: `novalon-manage-api/manage-common/src/main/java/cn/novalon/manage/common/`
- Create: `novalon-manage-api/manage-common/src/main/java/cn/novalon/manage/common/util/`
- Create: `novalon-manage-api/manage-common/src/main/java/cn/novalon/manage/common/config/`
- Create: `novalon-manage-api/manage-common/src/main/java/cn/novalon/manage/common/filter/`
- Create: `novalon-manage-api/manage-common/src/main/java/cn/novalon/manage/common/exception/`
**Step 1: Create manage-common pom.xml**
```xml
4.0.0
cn.novalon.manage
novalon-manage-api
1.0.0
manage-common
jar
Manage Common
Common module for Novalon Manage API
org.springframework.boot
spring-boot-starter-webflux
org.springframework.boot
spring-boot-starter-validation
org.springframework.boot
spring-boot-starter-cache
com.github.ben-manes.caffeine
caffeine
org.apache.commons
commons-lang3
io.jsonwebtoken
jjwt-api
io.jsonwebtoken
jjwt-impl
runtime
io.jsonwebtoken
jjwt-jackson
runtime
org.springframework.boot
spring-boot-starter-test
test
org.springframework.boot
spring-boot-maven-plugin
true
```
**Step 2: Create package structure**
Run: `mkdir -p novalon-manage-api/manage-common/src/main/java/cn/novalon/manage/common/{util,config,filter,exception,dto}`
Expected: Directories created successfully
**Step 3: Create common exception classes**
Create: `novalon-manage-api/manage-common/src/main/java/cn/novalon/manage/common/exception/BusinessException.java`
```java
package cn.novalon.manage.common.exception;
public class BusinessException extends RuntimeException {
private final String code;
private final String message;
public BusinessException(String code, String message) {
super(message);
this.code = code;
this.message = message;
}
public String getCode() {
return code;
}
@Override
public String getMessage() {
return message;
}
}
```
**Step 4: Compile and verify**
Run: `cd novalon-manage-api && mvn clean compile -pl manage-common -am`
Expected: BUILD SUCCESS
**Step 5: Commit**
```bash
git add novalon-manage-api/manage-common/
git commit -m "feat: create manage-common module structure"
```
---
### Task 4: Create manage-db module structure
**Files:**
- Create: `novalon-manage-api/manage-db/pom.xml`
- Create: `novalon-manage-api/manage-db/src/main/java/cn/novalon/manage/db/`
- Create: `novalon-manage-api/manage-db/src/main/java/cn/novalon/manage/db/entity/`
- Create: `novalon-manage-api/manage-db/src/main/java/cn/novalon/manage/db/repository/`
- Create: `novalon-manage-api/manage-db/src/main/resources/db/migration/`
**Step 1: Create manage-db pom.xml**
```xml
4.0.0
cn.novalon.manage
novalon-manage-api
1.0.0
manage-db
jar
Manage DB
Database module for Novalon Manage API
org.springframework.boot
spring-boot-starter-data-r2dbc
org.postgresql
r2dbc-postgresql
org.postgresql
postgresql
org.flywaydb
flyway-core
org.flywaydb
flyway-database-postgresql
org.mapstruct
mapstruct
1.5.5.Final
org.mapstruct
mapstruct-processor
1.5.5.Final
provided
org.springframework.boot
spring-boot-starter-test
test
org.springframework.boot
spring-boot-maven-plugin
true
```
**Step 2: Copy migration scripts**
Run: `cp -r novalon-manage-api/manage-sys/src/main/resources/db/migration/* novalon-manage-api/manage-db/src/main/resources/db/migration/`
Expected: Migration scripts copied successfully
**Step 3: Compile and verify**
Run: `cd novalon-manage-api && mvn clean compile -pl manage-db -am`
Expected: BUILD SUCCESS
**Step 4: Commit**
```bash
git add novalon-manage-api/manage-db/
git commit -m "feat: create manage-db module structure"
```
---
### Task 5: Create manage-audit module structure
**Files:**
- Create: `novalon-manage-api/manage-audit/pom.xml`
- Create: `novalon-manage-api/manage-audit/src/main/java/cn/novalon/manage/audit/`
- Create: `novalon-manage-api/manage-audit/src/main/java/cn/novalon/manage/audit/handler/`
- Create: `novalon-manage-api/manage-audit/src/main/java/cn/novalon/manage/audit/service/`
- Create: `novalon-manage-api/manage-audit/src/main/java/cn/novalon/manage/audit/dto/`
**Step 1: Create manage-audit pom.xml**
```xml
4.0.0
cn.novalon.manage
novalon-manage-api
1.0.0
manage-audit
jar
Manage Audit
Audit module for Novalon Manage API
cn.novalon.manage
manage-db
${project.version}
cn.novalon.manage
manage-common
${project.version}
org.springframework.boot
spring-boot-starter-webflux
org.springframework.boot
spring-boot-starter-test
test
org.springframework.boot
spring-boot-maven-plugin
true
```
**Step 2: Compile and verify**
Run: `cd novalon-manage-api && mvn clean compile -pl manage-audit -am`
Expected: BUILD SUCCESS
**Step 3: Commit**
```bash
git add novalon-manage-api/manage-audit/
git commit -m "feat: create manage-audit module structure"
```
---
### Task 6: Create manage-notify module structure
**Files:**
- Create: `novalon-manage-api/manage-notify/pom.xml`
- Create: `novalon-manage-api/manage-notify/src/main/java/cn/novalon/manage/notify/`
- Create: `novalon-manage-api/manage-notify/src/main/java/cn/novalon/manage/notify/handler/`
- Create: `novalon-manage-api/manage-notify/src/main/java/cn/novalon/manage/notify/service/`
- Create: `novalon-manage-api/manage-notify/src/main/java/cn/novalon/manage/notify/config/`
**Step 1: Create manage-notify pom.xml**
```xml
4.0.0
cn.novalon.manage
novalon-manage-api
1.0.0
manage-notify
jar
Manage Notify
Notify module for Novalon Manage API
cn.novalon.manage
manage-db
${project.version}
cn.novalon.manage
manage-common
${project.version}
org.springframework.boot
spring-boot-starter-webflux
org.springframework.boot
spring-boot-starter-websocket
org.springframework.boot
spring-boot-starter-test
test
org.springframework.boot
spring-boot-maven-plugin
true
```
**Step 2: Compile and verify**
Run: `cd novalon-manage-api && mvn clean compile -pl manage-notify -am`
Expected: BUILD SUCCESS
**Step 3: Commit**
```bash
git add novalon-manage-api/manage-notify/
git commit -m "feat: create manage-notify module structure"
```
---
### Task 7: Create manage-file module structure
**Files:**
- Create: `novalon-manage-api/manage-file/pom.xml`
- Create: `novalon-manage-api/manage-file/src/main/java/cn/novalon/manage/file/`
- Create: `novalon-manage-api/manage-file/src/main/java/cn/novalon/manage/file/handler/`
- Create: `novalon-manage-api/manage-file/src/main/java/cn/novalon/manage/file/service/`
- Create: `novalon-manage-api/manage-file/src/main/java/cn/novalon/manage/file/config/`
**Step 1: Create manage-file pom.xml**
```xml
4.0.0
cn.novalon.manage
novalon-manage-api
1.0.0
manage-file
jar
Manage File
File module for Novalon Manage API
cn.novalon.manage
manage-db
${project.version}
cn.novalon.manage
manage-common
${project.version}
org.springframework.boot
spring-boot-starter-webflux
org.springframework.boot
spring-boot-starter-test
test
org.springframework.boot
spring-boot-maven-plugin
true
```
**Step 2: Compile and verify**
Run: `cd novalon-manage-api && mvn clean compile -pl manage-file -am`
Expected: BUILD SUCCESS
**Step 3: Commit**
```bash
git add novalon-manage-api/manage-file/
git commit -m "feat: create manage-file module structure"
```
---
### Task 8: Update parent pom.xml with new modules
**Files:**
- Modify: `novalon-manage-api/pom.xml`
**Step 1: Update modules section**
Read: `novalon-manage-api/pom.xml`
Find: `` section and replace with:
```xml
manage-gateway
manage-app
manage-sys
manage-audit
manage-notify
manage-file
manage-common
manage-db
```
**Step 2: Verify build**
Run: `cd novalon-manage-api && mvn clean compile`
Expected: BUILD SUCCESS
**Step 3: Commit**
```bash
git add novalon-manage-api/pom.xml
git commit -m "feat: update parent pom.xml with new modules"
```
---
## Phase 2: Module Extraction (3-5 days)
### Task 9: Extract common utilities to manage-common
**Files:**
- Modify: `novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/utils/SnowflakeId.java`
- Create: `novalon-manage-api/manage-common/src/main/java/cn/novalon/manage/common/util/SnowflakeId.java`
- Modify: `novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/config/JwtProperties.java`
- Create: `novalon-manage-api/manage-common/src/main/java/cn/novalon/manage/common/config/JwtProperties.java`
**Step 1: Move SnowflakeId to manage-common**
Read: `novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/utils/SnowflakeId.java`
Copy content to: `novalon-manage-api/manage-common/src/main/java/cn/novalon/manage/common/util/SnowflakeId.java`
Update package declaration: `package cn.novalon.manage.common.util;`
**Step 2: Move JwtProperties to manage-common**
Read: `novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/config/JwtProperties.java`
Copy content to: `novalon-manage-api/manage-common/src/main/java/cn/novalon/manage/common/config/JwtProperties.java`
Update package declaration: `package cn.novalon.manage.common.config;`
**Step 3: Update manage-sys imports**
Find all files in manage-sys that import SnowflakeId or JwtProperties and update imports:
```bash
cd novalon-manage-api/manage-sys
find src -name "*.java" -exec grep -l "SnowflakeId\|JwtProperties" {} \;
```
Update imports from:
- `import cn.novalon.manage.sys.utils.SnowflakeId;` to `import cn.novalon.manage.common.util.SnowflakeId;`
- `import cn.novalon.manage.sys.config.JwtProperties;` to `import cn.novalon.manage.common.config.JwtProperties;`
**Step 4: Remove old files from manage-sys**
Run: `rm novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/utils/SnowflakeId.java`
Run: `rm novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/config/JwtProperties.java`
**Step 5: Compile and verify**
Run: `cd novalon-manage-api && mvn clean compile`
Expected: BUILD SUCCESS
**Step 6: Commit**
```bash
git add novalon-manage-api/manage-common/ novalon-manage-api/manage-sys/
git commit -m "refactor: extract common utilities to manage-common"
```
---
### Task 10: Extract database entities to manage-db
**Files:**
- Move: `novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/entity/*` to `novalon-manage-api/manage-db/src/main/java/cn/novalon/manage/db/entity/`
- Move: `novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/repository/*` to `novalon-manage-api/manage-db/src/main/java/cn/novalon/manage/db/repository/`
**Step 1: Move entity classes**
Run: `mkdir -p novalon-manage-api/manage-db/src/main/java/cn/novalon/manage/db/entity`
Run: `mv novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/entity/* novalon-manage-api/manage-db/src/main/java/cn/novalon/manage/db/entity/`
**Step 2: Update entity package declarations**
For each entity file in manage-db/entity, update package declaration:
From: `package cn.novalon.manage.sys.infrastructure.db.entity;`
To: `package cn.novalon.manage.db.entity;`
**Step 3: Move repository interfaces**
Run: `mkdir -p novalon-manage-api/manage-db/src/main/java/cn/novalon/manage/db/repository`
Run: `mv novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/infrastructure/db/repository/* novalon-manage-api/manage-db/src/main/java/cn/novalon/manage/db/repository/`
**Step 4: Update repository package declarations**
For each repository file in manage-db/repository, update package declaration:
From: `package cn.novalon.manage.sys.infrastructure.db.repository;`
To: `package cn.novalon.manage.db.repository;`
**Step 5: Update imports in manage-sys**
Find all files in manage-sys that import entities or repositories and update imports:
```bash
cd novalon-manage-api/manage-sys
find src -name "*.java" -exec grep -l "cn.novalon.manage.sys.infrastructure.db" {} \;
```
Update imports from:
- `import cn.novalon.manage.sys.infrastructure.db.entity.*;` to `import cn.novalon.manage.db.entity.*;`
- `import cn.novalon.manage.sys.infrastructure.db.repository.*;` to `import cn.novalon.manage.db.repository.*;`
**Step 6: Compile and verify**
Run: `cd novalon-manage-api && mvn clean compile`
Expected: BUILD SUCCESS
**Step 7: Commit**
```bash
git add novalon-manage-api/manage-db/ novalon-manage-api/manage-sys/
git commit -m "refactor: extract database entities to manage-db"
```
---
### Task 11: Refactor manage-sys module
**Files:**
- Modify: `novalon-manage-api/manage-sys/pom.xml`
- Modify: `novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/ManageSysApplication.java`
**Step 1: Update manage-sys pom.xml dependencies**
Read: `novalon-manage-api/manage-sys/pom.xml`
Replace dependencies section with:
```xml
cn.novalon.manage
manage-db
${project.version}
cn.novalon.manage
manage-common
${project.version}
org.springframework.boot
spring-boot-starter-webflux
org.springframework.boot
spring-boot-starter-validation
org.springdoc
springdoc-openapi-starter-webflux-ui
org.springframework.boot
spring-boot-starter-test
test
```
**Step 2: Update ManageSysApplication.java**
Read: `novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/ManageSysApplication.java`
Update package scan to include new packages:
```java
package cn.novalon.manage.sys;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.ConfigurationPropertiesScan;
import org.springframework.context.annotation.ComponentScan;
@SpringBootApplication
@ConfigurationPropertiesScan(basePackages = "cn.novalon.manage")
@ComponentScan(basePackages = "cn.novalon.manage")
public class ManageSysApplication {
public static void main(String[] args) {
SpringApplication.run(ManageSysApplication.class, args);
}
}
```
**Step 3: Compile and verify**
Run: `cd novalon-manage-api && mvn clean compile -pl manage-sys -am`
Expected: BUILD SUCCESS
**Step 4: Commit**
```bash
git add novalon-manage-api/manage-sys/
git commit -m "refactor: update manage-sys module dependencies"
```
---
### Task 12: Migrate audit functionality to manage-audit
**Files:**
- Move: `novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/handler/log/SysLogHandler.java` to `novalon-manage-api/manage-audit/src/main/java/cn/novalon/manage/audit/handler/`
- Move: `novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/service/impl/OperationLogService.java` to `novalon-manage-api/manage-audit/src/main/java/cn/novalon/manage/audit/service/impl/`
- Move: `novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/service/impl/SysLoginLogService.java` to `novalon-manage-api/manage-audit/src/main/java/cn/novalon/manage/audit/service/impl/`
- Move: `novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/service/impl/SysExceptionLogService.java` to `novalon-manage-api/manage-audit/src/main/java/cn/novalon/manage/audit/service/impl/`
**Step 1: Move audit handlers**
Run: `mkdir -p novalon-manage-api/manage-audit/src/main/java/cn/novalon/manage/audit/handler`
Run: `mv novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/handler/log/SysLogHandler.java novalon-manage-api/manage-audit/src/main/java/cn/novalon/manage/audit/handler/`
**Step 2: Move audit services**
Run: `mkdir -p novalon-manage-api/manage-audit/src/main/java/cn/novalon/manage/audit/service/impl`
Run: `mv novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/service/impl/OperationLogService.java novalon-manage-api/manage-audit/src/main/java/cn/novalon/manage/audit/service/impl/`
Run: `mv novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/service/impl/SysLoginLogService.java novalon-manage-api/manage-audit/src/main/java/cn/novalon/manage/audit/service/impl/`
Run: `mv novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/service/impl/SysExceptionLogService.java novalon-manage-api/manage-audit/src/main/java/cn/novalon/manage/audit/service/impl/`
**Step 3: Update package declarations**
For each moved file, update package declaration:
From: `package cn.novalon.manage.sys.handler.log;` to `package cn.novalon.manage.audit.handler;`
From: `package cn.novalon.manage.sys.core.service.impl;` to `package cn.novalon.manage.audit.service.impl;`
**Step 4: Compile and verify**
Run: `cd novalon-manage-api && mvn clean compile -pl manage-audit -am`
Expected: BUILD SUCCESS
**Step 5: Commit**
```bash
git add novalon-manage-api/manage-audit/ novalon-manage-api/manage-sys/
git commit -m "refactor: migrate audit functionality to manage-audit"
```
---
### Task 13: Migrate notify functionality to manage-notify
**Files:**
- Move: `novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/handler/notice/SysNoticeHandler.java` to `novalon-manage-api/manage-notify/src/main/java/cn/novalon/manage/notify/handler/`
- Move: `novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/handler/message/SysUserMessageHandler.java` to `novalon-manage-api/manage-notify/src/main/java/cn/novalon/manage/notify/handler/`
- Move: `novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/service/impl/SysNoticeService.java` to `novalon-manage-api/manage-notify/src/main/java/cn/novalon/manage/notify/service/impl/`
- Move: `novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/service/impl/SysUserMessageService.java` to `novalon-manage-api/manage-notify/src/main/java/cn/novalon/manage/notify/service/impl/`
- Move: `novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/service/impl/WebSocketServiceImpl.java` to `novalon-manage-api/manage-notify/src/main/java/cn/novalon/manage/notify/service/impl/`
- Move: `novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/config/WebSocketConfig.java` to `novalon-manage-api/manage-notify/src/main/java/cn/novalon/manage/notify/config/`
**Step 1: Move notify handlers**
Run: `mkdir -p novalon-manage-api/manage-notify/src/main/java/cn/novalon/manage/notify/handler`
Run: `mv novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/handler/notice/SysNoticeHandler.java novalon-manage-api/manage-notify/src/main/java/cn/novalon/manage/notify/handler/`
Run: `mv novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/handler/message/SysUserMessageHandler.java novalon-manage-api/manage-notify/src/main/java/cn/novalon/manage/notify/handler/`
**Step 2: Move notify services**
Run: `mkdir -p novalon-manage-api/manage-notify/src/main/java/cn/novalon/manage/notify/service/impl`
Run: `mv novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/service/impl/SysNoticeService.java novalon-manage-api/manage-notify/src/main/java/cn/novalon/manage/notify/service/impl/`
Run: `mv novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/service/impl/SysUserMessageService.java novalon-manage-api/manage-notify/src/main/java/cn/novalon/manage/notify/service/impl/`
Run: `mv novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/service/impl/WebSocketServiceImpl.java novalon-manage-api/manage-notify/src/main/java/cn/novalon/manage/notify/service/impl/`
**Step 3: Move notify config**
Run: `mkdir -p novalon-manage-api/manage-notify/src/main/java/cn/novalon/manage/notify/config`
Run: `mv novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/config/WebSocketConfig.java novalon-manage-api/manage-notify/src/main/java/cn/novalon/manage/notify/config/`
**Step 4: Update package declarations**
For each moved file, update package declaration:
From: `package cn.novalon.manage.sys.handler.notice;` to `package cn.novalon.manage.notify.handler;`
From: `package cn.novalon.manage.sys.handler.message;` to `package cn.novalon.manage.notify.handler;`
From: `package cn.novalon.manage.sys.core.service.impl;` to `package cn.novalon.manage.notify.service.impl;`
From: `package cn.novalon.manage.sys.config;` to `package cn.novalon.manage.notify.config;`
**Step 5: Compile and verify**
Run: `cd novalon-manage-api && mvn clean compile -pl manage-notify -am`
Expected: BUILD SUCCESS
**Step 6: Commit**
```bash
git add novalon-manage-api/manage-notify/ novalon-manage-api/manage-sys/
git commit -m "refactor: migrate notify functionality to manage-notify"
```
---
### Task 14: Migrate file functionality to manage-file
**Files:**
- Move: `novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/handler/file/SysFileHandler.java` to `novalon-manage-api/manage-file/src/main/java/cn/novalon/manage/file/handler/`
- Move: `novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/service/impl/SysFileService.java` to `novalon-manage-api/manage-file/src/main/java/cn/novalon/manage/file/service/impl/`
- Move: `novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/config/MultipartConfig.java` to `novalon-manage-api/manage-file/src/main/java/cn/novalon/manage/file/config/`
**Step 1: Move file handler**
Run: `mkdir -p novalon-manage-api/manage-file/src/main/java/cn/novalon/manage/file/handler`
Run: `mv novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/handler/file/SysFileHandler.java novalon-manage-api/manage-file/src/main/java/cn/novalon/manage/file/handler/`
**Step 2: Move file service**
Run: `mkdir -p novalon-manage-api/manage-file/src/main/java/cn/novalon/manage/file/service/impl`
Run: `mv novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/core/service/impl/SysFileService.java novalon-manage-api/manage-file/src/main/java/cn/novalon/manage/file/service/impl/`
**Step 3: Move file config**
Run: `mkdir -p novalon-manage-api/manage-file/src/main/java/cn/novalon/manage/file/config`
Run: `mv novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/config/MultipartConfig.java novalon-manage-api/manage-file/src/main/java/cn/novalon/manage/file/config/`
**Step 4: Update package declarations**
For each moved file, update package declaration:
From: `package cn.novalon.manage.sys.handler.file;` to `package cn.novalon.manage.file.handler;`
From: `package cn.novalon.manage.sys.core.service.impl;` to `package cn.novalon.manage.file.service.impl;`
From: `package cn.novalon.manage.sys.config;` to `package cn.novalon.manage.file.config;`
**Step 5: Compile and verify**
Run: `cd novalon-manage-api && mvn clean compile -pl manage-file -am`
Expected: BUILD SUCCESS
**Step 6: Commit**
```bash
git add novalon-manage-api/manage-file/ novalon-manage-api/manage-sys/
git commit -m "refactor: migrate file functionality to manage-file"
```
---
## Phase 3: Gateway and Application Layer (2-3 days)
### Task 15: Implement JWT authentication filter in manage-gateway
**Files:**
- Create: `novalon-manage-api/manage-gateway/src/main/java/cn/novalon/manage/gateway/filter/JwtAuthenticationFilter.java`
- Create: `novalon-manage-api/manage-common/src/main/java/cn/novalon/manage/common/util/JwtTokenProvider.java`
- Create: `novalon-manage-api/manage-common/src/main/java/cn/novalon/manage/common/dto/JwtUser.java`
**Step 1: Create JwtUser DTO**
Create: `novalon-manage-api/manage-common/src/main/java/cn/novalon/manage/common/dto/JwtUser.java`
```java
package cn.novalon.manage.common.dto;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class JwtUser {
private String userId;
private String username;
private List roles;
private List permissions;
}
```
**Step 2: Create JwtTokenProvider**
Create: `novalon-manage-api/manage-common/src/main/java/cn/novalon/manage/common/util/JwtTokenProvider.java`
```java
package cn.novalon.manage.common.util;
import cn.novalon.manage.common.config.JwtProperties;
import cn.novalon.manage.common.dto.JwtUser;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.security.Keys;
import org.springframework.stereotype.Component;
import javax.crypto.SecretKey;
import java.util.Date;
import java.util.List;
@Component
public class JwtTokenProvider {
private final JwtProperties jwtProperties;
private final SecretKey key;
public JwtTokenProvider(JwtProperties jwtProperties) {
this.jwtProperties = jwtProperties;
this.key = Keys.hmacShaKeyFor(jwtProperties.getSecret().getBytes());
}
public String generateToken(JwtUser user) {
Date now = new Date();
Date expiryDate = new Date(now.getTime() + jwtProperties.getExpiration() * 1000);
return Jwts.builder()
.subject(user.getUserId())
.claim("username", user.getUsername())
.claim("roles", user.getRoles())
.claim("permissions", user.getPermissions())
.issuedAt(now)
.expiration(expiryDate)
.signWith(key)
.compact();
}
public JwtUser parseToken(String token) {
Claims claims = Jwts.parserBuilder()
.setSigningKey(key)
.build()
.parseClaimsJws(token)
.getBody();
JwtUser user = new JwtUser();
user.setUserId(claims.getSubject());
user.setUsername(claims.get("username", String.class));
user.setRoles(claims.get("roles", List.class));
user.setPermissions(claims.get("permissions", List.class));
return user;
}
public boolean validateToken(String token) {
try {
Jwts.parserBuilder()
.setSigningKey(key)
.build()
.parseClaimsJws(token);
return true;
} catch (Exception e) {
return false;
}
}
}
```
**Step 3: Create JwtAuthenticationFilter**
Create: `novalon-manage-api/manage-gateway/src/main/java/cn/novalon/manage/gateway/filter/JwtAuthenticationFilter.java`
```java
package cn.novalon.manage.gateway.filter;
import cn.novalon.manage.common.dto.JwtUser;
import cn.novalon.manage.common.util.JwtTokenProvider;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
@Component
public class JwtAuthenticationFilter extends AbstractGatewayFilterFactory {
private final JwtTokenProvider jwtTokenProvider;
public JwtAuthenticationFilter(JwtTokenProvider jwtTokenProvider) {
super(Config.class);
this.jwtTokenProvider = jwtTokenProvider;
}
@Override
public GatewayFilter apply(Config config) {
return (exchange, chain) -> {
ServerHttpRequest request = exchange.getRequest();
String path = request.getPath().value();
if (isPublicPath(path)) {
return chain.filter(exchange);
}
String token = extractToken(request);
if (token == null || !jwtTokenProvider.validateToken(token)) {
return unauthorized(exchange.getResponse());
}
JwtUser user = jwtTokenProvider.parseToken(token);
addHeaders(exchange, user);
return chain.filter(exchange);
};
}
private boolean isPublicPath(String path) {
return path.startsWith("/api/auth/login") || path.startsWith("/api/auth/register");
}
private String extractToken(ServerHttpRequest request) {
String bearerToken = request.getHeaders().getFirst(HttpHeaders.AUTHORIZATION);
if (bearerToken != null && bearerToken.startsWith("Bearer ")) {
return bearerToken.substring(7);
}
return null;
}
private void addHeaders(ServerWebExchange exchange, JwtUser user) {
ServerHttpRequest mutatedRequest = exchange.getRequest().mutate()
.header("X-User-Id", user.getUserId())
.header("X-User-Username", user.getUsername())
.header("X-User-Roles", String.join(",", user.getRoles()))
.header("X-User-Permissions", String.join(",", user.getPermissions()))
.build();
exchange.mutate().request(mutatedRequest).build();
}
private Mono unauthorized(ServerHttpResponse response) {
response.setStatusCode(HttpStatus.UNAUTHORIZED);
return response.setComplete();
}
public static class Config {
}
}
```
**Step 4: Compile and verify**
Run: `cd novalon-manage-api && mvn clean compile -pl manage-gateway,manage-common -am`
Expected: BUILD SUCCESS
**Step 5: Commit**
```bash
git add novalon-manage-api/manage-gateway/ novalon-manage-api/manage-common/
git commit -m "feat: implement JWT authentication filter in manage-gateway"
```
---
### Task 16: Implement RBAC authorization filter in manage-gateway
**Files:**
- Create: `novalon-manage-api/manage-gateway/src/main/java/cn/novalon/manage/gateway/filter/RbacAuthorizationFilter.java`
- Create: `novalon-manage-api/manage-gateway/src/main/java/cn/novalon/manage/gateway/config/PermissionConfig.java`
**Step 1: Create PermissionConfig**
Create: `novalon-manage-api/manage-gateway/src/main/java/cn/novalon/manage/gateway/config/PermissionConfig.java`
```java
package cn.novalon.manage.gateway.config;
import org.springframework.context.annotation.Configuration;
import java.util.HashMap;
import java.util.Map;
@Configuration
public class PermissionConfig {
public static final Map PATH_PERMISSIONS = new HashMap<>();
static {
PATH_PERMISSIONS.put("/api/sys/users", "user:read");
PATH_PERMISSIONS.put("/api/sys/users/**", "user:write");
PATH_PERMISSIONS.put("/api/sys/roles", "role:read");
PATH_PERMISSIONS.put("/api/sys/roles/**", "role:write");
PATH_PERMISSIONS.put("/api/sys/menus", "menu:read");
PATH_PERMISSIONS.put("/api/sys/menus/**", "menu:write");
PATH_PERMISSIONS.put("/api/sys/config", "config:read");
PATH_PERMISSIONS.put("/api/sys/config/**", "config:write");
PATH_PERMISSIONS.put("/api/audit/logs", "audit:read");
PATH_PERMISSIONS.put("/api/notify/notices", "notice:read");
PATH_PERMISSIONS.put("/api/notify/notices/**", "notice:write");
PATH_PERMISSIONS.put("/api/file/files", "file:read");
PATH_PERMISSIONS.put("/api/file/files/**", "file:write");
}
public static String getRequiredPermission(String path, String method) {
String permissionKey = path;
if (!PATH_PERMISSIONS.containsKey(path)) {
permissionKey = path.substring(0, path.lastIndexOf('/'));
}
return PATH_PERMISSIONS.get(permissionKey);
}
}
```
**Step 2: Create RbacAuthorizationFilter**
Create: `novalon-manage-api/manage-gateway/src/main/java/cn/novalon/manage/gateway/filter/RbacAuthorizationFilter.java`
```java
package cn.novalon.manage.gateway.filter;
import cn.novalon.manage.gateway.config.PermissionConfig;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
import java.util.Arrays;
import java.util.List;
@Component
public class RbacAuthorizationFilter extends AbstractGatewayFilterFactory {
@Override
public GatewayFilter apply(Config config) {
return (exchange, chain) -> {
ServerHttpRequest request = exchange.getRequest();
String path = request.getPath().value();
String method = request.getMethod().name();
if (isPublicPath(path)) {
return chain.filter(exchange);
}
List permissions = request.getHeaders().get("X-User-Permissions");
List roles = request.getHeaders().get("X-User-Roles");
if (permissions == null || roles == null) {
return forbidden(exchange.getResponse());
}
String requiredPermission = PermissionConfig.getRequiredPermission(path, method);
if (requiredPermission != null && !hasPermission(permissions, requiredPermission)) {
return forbidden(exchange.getResponse());
}
return chain.filter(exchange);
};
}
private boolean isPublicPath(String path) {
return path.startsWith("/api/auth/login") || path.startsWith("/api/auth/register");
}
private boolean hasPermission(List permissions, String requiredPermission) {
return permissions.contains(requiredPermission) || permissions.contains("*:*");
}
private Mono forbidden(ServerHttpResponse response) {
response.setStatusCode(HttpStatus.FORBIDDEN);
return response.setComplete();
}
public static class Config {
}
}
```
**Step 3: Update GatewayApplication to register filters**
Read: `novalon-manage-api/manage-gateway/src/main/java/cn/novalon/manage/gateway/GatewayApplication.java`
Update to include filters:
```java
package cn.novalon.manage.gateway;
import cn.novalon.manage.gateway.filter.JwtAuthenticationFilter;
import cn.novalon.manage.gateway.filter.RbacAuthorizationFilter;
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) {
return builder.routes()
.route("manage-app", r -> r
.path("/api/**")
.filters(f -> f
.filter(new JwtAuthenticationFilter.Config())
.filter(new RbacAuthorizationFilter.Config()))
.uri("http://manage-app:8081"))
.build();
}
}
```
**Step 4: Compile and verify**
Run: `cd novalon-manage-api && mvn clean compile -pl manage-gateway -am`
Expected: BUILD SUCCESS
**Step 5: Commit**
```bash
git add novalon-manage-api/manage-gateway/
git commit -m "feat: implement RBAC authorization filter in manage-gateway"
```
---
### Task 17: Configure Caffeine cache in manage-common
**Files:**
- Create: `novalon-manage-api/manage-common/src/main/java/cn/novalon/manage/common/config/CacheConfig.java`
- Create: `novalon-manage-api/manage-common/src/main/java/cn/novalon/manage/common/service/TokenBlacklistService.java`
**Step 1: Create CacheConfig**
Create: `novalon-manage-api/manage-common/src/main/java/cn/novalon/manage/common/config/CacheConfig.java`
```java
package cn.novalon.manage.common.config;
import com.github.benmanes.caffeine.cache.Caffeine;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.caffeine.CaffeineCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.concurrent.TimeUnit;
@Configuration
@EnableCaching
public class CacheConfig {
@Bean
public CacheManager cacheManager() {
CaffeineCacheManager cacheManager = new CaffeineCacheManager();
cacheManager.setCaffeine(caffeineCacheBuilder());
return cacheManager;
}
@Bean
public com.github.benmanes.caffeine.cache.Cache