Compare commits

...

10 Commits

Author SHA1 Message Date
446b859a8a build: ADD PROJECT INFORMATION TO THE MANIFEST FOR THE JAR PACKAGE. MF- Add task configuration in build.gradle.kts, MANIFEST generated for jar package. Add the project name and version information to the MF file
- New attributes:
  - Implementation-Title: The name of the project
  - Implementation-Version: The version of the project
2025-06-04 10:52:33 +08:00
2753c27dca refactor: Remove the app name configuration from the app properties file
Removed the configuration items in the application.properties spring.application.name file of the Forgeboot-Trace-API and ForgeBoot-Trace-Impl modules. This configuration, which could lead to duplicate definitions of app names, has been removed from both modules to address possible name conflicts.
2025-06-04 10:51:58 +08:00
cd268c4d35 build:Remove the application.properties file for the internationalization module
- Removed the application.properties files in the ForgeBoot-i18N-API and ForgeBoot-i18N-IMPL modules
- These files only contain spring.application.name attributes and may not need to be configured separately
2025-06-04 10:51:35 +08:00
1bb8c40a70 chore: Remove the application.properties file from the forgeboot-banner-impl module
- Removed the application.properties file in the src/main/resources directory of the forgeboot-banner-impl module
- The file contains only the spring.application.name attribute and may have little impact on the overall functionality
2025-06-04 10:51:20 +08:00
7388883d70 feat(module): Add forgeboot-banner module
- Added forgeboot-banner module, including API, implementation and launcher submodules
- Update the project structure and integrate new modules into the root project
- Fixed a spelling error in exception-i18n module name
2025-06-03 15:15:15 +08:00
3821c8b8c7 feat(spec): Add solid soft delete function
- Add softDelete method to the CrudServiceSpec interface to soft delete entities
- Implement softDelete method in the CrudServiceImplSpec class, including finding entities, marking delete status, and updating entities
- Added setDeleted abstract method, and implements specific tag deletion logic from subclasses
- Add log records, output error message when the corresponding entity cannot be found
- Introduce log extension functions and Core. EXTENSION module
2025-06-03 15:14:05 +08:00
bf63580581 feat(dto): Enrich data conversion interface and add list copy methods
- Added copyList method to BaseMapper interface to convert object list in batch
- Added partialUpdate method in the ConversionMapper interface to partially update entity objects
- Optimized interface document annotations, clarifying the function and parameter meaning of the method
- Adjusted the order of generic parameters to improve code readability
2025-06-03 15:11:18 +08:00
799ae091c9 refactor(trace): Move TraceProperties from impl to api module
- Move the TraceProperties.kt file from the forgeboot-trace-impl module to the forgeboot-trace-api module
- Update package references in related modules
- Add necessary dependencies in the forgeboot-trace-api module
2025-06-03 15:10:43 +08:00
7cf739fca0 refactor(i18n):Reconstructing international modules
- Move I18nProperties from impl package to api package
- Update the build configuration of the api package and add Spring Boot Configuration Processor dependencies - Remove unused Spring Cloud dependencies in the api package
- Update package references in automatic configuration and implementation classes
2025-06-03 15:09:35 +08:00
bd03558440 feat(banner): Add Forge Banner Module
- Added Banner module, including API, implementation and automatic configuration components
- Add banner configuration properties and policy enumeration
- Implement configurable banner provider class
- Create necessary project structures and configuration files
2025-06-03 15:09:03 +08:00
43 changed files with 490 additions and 40 deletions

View File

