mirror of
https://github.moeyy.xyz/https://github.com/GeWuYou/forgeboot
synced 2025-10-27 09:52:10 +08:00
feat(plugin) 添加插件支持
This commit is contained in:
parent
bf1983ef62
commit
f3b571bf96
58
README.md
58
README.md
@ -1,23 +1,51 @@
|
||||
# forgeboot
|
||||
|
||||
This project uses [Gradle](https://gradle.org/).
|
||||
To build and run the application, use the *Gradle* tool window by clicking the Gradle icon in the right-hand toolbar,
|
||||
or run it directly from the terminal:
|
||||
多模块 Spring Boot 工具与 Starter 集合
|
||||
|
||||
* Run `./gradlew run` to build and run the application.
|
||||
* Run `./gradlew build` to only build the application.
|
||||
* Run `./gradlew check` to run all checks, including tests.
|
||||
* Run `./gradlew clean` to clean all build outputs.
|
||||
## 项目概览
|
||||
|
||||
Note the usage of the Gradle Wrapper (`./gradlew`).
|
||||
This is the suggested way to use Gradle in production projects.
|
||||
`forgeboot` 是一套面向 Spring Boot 的通用基础库,包含 Banner、缓存、上下文传播、核心工具、国际化、
|
||||
调用链追踪、Web MVC 公共组件以及示例模块。旨在帮助团队快速搭建企业级微服务应用。
|
||||
|
||||
[Learn more about the Gradle Wrapper](https://docs.gradle.org/current/userguide/gradle_wrapper.html).
|
||||
## 模块列表
|
||||
|
||||
[Learn more about Gradle tasks](https://docs.gradle.org/current/userguide/command_line_interface.html#common_tasks).
|
||||
| 模块名 | 功能简介 |
|
||||
|-------------------------------------------------|------------------------------|
|
||||
| forgeboot-banner | 启动横幅 Banner 管理 |
|
||||
| forgeboot-cache-spring-boot-starter | 缓存自动配置 |
|
||||
| forgeboot-context-spring-boot-starter | 上下文传播 |
|
||||
| forgeboot-core | 核心扩展与序列化 |
|
||||
| forgeboot-i18n-spring-boot-starter | 国际化支持 |
|
||||
| forgeboot-trace-spring-boot-starter | 分布式调用链追踪 |
|
||||
| forgeboot-webmvc-spring-boot-starter | Web MVC 公共组件集合 |
|
||||
| forgeboot-demo | 各模块功能示例 |
|
||||
|
||||
This project follows the suggested multi-module setup and consists of the `app` and `utils` subprojects.
|
||||
The shared build logic was extracted to a convention plugin located in `buildSrc`.
|
||||
## 快速开始
|
||||
|
||||
This project uses a version catalog (see `gradle/libs.versions.toml`) to declare and version dependencies
|
||||
and both a build cache and a configuration cache (see `gradle.properties`).
|
||||
1. 克隆仓库:
|
||||
```bash
|
||||
git clone https://github.com/GeWuYou/forgeboot.git
|
||||
```
|
||||
2. 构建所有模块:
|
||||
```bash
|
||||
./gradlew build
|
||||
```
|
||||
## 构建与发布
|
||||
|
||||
- **构建**
|
||||
```bash
|
||||
./gradlew clean build
|
||||
```
|
||||
- **发布到 Maven 仓库**
|
||||
已配置 `maven-publish` 与 `axion-release`,只需执行:
|
||||
```bash
|
||||
./gradlew release
|
||||
```
|
||||
|
||||
## 贡献指南
|
||||
|
||||
欢迎提交 Issue 和 PR,共同完善各模块功能与文档。
|
||||
|
||||
## 许可
|
||||
|
||||
Apache-2.0
|
||||
|
||||
@ -117,7 +117,19 @@ object Modules {
|
||||
"${AUTHORIZE}:forgeboot-security-authorize-autoconfigure"
|
||||
}
|
||||
}
|
||||
object Plugin {
|
||||
private const val PLUGIN = ":forgeboot-plugin"
|
||||
const val CORE = "${PLUGIN}:forgeboot-plugin-core"
|
||||
const val SPRING = "${PLUGIN}:forgeboot-plugin-spring"
|
||||
}
|
||||
object Demo{
|
||||
const val ROOT = ":forgeboot-demo"
|
||||
private const val ROOT = ":forgeboot-demo"
|
||||
object Plugin{
|
||||
private const val PLUGIN = "${ROOT}:forgeboot-plugin-demo"
|
||||
const val API = "${PLUGIN}:forgeboot-plugin-demo-api"
|
||||
const val IMPL = "${PLUGIN}:forgeboot-plugin-demo-impl"
|
||||
const val SERVER = "${PLUGIN}:forgeboot-plugin-demo-server"
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
57
forgeboot-banner/README.md
Normal file
57
forgeboot-banner/README.md
Normal file
@ -0,0 +1,57 @@
|
||||
# forgeboot-banner
|
||||
|
||||
Spring Boot Banner 启动横幅模块
|
||||
|
||||
## 简介
|
||||
|
||||
`forgeboot-banner` 提供了一个可插拔的启动横幅(Banner)框架,与 Spring Boot 无缝集成,支持多种横幅渲染策略与配置项。你可以自定义文本、图片或多策略组合的 Banner,在应用启动时显示。
|
||||
|
||||
## 核心功能
|
||||
|
||||
- 可通过 `forgeboot.banner.strategy` 配置多种渲染策略(随机、按环境、按时间等)。
|
||||
- 支持文本和图片两种 Banner 类型。
|
||||
- 提供默认实现,也可自定义 `BannerStrategy` 和 `BannerProvider`。
|
||||
- 自动集成 Spring Boot,启动时自动渲染。
|
||||
|
||||
## 引入依赖
|
||||
|
||||
使用 Maven:
|
||||
```xml
|
||||
<dependency>
|
||||
<groupId>io.github.gewuyou</groupId>
|
||||
<artifactId>forgeboot-banner</artifactId>
|
||||
<version>${version}</version>
|
||||
</dependency>
|
||||
```
|
||||
使用 Gradle:
|
||||
```groovy
|
||||
implementation "io.github.gewuyou:forgeboot-banner:${version}"
|
||||
```
|
||||
|
||||
## 子模块说明
|
||||
|
||||
- **forgeboot-banner-api**:核心接口与配置类(`BannerStrategy`, `BannerProvider`, `BannerProperties`)。
|
||||
- **forgeboot-banner-impl**:默认实现,包括文件加载、日志输出等逻辑。
|
||||
- **forgeboot-banner-launcher**:启动器模块,负责在 Spring Boot 启动阶段触发 Banner 渲染。
|
||||
|
||||
## 快速开始
|
||||
|
||||
1. 在 `application.yml` 中启用并配置:
|
||||
```yaml
|
||||
forgeboot:
|
||||
banner:
|
||||
enabled: true
|
||||
strategy: RANDOM
|
||||
text-location: classpath:/banner.txt
|
||||
image-location: classpath:/banner.png
|
||||
```
|
||||
2. 启动应用,查看控制台或日志中的横幅效果。
|
||||
|
||||
## 构建
|
||||
```bash
|
||||
./gradlew :forgeboot-banner:build
|
||||
```
|
||||
|
||||
## 许可
|
||||
|
||||
Apache-2.0
|
||||
54
forgeboot-cache/README.md
Normal file
54
forgeboot-cache/README.md
Normal file
@ -0,0 +1,54 @@
|
||||
# forgeboot-cache-spring-boot-starter
|
||||
|
||||
Spring Boot 缓存自动配置模块
|
||||
|
||||
## 简介
|
||||
|
||||
`forgeboot-cache-spring-boot-starter` 提供基于 Spring Cache 的一站式缓存解决方案,封装了常用的缓存接口、默认实现及自动配置。
|
||||
|
||||
## 核心功能
|
||||
|
||||
- **forgeboot-cache-api**:缓存接口定义,统一 `CacheManager`、`Cache` 操作。
|
||||
- **forgeboot-cache-impl**:默认内存或 Redis 实现。
|
||||
- **forgeboot-cache-autoconfigure**:Spring Boot 自动配置,读取 `forgeboot.cache.*` 配置属性,自动创建 `CacheManager`。
|
||||
|
||||
## 引入依赖
|
||||
|
||||
使用 Maven:
|
||||
```xml
|
||||
<dependency>
|
||||
<groupId>io.github.gewuyou</groupId>
|
||||
<artifactId>forgeboot-cache-spring-boot-starter</artifactId>
|
||||
<version>${version}</version>
|
||||
</dependency>
|
||||
```
|
||||
使用 Gradle:
|
||||
```groovy
|
||||
implementation "io.github.gewuyou:forgeboot-cache-spring-boot-starter:${version}"
|
||||
```
|
||||
|
||||
## 配置示例
|
||||
```yaml
|
||||
forgeboot:
|
||||
cache:
|
||||
type: redis
|
||||
redis:
|
||||
host: localhost
|
||||
port: 6379
|
||||
caffeine:
|
||||
spec: maximumSize=1000,expireAfterAccess=5m
|
||||
```
|
||||
|
||||
## 快速开始
|
||||
|
||||
1. 添加依赖并配置缓存类型。
|
||||
2. 在 Service 方法上使用 `@Cacheable("cacheName")`、`@CacheEvict` 等注解即可生效。
|
||||
|
||||
## 构建
|
||||
```bash
|
||||
./gradlew :forgeboot-cache:build
|
||||
```
|
||||
|
||||
## 许可
|
||||
|
||||
Apache-2.0
|
||||
103
forgeboot-context/README.md
Normal file
103
forgeboot-context/README.md
Normal file
@ -0,0 +1,103 @@
|
||||
# forgeboot-context-spring-boot-starter
|
||||
|
||||
> 🧠 请求上下文感知模块,支持在多线程、Reactor、协程等异步场景中透明传递上下文字段,如 traceId、userId、token 等。
|
||||
|
||||
---
|
||||
|
||||
## 🧩 简介
|
||||
|
||||
`forgeboot-context-spring-boot-starter` 是 ForgeBoot 提供的基础上下文传播模块,旨在解决异步环境下上下文(如用户信息、请求信息)无法传递的问题。
|
||||
|
||||
支持多执行模型(ThreadLocal、Reactor Context、Kotlin Coroutine Context)无缝上下文共享,并通过统一接口抽象、自动装配、可扩展的字段注入机制,提升服务内的数据一致性与可维护性。
|
||||
|
||||
---
|
||||
|
||||
## ✨ 核心功能
|
||||
|
||||
- ✅ 支持上下文字段自动注入与解析(Header、MDC、自定义)
|
||||
- ✅ 支持多执行模型(线程 / 协程 / Reactor)上下文透明传递
|
||||
- ✅ 提供统一 `ContextHolder` 访问入口
|
||||
- ✅ 提供字段注册器与注入策略 SPI 扩展
|
||||
- ✅ 支持 Spring Web(Servlet)、WebFlux、Feign、RestTemplate 等组件
|
||||
- ✅ 与 trace 模块无缝集成,自动传播 traceId/requestId
|
||||
|
||||
---
|
||||
|
||||
## 📦 引入依赖
|
||||
|
||||
使用 Maven:
|
||||
|
||||
```xml
|
||||
<dependency>
|
||||
<groupId>io.github.gewuyou</groupId>
|
||||
<artifactId>forgeboot-context-spring-boot-starter</artifactId>
|
||||
<version>${version}</version>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
使用 Gradle:
|
||||
|
||||
```groovy
|
||||
implementation "io.github.gewuyou:forgeboot-context-spring-boot-starter:${version}"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🚀 快速开始
|
||||
|
||||
### ✅ 基础使用
|
||||
|
||||
```kotlin
|
||||
@RestController
|
||||
class DemoController(private val contextHolder: ContextHolder) {
|
||||
@GetMapping("/demo")
|
||||
fun demo(): String {
|
||||
val traceId = contextHolder.get("traceId")
|
||||
return "traceId: $traceId"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔌 可扩展点
|
||||
|
||||
你可以通过实现以下接口来自定义字段注入行为:
|
||||
|
||||
- `ContextProcessor`:用于从请求中提取字段
|
||||
- `ContextFieldContributor`:用于注册要注入的上下文字段
|
||||
|
||||
示例:
|
||||
|
||||
```kotlin
|
||||
@Component
|
||||
class CustomContextFieldContributor : ContextFieldContributor {
|
||||
override fun contribute(registry: FieldRegistry) {
|
||||
registry.register("tenantId", Scope.THREAD_LOCAL)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ⚙️ 构建方式
|
||||
|
||||
使用 Gradle 命令进行构建发布:
|
||||
|
||||
```bash
|
||||
./gradlew :forgeboot-context:build
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📄 许可
|
||||
|
||||
本项目采用 [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0) 开源协议。
|
||||
|
||||
---
|
||||
|
||||
## 📬 联系作者
|
||||
|
||||
由 [@gewuyou](https://github.com/gewuyou) 维护。
|
||||
|
||||
欢迎提交 Issue 或 PR 改进本模块!
|
||||
40
forgeboot-core/README.md
Normal file
40
forgeboot-core/README.md
Normal file
@ -0,0 +1,40 @@
|
||||
# forgeboot-core
|
||||
|
||||
通用核心库
|
||||
|
||||
## 简介
|
||||
|
||||
`forgeboot-core` 包含项目中通用的扩展、工具与序列化支持,例如通用枚举处理、序列化接口、基础配置等。
|
||||
|
||||
## 核心功能
|
||||
|
||||
- **forgeboot-core-extension**:公共扩展函数、集合工具类等。
|
||||
- **forgeboot-core-serialization**:Jackson/Kotlin 序列化自定义注册与模块。
|
||||
|
||||
## 引入依赖
|
||||
|
||||
Maven:
|
||||
```xml
|
||||
<dependency>
|
||||
<groupId>io.github.gewuyou</groupId>
|
||||
<artifactId>forgeboot-core</artifactId>
|
||||
<version>${version}</version>
|
||||
</dependency>
|
||||
```
|
||||
使用 Gradle:
|
||||
```groovy
|
||||
implementation "io.github.gewuyou:forgeboot-core:${version}"
|
||||
```
|
||||
|
||||
## 快速开始
|
||||
|
||||
在 Spring Boot 中引入后,自动注册序列化模块,可直接使用扩展函数。
|
||||
|
||||
## 构建
|
||||
```bash
|
||||
./gradlew :forgeboot-core:build
|
||||
```
|
||||
|
||||
## 许可
|
||||
|
||||
Apache-2.0
|
||||
28
forgeboot-demo/README.md
Normal file
28
forgeboot-demo/README.md
Normal file
@ -0,0 +1,28 @@
|
||||
# forgeboot-demo
|
||||
|
||||
示例与演示模块
|
||||
|
||||
## 简介
|
||||
|
||||
`forgeboot-demo` 包含各模块功能的示例,帮助快速了解如何在项目中使用 `forgeboot-trace`, `forgeboot-cache` 等组件。
|
||||
|
||||
## 快速开始
|
||||
|
||||
1. 进入示例模块:
|
||||
```bash
|
||||
cd forgeboot-demo/forgeboot-trace-demo
|
||||
```
|
||||
2. 运行示例:
|
||||
```bash
|
||||
./gradlew bootRun
|
||||
```
|
||||
3. 访问 `http://localhost:8080/trace-demo` 查看效果。
|
||||
|
||||
## 构建
|
||||
```bash
|
||||
./gradlew :forgeboot-demo:build
|
||||
```
|
||||
|
||||
## 许可
|
||||
|
||||
Apache-2.0
|
||||
3
forgeboot-demo/forgeboot-plugin-demo/.gitattributes
vendored
Normal file
3
forgeboot-demo/forgeboot-plugin-demo/.gitattributes
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
/gradlew text eol=lf
|
||||
*.bat text eol=crlf
|
||||
*.jar binary
|
||||
40
forgeboot-demo/forgeboot-plugin-demo/.gitignore
vendored
Normal file
40
forgeboot-demo/forgeboot-plugin-demo/.gitignore
vendored
Normal file
@ -0,0 +1,40 @@
|
||||
HELP.md
|
||||
.gradle
|
||||
build/
|
||||
!gradle/wrapper/gradle-wrapper.jar
|
||||
!**/src/main/**/build/
|
||||
!**/src/test/**/build/
|
||||
|
||||
### STS ###
|
||||
.apt_generated
|
||||
.classpath
|
||||
.factorypath
|
||||
.project
|
||||
.settings
|
||||
.springBeans
|
||||
.sts4-cache
|
||||
bin/
|
||||
!**/src/main/**/bin/
|
||||
!**/src/test/**/bin/
|
||||
|
||||
### IntelliJ IDEA ###
|
||||
.idea
|
||||
*.iws
|
||||
*.iml
|
||||
*.ipr
|
||||
out/
|
||||
!**/src/main/**/out/
|
||||
!**/src/test/**/out/
|
||||
|
||||
### NetBeans ###
|
||||
/nbproject/private/
|
||||
/nbbuild/
|
||||
/dist/
|
||||
/nbdist/
|
||||
/.nb-gradle/
|
||||
|
||||
### VS Code ###
|
||||
.vscode/
|
||||
|
||||
### Kotlin ###
|
||||
.kotlin
|
||||
5
forgeboot-demo/forgeboot-plugin-demo/build.gradle.kts
Normal file
5
forgeboot-demo/forgeboot-plugin-demo/build.gradle.kts
Normal file
@ -0,0 +1,5 @@
|
||||
|
||||
dependencies {
|
||||
|
||||
}
|
||||
|
||||
3
forgeboot-demo/forgeboot-plugin-demo/forgeboot-plugin-demo-api/.gitattributes
vendored
Normal file
3
forgeboot-demo/forgeboot-plugin-demo/forgeboot-plugin-demo-api/.gitattributes
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
/gradlew text eol=lf
|
||||
*.bat text eol=crlf
|
||||
*.jar binary
|
||||
40
forgeboot-demo/forgeboot-plugin-demo/forgeboot-plugin-demo-api/.gitignore
vendored
Normal file
40
forgeboot-demo/forgeboot-plugin-demo/forgeboot-plugin-demo-api/.gitignore
vendored
Normal file
@ -0,0 +1,40 @@
|
||||
HELP.md
|
||||
.gradle
|
||||
build/
|
||||
!gradle/wrapper/gradle-wrapper.jar
|
||||
!**/src/main/**/build/
|
||||
!**/src/test/**/build/
|
||||
|
||||
### STS ###
|
||||
.apt_generated
|
||||
.classpath
|
||||
.factorypath
|
||||
.project
|
||||
.settings
|
||||
.springBeans
|
||||
.sts4-cache
|
||||
bin/
|
||||
!**/src/main/**/bin/
|
||||
!**/src/test/**/bin/
|
||||
|
||||
### IntelliJ IDEA ###
|
||||
.idea
|
||||
*.iws
|
||||
*.iml
|
||||
*.ipr
|
||||
out/
|
||||
!**/src/main/**/out/
|
||||
!**/src/test/**/out/
|
||||
|
||||
### NetBeans ###
|
||||
/nbproject/private/
|
||||
/nbbuild/
|
||||
/dist/
|
||||
/nbdist/
|
||||
/.nb-gradle/
|
||||
|
||||
### VS Code ###
|
||||
.vscode/
|
||||
|
||||
### Kotlin ###
|
||||
.kotlin
|
||||
@ -0,0 +1,7 @@
|
||||
plugins {
|
||||
alias(libs.plugins.kotlin.kapt)
|
||||
}
|
||||
dependencies {
|
||||
kapt(libs.org.pf4j)
|
||||
implementation(libs.org.pf4j)
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
package com.gewuyou.forgeboot.plugin.demo.api
|
||||
|
||||
/**
|
||||
*问候提供者
|
||||
*
|
||||
* @since 2025-07-24 15:09:07
|
||||
* @author gewuyou
|
||||
*/
|
||||
fun interface GreetingProvider {
|
||||
fun message(): String
|
||||
}
|
||||
@ -0,0 +1,13 @@
|
||||
package com.gewuyou.forgeboot.plugin.demo.api
|
||||
|
||||
import org.pf4j.ExtensionPoint
|
||||
|
||||
/**
|
||||
*问候服务
|
||||
*
|
||||
* @since 2025-07-23 14:04:12
|
||||
* @author gewuyou
|
||||
*/
|
||||
fun interface GreetingService: ExtensionPoint {
|
||||
fun greet(name: String): String
|
||||
}
|
||||
3
forgeboot-demo/forgeboot-plugin-demo/forgeboot-plugin-demo-impl/.gitattributes
vendored
Normal file
3
forgeboot-demo/forgeboot-plugin-demo/forgeboot-plugin-demo-impl/.gitattributes
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
/gradlew text eol=lf
|
||||
*.bat text eol=crlf
|
||||
*.jar binary
|
||||
40
forgeboot-demo/forgeboot-plugin-demo/forgeboot-plugin-demo-impl/.gitignore
vendored
Normal file
40
forgeboot-demo/forgeboot-plugin-demo/forgeboot-plugin-demo-impl/.gitignore
vendored
Normal file
@ -0,0 +1,40 @@
|
||||
HELP.md
|
||||
.gradle
|
||||
build/
|
||||
!gradle/wrapper/gradle-wrapper.jar
|
||||
!**/src/main/**/build/
|
||||
!**/src/test/**/build/
|
||||
|
||||
### STS ###
|
||||
.apt_generated
|
||||
.classpath
|
||||
.factorypath
|
||||
.project
|
||||
.settings
|
||||
.springBeans
|
||||
.sts4-cache
|
||||
bin/
|
||||
!**/src/main/**/bin/
|
||||
!**/src/test/**/bin/
|
||||
|
||||
### IntelliJ IDEA ###
|
||||
.idea
|
||||
*.iws
|
||||
*.iml
|
||||
*.ipr
|
||||
out/
|
||||
!**/src/main/**/out/
|
||||
!**/src/test/**/out/
|
||||
|
||||
### NetBeans ###
|
||||
/nbproject/private/
|
||||
/nbbuild/
|
||||
/dist/
|
||||
/nbdist/
|
||||
/.nb-gradle/
|
||||
|
||||
### VS Code ###
|
||||
.vscode/
|
||||
|
||||
### Kotlin ###
|
||||
.kotlin
|
||||
@ -0,0 +1,11 @@
|
||||
plugins {
|
||||
alias(libs.plugins.kotlin.kapt)
|
||||
alias(libs.plugins.kotlin.plugin.spring)
|
||||
}
|
||||
dependencies {
|
||||
kapt(libs.org.pf4j)
|
||||
implementation(project(Modules.Demo.Plugin.API))
|
||||
implementation(project(Modules.Plugin.CORE))
|
||||
implementation(project(Modules.Plugin.SPRING))
|
||||
implementation(libs.springBoot.starter)
|
||||
}
|
||||
@ -0,0 +1,21 @@
|
||||
package com.gewuyou.forgeboot.plugin.demo.impl
|
||||
|
||||
import com.gewuyou.forgeboot.plugin.demo.api.GreetingProvider
|
||||
import org.springframework.context.annotation.Bean
|
||||
import org.springframework.context.annotation.Configuration
|
||||
|
||||
/**
|
||||
*插件配置
|
||||
*
|
||||
* @since 2025-07-24 14:15:45
|
||||
* @author gewuyou
|
||||
*/
|
||||
@Configuration
|
||||
class PluginConfig{
|
||||
@Bean
|
||||
fun simpleGreetingService(
|
||||
greetingProvider: GreetingProvider
|
||||
): SimpleGreetingService {
|
||||
return SimpleGreetingService(greetingProvider)
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,28 @@
|
||||
package com.gewuyou.forgeboot.plugin.demo.impl
|
||||
|
||||
import com.gewuyou.forgeboot.plugin.spring.manager.SpringPluginManager
|
||||
import org.pf4j.PluginWrapper
|
||||
import org.pf4j.spring.SpringPlugin
|
||||
import org.springframework.context.ApplicationContext
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext
|
||||
|
||||
/**
|
||||
* 简单的问候插件
|
||||
*
|
||||
* 插件主类,必须继承 SpringPlugin 才能在 PF4J + Spring 框架中被识别。
|
||||
*
|
||||
* @author gewuyou
|
||||
* @since 2025-07-24 12:12:21
|
||||
*/
|
||||
class SimpleGreetingPlugin(
|
||||
private val pluginWrapper: PluginWrapper,
|
||||
) : SpringPlugin(pluginWrapper) {
|
||||
override fun createApplicationContext(): ApplicationContext {
|
||||
return AnnotationConfigApplicationContext().apply { ->
|
||||
classLoader = pluginWrapper.pluginClassLoader
|
||||
parent = (pluginWrapper.pluginManager as SpringPluginManager).applicationContext
|
||||
register(PluginConfig::class.java)
|
||||
refresh()
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,18 @@
|
||||
package com.gewuyou.forgeboot.plugin.demo.impl
|
||||
|
||||
import com.gewuyou.forgeboot.plugin.demo.api.GreetingProvider
|
||||
import com.gewuyou.forgeboot.plugin.demo.api.GreetingService
|
||||
import org.pf4j.Extension
|
||||
|
||||
/**
|
||||
*简单的问候服务
|
||||
*
|
||||
* @since 2025-07-24 12:08:15
|
||||
* @author gewuyou
|
||||
*/
|
||||
@Extension
|
||||
class SimpleGreetingService (
|
||||
private val greetingProvider: GreetingProvider
|
||||
): GreetingService {
|
||||
override fun greet(name: String) = "${greetingProvider.message()}, $name from plugin!"
|
||||
}
|
||||
@ -0,0 +1,4 @@
|
||||
pluginId: simple-greeting
|
||||
version: 1.0.0
|
||||
pluginClass: com.gewuyou.forgeboot.plugin.demo.impl.SimpleGreetingPlugin
|
||||
pluginDescription: A greeting plugin
|
||||
3
forgeboot-demo/forgeboot-plugin-demo/forgeboot-plugin-demo-server/.gitattributes
vendored
Normal file
3
forgeboot-demo/forgeboot-plugin-demo/forgeboot-plugin-demo-server/.gitattributes
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
/gradlew text eol=lf
|
||||
*.bat text eol=crlf
|
||||
*.jar binary
|
||||
40
forgeboot-demo/forgeboot-plugin-demo/forgeboot-plugin-demo-server/.gitignore
vendored
Normal file
40
forgeboot-demo/forgeboot-plugin-demo/forgeboot-plugin-demo-server/.gitignore
vendored
Normal file
@ -0,0 +1,40 @@
|
||||
HELP.md
|
||||
.gradle
|
||||
build/
|
||||
!gradle/wrapper/gradle-wrapper.jar
|
||||
!**/src/main/**/build/
|
||||
!**/src/test/**/build/
|
||||
|
||||
### STS ###
|
||||
.apt_generated
|
||||
.classpath
|
||||
.factorypath
|
||||
.project
|
||||
.settings
|
||||
.springBeans
|
||||
.sts4-cache
|
||||
bin/
|
||||
!**/src/main/**/bin/
|
||||
!**/src/test/**/bin/
|
||||
|
||||
### IntelliJ IDEA ###
|
||||
.idea
|
||||
*.iws
|
||||
*.iml
|
||||
*.ipr
|
||||
out/
|
||||
!**/src/main/**/out/
|
||||
!**/src/test/**/out/
|
||||
|
||||
### NetBeans ###
|
||||
/nbproject/private/
|
||||
/nbbuild/
|
||||
/dist/
|
||||
/nbdist/
|
||||
/.nb-gradle/
|
||||
|
||||
### VS Code ###
|
||||
.vscode/
|
||||
|
||||
### Kotlin ###
|
||||
.kotlin
|
||||
@ -0,0 +1,6 @@
|
||||
dependencies {
|
||||
implementation(project(Modules.Demo.Plugin.API))
|
||||
implementation(project(Modules.Plugin.CORE))
|
||||
implementation(project(Modules.Plugin.SPRING))
|
||||
implementation(libs.springBootStarter.web)
|
||||
}
|
||||
Binary file not shown.
@ -0,0 +1,11 @@
|
||||
package com.gewuyou.forgeboot.plugin.demo.server
|
||||
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication
|
||||
import org.springframework.boot.runApplication
|
||||
|
||||
@SpringBootApplication
|
||||
class ForgebootPluginDemoServerApplication
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
runApplication<ForgebootPluginDemoServerApplication>(*args)
|
||||
}
|
||||
@ -0,0 +1,22 @@
|
||||
package com.gewuyou.forgeboot.plugin.demo.server.controller
|
||||
|
||||
import com.gewuyou.forgeboot.plugin.demo.api.GreetingService
|
||||
import org.springframework.context.annotation.Lazy
|
||||
import org.springframework.web.bind.annotation.GetMapping
|
||||
import org.springframework.web.bind.annotation.RequestParam
|
||||
import org.springframework.web.bind.annotation.RestController
|
||||
|
||||
/**
|
||||
*演示控制器
|
||||
*
|
||||
* @since 2025-07-24 12:37:26
|
||||
* @author gewuyou
|
||||
*/
|
||||
@RestController
|
||||
class DemoController(
|
||||
@Lazy
|
||||
private val greetingService: GreetingService
|
||||
) {
|
||||
@GetMapping("/plugin/greet")
|
||||
fun greet(@RequestParam("name") name: String) = greetingService.greet(name)
|
||||
}
|
||||
@ -0,0 +1,15 @@
|
||||
package com.gewuyou.forgeboot.plugin.demo.server.provider
|
||||
|
||||
import com.gewuyou.forgeboot.plugin.demo.api.GreetingProvider
|
||||
import org.springframework.stereotype.Component
|
||||
|
||||
/**
|
||||
*服务器问候提供商
|
||||
*
|
||||
* @since 2025-07-24 15:10:38
|
||||
* @author gewuyou
|
||||
*/
|
||||
@Component
|
||||
class ServerGreetingProvider: GreetingProvider {
|
||||
override fun message(): String = "服务器问候"
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
forgeboot:
|
||||
plugin:
|
||||
path: .\forgeboot-demo\forgeboot-plugin-demo\forgeboot-plugin-demo-server\plugins
|
||||
49
forgeboot-i18n/README.md
Normal file
49
forgeboot-i18n/README.md
Normal file
@ -0,0 +1,49 @@
|
||||
# forgeboot-i18n-spring-boot-starter
|
||||
|
||||
国际化 (i18n) 支持模块
|
||||
|
||||
## 简介
|
||||
|
||||
`forgeboot-i18n-spring-boot-starter` 提供消息资源加载、动态刷新、注解支持等国际化能力。
|
||||
|
||||
## 核心功能
|
||||
|
||||
- **forgeboot-i18n-api**:定义消息服务接口。
|
||||
- **forgeboot-i18n-impl**:基于 Spring `MessageSource` 的默认实现,支持多语言资源。
|
||||
- **forgeboot-i18n-autoconfigure**:自动配置 `MessageSource`、配置属性读取。
|
||||
|
||||
## 引入依赖
|
||||
|
||||
Maven:
|
||||
```xml
|
||||
<dependency>
|
||||
<groupId>io.github.gewuyou</groupId>
|
||||
<artifactId>forgeboot-i18n-spring-boot-starter</artifactId>
|
||||
<version>${version}</version>
|
||||
</dependency>
|
||||
```
|
||||
使用 Gradle:
|
||||
```groovy
|
||||
implementation "io.github.gewuyou:forgeboot-i18n-spring-boot-starter:${version}"
|
||||
```
|
||||
|
||||
## 快速开始
|
||||
|
||||
在 `application.yml` 中添加:
|
||||
```yaml
|
||||
forgeboot:
|
||||
i18n:
|
||||
basename: messages
|
||||
default-locale: en_US
|
||||
cache-seconds: 3600
|
||||
```
|
||||
通过 `@Autowired Messages messages; messages.get("key");` 获取消息。
|
||||
|
||||
## 构建
|
||||
```bash
|
||||
./gradlew :forgeboot-i18n:build
|
||||
```
|
||||
|
||||
## 许可
|
||||
|
||||
Apache-2.0
|
||||
3
forgeboot-plugin/.gitattributes
vendored
Normal file
3
forgeboot-plugin/.gitattributes
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
/gradlew text eol=lf
|
||||
*.bat text eol=crlf
|
||||
*.jar binary
|
||||
40
forgeboot-plugin/.gitignore
vendored
Normal file
40
forgeboot-plugin/.gitignore
vendored
Normal file
@ -0,0 +1,40 @@
|
||||
HELP.md
|
||||
.gradle
|
||||
build/
|
||||
!gradle/wrapper/gradle-wrapper.jar
|
||||
!**/src/main/**/build/
|
||||
!**/src/test/**/build/
|
||||
|
||||
### STS ###
|
||||
.apt_generated
|
||||
.classpath
|
||||
.factorypath
|
||||
.project
|
||||
.settings
|
||||
.springBeans
|
||||
.sts4-cache
|
||||
bin/
|
||||
!**/src/main/**/bin/
|
||||
!**/src/test/**/bin/
|
||||
|
||||
### IntelliJ IDEA ###
|
||||
.idea
|
||||
*.iws
|
||||
*.iml
|
||||
*.ipr
|
||||
out/
|
||||
!**/src/main/**/out/
|
||||
!**/src/test/**/out/
|
||||
|
||||
### NetBeans ###
|
||||
/nbproject/private/
|
||||
/nbbuild/
|
||||
/dist/
|
||||
/nbdist/
|
||||
/.nb-gradle/
|
||||
|
||||
### VS Code ###
|
||||
.vscode/
|
||||
|
||||
### Kotlin ###
|
||||
.kotlin
|
||||
4
forgeboot-plugin/build.gradle.kts
Normal file
4
forgeboot-plugin/build.gradle.kts
Normal file
@ -0,0 +1,4 @@
|
||||
|
||||
dependencies {
|
||||
|
||||
}
|
||||
3
forgeboot-plugin/forgeboot-plugin-core/.gitattributes
vendored
Normal file
3
forgeboot-plugin/forgeboot-plugin-core/.gitattributes
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
/gradlew text eol=lf
|
||||
*.bat text eol=crlf
|
||||
*.jar binary
|
||||
40
forgeboot-plugin/forgeboot-plugin-core/.gitignore
vendored
Normal file
40
forgeboot-plugin/forgeboot-plugin-core/.gitignore
vendored
Normal file
@ -0,0 +1,40 @@
|
||||
HELP.md
|
||||
.gradle
|
||||
build/
|
||||
!gradle/wrapper/gradle-wrapper.jar
|
||||
!**/src/main/**/build/
|
||||
!**/src/test/**/build/
|
||||
|
||||
### STS ###
|
||||
.apt_generated
|
||||
.classpath
|
||||
.factorypath
|
||||
.project
|
||||
.settings
|
||||
.springBeans
|
||||
.sts4-cache
|
||||
bin/
|
||||
!**/src/main/**/bin/
|
||||
!**/src/test/**/bin/
|
||||
|
||||
### IntelliJ IDEA ###
|
||||
.idea
|
||||
*.iws
|
||||
*.iml
|
||||
*.ipr
|
||||
out/
|
||||
!**/src/main/**/out/
|
||||
!**/src/test/**/out/
|
||||
|
||||
### NetBeans ###
|
||||
/nbproject/private/
|
||||
/nbbuild/
|
||||
/dist/
|
||||
/nbdist/
|
||||
/.nb-gradle/
|
||||
|
||||
### VS Code ###
|
||||
.vscode/
|
||||
|
||||
### Kotlin ###
|
||||
.kotlin
|
||||
9
forgeboot-plugin/forgeboot-plugin-core/build.gradle.kts
Normal file
9
forgeboot-plugin/forgeboot-plugin-core/build.gradle.kts
Normal file
@ -0,0 +1,9 @@
|
||||
|
||||
dependencies {
|
||||
api(libs.org.yaml.snakeyaml)
|
||||
api(libs.org.pf4j)
|
||||
}
|
||||
// 全局排除 slf4j-reload4j
|
||||
configurations.all {
|
||||
exclude(group = "org.slf4j", module = "slf4j-reload4j")
|
||||
}
|
||||
@ -0,0 +1,85 @@
|
||||
package com.gewuyou.forgeboot.plugin.core.finder
|
||||
|
||||
import com.gewuyou.forgeboot.plugin.core.mapper.YamlPluginDescriptorMapper
|
||||
import org.pf4j.PluginDescriptor
|
||||
import org.pf4j.PluginDescriptorFinder
|
||||
import org.pf4j.PluginRuntimeException
|
||||
import org.pf4j.util.FileUtils
|
||||
import org.yaml.snakeyaml.LoaderOptions
|
||||
import org.yaml.snakeyaml.Yaml
|
||||
import org.yaml.snakeyaml.constructor.Constructor
|
||||
import java.io.IOException
|
||||
import java.io.InputStreamReader
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.Path
|
||||
import java.nio.file.Paths
|
||||
|
||||
/**
|
||||
* 映射YAML插件描述符查找器
|
||||
*
|
||||
* @since 2025-07-22 22:46:42
|
||||
* @author gewuyou
|
||||
*/
|
||||
class MappableYamlPluginDescriptorFinder<T : PluginDescriptor, R>(
|
||||
private val metadataClass: Class<R>,
|
||||
private val descriptorMapper: YamlPluginDescriptorMapper<T, R>,
|
||||
private val yamlFileName: String = "plugin.yml"
|
||||
) : PluginDescriptorFinder {
|
||||
|
||||
/**
|
||||
* 判断插件路径是否适用当前查找器
|
||||
*
|
||||
* @param pluginPath 插件路径
|
||||
* @return 如果路径存在且为目录或 ZIP/JAR 文件则返回 true
|
||||
*/
|
||||
override fun isApplicable(pluginPath: Path): Boolean {
|
||||
return Files.exists(pluginPath) && (Files.isDirectory(pluginPath) || FileUtils.isZipOrJarFile(pluginPath))
|
||||
}
|
||||
|
||||
/**
|
||||
* 查找并解析插件描述符
|
||||
*
|
||||
* @param pluginPath 插件路径
|
||||
* @return 解析后的插件描述符
|
||||
*/
|
||||
override fun find(pluginPath: Path): PluginDescriptor {
|
||||
val path = getYamlPath(pluginPath)
|
||||
if (!Files.exists(path)) {
|
||||
throw PluginRuntimeException("Cannot find descriptor file: $path")
|
||||
}
|
||||
val metadata = loadYamlFromPath(path)
|
||||
return descriptorMapper.mapFrom(metadata)
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 YAML 文件的路径
|
||||
*
|
||||
* @param pluginPath 插件路径
|
||||
* @return YAML 文件的路径
|
||||
*/
|
||||
private fun getYamlPath(pluginPath: Path): Path {
|
||||
return if (Files.isDirectory(pluginPath)) {
|
||||
pluginPath.resolve(Paths.get(yamlFileName))
|
||||
} else {
|
||||
try {
|
||||
FileUtils.getPath(pluginPath, yamlFileName)
|
||||
} catch (e: IOException) {
|
||||
throw PluginRuntimeException(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 从指定路径加载 YAML 数据
|
||||
*
|
||||
* @param path YAML 文件路径
|
||||
* @return 解析后的对象
|
||||
*/
|
||||
private fun loadYamlFromPath(path: Path): R {
|
||||
val inputStream = Files.newInputStream(path)
|
||||
val reader = InputStreamReader(inputStream, Charsets.UTF_8)
|
||||
val yaml = Yaml(Constructor(metadataClass, LoaderOptions()))
|
||||
return yaml.load<R>(reader)
|
||||
?: throw PluginRuntimeException("Failed to load YAML from: $path")
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,98 @@
|
||||
package com.gewuyou.forgeboot.plugin.core.finder
|
||||
|
||||
import org.pf4j.PluginDescriptor
|
||||
import org.pf4j.PluginDescriptorFinder
|
||||
import org.pf4j.PluginRuntimeException
|
||||
import org.pf4j.util.FileUtils
|
||||
import org.yaml.snakeyaml.LoaderOptions
|
||||
import org.yaml.snakeyaml.Yaml
|
||||
import org.yaml.snakeyaml.constructor.Constructor
|
||||
import java.io.IOException
|
||||
import java.io.InputStreamReader
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.Path
|
||||
import java.nio.file.Paths
|
||||
|
||||
/**
|
||||
* 强类型泛型YAML插件描述符查找器
|
||||
* 用于从指定路径中查找并解析YAML格式的插件描述符文件
|
||||
*
|
||||
* @param descriptorClass 插件描述符的类类型,用于解析YAML文件时构造对应的对象
|
||||
* @param yamlFileName YAML文件的名称,默认为"plugin.yml"
|
||||
* @since 2025-07-22 22:26:20
|
||||
* @author gewuyou
|
||||
*/
|
||||
open class TypedYamlPluginDescriptorFinder<T : PluginDescriptor>(
|
||||
protected val descriptorClass: Class<T>,
|
||||
protected val yamlFileName: String = "plugin.yml",
|
||||
) : PluginDescriptorFinder {
|
||||
|
||||
/**
|
||||
* 检查给定的插件路径是否适用于此查找器
|
||||
*
|
||||
* @param pluginPath 插件的路径
|
||||
* @return 如果路径存在且为目录或ZIP/JAR文件,则返回true,否则返回false
|
||||
*/
|
||||
override fun isApplicable(pluginPath: Path): Boolean {
|
||||
return Files.exists(pluginPath) && (Files.isDirectory(pluginPath) || FileUtils.isZipOrJarFile(pluginPath))
|
||||
}
|
||||
|
||||
/**
|
||||
* 在给定的插件路径中查找并解析插件描述符
|
||||
*
|
||||
* @param pluginPath 插件的路径
|
||||
* @return 解析后的PluginDescriptor对象
|
||||
* @throws PluginRuntimeException 如果无法找到描述符文件,则抛出此异常
|
||||
*/
|
||||
override fun find(pluginPath: Path): PluginDescriptor {
|
||||
val path = getYamlPath(pluginPath)
|
||||
if (!Files.exists(path)) {
|
||||
throw PluginRuntimeException("Cannot find descriptor file: $path")
|
||||
}
|
||||
return parseYamlDescriptor(path)
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取YAML描述符文件的路径
|
||||
*
|
||||
* @param pluginPath 插件的路径
|
||||
* @return 描述符文件的路径
|
||||
* @throws PluginRuntimeException 如果路径不存在,则抛出此异常
|
||||
*/
|
||||
private fun getYamlPath(pluginPath: Path): Path {
|
||||
if (Files.isDirectory(pluginPath)) {
|
||||
return pluginPath.resolve(Paths.get(yamlFileName))
|
||||
}
|
||||
// 处理ZIP或JAR文件的情况,获取其中的YAML文件路径
|
||||
try {
|
||||
return FileUtils.getPath(pluginPath, yamlFileName)
|
||||
} catch (e: IOException) {
|
||||
throw PluginRuntimeException(e)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析YAML格式的插件描述符
|
||||
*
|
||||
* @param path 插件描述符的路径
|
||||
* @return 解析后的PluginDescriptor对象
|
||||
*/
|
||||
protected open fun parseYamlDescriptor(path: Path): PluginDescriptor {
|
||||
return loadYamlFromPath(path)
|
||||
}
|
||||
|
||||
/**
|
||||
* 从指定路径加载YAML文件并解析为指定的类型
|
||||
*
|
||||
* @param path YAML文件的路径
|
||||
* @return 解析后的对象,类型为T
|
||||
* @throws PluginRuntimeException 如果加载或解析YAML失败,则抛出此异常
|
||||
*/
|
||||
protected fun loadYamlFromPath(path: Path): T {
|
||||
val inputStream = Files.newInputStream(path)
|
||||
val reader = InputStreamReader(inputStream, Charsets.UTF_8)
|
||||
val yaml = Yaml(Constructor(descriptorClass, LoaderOptions()))
|
||||
return yaml.load<T>(reader)
|
||||
?: throw PluginRuntimeException("Failed to load YAML from: $path")
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,77 @@
|
||||
package com.gewuyou.forgeboot.plugin.core.finder
|
||||
|
||||
import org.pf4j.*
|
||||
import org.pf4j.util.FileUtils
|
||||
import org.yaml.snakeyaml.LoaderOptions
|
||||
import org.yaml.snakeyaml.Yaml
|
||||
import java.io.InputStreamReader
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.Path
|
||||
import java.nio.file.Paths
|
||||
|
||||
|
||||
/**
|
||||
*YAML插件描述符查找器
|
||||
*
|
||||
* @since 2025-07-24 13:24:18
|
||||
* @author gewuyou
|
||||
*/
|
||||
class YamlPluginDescriptorFinder(
|
||||
private val yamlFileName: String = "plugin.yml",
|
||||
) : PluginDescriptorFinder {
|
||||
|
||||
class YamlDescriptor {
|
||||
var pluginId: String? = null
|
||||
var pluginDescription: String? = null
|
||||
var pluginClass: String? = null
|
||||
var version: String? = null
|
||||
var provider: String? = null
|
||||
var dependencies: String? = null
|
||||
var requires: String = "*" // SemVer format
|
||||
var license: String? = null
|
||||
}
|
||||
|
||||
|
||||
override fun isApplicable(pluginPath: Path): Boolean {
|
||||
return Files.exists(pluginPath) && (Files.isDirectory(pluginPath) || FileUtils.isZipOrJarFile(pluginPath))
|
||||
}
|
||||
|
||||
override fun find(pluginPath: Path): PluginDescriptor {
|
||||
val descriptorPath = getYamlPath(pluginPath)
|
||||
if (!Files.exists(descriptorPath)) {
|
||||
throw PluginRuntimeException("YAML descriptor file not found: $descriptorPath")
|
||||
}
|
||||
|
||||
val yaml = Yaml(LoaderOptions())
|
||||
val reader = InputStreamReader(Files.newInputStream(descriptorPath), Charsets.UTF_8)
|
||||
val yamlDescriptor = yaml.loadAs(reader, YamlDescriptor::class.java)
|
||||
|
||||
return DefaultPluginDescriptor(
|
||||
yamlDescriptor.pluginId,
|
||||
yamlDescriptor.pluginDescription,
|
||||
yamlDescriptor.pluginClass,
|
||||
yamlDescriptor.version,
|
||||
yamlDescriptor.requires,
|
||||
yamlDescriptor.provider,
|
||||
yamlDescriptor.license
|
||||
).apply {
|
||||
yamlDescriptor.dependencies
|
||||
?.split(",")
|
||||
?.map { it.trim() }
|
||||
?.filter { it.isNotEmpty() }
|
||||
?.forEach { addDependency(PluginDependency(it)) }
|
||||
}
|
||||
}
|
||||
|
||||
private fun getYamlPath(pluginPath: Path): Path {
|
||||
return if (Files.isDirectory(pluginPath)) {
|
||||
pluginPath.resolve(Paths.get(yamlFileName))
|
||||
} else {
|
||||
try {
|
||||
FileUtils.getPath(pluginPath, yamlFileName)
|
||||
} catch (e: Exception) {
|
||||
throw PluginRuntimeException(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,25 @@
|
||||
package com.gewuyou.forgeboot.plugin.core.mapper
|
||||
|
||||
import org.pf4j.PluginDescriptor
|
||||
|
||||
/**
|
||||
* YAML插件描述符映射器
|
||||
*
|
||||
* 该函数式接口用于将一种数据结构(R类型)映射为插件描述符对象(T类型,继承自PluginDescriptor)。
|
||||
* 主要用于插件系统中对不同格式的描述信息进行统一转换。
|
||||
*
|
||||
* @param T 插件描述符类型,必须继承自 PluginDescriptor
|
||||
* @param R 源数据类型,用于提供映射所需的原始信息
|
||||
*
|
||||
* @since 2025-07-22 22:45:25
|
||||
* @author gewuyou
|
||||
*/
|
||||
fun interface YamlPluginDescriptorMapper<T : PluginDescriptor, R> {
|
||||
/**
|
||||
* 将给定的源数据对象映射为插件描述符实例。
|
||||
*
|
||||
* @param metadata 提供映射所需数据的源对象
|
||||
* @return 返回映射生成的插件描述符对象(T类型)
|
||||
*/
|
||||
fun mapFrom(metadata: R): T
|
||||
}
|
||||
3
forgeboot-plugin/forgeboot-plugin-spring/.gitattributes
vendored
Normal file
3
forgeboot-plugin/forgeboot-plugin-spring/.gitattributes
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
/gradlew text eol=lf
|
||||
*.bat text eol=crlf
|
||||
*.jar binary
|
||||
37
forgeboot-plugin/forgeboot-plugin-spring/.gitignore
vendored
Normal file
37
forgeboot-plugin/forgeboot-plugin-spring/.gitignore
vendored
Normal file
@ -0,0 +1,37 @@
|
||||
HELP.md
|
||||
.gradle
|
||||
build/
|
||||
!gradle/wrapper/gradle-wrapper.jar
|
||||
!**/src/main/**/build/
|
||||
!**/src/test/**/build/
|
||||
|
||||
### STS ###
|
||||
.apt_generated
|
||||
.classpath
|
||||
.factorypath
|
||||
.project
|
||||
.settings
|
||||
.springBeans
|
||||
.sts4-cache
|
||||
bin/
|
||||
!**/src/main/**/bin/
|
||||
!**/src/test/**/bin/
|
||||
|
||||
### IntelliJ IDEA ###
|
||||
.idea
|
||||
*.iws
|
||||
*.iml
|
||||
*.ipr
|
||||
out/
|
||||
!**/src/main/**/out/
|
||||
!**/src/test/**/out/
|
||||
|
||||
### NetBeans ###
|
||||
/nbproject/private/
|
||||
/nbbuild/
|
||||
/dist/
|
||||
/nbdist/
|
||||
/.nb-gradle/
|
||||
|
||||
### VS Code ###
|
||||
.vscode/
|
||||
11
forgeboot-plugin/forgeboot-plugin-spring/build.gradle.kts
Normal file
11
forgeboot-plugin/forgeboot-plugin-spring/build.gradle.kts
Normal file
@ -0,0 +1,11 @@
|
||||
dependencies {
|
||||
api(libs.org.yaml.snakeyaml)
|
||||
api(libs.org.pf4jSpring)
|
||||
compileOnly(libs.springBoot.starter)
|
||||
implementation(project(Modules.Plugin.CORE))
|
||||
implementation(project(Modules.Core.EXTENSION))
|
||||
}
|
||||
// 全局排除 slf4j-reload4j
|
||||
configurations.all {
|
||||
exclude(group = "org.slf4j", module = "slf4j-reload4j")
|
||||
}
|
||||
@ -0,0 +1,48 @@
|
||||
package com.gewuyou.forgeboot.plugin.spring
|
||||
|
||||
import org.pf4j.PluginWrapper
|
||||
import org.pf4j.spring.SpringPlugin
|
||||
import org.springframework.context.ApplicationContext
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext
|
||||
|
||||
/**
|
||||
* 隔离的Spring插件
|
||||
*
|
||||
* 该抽象类继承自SpringPlugin,提供了独立的Spring应用上下文,
|
||||
* 使得每个插件可以在自己的上下文中管理Bean,实现插件间的隔离。
|
||||
*
|
||||
* @property pluginWrapper 插件包装器,提供插件的基本信息和类加载器
|
||||
*
|
||||
* @since 2025-07-24 15:26:45
|
||||
* @author gewuyou
|
||||
*/
|
||||
abstract class IsolatedSpringPlugin(
|
||||
private val pluginWrapper: PluginWrapper
|
||||
) : SpringPlugin(pluginWrapper) {
|
||||
|
||||
/**
|
||||
* 创建应用上下文
|
||||
*
|
||||
* 该方法覆盖了父类的实现,创建一个独立的AnnotationConfigApplicationContext,
|
||||
* 设置插件的类加载器,并注册插件特定的配置类。
|
||||
*
|
||||
* @return 配置完成的ApplicationContext实例
|
||||
*/
|
||||
override fun createApplicationContext(): ApplicationContext {
|
||||
return AnnotationConfigApplicationContext().apply {
|
||||
classLoader = pluginWrapper.pluginClassLoader
|
||||
register(pluginConfigurationClass())
|
||||
refresh()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取插件配置类
|
||||
*
|
||||
* 抽象方法,子类需要提供插件特定的配置类,
|
||||
* 该配置类将被注册到插件的应用上下文中。
|
||||
*
|
||||
* @return 插件配置类的Class对象
|
||||
*/
|
||||
abstract fun pluginConfigurationClass(): Class<*>
|
||||
}
|
||||
@ -0,0 +1,54 @@
|
||||
package com.gewuyou.forgeboot.plugin.spring
|
||||
|
||||
import org.pf4j.PluginWrapper
|
||||
import org.pf4j.spring.SpringPlugin
|
||||
import org.pf4j.spring.SpringPluginManager
|
||||
import org.springframework.context.ApplicationContext
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext
|
||||
import org.springframework.core.env.ConfigurableEnvironment
|
||||
|
||||
/**
|
||||
* 合并的Spring插件
|
||||
*
|
||||
* 该抽象类继承自SpringPlugin,与IsolatedSpringPlugin不同,
|
||||
* 它创建的插件应用上下文与主应用上下文建立父子关系,
|
||||
* 使得插件可以访问主应用上下文中的Bean,实现插件与主应用的合并。
|
||||
*
|
||||
* @property pluginWrapper 插件包装器,提供插件的基本信息和类加载器
|
||||
*
|
||||
* @since 2025-07-24 15:35:52
|
||||
* @author gewuyou
|
||||
*/
|
||||
abstract class MergedSpringPlugin(
|
||||
private val pluginWrapper: PluginWrapper
|
||||
) : SpringPlugin(pluginWrapper) {
|
||||
|
||||
/**
|
||||
* 创建应用上下文
|
||||
*
|
||||
* 该方法覆盖了父类的实现,创建一个与主应用上下文有关联的AnnotationConfigApplicationContext,
|
||||
* 设置插件的类加载器,建立父子上下文关系,并注册插件特定的配置类。
|
||||
*
|
||||
* @return 配置完成的ApplicationContext实例
|
||||
*/
|
||||
override fun createApplicationContext(): ApplicationContext {
|
||||
return AnnotationConfigApplicationContext().apply {
|
||||
classLoader = pluginWrapper.pluginClassLoader
|
||||
parent = (pluginWrapper.pluginManager as SpringPluginManager).applicationContext
|
||||
// 保证配置文件能读取
|
||||
environment = parent?.environment as ConfigurableEnvironment
|
||||
register(pluginConfigurationClass())
|
||||
refresh()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取插件配置类
|
||||
*
|
||||
* 抽象方法,子类需要提供插件特定的配置类,
|
||||
* 该配置类将被注册到插件的应用上下文中。
|
||||
*
|
||||
* @return 插件配置类的Class对象
|
||||
*/
|
||||
abstract fun pluginConfigurationClass(): Class<*>
|
||||
}
|
||||
@ -0,0 +1,52 @@
|
||||
package com.gewuyou.forgeboot.plugin.spring.config
|
||||
|
||||
import com.gewuyou.forgeboot.plugin.spring.manager.SpringPluginManager
|
||||
import org.pf4j.DefaultPluginManager.PLUGINS_DIR_CONFIG_PROPERTY_NAME
|
||||
import org.pf4j.ExtensionFactory
|
||||
import org.pf4j.PluginManager
|
||||
import org.pf4j.spring.SingletonSpringExtensionFactory
|
||||
import org.springframework.beans.factory.annotation.Value
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean
|
||||
import org.springframework.context.annotation.Bean
|
||||
import org.springframework.context.annotation.Configuration
|
||||
import java.nio.file.Paths
|
||||
|
||||
/**
|
||||
* 插件Spring自动配置类
|
||||
*
|
||||
* 该类用于在Spring环境中自动配置插件管理器及相关功能。
|
||||
* 提供了插件管理器的Bean定义以及插件集成的初始化逻辑。
|
||||
*
|
||||
* @since 2025-07-23 13:01:27
|
||||
* @author gewuyou
|
||||
*/
|
||||
@Configuration
|
||||
class PluginSpringAutoConfiguration() {
|
||||
/**
|
||||
* 提供一个默认的插件管理器Bean。
|
||||
*
|
||||
* 当Spring容器中尚未定义PluginManager类型的Bean时,
|
||||
* 该方法将创建并配置一个SpringPluginManager实例作为默认插件管理器。
|
||||
* 插件路径通过@Value注解从配置文件中解析,若未配置则使用默认值。
|
||||
*
|
||||
* @param pluginPath 插件存放路径,从配置文件中读取,默认值为"plugins"
|
||||
* @return 返回一个配置好的PluginManager实例,用于管理插件的生命周期和功能
|
||||
*/
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
fun pluginManager(@Value("\${forgeboot.plugin.path}") pluginPath: String = PLUGINS_DIR_CONFIG_PROPERTY_NAME): PluginManager {
|
||||
return SpringPluginManager(listOf(Paths.get(pluginPath)))
|
||||
}
|
||||
/**
|
||||
* 创建并配置ExtensionFactory实例
|
||||
* 该方法在插件管理器初始化之后调用,用于创建扩展工厂,进一步扩展系统功能
|
||||
*
|
||||
* @param pluginManager 已初始化并启动的插件管理器,用于扩展工厂的构建
|
||||
* @return ExtensionFactory 初始化后的扩展工厂实例
|
||||
*/
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
fun extensionFactory(pluginManager: PluginManager): ExtensionFactory {
|
||||
return SingletonSpringExtensionFactory(pluginManager)
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,25 @@
|
||||
package com.gewuyou.forgeboot.plugin.spring.manager
|
||||
|
||||
import com.gewuyou.forgeboot.plugin.core.finder.YamlPluginDescriptorFinder
|
||||
import org.pf4j.CompoundPluginDescriptorFinder
|
||||
import org.pf4j.ManifestPluginDescriptorFinder
|
||||
import org.pf4j.PropertiesPluginDescriptorFinder
|
||||
import org.pf4j.spring.SpringPluginManager
|
||||
import java.nio.file.Path
|
||||
|
||||
/**
|
||||
*Spring插件管理器
|
||||
*
|
||||
* @since 2025-07-24 13:15:40
|
||||
* @author gewuyou
|
||||
*/
|
||||
open class SpringPluginManager(
|
||||
pluginsRoots: List<Path>,
|
||||
) : SpringPluginManager(pluginsRoots) {
|
||||
override fun createPluginDescriptorFinder(): CompoundPluginDescriptorFinder {
|
||||
return CompoundPluginDescriptorFinder()
|
||||
.add(YamlPluginDescriptorFinder())
|
||||
.add(PropertiesPluginDescriptorFinder())
|
||||
.add(ManifestPluginDescriptorFinder())
|
||||
}
|
||||
}
|
||||
@ -0,0 +1 @@
|
||||
com.gewuyou.forgeboot.plugin.spring.config.PluginSpringAutoConfiguration
|
||||
84
forgeboot-trace/README.md
Normal file
84
forgeboot-trace/README.md
Normal file
@ -0,0 +1,84 @@
|
||||
# forgeboot-trace-spring-boot-starter
|
||||
|
||||
> 🔍 分布式调用链追踪模块,基于上下文感知系统实现 requestId / traceId 的自动生成、注入与传播,适配协程、Reactor、线程池等多种执行模型。
|
||||
|
||||
---
|
||||
|
||||
## 🧩 简介
|
||||
|
||||
`forgeboot-trace-spring-boot-starter` 是 ForgeBoot 提供的轻量级调用链追踪模块,致力于在服务内部及分布式场景中提供统一的 traceId 管理机制。
|
||||
|
||||
该模块依赖 `forgeboot-context` 实现 traceId 的透明传递,支持与日志系统(MDC)、Web 框架(Servlet / WebFlux)无缝集成。
|
||||
|
||||
---
|
||||
|
||||
## ✨ 核心功能
|
||||
|
||||
- ✅ 支持全局唯一的 traceId/requestId 自动生成与注入
|
||||
- ✅ 与日志系统集成(MDC 支持)
|
||||
- ✅ 支持从 HTTP 请求头中自动提取 traceId
|
||||
- ✅ 基于 `forgeboot-context` 实现跨线程 / 协程 / Reactor 任务 traceId 传递
|
||||
- ✅ 可配置的 traceId 生成策略(内置 UUID,支持扩展如 OpenTelemetry)
|
||||
- ✅ 适配 Spring Boot 自动装配,开箱即用
|
||||
|
||||
---
|
||||
|
||||
## 📦 引入依赖
|
||||
|
||||
使用 Maven:
|
||||
|
||||
```xml
|
||||
<dependency>
|
||||
<groupId>io.github.gewuyou</groupId>
|
||||
<artifactId>forgeboot-trace-spring-boot-starter</artifactId>
|
||||
<version>${version}</version>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
使用 Gradle:
|
||||
|
||||
```groovy
|
||||
implementation "io.github.gewuyou:forgeboot-trace-spring-boot-starter:${version}"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🚀 快速开始
|
||||
|
||||
1. 引入依赖并启用自动配置(Spring Boot 自动生效)
|
||||
|
||||
2. 在日志配置中添加 traceId(以 logback 为例):
|
||||
|
||||
```xml
|
||||
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level traceId=%X{traceId} %logger{36} - %msg%n</pattern>
|
||||
```
|
||||
|
||||
3. 可在任何业务代码中通过上下文访问:
|
||||
|
||||
```kotlin
|
||||
val traceId = ContextHolder.get("traceId")
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ⚙️ 构建方式
|
||||
|
||||
使用 Gradle 命令进行构建发布:
|
||||
|
||||
```bash
|
||||
./gradlew :forgeboot-trace:build
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📄 许可
|
||||
|
||||
本项目采用 [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0) 开源协议。
|
||||
|
||||
---
|
||||
|
||||
## 📬 联系作者
|
||||
|
||||
由 [@gewuyou](https://github.com/gewuyou) 维护。
|
||||
|
||||
欢迎提交 Issue 或 PR 改进本模块!
|
||||
47
forgeboot-webmvc/README.md
Normal file
47
forgeboot-webmvc/README.md
Normal file
@ -0,0 +1,47 @@
|
||||
# forgeboot-webmvc-spring-boot-starter
|
||||
|
||||
Web MVC 通用组件集合
|
||||
|
||||
## 简介
|
||||
|
||||
`forgeboot-webmvc-spring-boot-starter` 提供常用 Web 层组件,如版本管理、统一日志、全局异常处理、DTO 封装、参数校验、接口规范等。
|
||||
|
||||
## 核心模块
|
||||
|
||||
- **forgeboot-webmvc-version-spring-boot-starter**:API 版本控制
|
||||
- **forgeboot-webmvc-logger-spring-boot-starter**:请求/响应日志 AOP
|
||||
- **forgeboot-webmvc-exception-spring-boot-starter**:全局异常处理
|
||||
- **forgeboot-webmvc-exception-i18n-spring-boot-starter**:异常国际化
|
||||
- **forgeboot-webmvc-dto**:统一返回结构与分页工具
|
||||
- **forgeboot-webmvc-validation**:请求校验封装
|
||||
- **forgeboot-webmvc-spec**:自动生成接口规范文档
|
||||
|
||||
## 引入依赖
|
||||
|
||||
Maven:
|
||||
```xml
|
||||
<dependency>
|
||||
<groupId>io.github.gewuyou</groupId>
|
||||
<artifactId>forgeboot-webmvc-spring-boot-starter</artifactId>
|
||||
<version>${version}</version>
|
||||
</dependency>
|
||||
```
|
||||
使用 Gradle:
|
||||
```groovy
|
||||
implementation "io.github.gewuyou:forgeboot-webmvc-spring-boot-starter:${version}"
|
||||
```
|
||||
|
||||
## 快速开始
|
||||
|
||||
- 在 `application.yml` 中配置各模块开关和策略。
|
||||
- 使用 `BaseResult<T>` 或 `PageResult<T>` 封装返回值。
|
||||
- Controller 中使用 `@ApiVersion`, `@Validated` 等注解。
|
||||
|
||||
## 构建
|
||||
```bash
|
||||
./gradlew :forgeboot-webmvc:build
|
||||
```
|
||||
|
||||
## 许可
|
||||
|
||||
Apache-2.0
|
||||
197
forgeboot-webmvc/dto/README.md
Normal file
197
forgeboot-webmvc/dto/README.md
Normal file
@ -0,0 +1,197 @@
|
||||
# forgeboot-webmvc-dto
|
||||
|
||||
> 📦 Web 项目通用 DTO 模块,包含统一响应封装、分页/排序/过滤模型、JPA 查询构造扩展等内容。
|
||||
|
||||
---
|
||||
|
||||
## 🧩 简介
|
||||
|
||||
`forgeboot-webmvc-dto` 是 ForgeBoot 提供的 Web 项目 DTO 抽象模块,封装了常用的分页、排序、状态过滤等通用接口与请求模型,并提供统一的响应结构与查询构建工具,助力快速开发一致性良好的接口风格。
|
||||
|
||||
---
|
||||
|
||||
## ✨ 核心功能
|
||||
|
||||
- ✅ 标准化 API 响应结构:`BaseResult` / `PageResult` / `R`
|
||||
- ✅ 通用分页/排序/过滤参数模型:`Pageable`, `Sortable`, `StatusFilterable`
|
||||
- ✅ 查询构件组合接口:`QueryComponent` + 多种 Filterable 接口
|
||||
- ✅ JPA 查询扩展支持:`JpaPredicateExtensions`, `PredicateExtensions`
|
||||
- ✅ 响应信息国际化扩展:`I18nResult`
|
||||
- ✅ 日期范围、关键字等实体查询条件模型
|
||||
|
||||
---
|
||||
|
||||
## 📦 引入依赖
|
||||
|
||||
使用 Maven:
|
||||
|
||||
```xml
|
||||
<dependency>
|
||||
<groupId>io.github.gewuyou</groupId>
|
||||
<artifactId>forgeboot-webmvc-dto</artifactId>
|
||||
<version>${version}</version>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
使用 Gradle:
|
||||
|
||||
```groovy
|
||||
implementation "io.github.gewuyou:forgeboot-webmvc-dto:${version}"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🚀 快速开始
|
||||
|
||||
### ✅ 统一响应使用示例
|
||||
|
||||
```kotlin
|
||||
@GetMapping("/hello")
|
||||
fun hello(): R<String> {
|
||||
return R.ok("Hello, world!")
|
||||
}
|
||||
```
|
||||
|
||||
### ✅ 构建分页查询请求
|
||||
|
||||
```kotlin
|
||||
data class UserPageRequest(
|
||||
override val currentPage: Int,
|
||||
override val pageSize: Int,
|
||||
override val keyword: String?
|
||||
) : Pageable, KeywordSearchable
|
||||
```
|
||||
|
||||
结合 JPA Predicate 扩展:
|
||||
|
||||
```kotlin
|
||||
fun buildPredicate(request: UserPageRequest): Predicate {
|
||||
return where {
|
||||
orLike("username", request.keyword)
|
||||
andEqual("status", "ACTIVE")
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📘 高级用法
|
||||
|
||||
### 🔄 自动封装分页响应
|
||||
|
||||
```kotlin
|
||||
fun <T> toPageResult(page: Page<T>): PageResult<T> {
|
||||
return PageResult.of(page)
|
||||
}
|
||||
```
|
||||
|
||||
控制器示例:
|
||||
|
||||
```kotlin
|
||||
@GetMapping("/users")
|
||||
fun listUsers(request: UserPageRequest): PageResult<UserDTO> {
|
||||
val page = userService.query(request)
|
||||
return PageResult.of(page)
|
||||
}
|
||||
```
|
||||
|
||||
### 🔍 自定义查询组件组合
|
||||
|
||||
你可以组合多种查询接口,让请求类直接实现 `QueryComponent`,构建强类型的 DSL 查询请求对象:
|
||||
|
||||
```kotlin
|
||||
data class ProductQueryRequest(
|
||||
override val currentPage: Int,
|
||||
override val pageSize: Int,
|
||||
override val keyword: String?,
|
||||
override val status: Int?,
|
||||
override val dateRange: DateRangeCondition?
|
||||
) : QueryComponent, Pageable, KeywordSearchable, StatusFilterable, DateRangeFilterable
|
||||
```
|
||||
|
||||
一旦实现了这些接口,你就可以直接在 Controller 中使用 `.toJpaQuery()` 方法,无需再手动构建查询逻辑:
|
||||
|
||||
```kotlin
|
||||
@GetMapping("/products")
|
||||
fun query(request: ProductQueryRequest): PageResult<ProductDTO> {
|
||||
val (spec, pageRequest) = request.toJpaQuery<ProductEntity>()
|
||||
val page = productRepository.findAll(spec, pageRequest)
|
||||
return PageResult.of(page.map { it.toDTO() })
|
||||
}
|
||||
```
|
||||
|
||||
> ✅ 会自动根据你实现的接口生成分页、排序、关键字搜索、状态过滤、日期范围等查询条件,无需重复写繁琐的 JPA 条件拼接逻辑。
|
||||
|
||||
|
||||
---
|
||||
|
||||
## 🔍 JPA 查询构造器扩展
|
||||
|
||||
你可以使用 `QueryComponent.toJpaQuery()` 一键将请求对象转换为 JPA 查询规范和分页条件。
|
||||
|
||||
### ✅ 示例请求类
|
||||
|
||||
```kotlin
|
||||
data class ProductQueryRequest(
|
||||
override val currentPage: Int,
|
||||
override val pageSize: Int,
|
||||
override val keyword: String?,
|
||||
override val status: Int?,
|
||||
override val dateRange: DateRangeCondition?
|
||||
) : Pageable, Sortable, KeywordSearchable, StatusFilterable, DateRangeFilterable
|
||||
```
|
||||
|
||||
### ✅ 控制器代码(极简)
|
||||
|
||||
```kotlin
|
||||
@GetMapping("/products")
|
||||
fun query(request: ProductQueryRequest): PageResult<ProductDTO> {
|
||||
val (spec, pageRequest) = request.toJpaQuery<ProductEntity>()
|
||||
val page = productRepository.findAll(spec, pageRequest)
|
||||
return PageResult.of(page.map { it.toDTO() })
|
||||
}
|
||||
```
|
||||
|
||||
### ✅ 内部处理逻辑(你无需手写)
|
||||
|
||||
- 组合关键字模糊查询:`like lower(name)`、`like lower(description)`
|
||||
- 处理状态过滤:`where status = ?`
|
||||
- 构建日期范围:`createdAt >= ? and createdAt <= ?`
|
||||
- 构建排序条件(多字段或默认排序)
|
||||
- 构建分页信息(从 `currentPage` 开始,默认每页 10 条)
|
||||
|
||||
> 默认行为:如果请求未实现 `Pageable` 或 `Sortable`,会使用默认分页第 1 页、每页 10 条,无排序。
|
||||
|
||||
---
|
||||
|
||||
## 🧩 扩展组件介绍
|
||||
|
||||
|
||||
|
||||
| 模块 | 说明 |
|
||||
|--------------------------|----------------------------|
|
||||
| `BaseResult` | 基础响应模型(带状态码与信息) |
|
||||
| `PageResult` | 分页响应结构 |
|
||||
| `R` | 快捷响应构造器(等价于 Result.ok/err) |
|
||||
| `Pageable` | 分页能力接口 |
|
||||
| `Sortable` | 排序参数接口 |
|
||||
| `Filterable` | 通用过滤接口(可自定义字段过滤) |
|
||||
| `QueryComponent` | 查询字段组合容器(支持 DSL 构造) |
|
||||
| `DateRangeCondition` | 日期范围过滤器 |
|
||||
| `JpaPredicateExtensions` | JPA 查询构建扩展函数集 |
|
||||
|
||||
|
||||
|
||||
---
|
||||
|
||||
## 📄 许可协议
|
||||
|
||||
本项目采用 [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0) 开源协议。
|
||||
|
||||
---
|
||||
|
||||
## 📬 联系作者
|
||||
|
||||
由 [@gewuyou](https://github.com/gewuyou) 维护。
|
||||
|
||||
欢迎提交 Issue 或 PR 改进本模块!
|
||||
@ -9,7 +9,6 @@ dependencies {
|
||||
compileOnly(libs.jackson.annotations)
|
||||
compileOnly(libs.springBootStarter.jpa)
|
||||
compileOnly(libs.springBootStarter.validation)
|
||||
compileOnly(libs.org.mapstruct)
|
||||
}
|
||||
i18nKeyGen {
|
||||
rootPackage.set("com.gewuyou.forgeboot.webmvc.dto.i18n")
|
||||
|
||||
@ -1,49 +0,0 @@
|
||||
package com.gewuyou.forgeboot.webmvc.dto.mapper
|
||||
|
||||
import org.mapstruct.BeanMapping
|
||||
import org.mapstruct.MappingTarget
|
||||
import org.mapstruct.NullValuePropertyMappingStrategy
|
||||
|
||||
/**
|
||||
* Base Mapper(基础映射器)
|
||||
* 提供基础的对象映射操作定义,包含合并、覆盖合并、单个对象拷贝及列表拷贝的方法。
|
||||
*
|
||||
* @since 2025-05-30 22:50:18
|
||||
* @author gewuyou
|
||||
*/
|
||||
interface BaseMapper<S, T> {
|
||||
/**
|
||||
* 将 source 对象中的非 null 属性合并到 target 对象中。
|
||||
* 注意:null 值的属性不会覆盖 target 中已有的值。
|
||||
*
|
||||
* @param target 目标对象,将被更新
|
||||
* @param source 源对象,提供需要合并的数据
|
||||
*/
|
||||
@BeanMapping(nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE)
|
||||
fun mergeIgnoreNull(@MappingTarget target: T, source: S)
|
||||
|
||||
/**
|
||||
* 全量覆盖合并 source 到 target。
|
||||
* 注意:即使 source 中的字段为 null,也会覆盖 target 中对应的字段。
|
||||
*
|
||||
* @param target 目标对象,将被更新
|
||||
* @param source 源对象,提供需要合并的数据
|
||||
*/
|
||||
fun overwriteMerge(@MappingTarget target: T, source: S)
|
||||
|
||||
/**
|
||||
* 将 source 对象的内容拷贝到一个新的 T 类型对象中。
|
||||
*
|
||||
* @param source 源对象,提供数据
|
||||
* @return 返回一个新的目标类型对象
|
||||
*/
|
||||
fun copy(source: S): T
|
||||
|
||||
/**
|
||||
* 将源对象列表中的每个元素拷贝为新的目标类型对象,生成一个目标对象列表。
|
||||
*
|
||||
* @param sources 源对象列表
|
||||
* @return 返回目标类型对象的列表
|
||||
*/
|
||||
fun copyList(sources: List<S>): List<T>
|
||||
}
|
||||
@ -1,63 +0,0 @@
|
||||
package com.gewuyou.forgeboot.webmvc.dto.mapper
|
||||
|
||||
import org.mapstruct.BeanMapping
|
||||
import org.mapstruct.MappingTarget
|
||||
import org.mapstruct.NullValuePropertyMappingStrategy
|
||||
|
||||
/**
|
||||
* 转换映射器接口
|
||||
*
|
||||
* 提供通用的实体类(Entity)与数据传输对象(DTO)之间的双向转换能力。
|
||||
* 该接口定义了基础的数据转换方法,包括单个对象和集合对象的转换,
|
||||
* 并支持部分更新操作(忽略空值属性)。
|
||||
*
|
||||
* @param <Entity> 实体类类型
|
||||
* @param <Dto> 数据传输对象类型
|
||||
*
|
||||
* @since 2025-05-30 22:53:35
|
||||
* @author gewuyou
|
||||
*/
|
||||
interface ConversionMapper<Entity, Dto> {
|
||||
/**
|
||||
* 将实体对象转换为对应的DTO对象
|
||||
*
|
||||
* @param entity 需要转换的实体对象
|
||||
* @return 转换后的DTO对象
|
||||
*/
|
||||
fun toDto(entity: Entity): Dto
|
||||
|
||||
/**
|
||||
* 将DTO对象转换为对应的实体对象
|
||||
*
|
||||
* @param dto 需要转换的DTO对象
|
||||
* @return 转换后的实体对象
|
||||
*/
|
||||
fun toEntity(dto: Dto): Entity
|
||||
|
||||
/**
|
||||
* 将实体对象列表转换为对应的DTO对象列表
|
||||
*
|
||||
* @param entityList 需要转换的实体对象列表
|
||||
* @return 转换后的DTO对象列表
|
||||
*/
|
||||
fun toDtoList(entityList: List<Entity>): List<Dto>
|
||||
|
||||
/**
|
||||
* 将DTO对象列表转换为对应的实体对象列表
|
||||
*
|
||||
* @param dtoList 需要转换的DTO对象列表
|
||||
* @return 转换后的实体对象列表
|
||||
*/
|
||||
fun toEntityList(dtoList: List<Dto>): List<Entity>
|
||||
|
||||
/**
|
||||
* 使用非空属性对实体进行部分更新
|
||||
*
|
||||
* 注意:此操作不会覆盖实体中为空的属性
|
||||
*
|
||||
* @param dto 需要用于更新的DTO对象
|
||||
* @param entity 需要被更新的实体对象
|
||||
*/
|
||||
@BeanMapping(nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE)
|
||||
fun partialUpdate(dto: Dto, @MappingTarget entity: Entity)
|
||||
}
|
||||
117
forgeboot-webmvc/spec/README.md
Normal file
117
forgeboot-webmvc/spec/README.md
Normal file
@ -0,0 +1,117 @@
|
||||
# forgeboot-webmvc-spec
|
||||
|
||||
> 🧩 Web 项目通用 CRUD 接口规范模块,封装 Repository 与 Service 层的标准增删改查接口与默认实现,简化重复代码。
|
||||
|
||||
---
|
||||
|
||||
## 🧩 简介
|
||||
|
||||
`forgeboot-webmvc-spec` 是 ForgeBoot 提供的统一接口规范模块,旨在为常见的 Web 开发提供可复用的 Repository 和 Service 层增删改查基础接口及实现模板。
|
||||
|
||||
通过继承和组合该模块中的接口和基类,可以快速构建具有一致风格的业务组件,提升开发效率、降低重复代码、统一项目结构。
|
||||
|
||||
---
|
||||
|
||||
## ✨ 核心功能
|
||||
|
||||
- ✅ `CrudRepositorySpec<T, ID>`:通用 Repository 接口规范(继承自 `JpaRepository`)
|
||||
- ✅ `CrudServiceSpec<T, ID>`:业务层接口标准化定义
|
||||
- ✅ `CrudServiceImplSpec<T, ID>`:默认 Service 实现(依赖 Repository)
|
||||
- ✅ 泛型支持 Entity 类型与主键类型的自动推导
|
||||
- ✅ 与 DTO 模块 (`forgeboot-webmvc-dto`) 无缝协作
|
||||
|
||||
---
|
||||
|
||||
## 📦 引入依赖
|
||||
|
||||
使用 Maven:
|
||||
|
||||
```xml
|
||||
<dependency>
|
||||
<groupId>io.github.gewuyou</groupId>
|
||||
<artifactId>forgeboot-webmvc-spec</artifactId>
|
||||
<version>${version}</version>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
使用 Gradle:
|
||||
|
||||
```groovy
|
||||
implementation "io.github.gewuyou:forgeboot-webmvc-spec:${version}"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🚀 快速开始
|
||||
|
||||
### ✅ 定义实体类
|
||||
|
||||
```kotlin
|
||||
@Entity
|
||||
data class Product(
|
||||
@Id val id: Long,
|
||||
val name: String,
|
||||
val status: Int
|
||||
)
|
||||
```
|
||||
|
||||
### ✅ 创建 Repository 接口
|
||||
|
||||
```kotlin
|
||||
interface ProductRepository : CrudRepositorySpec<Product, Long>
|
||||
```
|
||||
|
||||
### ✅ 创建 Service 接口
|
||||
|
||||
```kotlin
|
||||
interface ProductService : CrudServiceSpec<Product, Long>
|
||||
```
|
||||
|
||||
### ✅ 创建默认实现类
|
||||
|
||||
```kotlin
|
||||
@Service
|
||||
class ProductServiceImpl(
|
||||
override val repository: ProductRepository
|
||||
) : CrudServiceImplSpec<Product, Long>(), ProductService
|
||||
```
|
||||
|
||||
现在你就拥有了以下功能:
|
||||
- 新增:`save(entity)`
|
||||
- 修改:`updateById(id, modifier)`
|
||||
- 删除:`deleteById(id)`
|
||||
- 查询单个:`findById(id)`
|
||||
- 查询全部:`findAll()`
|
||||
|
||||
---
|
||||
|
||||
## 🧩 扩展方法(默认实现中提供)
|
||||
|
||||
```kotlin
|
||||
fun updateById(id: ID, modifier: (T) -> Unit): Boolean
|
||||
fun existsById(id: ID): Boolean
|
||||
fun deleteById(id: ID): Boolean
|
||||
```
|
||||
|
||||
可自由覆写或组合使用。
|
||||
|
||||
---
|
||||
|
||||
## 🧠 与其他模块集成建议
|
||||
|
||||
| 模块 | 集成方式说明 |
|
||||
|------------------------|-------------------------------------------|
|
||||
| `forgeboot-webmvc-dto` | 可配合 `PageResult`, `QueryComponent` 返回分页数据 |
|
||||
---
|
||||
|
||||
## 📄 许可协议
|
||||
|
||||
本项目采用 [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0) 开源协议。
|
||||
|
||||
---
|
||||
|
||||
## 📬 联系作者
|
||||
|
||||
由 [@gewuyou](https://github.com/gewuyou) 维护。
|
||||
|
||||
欢迎提交 Issue 或 PR 改进本模块!
|
||||
@ -17,6 +17,10 @@ slf4j-version = "2.0.17"
|
||||
map-struct-version="1.6.3"
|
||||
caffeine-version="3.2.1"
|
||||
redisson-version="3.50.0"
|
||||
org-pf4j-version = "3.13.0"
|
||||
org-pf4j-spring-version = "0.10.0"
|
||||
org-yaml-snakeyaml-version = "2.4"
|
||||
org-yaml-snakeyaml-engine-version = "2.9"
|
||||
[libraries]
|
||||
kotlinGradlePlugin = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kotlin-version" }
|
||||
kotlinxDatetime = { module = "org.jetbrains.kotlinx:kotlinx-datetime", version.ref = "kotlinxDatetime-version" }
|
||||
@ -41,7 +45,7 @@ springBootStarter-redis = { group = "org.springframework.boot", name = "spring-b
|
||||
redisson-springBootStarter= { group = "org.redisson", name = "redisson-spring-boot-starter", version.ref = "redisson-version" }
|
||||
springBoot-configuration-processor = { group = "org.springframework.boot", name = "spring-boot-configuration-processor", version.ref = "spring-boot-version" }
|
||||
springBoot-autoconfigure = { group = "org.springframework.boot", name = "spring-boot-autoconfigure" }
|
||||
|
||||
springBoot-starter = { group = "org.springframework.boot", name = "spring-boot-starter" }
|
||||
springExpression = { group = "org.springframework", name = "spring-expression", version.ref = "spring-framework-version" }
|
||||
|
||||
springCloudDependencies-bom = { module = "org.springframework.cloud:spring-cloud-dependencies", version.ref = "spring-cloud-version" }
|
||||
@ -57,6 +61,10 @@ jackson-module-kotlin = { group = "com.fasterxml.jackson.module", name = "jackso
|
||||
reactor-core = { group = "io.projectreactor", name = "reactor-core" }
|
||||
#org
|
||||
org-mapstruct = { group = "org.mapstruct", name = "mapstruct", version.ref = "map-struct-version" }
|
||||
org-snakeyaml-snakeyamlEngine = { group = "org.snakeyaml", name = "snakeyaml-engine", version.ref = "org-yaml-snakeyaml-engine-version" }
|
||||
org-yaml-snakeyaml = { group = "org.yaml", name = "snakeyaml", version.ref = "org-yaml-snakeyaml-version" }
|
||||
org-pf4j = { group = "org.pf4j", name = "pf4j", version.ref = "org-pf4j-version" }
|
||||
org-pf4jSpring = { group = "org.pf4j", name = "pf4j-spring", version.ref = "org-pf4j-spring-version" }
|
||||
# Libraries can be bundled together for easier import
|
||||
# jwt
|
||||
jjwt-api = { module = "io.jsonwebtoken:jjwt-api", version.ref = "jjwt-version" }
|
||||
@ -64,6 +72,8 @@ jjwt-impl = { module = "io.jsonwebtoken:jjwt-impl", version.ref = "jjwt-version"
|
||||
jjwt-jackson = { module = "io.jsonwebtoken:jjwt-jackson", version.ref = "jjwt-version" }
|
||||
# com
|
||||
com-github-benManes-caffeine = { module = "com.github.ben-manes.caffeine:caffeine",version.ref = "caffeine-version" }
|
||||
# io
|
||||
|
||||
[bundles]
|
||||
kotlinxEcosystem = ["kotlinxDatetime", "kotlinxSerialization", "kotlinxCoroutines-core"]
|
||||
jacksonAll = [
|
||||
|
||||
@ -136,50 +136,25 @@ project(":forgeboot-trace:forgeboot-trace-impl").name = "forgeboot-trace-impl"
|
||||
project(":forgeboot-trace:forgeboot-trace-autoconfigure").name = "forgeboot-trace-autoconfigure"
|
||||
//endregion
|
||||
|
||||
////region module demo
|
||||
//region module trace
|
||||
/**
|
||||
* Includes and configures projects related to 'forgeboot-trace'
|
||||
* This module handles distributed tracing functionality.
|
||||
*/
|
||||
include(
|
||||
"forgeboot-demo",
|
||||
":forgeboot-demo:forgeboot-trace-demo"
|
||||
":forgeboot-demo:forgeboot-trace-demo",
|
||||
":forgeboot-demo:forgeboot-plugin-demo",
|
||||
":forgeboot-demo:forgeboot-plugin-demo:forgeboot-plugin-demo-api",
|
||||
":forgeboot-demo:forgeboot-plugin-demo:forgeboot-plugin-demo-impl",
|
||||
":forgeboot-demo:forgeboot-plugin-demo:forgeboot-plugin-demo-server",
|
||||
)
|
||||
//endregion
|
||||
include(
|
||||
"forgeboot-plugin",
|
||||
":forgeboot-plugin:forgeboot-plugin-core",
|
||||
":forgeboot-plugin:forgeboot-plugin-spring",
|
||||
)
|
||||
|
||||
|
||||
|
||||
////region module security
|
||||
///**
|
||||
// * Includes and configures projects related to 'forgeboot-security'
|
||||
// * This module handles security-related functionality.
|
||||
// */
|
||||
//include(
|
||||
// "forgeboot-security",
|
||||
// ":forgeboot-security:forgeboot-security-core",
|
||||
//
|
||||
// ":forgeboot-security:forgeboot-security-authenticate",
|
||||
// ":forgeboot-security:forgeboot-security-authenticate:api",
|
||||
// ":forgeboot-security:forgeboot-security-authenticate:impl",
|
||||
// ":forgeboot-security:forgeboot-security-authenticate:autoconfigure",
|
||||
//
|
||||
// ":forgeboot-security:forgeboot-security-authorize",
|
||||
// ":forgeboot-security:forgeboot-security-authorize:api",
|
||||
// ":forgeboot-security:forgeboot-security-authorize:impl",
|
||||
// ":forgeboot-security:forgeboot-security-authorize:autoconfigure"
|
||||
//)
|
||||
//project(":forgeboot-security").name = "forgeboot-security-spring-boot-starter"
|
||||
//project(":forgeboot-security:forgeboot-security-core").name = "forgeboot-security-core"
|
||||
//
|
||||
//project(":forgeboot-security:forgeboot-security-authenticate").name =
|
||||
// "forgeboot-security-authenticate-spring-boot-starter"
|
||||
//project(":forgeboot-security:forgeboot-security-authenticate:api").name = "forgeboot-security-authenticate-api"
|
||||
//project(":forgeboot-security:forgeboot-security-authenticate:impl").name = "forgeboot-security-authenticate-impl"
|
||||
//project(":forgeboot-security:forgeboot-security-authenticate:autoconfigure").name =
|
||||
// "forgeboot-security-authenticate-autoconfigure"
|
||||
//
|
||||
//project(":forgeboot-security:forgeboot-security-authorize").name = "forgeboot-security-authorize-spring-boot-starter"
|
||||
//project(":forgeboot-security:forgeboot-security-authorize:api").name = "forgeboot-security-authorize-api"
|
||||
//project(":forgeboot-security:forgeboot-security-authorize:impl").name = "forgeboot-security-authorize-impl"
|
||||
//project(":forgeboot-security:forgeboot-security-authorize:autoconfigure").name =
|
||||
// "forgeboot-security-authorize-autoconfigure"
|
||||
//
|
||||
////endregion
|
||||
|
||||
//region module cache
|
||||
include(
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user