@ -41,7 +41,6 @@ version = scmVersion.version
// 配置目录路径 // 配置目录路径
val configDir = "$rootDir/config/" val configDir = "$rootDir/config/"
val tasksDir = "$configDir/tasks/"
// 全局项目配置 // 全局项目配置
allprojects { allprojects {
@ -189,7 +188,14 @@ subprojects {
languageVersion.set(JavaLanguageVersion.of(21)) languageVersion.set(JavaLanguageVersion.of(21))
} }
} }
tasks.named<Jar>("jar") {
manifest {
attributes(
"Implementation-Title" to project.name,
"Implementation-Version" to project.version
)
}
}
// 任务配置 // 任务配置
tasks.withType<Jar> { tasks.withType<Jar> {
isEnabled = true isEnabled = true

View File

@ -30,4 +30,10 @@ object Modules {
const val IMPL = ":forgeboot-trace-spring-boot-starter:forgeboot-trace-impl" const val IMPL = ":forgeboot-trace-spring-boot-starter:forgeboot-trace-impl"
const val AUTOCONFIGURE = ":forgeboot-trace-spring-boot-starter:forgeboot-trace-autoconfigure" const val AUTOCONFIGURE = ":forgeboot-trace-spring-boot-starter:forgeboot-trace-autoconfigure"
} }
object Banner {
const val STARTER = ":forgeboot-banner"
const val API = ":forgeboot-banner:forgeboot-banner-api"
const val IMPL = ":forgeboot-banner:forgeboot-banner-impl"
const val AUTOCONFIGURE = ":forgeboot-banner:forgeboot-banner-autoconfigure"
}
} }

3
forgeboot-banner/.gitattributes vendored Normal file
View File

@ -0,0 +1,3 @@
/gradlew text eol=lf
*.bat text eol=crlf
*.jar binary

40
forgeboot-banner/.gitignore vendored Normal file
View 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

View File

@ -0,0 +1,6 @@
extra{
setProperty(ProjectFlags.IS_ROOT_MODULE,true)
}
dependencies {
}

View File

@ -0,0 +1,3 @@
/gradlew text eol=lf
*.bat text eol=crlf
*.jar binary

View 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

View File

@ -0,0 +1,6 @@
dependencies {
compileOnly(platform(libs.springBootDependencies.bom))
compileOnly(libs.springBootStarter.web)
kapt(libs.springBoot.configuration.processor)
}

View File

@ -0,0 +1,16 @@
package com.gewuyou.forgeboot.banner.api.config.entities
import com.gewuyou.forgeboot.banner.api.enums.BannerStrategy
import org.springframework.boot.context.properties.ConfigurationProperties
/**
*横幅配置
*
* @since 2025-06-03 12:55:18
* @author gewuyou
*/
@ConfigurationProperties("forgeboot.banner")
class BannerProperties {
var path: String = "banners/"
var strategy: BannerStrategy = BannerStrategy.Random
}

View File

@ -0,0 +1,13 @@
package com.gewuyou.forgeboot.banner.api.enums
/**
*横幅策略
*
* @since 2025-06-03 13:04:30
* @author gewuyou
*/
enum class BannerStrategy {
First,
Random,
All
}

View File

@ -0,0 +1,18 @@
package com.gewuyou.forgeboot.banner.api.provider
import java.io.PrintStream
/**
* 横幅提供商接口用于定义横幅输出行为
*
* @since 2025-06-03 12:17:19
* @author gewuyou
*/
fun interface BannerProvider {
/**
* 输出横幅内容到指定的输出流
*
* @param out 输出流对象
*/
fun printBanner(out: PrintStream)
}

View File

@ -0,0 +1,3 @@
/gradlew text eol=lf
*.bat text eol=crlf
*.jar binary

View 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

View File

@ -0,0 +1,6 @@
dependencies {
compileOnly(platform(libs.springBootDependencies.bom))
compileOnly(libs.springBootStarter.web)
compileOnly(project(Modules.Banner.API))
}

View File

@ -0,0 +1,75 @@
package com.gewuyou.forgeboot.banner.impl
import com.gewuyou.forgeboot.banner.api.enums.BannerStrategy
import com.gewuyou.forgeboot.banner.api.provider.BannerProvider
import com.gewuyou.forgeboot.banner.api.config.entities.BannerProperties
import org.springframework.core.io.Resource
import org.springframework.core.io.support.PathMatchingResourcePatternResolver
import java.io.PrintStream
import java.util.Random
import java.util.Scanner
/**
* 可配置横幅提供者类根据配置属性输出横幅
*
* @param properties 横幅属性配置对象
*/
class ConfigurableBannerProvider(
private val properties: BannerProperties,
): BannerProvider {
/**
* 输出横幅内容到指定的输出流
*
* @param out 输出流对象可为空
*/
override fun printBanner(out: PrintStream) {
try {
// 根据属性配置获取横幅资源路径模式
val pattern = "classpath*:" + properties.path + "*.txt"
// 使用路径匹配获取所有符合条件的资源
val resources: Array<Resource?> = PathMatchingResourcePatternResolver().getResources(pattern)
// 如果没有找到任何资源,则输出提示信息并返回
if (resources.isEmpty()) {
out.println("No banner found in: " + properties.path)
return
}
// 根据配置的策略选择横幅输出方式
when (properties.strategy) {
BannerStrategy.First-> resources[0]?.let { printResource(it, out) }
BannerStrategy.Random -> resources[Random().nextInt(resources.size)]?.let { printResource(it, out) }
BannerStrategy.All -> {
for (resource in resources) {
resource?.let { printResource(it, out) }
out.println()
}
}
}
} catch (e: Exception) {
// 异常处理:输出错误信息
out.println("Error loading banners: " + e.message)
}
}
/**
* 打印资源内容到指定的输出流
*
* @param resource 要打印的资源对象
* @param out 输出流对象
*/
private fun printResource(resource: Resource, out: PrintStream) {
try {
// 使用输入流读取资源内容并输出
resource.inputStream.use { `is` ->
Scanner(`is`).useDelimiter("\\A").use { scanner ->
while (scanner.hasNext()) {
out.println(scanner.next())
}
}
}
} catch (e: java.lang.Exception) {
// 异常处理:输出错误信息
out.println("Failed to print banner: " + e.message)
}
}
}

View File

@ -0,0 +1,3 @@
/gradlew text eol=lf
*.bat text eol=crlf
*.jar binary

View 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

View File

@ -0,0 +1,8 @@
dependencies {
compileOnly(platform(libs.springBootDependencies.bom))
compileOnly(libs.springBootStarter.web)
compileOnly(project(Modules.Banner.IMPL))
compileOnly(project(Modules.Banner.API))
implementation(project(Modules.Core.EXTENSION))
}

View File

@ -0,0 +1,34 @@
package com.gewuyou.forgeboot.banner.launcher
import com.gewuyou.forgeboot.banner.api.config.entities.BannerProperties
import com.gewuyou.forgeboot.banner.impl.ConfigurableBannerProvider
import org.springframework.boot.Banner
import org.springframework.boot.builder.SpringApplicationBuilder
import org.springframework.boot.context.properties.bind.Binder
import org.springframework.core.env.StandardEnvironment
/**
* 使用Forge横幅运行Spring应用的函数
* 该函数主要用于简化Spring应用的启动过程特别是当需要自定义横幅时
* 它通过反射启动一个Spring应用并允许开发者在启动时自定义横幅
*
* @param T Spring应用的主类类型必须是Any的子类
* @param args 命令行参数传递给Spring应用
*/
inline fun <reified T : Any> runApplicationWithForgeBanner(vararg args: String) {
// 创建并配置Spring应用的环境
val env = StandardEnvironment()
// 获取配置属性绑定器
val binder = Binder.get(env)
// 从配置中绑定BannerProperties属性如果没有找到则使用默认值
val props = binder.bind("banner", BannerProperties::class.java).orElse(BannerProperties())
// 创建一个自定义的Banner实例
val banner = Banner { _, _, out -> ConfigurableBannerProvider(props).printBanner(out) }
// 构建并运行Spring应用
SpringApplicationBuilder()
.sources(T::class.java)
.banner(banner)
.environment(env)
.run(*args)
}

View File

@ -1,8 +1,7 @@
dependencies { dependencies {
compileOnly(platform(libs.springBootDependencies.bom)) compileOnly(platform(libs.springBootDependencies.bom))
// compileOnly(platform(libs.springCloudDependencies.bom))
// compileOnly(libs.springBootStarter.web)
compileOnly(libs.springBootStarter.webflux) compileOnly(libs.springBootStarter.webflux)
kapt(libs.springBoot.configuration.processor)
} }

View File

@ -1,4 +1,4 @@
package com.gewuyou.forgeboot.i18n.impl.config package com.gewuyou.forgeboot.i18n.api.config
import org.springframework.boot.context.properties.ConfigurationProperties import org.springframework.boot.context.properties.ConfigurationProperties

View File

@ -1 +0,0 @@
spring.application.name=forgeboot-i18n-api

View File

@ -3,7 +3,7 @@ package com.gewuyou.forgeboot.i18n.autoconfigure
import com.gewuyou.forgeboot.core.extension.log import com.gewuyou.forgeboot.core.extension.log
import com.gewuyou.forgeboot.i18n.api.MessageResolver import com.gewuyou.forgeboot.i18n.api.MessageResolver
import com.gewuyou.forgeboot.i18n.impl.config.I18nProperties import com.gewuyou.forgeboot.i18n.api.config.I18nProperties
import com.gewuyou.forgeboot.i18n.impl.filter.ReactiveLocaleResolver import com.gewuyou.forgeboot.i18n.impl.filter.ReactiveLocaleResolver
import com.gewuyou.forgeboot.i18n.impl.resolver.I18nMessageResolver import com.gewuyou.forgeboot.i18n.impl.resolver.I18nMessageResolver
import jakarta.servlet.http.HttpServletRequest import jakarta.servlet.http.HttpServletRequest

View File

@ -2,7 +2,7 @@ package com.gewuyou.forgeboot.i18n.impl.filter
import com.gewuyou.forgeboot.i18n.api.WebFluxLocaleResolver import com.gewuyou.forgeboot.i18n.api.WebFluxLocaleResolver
import com.gewuyou.forgeboot.i18n.impl.config.I18nProperties import com.gewuyou.forgeboot.i18n.api.config.I18nProperties
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
import org.springframework.context.i18n.LocaleContextHolder import org.springframework.context.i18n.LocaleContextHolder

View File

@ -1 +0,0 @@
spring.application.name=forgeboot-i18n-impl-starter

View File

@ -1,3 +1,5 @@
dependencies { dependencies {
compileOnly(platform(libs.springBootDependencies.bom))
compileOnly(libs.springBootStarter.web)
kapt(libs.springBoot.configuration.processor)
} }

View File

@ -1,4 +1,4 @@
package com.gewuyou.forgeboot.trace.impl.config package com.gewuyou.forgeboot.trace.api.config
import org.springframework.boot.context.properties.ConfigurationProperties import org.springframework.boot.context.properties.ConfigurationProperties

View File

@ -1 +0,0 @@
spring.application.name=api

View File

@ -1,7 +1,7 @@
package com.gewuyou.forgeboot.trace.autoconfig package com.gewuyou.forgeboot.trace.autoconfig
import com.gewuyou.forgeboot.core.extension.log import com.gewuyou.forgeboot.core.extension.log
import com.gewuyou.forgeboot.trace.impl.config.TraceProperties import com.gewuyou.forgeboot.trace.api.config.TraceProperties
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass import org.springframework.boot.autoconfigure.condition.ConditionalOnClass
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean
import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Bean

View File

@ -3,7 +3,7 @@ package com.gewuyou.forgeboot.trace.autoconfig
import com.gewuyou.forgeboot.core.extension.log import com.gewuyou.forgeboot.core.extension.log
import com.gewuyou.forgeboot.trace.api.RequestIdProvider import com.gewuyou.forgeboot.trace.api.RequestIdProvider
import com.gewuyou.forgeboot.trace.impl.config.TraceProperties import com.gewuyou.forgeboot.trace.api.config.TraceProperties
import com.gewuyou.forgeboot.trace.impl.decorator.RequestIdTaskDecorator import com.gewuyou.forgeboot.trace.impl.decorator.RequestIdTaskDecorator
import com.gewuyou.forgeboot.trace.impl.filter.ReactiveRequestIdFilter import com.gewuyou.forgeboot.trace.impl.filter.ReactiveRequestIdFilter
import com.gewuyou.forgeboot.trace.impl.filter.RequestIdFilter import com.gewuyou.forgeboot.trace.impl.filter.RequestIdFilter

View File

@ -1,7 +1,7 @@
package com.gewuyou.forgeboot.trace.autoconfig package com.gewuyou.forgeboot.trace.autoconfig
import com.gewuyou.forgeboot.core.extension.log import com.gewuyou.forgeboot.core.extension.log
import com.gewuyou.forgeboot.trace.impl.config.TraceProperties import com.gewuyou.forgeboot.trace.api.config.TraceProperties
import com.gewuyou.forgeboot.trace.impl.filter.WebClientRequestIdFilter import com.gewuyou.forgeboot.trace.impl.filter.WebClientRequestIdFilter
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean import org.springframework.boot.autoconfigure.condition.ConditionalOnBean
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass import org.springframework.boot.autoconfigure.condition.ConditionalOnClass

View File

@ -1,6 +1,6 @@
package com.gewuyou.forgeboot.trace.impl.decorator package com.gewuyou.forgeboot.trace.impl.decorator
import com.gewuyou.forgeboot.trace.impl.config.TraceProperties import com.gewuyou.forgeboot.trace.api.config.TraceProperties
import org.slf4j.MDC import org.slf4j.MDC
import org.springframework.core.task.TaskDecorator import org.springframework.core.task.TaskDecorator

View File

@ -3,7 +3,7 @@ package com.gewuyou.forgeboot.trace.impl.filter
import com.gewuyou.forgeboot.core.extension.log import com.gewuyou.forgeboot.core.extension.log
import com.gewuyou.forgeboot.trace.impl.config.TraceProperties import com.gewuyou.forgeboot.trace.api.config.TraceProperties
import com.gewuyou.forgeboot.trace.impl.extension.isSkipRequest import com.gewuyou.forgeboot.trace.impl.extension.isSkipRequest
import com.gewuyou.forgeboot.trace.impl.util.RequestIdUtil import com.gewuyou.forgeboot.trace.impl.util.RequestIdUtil

View File

@ -2,7 +2,7 @@ package com.gewuyou.forgeboot.trace.impl.filter
import com.gewuyou.forgeboot.core.extension.log import com.gewuyou.forgeboot.core.extension.log
import com.gewuyou.forgeboot.trace.impl.config.TraceProperties import com.gewuyou.forgeboot.trace.api.config.TraceProperties
import com.gewuyou.forgeboot.trace.impl.extension.isSkipRequest import com.gewuyou.forgeboot.trace.impl.extension.isSkipRequest
import com.gewuyou.forgeboot.trace.impl.util.RequestIdUtil import com.gewuyou.forgeboot.trace.impl.util.RequestIdUtil

View File

@ -1,7 +1,7 @@
package com.gewuyou.forgeboot.trace.impl.filter package com.gewuyou.forgeboot.trace.impl.filter
import com.gewuyou.forgeboot.core.extension.log import com.gewuyou.forgeboot.core.extension.log
import com.gewuyou.forgeboot.trace.impl.config.TraceProperties import com.gewuyou.forgeboot.trace.api.config.TraceProperties
import com.gewuyou.forgeboot.trace.impl.extension.isSkipRequest import com.gewuyou.forgeboot.trace.impl.extension.isSkipRequest
import com.gewuyou.forgeboot.trace.impl.util.RequestIdUtil import com.gewuyou.forgeboot.trace.impl.util.RequestIdUtil

View File

@ -3,7 +3,7 @@ package com.gewuyou.forgeboot.trace.impl.interceptor
import com.gewuyou.forgeboot.core.extension.log import com.gewuyou.forgeboot.core.extension.log
import com.gewuyou.forgeboot.trace.impl.config.TraceProperties import com.gewuyou.forgeboot.trace.api.config.TraceProperties
import com.gewuyou.forgeboot.trace.impl.util.RequestIdUtil import com.gewuyou.forgeboot.trace.impl.util.RequestIdUtil
import feign.RequestInterceptor import feign.RequestInterceptor
import feign.RequestTemplate import feign.RequestTemplate

View File

@ -1 +0,0 @@
spring.application.name=impl

View File

@ -6,24 +6,44 @@ import org.mapstruct.NullValuePropertyMappingStrategy
/** /**
* Base Mapper基础映射器 * Base Mapper基础映射器
* 提供基础的对象映射操作定义包含合并覆盖合并单个对象拷贝及列表拷贝的方法
* *
* @since 2025-05-30 22:50:18 * @since 2025-05-30 22:50:18
* @author gewuyou * @author gewuyou
*/ */
interface BaseMapper<T,S> { interface BaseMapper<S, T> {
/** /**
* 合并 source target忽略 null * source 对象中的非 null 属性合并到 target 对象中
* 注意null 值的属性不会覆盖 target 中已有的值
*
* @param target 目标对象将被更新
* @param source 源对象提供需要合并的数据
*/ */
@BeanMapping(nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE) @BeanMapping(nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE)
fun mergeIgnoreNull(@MappingTarget target: T, source: S) fun mergeIgnoreNull(@MappingTarget target: T, source: S)
/** /**
* 全量覆盖合并source 字段即使为 null 也覆盖 target * 全量覆盖合并 source target
* 注意即使 source 中的字段为 null也会覆盖 target 中对应的字段
*
* @param target 目标对象将被更新
* @param source 源对象提供需要合并的数据
*/ */
fun overwriteMerge(@MappingTarget target: T, source: S) fun overwriteMerge(@MappingTarget target: T, source: S)
/** /**
* 拷贝 source 到新对象 * source 对象的内容拷贝到一个新的 T 类型对象中
*
* @param source 源对象提供数据
* @return 返回一个新的目标类型对象
*/ */
fun copy(source: S): T fun copy(source: S): T
/**
* 将源对象列表中的每个元素拷贝为新的目标类型对象生成一个目标对象列表
*
* @param sources 源对象列表
* @return 返回目标类型对象的列表
*/
fun copyList(sources: List<S>): List<T>
} }

View File

@ -1,10 +1,15 @@
package com.gewuyou.forgeboot.webmvc.dto.dto.mapper package com.gewuyou.forgeboot.webmvc.dto.mapper
import org.mapstruct.BeanMapping
import org.mapstruct.MappingTarget
import org.mapstruct.NullValuePropertyMappingStrategy
/** /**
* 转换 映射器 * 转换映射器接口
* *
* 定义了一个转换映射器接口用于在实体类和数据传输对象DTO之间进行转换 * 提供通用的实体类(Entity)与数据传输对象(DTO)之间的双向转换能力
* 这个接口定义了四个基本转换方法实体到DTODTO到实体实体列表到DTO列表和DTO列表到实体列表 * 该接口定义了基础的数据转换方法包括单个对象和集合对象的转换
* 并支持部分更新操作忽略空值属性
* *
* @param <Entity> 实体类类型 * @param <Entity> 实体类类型
* @param <Dto> 数据传输对象类型 * @param <Dto> 数据传输对象类型
@ -14,34 +19,45 @@ package com.gewuyou.forgeboot.webmvc.dto.dto.mapper
*/ */
interface ConversionMapper<Entity, Dto> { interface ConversionMapper<Entity, Dto> {
/** /**
* 将实体对象转换为DTO对象 * 将实体对象转换为对应的DTO对象
* *
* @param entity 实体对象 * @param entity 需要转换的实体对象
* @return 转换后的DTO对象 * @return 转换后的DTO对象
*/ */
fun toDto(entity: Entity): Dto fun toDto(entity: Entity): Dto
/** /**
* 将DTO对象转换为实体对象 * 将DTO对象转换为对应的实体对象
* *
* @param dto DTO对象 * @param dto 需要转换的DTO对象
* @return 转换后的实体对象 * @return 转换后的实体对象
*/ */
fun toEntity(dto: Dto): Entity fun toEntity(dto: Dto): Entity
/** /**
* 将实体对象列表转换为DTO对象列表 * 将实体对象列表转换为对应的DTO对象列表
* *
* @param entityList 实体对象列表 * @param entityList 需要转换的实体对象列表
* @return 转换后的DTO对象列表 * @return 转换后的DTO对象列表
*/ */
fun toDtoList(entityList: List<Entity>): List<Dto> fun toDtoList(entityList: List<Entity>): List<Dto>
/** /**
* 将DTO对象列表转换为实体对象列表 * 将DTO对象列表转换为对应的实体对象列表
* *
* @param dtoList DTO对象列表 * @param dtoList 需要转换的DTO对象列表
* @return 转换后的实体对象列表 * @return 转换后的实体对象列表
*/ */
fun toEntityList(dtoList: List<Dto>): List<Entity> fun toEntityList(dtoList: List<Dto>): List<Entity>
/**
* 使用非空属性对实体进行部分更新
*
* 注意此操作不会覆盖实体中为空的属性
*
* @param dto 需要用于更新的DTO对象
* @param entity 需要被更新的实体对象
*/
@BeanMapping(nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE)
fun partialUpdate(dto: Dto, @MappingTarget entity: Entity)
} }

View File

@ -2,4 +2,5 @@
dependencies { dependencies {
compileOnly(libs.springBootStarter.jpa) compileOnly(libs.springBootStarter.jpa)
implementation(project(Modules.Webmvc.DTO)) implementation(project(Modules.Webmvc.DTO))
implementation(project(Modules.Core.EXTENSION))
} }

View File

@ -74,6 +74,16 @@ interface CrudServiceSpec<Entity: Any, Id: Any, Filter: Any> {
*/ */
fun deleteByAll(entities: List<Entity>) fun deleteByAll(entities: List<Entity>)
/**
* 软删除
*
* 本函数用于标记实体为删除状态而不是真正从数据库中移除
* 这种方法可以保留历史数据同时避免数据泄露
*
* @param id 实体的唯一标识符
*/
fun softDelete(id: Id)
/** /**
* 根据ID检查实体是否存在 * 根据ID检查实体是否存在
* *

View File

@ -1,5 +1,6 @@
package com.gewuyou.forgeboot.webmvc.spec.service.impl package com.gewuyou.forgeboot.webmvc.spec.service.impl
import com.gewuyou.forgeboot.core.extension.log
import com.gewuyou.forgeboot.webmvc.dto.PageResult import com.gewuyou.forgeboot.webmvc.dto.PageResult
import com.gewuyou.forgeboot.webmvc.dto.extension.map import com.gewuyou.forgeboot.webmvc.dto.extension.map
import com.gewuyou.forgeboot.webmvc.dto.extension.toPageResult import com.gewuyou.forgeboot.webmvc.dto.extension.toPageResult
@ -201,4 +202,31 @@ abstract class CrudServiceImplSpec<Entity : Any, Id : Any, Filter : Any>(
override fun saveAll(entities: List<Entity>): List<Entity> { override fun saveAll(entities: List<Entity>): List<Entity> {
return repository.saveAll(entities) return repository.saveAll(entities)
} }
/**
* 标记实体为软删除状态
*
* 此方法应在子类中实现用于定义如何将实体标记为已删除例如设置一个 deleted 字段
* 软删除不会从数据库中物理移除记录而是将其标记为已删除状态以便保留历史数据
*
* @param entity 实体对象表示要标记为删除状态的对象
*/
protected abstract fun setDeleted(entity: Entity)
/**
* 执行软删除操作
*
* 该方法会根据提供的 ID 查找实体如果找到该实体则调用 [setDeleted] 方法将其标记为删除状态
* 然后通过 [update] 方法保存更改如果没有找到实体则记录一条错误日志
*
* 软删除机制可以保留历史数据同时避免敏感信息的直接删除确保数据可追溯且安全
*
* @param id 实体的唯一标识符用于查找需要删除的实体
*/
override fun softDelete(id: Id) {
val exist: Entity? = findById(id)
exist?.let {
setDeleted(it)
update(it)
} ?: log.error("删除失败,找不到该租户")
}
} }

View File

@ -22,6 +22,18 @@ plugins {
rootProject.name = "forgeboot" rootProject.name = "forgeboot"
//region module banner
include(
"forgeboot-banner",
":forgeboot-banner:forgeboot-banner-api",
":forgeboot-banner:forgeboot-banner-impl",
":forgeboot-banner:forgeboot-banner-launcher",
)
project(":forgeboot-banner").name = "forgeboot-banner"
project(":forgeboot-banner:forgeboot-banner-api").name = "forgeboot-banner-api"
project(":forgeboot-banner:forgeboot-banner-impl").name = "forgeboot-banner-impl"
project(":forgeboot-banner:forgeboot-banner-launcher").name = "forgeboot-banner-launcher"
//endregion
//region module webmvc //region module webmvc
include( include(