mirror of
				https://github.moeyy.xyz/https://github.com/GeWuYou/forgeboot
				synced 2025-10-31 06:36:39 +08:00 
			
		
		
		
	Compare commits
	
		
			No commits in common. "9c11b7e2e5e3c0a2eb9b0a907f783d81cb049054" and "21b79551a521115f47002cf159574276a5780277" have entirely different histories.
		
	
	
		
			9c11b7e2e5
			...
			21b79551a5
		
	
		
| @ -11,7 +11,6 @@ plugins { | |||||||
|     // Kotlin kapt 支持 |     // Kotlin kapt 支持 | ||||||
|     alias(libs.plugins.kotlin.kapt) |     alias(libs.plugins.kotlin.kapt) | ||||||
|     id(libs.plugins.kotlin.jvm.get().pluginId) |     id(libs.plugins.kotlin.jvm.get().pluginId) | ||||||
|     alias(libs.plugins.gradleMavenPublishPlugin) |  | ||||||
| } | } | ||||||
| java { | java { | ||||||
|     withSourcesJar() |     withSourcesJar() | ||||||
| @ -59,7 +58,7 @@ allprojects { | |||||||
|             } |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|     project.group = "io.github.gewuyou" |     project.group = "com.gewuyou.forgeboot" | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // 子项目配置 | // 子项目配置 | ||||||
| @ -105,15 +104,9 @@ subprojects { | |||||||
|         plugin(libs.plugins.kotlin.jvm.get().pluginId) |         plugin(libs.plugins.kotlin.jvm.get().pluginId) | ||||||
|         plugin(libs.plugins.axionRelease.get().pluginId) |         plugin(libs.plugins.axionRelease.get().pluginId) | ||||||
|         plugin(libs.plugins.kotlin.kapt.get().pluginId) |         plugin(libs.plugins.kotlin.kapt.get().pluginId) | ||||||
|         plugin(libs.plugins.gradleMavenPublishPlugin.get().pluginId) |  | ||||||
|         // 导入仓库配置 |         // 导入仓库配置 | ||||||
|         from(file("$configDir/repositories.gradle.kts")) |         from(file("$configDir/repositories.gradle.kts")) | ||||||
|     } |     } | ||||||
|     // 中央仓库 |  | ||||||
|     mavenPublishing { |  | ||||||
|         publishToMavenCentral("DEFAULT", true) |  | ||||||
|         signAllPublications() |  | ||||||
|     } |  | ||||||
|     // 发布配置 |     // 发布配置 | ||||||
|     publishing { |     publishing { | ||||||
|         repositories { |         repositories { | ||||||
| @ -135,8 +128,9 @@ subprojects { | |||||||
|             val host = System.getenv("GITEA_HOST") |             val host = System.getenv("GITEA_HOST") | ||||||
|             host?.let { |             host?.let { | ||||||
|                 maven { |                 maven { | ||||||
|  |                     isAllowInsecureProtocol = true | ||||||
|                     name = "Gitea" |                     name = "Gitea" | ||||||
|                     url = uri("${it}/api/packages/gewuyou/maven") |                     url = uri("http://${it}/api/packages/gewuyou/maven") | ||||||
|                     credentials(HttpHeaderCredentials::class.java) { |                     credentials(HttpHeaderCredentials::class.java) { | ||||||
|                         name = "Authorization" |                         name = "Authorization" | ||||||
|                         value = "token ${System.getenv("GITEA_TOKEN")}" |                         value = "token ${System.getenv("GITEA_TOKEN")}" | ||||||
| @ -210,88 +204,9 @@ subprojects { | |||||||
|     tasks.named<Test>("test") { |     tasks.named<Test>("test") { | ||||||
|         useJUnitPlatform() |         useJUnitPlatform() | ||||||
|     } |     } | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
| /** |  | ||||||
|  * 注册一个 Gradle 任务用于清理项目中的无用文件。 |  | ||||||
|  * |  | ||||||
|  * 该任务会清理以下内容: |  | ||||||
|  * - gradlew 和 gradlew.bat(Gradle 包装器脚本) |  | ||||||
|  * - gradle-wrapper.jar 和 gradle-wrapper.properties(Gradle 包装器库和配置) |  | ||||||
|  * - .gradle 和 gradle 目录(Gradle 缓存和配置目录) |  | ||||||
|  * - src/main/resources/application.properties(开发环境配置文件) |  | ||||||
|  * - src/test 目录(测试资源) |  | ||||||
|  */ |  | ||||||
| tasks.register<CleanUselessFilesTask>("cleanUselessFiles") { |  | ||||||
|     group = "project" |  | ||||||
|     description = "删除根目录及子模块的无用文件" |  | ||||||
| 
 |  | ||||||
|     includedProjectPaths.set(rootProject.subprojects.map { it.projectDir.absolutePath }) |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /** | // 获取项目布尔属性的辅助函数 | ||||||
|  * 获取项目的布尔属性值。 |  | ||||||
|  * |  | ||||||
|  * 用于从项目属性中获取指定键对应的布尔值,如果未设置或无法解析为布尔值,则返回默认值 false。 |  | ||||||
|  * |  | ||||||
|  * @param key 属性键名 |  | ||||||
|  * @return 属性对应的布尔值,若不存在或无效则返回 false |  | ||||||
|  */ |  | ||||||
| fun Project.getPropertyByBoolean(key: String): Boolean { | fun Project.getPropertyByBoolean(key: String): Boolean { | ||||||
|     return properties[key]?.toString()?.toBoolean() ?: false |     return properties[key]?.toString()?.toBoolean() ?: false | ||||||
| } | } | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * CleanUselessFilesTask 是一个 Gradle 自定义任务类,用于清理项目中的无用文件。 |  | ||||||
|  * |  | ||||||
|  * 该任务会遍历所有子项目,并删除预定义的无用文件和目录。 |  | ||||||
|  */ |  | ||||||
| abstract class CleanUselessFilesTask : DefaultTask() { |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 获取需要清理的项目路径列表。 |  | ||||||
|      * |  | ||||||
|      * 每个路径代表一个项目的根目录,任务将基于这些目录查找并删除无用文件。 |  | ||||||
|      */ |  | ||||||
|     @get:Input |  | ||||||
|     abstract val includedProjectPaths: ListProperty<String> |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 执行清理操作的主要方法。 |  | ||||||
|      * |  | ||||||
|      * 此方法会构建待删除文件列表,并逐个检查是否存在并删除,最后输出删除结果。 |  | ||||||
|      */ |  | ||||||
|     @TaskAction |  | ||||||
|     fun clean() { |  | ||||||
|         val targets = mutableListOf<File>() |  | ||||||
| 
 |  | ||||||
|         // 构建需要清理的文件和目录列表 |  | ||||||
|         includedProjectPaths.get().forEach { path -> |  | ||||||
|             val projectDir = File(path) |  | ||||||
|             targets.add(projectDir.resolve("gradlew")) |  | ||||||
|             targets.add(projectDir.resolve("gradlew.bat")) |  | ||||||
|             targets.add(projectDir.resolve("gradle/wrapper/gradle-wrapper.jar")) |  | ||||||
|             targets.add(projectDir.resolve("gradle/wrapper/gradle-wrapper.properties")) |  | ||||||
|             targets.add(projectDir.resolve(".gradle")) |  | ||||||
|             targets.add(projectDir.resolve("gradle")) |  | ||||||
|             targets.add(projectDir.resolve("src/main/resources/application.properties")) |  | ||||||
|             targets.add(projectDir.resolve("src/test")) |  | ||||||
|             targets.add(projectDir.resolve("HELP.md")) |  | ||||||
|             targets.add(projectDir.resolve("settings.gradle.kts")) |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         // 执行删除操作并统计结果 |  | ||||||
|         var count = 0 |  | ||||||
|         targets.filter { it.exists() }.forEach { |  | ||||||
|             logger.lifecycle("删除:${it.absolutePath}") |  | ||||||
|             count++ |  | ||||||
|             it.deleteRecursively() |  | ||||||
|         } |  | ||||||
|         if (count > 0) { |  | ||||||
|             logger.lifecycle("已删除 $count 个无用文件。") |  | ||||||
|         } else { |  | ||||||
|             logger.lifecycle("无无用文件。") |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  | |||||||
| @ -7,114 +7,39 @@ | |||||||
|  */ |  */ | ||||||
| object Modules { | object Modules { | ||||||
| 
 | 
 | ||||||
|     /** |     object Context{ | ||||||
|      * Context模块:Spring Boot Starter上下文支持模块 |  | ||||||
|      * 提供基础的上下文功能,包含API、实现及自动配置模块 |  | ||||||
|      */ |  | ||||||
|     object Context { |  | ||||||
|         const val STARTER = ":forgeboot-context-spring-boot-starter" |         const val STARTER = ":forgeboot-context-spring-boot-starter" | ||||||
|         const val API = ":forgeboot-context-spring-boot-starter:forgeboot-context-api" |         const val API = ":forgeboot-context-spring-boot-starter:forgeboot-context-api" | ||||||
|         const val IMPL = ":forgeboot-context-spring-boot-starter:forgeboot-context-impl" |         const val IMPL = ":forgeboot-context-spring-boot-starter:forgeboot-context-impl" | ||||||
|         const val AUTOCONFIGURE = ":forgeboot-context-spring-boot-starter:forgeboot-context-autoconfigure" |         const val AUTOCONFIGURE = ":forgeboot-context-spring-boot-starter:forgeboot-context-autoconfigure" | ||||||
|     } |     } | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * Webmvc模块:Spring Boot Starter对WebMVC的支持模块 |  | ||||||
|      * 提供Web开发相关的功能,包括数据传输对象(DTO)、验证、版本控制及日志功能 |  | ||||||
|      */ |  | ||||||
|     object Webmvc { |     object Webmvc { | ||||||
|         const val STARTER = ":forgeboot-webmvc-spring-boot-starter" |         const val STARTER = ":forgeboot-webmvc-spring-boot-starter" | ||||||
|         const val DTO = ":forgeboot-webmvc-spring-boot-starter:forgeboot-webmvc-dto" |         const val DTO = ":forgeboot-webmvc-spring-boot-starter:forgeboot-webmvc-dto" | ||||||
|         const val EXCEPTION = ":forgeboot-webmvc-spring-boot-starter:forgeboot-webmvc-exception-spring-boot-starter" |  | ||||||
|         const val VALIDATION = ":forgeboot-webmvc-spring-boot-starter:forgeboot-webmvc-validation" |         const val VALIDATION = ":forgeboot-webmvc-spring-boot-starter:forgeboot-webmvc-validation" | ||||||
|         const val VERSION = ":forgeboot-webmvc-spring-boot-starter:forgeboot-webmvc-version-spring-boot-starter" |         const val VERSION = ":forgeboot-webmvc-spring-boot-starter:forgeboot-webmvc-version-spring-boot-starter" | ||||||
|         const val LOGGER = ":forgeboot-webmvc-spring-boot-starter:forgeboot-webmvc-logger-spring-boot-starter" |         const val LOGGER = ":forgeboot-webmvc-spring-boot-starter:forgeboot-webmvc-logger-spring-boot-starter" | ||||||
|     } |     } | ||||||
| 
 |     object Core{ | ||||||
|     /** |  | ||||||
|      * Core模块:项目的基础核心模块 |  | ||||||
|      * 包含项目的通用核心功能以及扩展支持 |  | ||||||
|      */ |  | ||||||
|     object Core { |  | ||||||
|         const val ROOT = ":forgeboot-core" |         const val ROOT = ":forgeboot-core" | ||||||
|         const val EXTENSION = ":forgeboot-core:forgeboot-core-extension" |         const val EXTENSION = ":forgeboot-core:forgeboot-core-extension" | ||||||
|         const val SERIALIZATION = ":forgeboot-core:forgeboot-core-serialization" |  | ||||||
|     } |     } | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * Cache模块:缓存支持模块 |  | ||||||
|      * 提供缓存功能,包含API、实现及自动配置模块 |  | ||||||
|      */ |  | ||||||
|     object Cache { |  | ||||||
|         const val STARTER = ":forgeboot-cache-spring-boot-starter" |  | ||||||
|         const val API = ":forgeboot-cache-spring-boot-starter:forgeboot-cache-api" |  | ||||||
|         const val IMPL = ":forgeboot-cache-spring-boot-starter:forgeboot-cache-impl" |  | ||||||
|         const val AUTOCONFIGURE = ":forgeboot-cache-spring-boot-starter:forgeboot-cache-autoconfigure" |  | ||||||
|     } |  | ||||||
|     /** |  | ||||||
|      * I18n模块:国际化支持模块 |  | ||||||
|      * 提供多语言支持功能,包含API、实现及自动配置模块 |  | ||||||
|      */ |  | ||||||
|     object I18n { |     object I18n { | ||||||
|         const val STARTER = ":forgeboot-i18n-spring-boot-starter" |         const val STARTER = ":forgeboot-i18n-spring-boot-starter" | ||||||
|         const val API = ":forgeboot-i18n-spring-boot-starter:forgeboot-i18n-api" |         const val API = ":forgeboot-i18n-spring-boot-starter:forgeboot-i18n-api" | ||||||
|         const val IMPL = ":forgeboot-i18n-spring-boot-starter:forgeboot-i18n-impl" |         const val IMPL = ":forgeboot-i18n-spring-boot-starter:forgeboot-i18n-impl" | ||||||
|         const val AUTOCONFIGURE = ":forgeboot-i18n-spring-boot-starter:forgeboot-i18n-autoconfigure" |         const val AUTOCONFIGURE = ":forgeboot-i18n-spring-boot-starter:forgeboot-i18n-autoconfigure" | ||||||
|     } |     } | ||||||
| 
 |     object TRACE{ | ||||||
|     /** |  | ||||||
|      * TRACE模块:分布式链路追踪支持模块 |  | ||||||
|      * 提供请求链路追踪能力,包含API、实现及自动配置模块 |  | ||||||
|      */ |  | ||||||
|     object TRACE { |  | ||||||
|         const val STARTER = ":forgeboot-trace-spring-boot-starter" |         const val STARTER = ":forgeboot-trace-spring-boot-starter" | ||||||
|         const val API = ":forgeboot-trace-spring-boot-starter:forgeboot-trace-api" |         const val API = ":forgeboot-trace-spring-boot-starter:forgeboot-trace-api" | ||||||
|         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 { | ||||||
|     /** |  | ||||||
|      * Banner模块:启动横幅定制模块 |  | ||||||
|      * 负责自定义应用启动时显示的横幅信息 |  | ||||||
|      */ |  | ||||||
|     object Banner { |  | ||||||
|         const val STARTER = ":forgeboot-banner" |         const val STARTER = ":forgeboot-banner" | ||||||
|         const val API = ":forgeboot-banner:forgeboot-banner-api" |         const val API = ":forgeboot-banner:forgeboot-banner-api" | ||||||
|         const val IMPL = ":forgeboot-banner:forgeboot-banner-impl" |         const val IMPL = ":forgeboot-banner:forgeboot-banner-impl" | ||||||
|         const val AUTOCONFIGURE = ":forgeboot-banner:forgeboot-banner-autoconfigure" |         const val AUTOCONFIGURE = ":forgeboot-banner:forgeboot-banner-autoconfigure" | ||||||
|     } |     } | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * Security模块:安全认证与授权模块集合 |  | ||||||
|      * 包含认证(Authenticate)和授权(Authorize)两个子模块 |  | ||||||
|      */ |  | ||||||
|     object Security { |  | ||||||
|         private const val SECURITY = ":forgeboot-security-spring-boot-starter" |  | ||||||
|         private const val AUTHENTICATE = "${SECURITY}:forgeboot-security-authenticate-spring-boot-starter" |  | ||||||
|         private const val AUTHORIZE = "${SECURITY}:forgeboot-security-authorize-spring-boot-starter" |  | ||||||
|         const val CORE = "${SECURITY}:forgeboot-security-core" |  | ||||||
|         /** |  | ||||||
|          * Authenticate模块:身份认证支持模块 |  | ||||||
|          * 提供用户身份认证相关功能,包含API、实现及自动配置模块 |  | ||||||
|          */ |  | ||||||
|         object Authenticate { |  | ||||||
|             const val STARTER = AUTHENTICATE |  | ||||||
|             const val API = "${AUTHENTICATE}:forgeboot-security-authenticate-api" |  | ||||||
|             const val IMPL = "${AUTHENTICATE}:forgeboot-security-authenticate-impl" |  | ||||||
|             const val AUTOCONFIGURE = |  | ||||||
|                 "${AUTHENTICATE}:forgeboot-security-authenticate" |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         /** |  | ||||||
|          * Authorize模块:权限控制支持模块 |  | ||||||
|          * 提供基于角色或策略的权限控制功能,包含API、实现及自动配置模块 |  | ||||||
|          */ |  | ||||||
|         object Authorize { |  | ||||||
|             const val STARTER = AUTHORIZE |  | ||||||
|             const val API = "${AUTHORIZE}:forgeboot-security-authorize-api" |  | ||||||
|             const val IMPL =  "${AUTHORIZE}:forgeboot-security-authorize-impl" |  | ||||||
|             const val AUTOCONFIGURE = |  | ||||||
|                 "${AUTHORIZE}:forgeboot-security-authorize-autoconfigure" |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } | } | ||||||
							
								
								
									
										3
									
								
								forgeboot-cache/.gitattributes
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								forgeboot-cache/.gitattributes
									
									
									
									
										vendored
									
									
								
							| @ -1,3 +0,0 @@ | |||||||
| /gradlew text eol=lf |  | ||||||
| *.bat text eol=crlf |  | ||||||
| *.jar binary |  | ||||||
							
								
								
									
										39
									
								
								forgeboot-cache/.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										39
									
								
								forgeboot-cache/.gitignore
									
									
									
									
										vendored
									
									
								
							| @ -1,39 +0,0 @@ | |||||||
| .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 |  | ||||||
| @ -1,8 +0,0 @@ | |||||||
| extra { |  | ||||||
|     // 标记为根项目 |  | ||||||
|     setProperty(ProjectFlags.IS_ROOT_MODULE, true) |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| dependencies { |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
| @ -1,3 +0,0 @@ | |||||||
| /gradlew text eol=lf |  | ||||||
| *.bat text eol=crlf |  | ||||||
| *.jar binary |  | ||||||
							
								
								
									
										40
									
								
								forgeboot-cache/forgeboot-cache-api/.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										40
									
								
								forgeboot-cache/forgeboot-cache-api/.gitignore
									
									
									
									
										vendored
									
									
								
							| @ -1,40 +0,0 @@ | |||||||
| 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 |  | ||||||
| @ -1,5 +0,0 @@ | |||||||
| 
 |  | ||||||
| dependencies { |  | ||||||
|     compileOnly(libs.springBoot.autoconfigure) |  | ||||||
|     kapt(libs.springBoot.configuration.processor) |  | ||||||
| } |  | ||||||
| @ -1,20 +0,0 @@ | |||||||
| package com.gewuyou.forgeboot.cache.api.annotations |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * 缓存移除扩展注解,用于标识需要清除缓存的方法 |  | ||||||
|  * |  | ||||||
|  * 该注解应用于方法上,表示在方法执行前后可以触发缓存清除操作。 |  | ||||||
|  * 支持通过命名空间和SpEL表达式定义缓存键,并指定缓存层级。 |  | ||||||
|  * |  | ||||||
|  * @property namespace 缓存的命名空间,用于对缓存进行逻辑分组,默认为空字符串 |  | ||||||
|  * @property keySpEL 缓存键的SpEL表达式,用于动态生成缓存键,默认为空字符串 |  | ||||||
|  * |  | ||||||
|  * @since 2025-06-16 22:29:52 |  | ||||||
|  * @author gewuyou |  | ||||||
|  */ |  | ||||||
| @Target(AnnotationTarget.FUNCTION) |  | ||||||
| @Retention(AnnotationRetention.RUNTIME) |  | ||||||
| annotation class CacheEvictEx( |  | ||||||
|     val namespace: String, |  | ||||||
|     val keySpEL: String |  | ||||||
| ) |  | ||||||
| @ -1,21 +0,0 @@ | |||||||
| package com.gewuyou.forgeboot.cache.api.annotations |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * 缓存 put ex |  | ||||||
|  * |  | ||||||
|  * 用于声明式缓存更新操作的注解,适用于方法级别 |  | ||||||
|  * |  | ||||||
|  * @property namespace 命名空间,用于缓存键的逻辑分组,默认为空字符串 |  | ||||||
|  * @property keySpEL 缓存键的 SpEL 表达式,默认为空字符串 |  | ||||||
|  * @property ttl 缓存键生存时间 |  | ||||||
|  * |  | ||||||
|  * @since 2025-06-16 22:33:35 |  | ||||||
|  * @author gewuyou |  | ||||||
|  */ |  | ||||||
| @Target(AnnotationTarget.FUNCTION) |  | ||||||
| @Retention(AnnotationRetention.RUNTIME) |  | ||||||
| annotation class CachePutEx( |  | ||||||
|     val namespace: String, |  | ||||||
|     val keySpEL: String, |  | ||||||
|     val ttl: Long = 300L |  | ||||||
| ) |  | ||||||
| @ -1,29 +0,0 @@ | |||||||
| package com.gewuyou.forgeboot.cache.api.annotations |  | ||||||
| 
 |  | ||||||
| import kotlin.reflect.KClass |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * 缓存注解扩展,用于标记可缓存的方法。 |  | ||||||
|  * |  | ||||||
|  * 该注解应用于方法级别,表示该方法的结果可以被缓存。通过指定不同的参数, |  | ||||||
|  * 可以控制缓存的命名空间、键生成表达式、过期时间、是否缓存空值以及缓存层级。 |  | ||||||
|  * |  | ||||||
|  * @property namespace 缓存的命名空间,用于区分不同业务场景下的缓存数据,默认为空字符串。 |  | ||||||
|  * @property keySpEL 缓存键的 SpEL 表达式,用于动态生成缓存键,默认为空字符串。 |  | ||||||
|  * @property ttl 缓存过期时间,单位为秒,默认值为 300 秒(即 10 分钟)。 |  | ||||||
|  * @property cacheNull 是否缓存空值,默认为 false,表示不缓存空结果。 |  | ||||||
|  * @property type 指定缓存值的类型,用于确保类型安全,默认使用 KClass<*> 表示任意类型。 |  | ||||||
|  * |  | ||||||
|  * @since 2025-06-16 |  | ||||||
|  * @author gewuyou |  | ||||||
|  */ |  | ||||||
| @Target(AnnotationTarget.FUNCTION) |  | ||||||
| @Retention(AnnotationRetention.RUNTIME) |  | ||||||
| @MustBeDocumented |  | ||||||
| annotation class CacheableEx( |  | ||||||
|     val namespace: String, |  | ||||||
|     val keySpEL: String, |  | ||||||
|     val ttl: Long = 300L, |  | ||||||
|     val cacheNull: Boolean = false, |  | ||||||
|     @JvmSuppressWildcards val type: KClass<*> = Any::class |  | ||||||
| ) |  | ||||||
| @ -1,31 +0,0 @@ | |||||||
| package com.gewuyou.forgeboot.cache.api.config |  | ||||||
| 
 |  | ||||||
| import org.springframework.boot.context.properties.ConfigurationProperties |  | ||||||
| import java.time.Duration |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * 缓存属性配置类 |  | ||||||
|  * |  | ||||||
|  * 该类用于定义缓存相关的配置属性,通过@ConfigurationProperties绑定配置前缀"forgeboot.cache" |  | ||||||
|  * 支持配置默认缓存过期时间(TTL) |  | ||||||
|  * |  | ||||||
|  * @since 2025-06-17 10:04:48 |  | ||||||
|  * @author gewuyou |  | ||||||
|  */ |  | ||||||
| @ConfigurationProperties("forgeboot.cache") |  | ||||||
| class CacheProperties { |  | ||||||
|     /** |  | ||||||
|      * 默认缓存过期时间(Time To Live) |  | ||||||
|      * |  | ||||||
|      * 用于指定缓存项在未被访问后的最大存活时间 |  | ||||||
|      * 默认值为15分钟 |  | ||||||
|      */ |  | ||||||
|     var theDefaultCacheTTL: Duration = Duration.ofMinutes(15) |  | ||||||
|     /** |  | ||||||
|      * 缓存项为null时使用的占位符 |  | ||||||
|      * |  | ||||||
|      * 用于在缓存项为null时返回的占位符 |  | ||||||
|      * 默认值为"__NULL__" |  | ||||||
|      */ |  | ||||||
|     var nullValuePlaceholder: String = "__NULL__" |  | ||||||
| } |  | ||||||
| @ -1,69 +0,0 @@ | |||||||
| package com.gewuyou.forgeboot.cache.api.contract |  | ||||||
| 
 |  | ||||||
| import java.time.Duration |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * 缓存接口定义 |  | ||||||
|  * |  | ||||||
|  * 提供统一的缓存操作方法,包括获取、存储、删除和判断键是否存在。 |  | ||||||
|  * |  | ||||||
|  * @since 2025-06-16 22:39:16 |  | ||||||
|  * @author gewuyou |  | ||||||
|  */ |  | ||||||
| interface Cache { |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 获取指定键对应的缓存值。 |  | ||||||
|      * |  | ||||||
|      * @param key 缓存键 |  | ||||||
|      * @return 缓存值,如果不存在则返回 null |  | ||||||
|      */ |  | ||||||
|     fun retrieve(key: String): String? |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 将键值对存储到缓存中,并设置过期时间。 |  | ||||||
|      * |  | ||||||
|      * @param key   缓存键 |  | ||||||
|      * @param value 缓存值,可以为 null |  | ||||||
|      * @param ttl   缓存存活时间(Time To Live) |  | ||||||
|      */ |  | ||||||
|     fun put(key: String, value: String?, ttl: Duration) |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 删除指定键的缓存。 |  | ||||||
|      * |  | ||||||
|      * @param key 要删除的缓存键 |  | ||||||
|      * @return 如果删除成功返回 true,否则返回 false |  | ||||||
|      */ |  | ||||||
|     fun remove(key: String): Boolean |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 判断指定键是否存在于缓存中。 |  | ||||||
|      * |  | ||||||
|      * @param key 缓存键 |  | ||||||
|      * @return 如果存在返回 true,否则返回 false |  | ||||||
|      */ |  | ||||||
|     fun exists(key: String): Boolean |  | ||||||
|     /** |  | ||||||
|      * 清空缓存中的所有数据。 |  | ||||||
|      * @param namespace 命名空间 |  | ||||||
|      */ |  | ||||||
|     fun clear(namespace: String) |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 通过操作符重载实现缓存的获取操作。 |  | ||||||
|      * |  | ||||||
|      * @param key 缓存键 |  | ||||||
|      * @return 缓存值,如果不存在则返回 null |  | ||||||
|      */ |  | ||||||
|     fun Cache.get(key: String): String? = this.retrieve(key) |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 通过操作符重载实现缓存的存储操作。 |  | ||||||
|      * |  | ||||||
|      * @param key   缓存键 |  | ||||||
|      * @param value 缓存值,可以为 null |  | ||||||
|      * @param ttl   缓存存活时间(Time To Live) |  | ||||||
|      */ |  | ||||||
|     operator fun Cache.set(key: String, value: String?, ttl: Duration) = this.put(key, value, ttl) |  | ||||||
| } |  | ||||||
| @ -1,17 +0,0 @@ | |||||||
| package com.gewuyou.forgeboot.cache.api.entities |  | ||||||
| 
 |  | ||||||
| import com.gewuyou.forgeboot.cache.api.contract.Cache |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * 缓存层实体类,用于定义缓存层级结构。 |  | ||||||
|  *  |  | ||||||
|  * @property cache 关联的缓存实例,用于实际执行缓存操作。 |  | ||||||
|  * @property priority 缓存优先级,用于决定多个缓存实现中的调用顺序。 |  | ||||||
|  * |  | ||||||
|  * @since 2025-06-16 22:43:15 |  | ||||||
|  * @author gewuyou |  | ||||||
|  */ |  | ||||||
| data class CacheLayer( |  | ||||||
|     val cache: Cache, |  | ||||||
|     val priority: Int |  | ||||||
| ) |  | ||||||
| @ -1,17 +0,0 @@ | |||||||
| package com.gewuyou.forgeboot.cache.api.exception |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * 缓存异常类,用于封装与缓存操作相关的异常信息。 |  | ||||||
|  * |  | ||||||
|  * @param message 异常的详细描述信息,默认为 null。 |  | ||||||
|  * @param cause   导致此异常的底层异常,默认为 null。 |  | ||||||
|  * |  | ||||||
|  * @since 2025-06-17 21:14:40 |  | ||||||
|  * @author gewuyou |  | ||||||
|  */ |  | ||||||
| class CacheException( |  | ||||||
|     message: String? = null, |  | ||||||
|     cause: Throwable? = null, |  | ||||||
| ) : RuntimeException( |  | ||||||
|     message, cause |  | ||||||
| ) |  | ||||||
| @ -1,32 +0,0 @@ | |||||||
| package com.gewuyou.forgeboot.cache.api.extension |  | ||||||
| 
 |  | ||||||
| import com.gewuyou.forgeboot.cache.api.contract.Cache |  | ||||||
| import java.time.Duration |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * 重载 set 操作符,用于通过 [] 语法将指定键值对及存活时间存入缓存。 |  | ||||||
|  * |  | ||||||
|  * 此方法封装了缓存的存储操作,并支持指定缓存项的存活时间(TTL)。 |  | ||||||
|  * |  | ||||||
|  * @param key   要存储的缓存键,类型为 [String]。 |  | ||||||
|  * @param value 要存储的缓存值,类型为 [String?],允许为 null。 |  | ||||||
|  * @param ttl   存活时间,类型为 [Duration],表示缓存项的有效期。 |  | ||||||
|  */ |  | ||||||
| operator fun Cache.set(key: String, value: String?, ttl: Duration) { |  | ||||||
|     this.put(key, value, ttl) |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * 获取指定键对应的缓存值。 |  | ||||||
|  * |  | ||||||
|  * 从最高优先级的缓存层开始查找,一旦找到有效值,则将其回填到 |  | ||||||
|  * 所有优先级高于当前层的缓存中,并返回该值。 |  | ||||||
|  * |  | ||||||
|  * 此方法封装了缓存的读取逻辑,并负责维护缓存层级间的数据一致性。 |  | ||||||
|  * |  | ||||||
|  * @param key 要获取的缓存键,类型为 [String]。 |  | ||||||
|  * @return 如果存在缓存值则返回对应值,类型为 [String?];否则返回 null。 |  | ||||||
|  */ |  | ||||||
| operator fun Cache.get(key: String): String? { |  | ||||||
|    return this.retrieve(key) |  | ||||||
| } |  | ||||||
| @ -1,77 +0,0 @@ | |||||||
| package com.gewuyou.forgeboot.cache.api.extension |  | ||||||
| 
 |  | ||||||
| import com.gewuyou.forgeboot.cache.api.loader.CacheLoader |  | ||||||
| import com.gewuyou.forgeboot.cache.api.service.CacheService |  | ||||||
| import java.time.Duration |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * 操作符扩展函数,用于通过 set(key, value, ttl) 存储带有过期时间的泛型值。 |  | ||||||
|  * |  | ||||||
|  * 该函数扩展了 CacheService 接口,允许使用操作符语法设置缓存键值对,并指定生存时间。 |  | ||||||
|  * 实际调用 put 方法完成缓存写入操作。 |  | ||||||
|  * |  | ||||||
|  * @param key   缓存键,用于唯一标识存储的数据 |  | ||||||
|  * @param value 值,支持任意对象类型,将被序列化后存储 |  | ||||||
|  * @param ttl   缓存生存时间,指定该值后缓存将在设定的时间后自动失效 |  | ||||||
|  */ |  | ||||||
| operator fun CacheService.set(key: String, value: Any, ttl: Duration) { |  | ||||||
|     this.put(key, value, ttl) |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * 获取指定键的缓存值。 |  | ||||||
|  * |  | ||||||
|  * @param key  缓存键 |  | ||||||
|  * @param type 值的类型 Class |  | ||||||
|  * @return 缓存中的对象,如果不存在则为 null |  | ||||||
|  */ |  | ||||||
| operator fun <T : Any> CacheService.get(key: String, type: Class<T>): T? { |  | ||||||
|     return this.retrieve(key, type) |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * 通过泛型方式获取指定键的缓存值。 |  | ||||||
|  * |  | ||||||
|  * @param key 缓存键 |  | ||||||
|  * @return 缓存中的对象,如果不存在则为 null |  | ||||||
|  */ |  | ||||||
| inline fun <reified T : Any> CacheService.get(key: String): T? { |  | ||||||
|     return this.retrieve(key, T::class.java) |  | ||||||
| } |  | ||||||
| /** |  | ||||||
|  * 获取指定键的缓存值,若不存在则使用给定的加载器进行加载,并将结果存入缓存。 |  | ||||||
|  * |  | ||||||
|  * @param key   缓存键 |  | ||||||
|  * @param type  值的类型 Class |  | ||||||
|  * @param ttl   缓存生存时间,指定该值后缓存将在设定的时间后自动失效 |  | ||||||
|  * @param loader 用于加载数据的 CacheLoader 实例 |  | ||||||
|  * @return 缓存中的对象,如果不存在且 loader 也无法加载则为 null |  | ||||||
|  */ |  | ||||||
| fun <T : Any> CacheService.getOrLoad( |  | ||||||
|     key: String, |  | ||||||
|     type: Class<T>, |  | ||||||
|     ttl: Duration, |  | ||||||
|     loader: CacheLoader<T> = CacheLoader { _, _ -> null } |  | ||||||
| ): T? { |  | ||||||
|     return this.retrieve(key, type) ?: loader.load(key, type)?.also { |  | ||||||
|         this.put(key, it, ttl) |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * 通过泛型方式获取指定键的缓存值,若不存在则使用给定的加载函数进行加载,并将结果存入缓存。 |  | ||||||
|  * |  | ||||||
|  * @param key 缓存键 |  | ||||||
|  * @param ttl 缓存生存时间,指定该值后缓存将在设定的时间后自动失效 |  | ||||||
|  * @param loader 一个函数,接收键并返回加载的数据(或 null) |  | ||||||
|  * @return 缓存中的对象,如果不存在且 loader 也无法加载则为 null |  | ||||||
|  */ |  | ||||||
| inline fun <reified T : Any> CacheService.getOrLoad( |  | ||||||
|     key: String, |  | ||||||
|     ttl: Duration, |  | ||||||
|     loader: CacheLoader<T> = CacheLoader { _, _ -> null } |  | ||||||
| ): T? { |  | ||||||
|     return retrieve(key, T::class.java) ?: loader.load(key, T::class.java)?.also { |  | ||||||
|         put(key, it, ttl) |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @ -1,32 +0,0 @@ | |||||||
| package com.gewuyou.forgeboot.cache.api.generator |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * 键生成器接口 |  | ||||||
|  * |  | ||||||
|  * 该接口用于统一管理不同场景下的缓存键生成逻辑,通过命名空间和基础键值组合生成完整键。 |  | ||||||
|  * |  | ||||||
|  * @since 2025-06-16 22:17:36 |  | ||||||
|  * @author gewuyou |  | ||||||
|  */ |  | ||||||
| interface KeyGenerator { |  | ||||||
|     /** |  | ||||||
|      * 生成缓存键 |  | ||||||
|      * |  | ||||||
|      * 根据传入的命名空间和基础键值,组合生成一个完整的缓存键。实现类应确保返回的键具有唯一性与可读性。 |  | ||||||
|      * |  | ||||||
|      * @param namespace 命名空间,用于隔离不同的缓存区域,例如模块名称或业务标识 |  | ||||||
|      * @param key       基础键值,表示具体缓存项标识,通常是动态参数或固定字符串 |  | ||||||
|      * @return 返回生成的完整缓存键,通常格式为 "namespace:key" |  | ||||||
|      */ |  | ||||||
|     fun generateKey(namespace: String, key: String): String |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 获取连接符 |  | ||||||
|      * |  | ||||||
|      * 返回用于拼接命名空间和基础键值的连接符,默认实现可能返回冒号(:)或其他特定字符。 |  | ||||||
|      * 此方法允许子类自定义连接符,以满足不同存储结构或命名规范的需求。 |  | ||||||
|      * |  | ||||||
|      * @return 返回连接符字符串 |  | ||||||
|      */ |  | ||||||
|     fun getConnectors(): String |  | ||||||
| } |  | ||||||
| @ -1,18 +0,0 @@ | |||||||
| package com.gewuyou.forgeboot.cache.api.loader |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * 通用缓存加载器接口,支持缓存未命中时从源头加载数据。 |  | ||||||
|  * |  | ||||||
|  * @since 2025-06-16 |  | ||||||
|  */ |  | ||||||
| fun interface CacheLoader<T : Any> { |  | ||||||
|     /** |  | ||||||
|      * 加载与指定缓存键关联的数据。 |  | ||||||
|      * |  | ||||||
|      * @param key 缓存键(字符串形式) |  | ||||||
|      * @param type 缓存值类型(用于反序列化) |  | ||||||
|      * @return 加载到的数据,若无则返回 null |  | ||||||
|      */ |  | ||||||
|     fun load(key: String, type: Class<T>): T? |  | ||||||
| } |  | ||||||
| @ -1,37 +0,0 @@ | |||||||
| package com.gewuyou.forgeboot.cache.api.manager |  | ||||||
| 
 |  | ||||||
| import com.gewuyou.forgeboot.cache.api.service.CacheService |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * 缓存管理器 |  | ||||||
|  * |  | ||||||
|  * 提供对不同缓存服务的统一访问接口,通过指定的命名空间获取对应的缓存服务实例。 |  | ||||||
|  * 该接口定义了核心方法用于获取泛型化的缓存服务对象。 |  | ||||||
|  * |  | ||||||
|  * @since 2025-06-16 22:11:06 |  | ||||||
|  * @author gewuyou |  | ||||||
|  */ |  | ||||||
| interface CacheManager { |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 获取指定命名空间的缓存服务实例 |  | ||||||
|      * |  | ||||||
|      * @param namespace 缓存服务的命名空间标识 |  | ||||||
|      * @return 返回与命名空间关联的 CacheService 实例 |  | ||||||
|      */ |  | ||||||
|     fun getCache(namespace: String): CacheService |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 清除指定命名空间下的所有缓存数据 |  | ||||||
|      * |  | ||||||
|      * @param namespace 要清除缓存数据的命名空间标识 |  | ||||||
|      */ |  | ||||||
|     fun clear(namespace: String) |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 清除所有命名空间下的缓存数据 |  | ||||||
|      * |  | ||||||
|      * 通常用于全局缓存刷新或系统清理操作 |  | ||||||
|      */ |  | ||||||
|     fun clearAll() |  | ||||||
| } |  | ||||||
| @ -1,28 +0,0 @@ | |||||||
| package com.gewuyou.forgeboot.cache.api.policy |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * 缓存策略接口,定义了缓存数据应用的规则。 |  | ||||||
|  * |  | ||||||
|  * 实现该接口的类应提供一个 apply 方法,用于根据给定的键和值来执行特定的缓存策略。 |  | ||||||
|  * 例如,可以在此方法中实现过期时间设置、缓存淘汰算法等逻辑。 |  | ||||||
|  * |  | ||||||
|  * @since 2025-06-21 11:54:50 |  | ||||||
|  * @author gewuyou |  | ||||||
|  */ |  | ||||||
| interface CachePolicy { |  | ||||||
|     /** |  | ||||||
|      * 根据给定的键和值来执行缓存策略。 |  | ||||||
|      * |  | ||||||
|      * @param key   缓存项的键,用于唯一标识一个缓存条目 |  | ||||||
|      * @param value 可为空的字符串,表示与键关联的值;为 null 时可能指示移除或跳过缓存操作 |  | ||||||
|      * @return      返回处理后的缓存值,也可以是 null 表示不进行缓存 |  | ||||||
|      */ |  | ||||||
|     fun apply(key: String, value: String?): String? |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 获取该策略的优先级,用于决定多个策略的执行顺序 |  | ||||||
|      * |  | ||||||
|      * @return 优先级,值越小表示优先级越高 |  | ||||||
|      */ |  | ||||||
|     fun getOrder(): Int |  | ||||||
| } |  | ||||||
| @ -1,34 +0,0 @@ | |||||||
| package com.gewuyou.forgeboot.cache.api.policy |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * Null 值策略接口 |  | ||||||
|  * |  | ||||||
|  * 用于定义缓存中 null 值的处理策略,包括是否允许缓存 null 值、获取 null 占位符以及判断值是否为 null 占位符。 |  | ||||||
|  * |  | ||||||
|  * @since 2025-06-16 22:15:13 |  | ||||||
|  * @author gewuyou |  | ||||||
|  */ |  | ||||||
| interface NullValuePolicy { |  | ||||||
|     /** |  | ||||||
|      * 判断给定的 key 是否允许缓存 null 值。 |  | ||||||
|      * |  | ||||||
|      * @param key 缓存项的键 |  | ||||||
|      * @return Boolean 返回 true 表示允许缓存 null 值,否则不允许 |  | ||||||
|      */ |  | ||||||
|     fun allowCacheNull(key: String): Boolean |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 获取用于表示 null 值的占位符字符串。 |  | ||||||
|      * |  | ||||||
|      * @return String 返回 null 值的占位符 |  | ||||||
|      */ |  | ||||||
|     fun nullPlaceholder(): String |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 判断给定的 value 是否为 null 占位符。 |  | ||||||
|      * |  | ||||||
|      * @param value 要判断的值 |  | ||||||
|      * @return Boolean 返回 true 表示是 null 占位符,否则不是 |  | ||||||
|      */ |  | ||||||
|     fun isNullPlaceholder(value: String): Boolean |  | ||||||
| } |  | ||||||
| @ -1,54 +0,0 @@ | |||||||
| package com.gewuyou.forgeboot.cache.api.service |  | ||||||
| 
 |  | ||||||
| import java.time.Duration |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * 缓存服务接口,定义了缓存的基本操作。 |  | ||||||
|  * |  | ||||||
|  * @since 2025-06-16 21:58:56 |  | ||||||
|  * @author gewuyou |  | ||||||
|  */ |  | ||||||
| interface CacheService { |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 获取指定键的缓存值。 |  | ||||||
|      * |  | ||||||
|      * @param key  缓存键 |  | ||||||
|      * @param type 值的类型 Class |  | ||||||
|      * @return 缓存中的对象,如果不存在则为 null |  | ||||||
|      */ |  | ||||||
|     fun <T : Any> retrieve(key: String, type: Class<T>): T? |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 设置缓存值。 |  | ||||||
|      * |  | ||||||
|      * @param key   缓存键 |  | ||||||
|      * @param value 值(支持任意对象) |  | ||||||
|      * @param ttl   缓存时长,null 表示使用默认 TTL |  | ||||||
|      */ |  | ||||||
|     fun put(key: String, value: Any, ttl: Duration? = null) |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 删除缓存。 |  | ||||||
|      * |  | ||||||
|      * @param key 缓存键 |  | ||||||
|      * @return 删除成功返回 true |  | ||||||
|      */ |  | ||||||
|     fun remove(key: String): Boolean |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 判断缓存是否存在。 |  | ||||||
|      * |  | ||||||
|      * @param key 缓存键 |  | ||||||
|      * @return 如果存在返回 true,否则返回 false |  | ||||||
|      */ |  | ||||||
|     fun exists(key: String): Boolean |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 清空指定命名空间下的缓存。 |  | ||||||
|      * |  | ||||||
|      * @param namespace 命名空间 |  | ||||||
|      */ |  | ||||||
|     fun clear(namespace: String) |  | ||||||
| } |  | ||||||
| @ -1,16 +0,0 @@ | |||||||
| package com.gewuyou.forgeboot.cache.api.service |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * 缓存预热服务 |  | ||||||
|  * 用于在系统启动或特定时机提前加载常用缓存数据,提升后续请求的访问效率 |  | ||||||
|  * |  | ||||||
|  * @since 2025-06-16 22:18:29 |  | ||||||
|  * @author gewuyou |  | ||||||
|  */ |  | ||||||
| fun interface CacheWarmUpService { |  | ||||||
|     /** |  | ||||||
|      * 执行缓存预热操作 |  | ||||||
|      * 该方法应包含具体的缓存加载逻辑,例如查询数据库或调用其他服务获取数据并写入缓存 |  | ||||||
|      */ |  | ||||||
|     fun warmUp() |  | ||||||
| } |  | ||||||
| @ -1,43 +0,0 @@ | |||||||
| package com.gewuyou.forgeboot.cache.api.service |  | ||||||
| 
 |  | ||||||
| import java.time.Duration |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * 锁服务接口,用于在分布式环境中执行需要加锁的操作。 |  | ||||||
|  * |  | ||||||
|  * @since 2025-06-16 22:11:57 |  | ||||||
|  * @author gewuyou |  | ||||||
|  */ |  | ||||||
| interface LockService { |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 在锁的保护下执行指定操作。 |  | ||||||
|      * |  | ||||||
|      * 使用给定的 key 获取锁,并在指定的超时时间内执行 supplier 提供的操作。 |  | ||||||
|      * 如果无法在超时时间内获取锁,则可能抛出异常或返回默认值,具体取决于实现方式。 |  | ||||||
|      * |  | ||||||
|      * @param <T> 返回值类型 |  | ||||||
|      * @param key 锁的唯一标识符,用于区分不同的资源锁 |  | ||||||
|      * @param timeout 获取锁的最大等待时间,单位为秒 |  | ||||||
|      * @param supplier 需要在锁保护下执行的操作,提供返回值 |  | ||||||
|      * @return 执行 supplier 后返回的结果 |  | ||||||
|      */ |  | ||||||
|     fun <T> executeWithLock(key: String, timeout: Duration, supplier: () -> T): T |  | ||||||
|     /** |  | ||||||
|      * 执行带读锁的操作。 |  | ||||||
|      * |  | ||||||
|      * @param key 锁键 |  | ||||||
|      * @param timeout 获取锁超时时间 |  | ||||||
|      * @param supplier 要执行的读操作 |  | ||||||
|      */ |  | ||||||
|     fun <T> executeWithReadLock(key: String, timeout: Duration, supplier: () -> T): T |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 执行带写锁的操作。 |  | ||||||
|      * |  | ||||||
|      * @param key 锁键 |  | ||||||
|      * @param timeout 获取锁超时时间 |  | ||||||
|      * @param supplier 要执行的写操作 |  | ||||||
|      */ |  | ||||||
|     fun <T> executeWithWriteLock(key: String, timeout: Duration, supplier: () -> T): T |  | ||||||
| } |  | ||||||
| @ -1,3 +0,0 @@ | |||||||
| /gradlew text eol=lf |  | ||||||
| *.bat text eol=crlf |  | ||||||
| *.jar binary |  | ||||||
| @ -1,40 +0,0 @@ | |||||||
| 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 |  | ||||||
| @ -1,12 +0,0 @@ | |||||||
| plugins { |  | ||||||
|     alias { libs.plugins.kotlin.plugin.spring } |  | ||||||
| } |  | ||||||
| dependencies { |  | ||||||
|     compileOnly(project(Modules.Cache.API)) |  | ||||||
|     compileOnly(project(Modules.Cache.IMPL)) |  | ||||||
|     compileOnly(libs.springBoot.autoconfigure) |  | ||||||
|     implementation(libs.springBootStarter.redis) |  | ||||||
|     implementation(libs.jackson.databind) |  | ||||||
|     implementation(libs.redisson.springBootStarter) |  | ||||||
|     api(project(Modules.Core.SERIALIZATION)) |  | ||||||
| } |  | ||||||
| @ -1,43 +0,0 @@ | |||||||
| package com.gewuyou.forgeboot.cache.autoconfigure |  | ||||||
| 
 |  | ||||||
| import com.gewuyou.forgeboot.cache.api.config.CacheProperties |  | ||||||
| import com.gewuyou.forgeboot.cache.autoconfigure.config.* |  | ||||||
| import org.springframework.boot.context.properties.EnableConfigurationProperties |  | ||||||
| import org.springframework.context.annotation.Import |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * 缓存自动配置类 |  | ||||||
|  * |  | ||||||
|  * 该类通过组合多个配置类实现完整的缓存功能装配,负责集成并协调以下模块: |  | ||||||
|  * - Redis 基础设施:连接工厂与操作模板([CacheBaseConfig]) |  | ||||||
|  * - 缓存策略定义:该配置类用于定义缓存相关的策略 Bean([CachePolicyConfig]) |  | ||||||
|  * - 缓存实现层:基于 Redis 和 Caffeine 的两级缓存支持([CacheImplConfig]) |  | ||||||
|  * - 多级缓存架构:支持本地缓存与分布式缓存的协同工作([CacheLayerConfig]) |  | ||||||
|  * - 组合缓存配置:用于构建复合缓存操作逻辑([CacheCompositeConfig]) |  | ||||||
|  * - 序列化管理:统一处理键值序列化与反序列化([CacheSerializerConfig]) |  | ||||||
|  * - 缓存管理器:提供统一访问入口和运行时管理能力([CacheManagerConfig]) |  | ||||||
|  * - 缓存预热机制:系统启动后自动加载热点数据([CacheWarmUpConfig]) |  | ||||||
|  * - 缓存切面支持:为注解如 @CacheableEx, @CacheEvictEx 提供执行上下文([CacheAspectConfig]) |  | ||||||
|  * - 分布式锁服务:提供跨节点资源同步机制([LockServiceConfig]) |  | ||||||
|  * |  | ||||||
|  * 所有导入的配置类共同构成完整的缓存解决方案,适用于高并发场景下的性能优化需求。 |  | ||||||
|  * |  | ||||||
|  * @property CacheProperties 提供外部可配置参数,用于定制缓存行为 |  | ||||||
|  * |  | ||||||
|  * @since 2025-06-17 20:49:17 |  | ||||||
|  * @author gewuyou |  | ||||||
|  */ |  | ||||||
| @Import( |  | ||||||
|     CacheBaseConfig::class, |  | ||||||
|     CachePolicyConfig::class, |  | ||||||
|     CacheImplConfig::class, |  | ||||||
|     CacheLayerConfig::class, |  | ||||||
|     CacheCompositeConfig::class, |  | ||||||
|     CacheSerializerConfig::class, |  | ||||||
|     CacheManagerConfig::class, |  | ||||||
|     CacheWarmUpConfig::class, |  | ||||||
|     CacheAspectConfig::class, |  | ||||||
|     LockServiceConfig::class |  | ||||||
| ) |  | ||||||
| @EnableConfigurationProperties(CacheProperties::class) |  | ||||||
| class CacheAutoConfiguration |  | ||||||
| @ -1,76 +0,0 @@ | |||||||
| package com.gewuyou.forgeboot.cache.autoconfigure.config |  | ||||||
| 
 |  | ||||||
| import com.gewuyou.forgeboot.cache.api.generator.KeyGenerator |  | ||||||
| import com.gewuyou.forgeboot.cache.api.manager.CacheManager |  | ||||||
| import com.gewuyou.forgeboot.cache.impl.aspect.CacheEvictExAspect |  | ||||||
| import com.gewuyou.forgeboot.cache.impl.aspect.CachePutExAspect |  | ||||||
| import com.gewuyou.forgeboot.cache.impl.aspect.CacheableExAspect |  | ||||||
| import org.springframework.context.annotation.Bean |  | ||||||
| import org.springframework.context.annotation.Configuration |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * 缓存切面配置类 |  | ||||||
|  * |  | ||||||
|  * 用于定义缓存相关的切面 Bean,包括 CacheableExAspect、CacheEvictExAspect 和 CachePutExAspect。 |  | ||||||
|  * 这些切面处理基于 Spring AOP 的缓存操作逻辑。 |  | ||||||
|  * |  | ||||||
|  * @since 2025-06-21 11:41:51 |  | ||||||
|  * @author gewuyou |  | ||||||
|  */ |  | ||||||
| @Configuration |  | ||||||
| class CacheAspectConfig { |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 创建 CacheableExAspect 切面 Bean |  | ||||||
|      * |  | ||||||
|      * 该方法将 CacheManager 和 KeyGenerator 注入到 CacheableExAspect 实例中, |  | ||||||
|      * 用于构建支持扩展的缓存获取切面逻辑。 |  | ||||||
|      * |  | ||||||
|      * @param cacheManager 缓存管理器,用于管理具体的缓存实现 |  | ||||||
|      * @param keyGenerator 键生成器,用于根据方法参数生成缓存键 |  | ||||||
|      * @return 初始化完成的 CacheableExAspect 实例 |  | ||||||
|      */ |  | ||||||
|     @Bean |  | ||||||
|     fun cacheableExAspect( |  | ||||||
|         cacheManager: CacheManager, |  | ||||||
|         keyGenerator: KeyGenerator |  | ||||||
|     ): CacheableExAspect { |  | ||||||
|         return CacheableExAspect(cacheManager, keyGenerator) |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 创建 CacheEvictExAspect 切面 Bean |  | ||||||
|      * |  | ||||||
|      * 该方法将 CacheManager 和 KeyGenerator 注入到 CacheEvictExAspect 实例中, |  | ||||||
|      * 用于构建支持扩展的缓存清除切面逻辑。 |  | ||||||
|      * |  | ||||||
|      * @param cacheManager 缓存管理器,用于管理具体的缓存实现 |  | ||||||
|      * @param keyGenerator 键生成器,用于根据方法参数生成缓存键 |  | ||||||
|      * @return 初始化完成的 CacheEvictExAspect 实例 |  | ||||||
|      */ |  | ||||||
|     @Bean |  | ||||||
|     fun cacheEvictExAspect( |  | ||||||
|         cacheManager: CacheManager, |  | ||||||
|         keyGenerator: KeyGenerator |  | ||||||
|     ): CacheEvictExAspect { |  | ||||||
|         return CacheEvictExAspect(cacheManager, keyGenerator) |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 创建 CachePutExAspect 切面 Bean |  | ||||||
|      * |  | ||||||
|      * 该方法将 CacheManager 和 KeyGenerator 注入到 CachePutExAspect 实例中, |  | ||||||
|      * 用于构建支持扩展的缓存更新切面逻辑。 |  | ||||||
|      * |  | ||||||
|      * @param cacheManager 缓存管理器,用于管理具体的缓存实现 |  | ||||||
|      * @param keyGenerator 键生成器,用于根据方法参数生成缓存键 |  | ||||||
|      * @return 初始化完成的 CachePutExAspect 实例 |  | ||||||
|      */ |  | ||||||
|     @Bean |  | ||||||
|     fun cachePutExAspect( |  | ||||||
|         cacheManager: CacheManager, |  | ||||||
|         keyGenerator: KeyGenerator |  | ||||||
|     ): CachePutExAspect { |  | ||||||
|         return CachePutExAspect(cacheManager, keyGenerator) |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @ -1,73 +0,0 @@ | |||||||
| package com.gewuyou.forgeboot.cache.autoconfigure.config |  | ||||||
| 
 |  | ||||||
| import com.gewuyou.forgeboot.cache.api.generator.KeyGenerator |  | ||||||
| import com.gewuyou.forgeboot.cache.impl.generator.DefaultKeyGenerator |  | ||||||
| import com.gewuyou.forgeboot.cache.impl.utils.RedisKeyScanner |  | ||||||
| import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean |  | ||||||
| import org.springframework.context.annotation.Bean |  | ||||||
| import org.springframework.context.annotation.Configuration |  | ||||||
| import org.springframework.data.redis.connection.RedisConnectionFactory |  | ||||||
| import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory |  | ||||||
| import org.springframework.data.redis.core.StringRedisTemplate |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * 缓存基础配置类,用于定义缓存相关的基础 Bean。 |  | ||||||
|  * |  | ||||||
|  * @since 2025-06-20 23:31:09 |  | ||||||
|  * @author gewuyou |  | ||||||
|  */ |  | ||||||
| @Configuration(proxyBeanMethods = false) |  | ||||||
| class CacheBaseConfig { |  | ||||||
|     /** |  | ||||||
|      * 创建 StringRedisTemplate Bean。 |  | ||||||
|      * |  | ||||||
|      * StringRedisTemplate 是 Spring Data Redis 提供的模板类, |  | ||||||
|      * 专门用于操作 Redis 中的字符串类型数据。 |  | ||||||
|      * |  | ||||||
|      * @return 配置好的 StringRedisTemplate 实例 |  | ||||||
|      */ |  | ||||||
|     @Bean |  | ||||||
|     fun redisTemplate(): StringRedisTemplate { |  | ||||||
|         return StringRedisTemplate() |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 创建 RedisConnectionFactory Bean。 |  | ||||||
|      * |  | ||||||
|      * RedisConnectionFactory 是连接 Redis 数据库的基础组件, |  | ||||||
|      * 使用 Lettuce 客户端实现连接。 |  | ||||||
|      * |  | ||||||
|      * @return 配置好的 LettuceConnectionFactory 实例 |  | ||||||
|      */ |  | ||||||
|     @Bean |  | ||||||
|     fun redisConnectionFactory(): RedisConnectionFactory { |  | ||||||
|         return LettuceConnectionFactory() |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 创建 RedisKeyScanner Bean。 |  | ||||||
|      * |  | ||||||
|      * RedisKeyScanner 用于扫描 Redis 中的键(Key),便于管理与维护缓存数据。 |  | ||||||
|      * |  | ||||||
|      * @param redisConnectionFactory 已注入的 Redis 连接工厂实例 |  | ||||||
|      * @return 配置好的 RedisKeyScanner 实例 |  | ||||||
|      */ |  | ||||||
|     @Bean |  | ||||||
|     fun redisKeyScanner(redisConnectionFactory: RedisConnectionFactory): RedisKeyScanner { |  | ||||||
|         return RedisKeyScanner(redisConnectionFactory) |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 创建默认的 KeyGenerator Bean。 |  | ||||||
|      * |  | ||||||
|      * DefaultKeyGenerator 用于生成统一格式的缓存键,确保缓存键的命名一致性。 |  | ||||||
|      * 若上下文中不存在 KeyGenerator 类型的 Bean,则自动创建此默认实例。 |  | ||||||
|      * |  | ||||||
|      * @return 默认的 KeyGenerator 实现实例 |  | ||||||
|      */ |  | ||||||
|     @Bean |  | ||||||
|     @ConditionalOnMissingBean |  | ||||||
|     fun keyGenerator(): KeyGenerator { |  | ||||||
|         return DefaultKeyGenerator() |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @ -1,41 +0,0 @@ | |||||||
| package com.gewuyou.forgeboot.cache.autoconfigure.config |  | ||||||
| 
 |  | ||||||
| import com.gewuyou.forgeboot.cache.api.config.CacheProperties |  | ||||||
| import com.gewuyou.forgeboot.cache.api.contract.Cache |  | ||||||
| import com.gewuyou.forgeboot.cache.api.entities.CacheLayer |  | ||||||
| import com.gewuyou.forgeboot.cache.impl.contract.CompositeCache |  | ||||||
| import org.springframework.context.annotation.Bean |  | ||||||
| import org.springframework.context.annotation.Configuration |  | ||||||
| import org.springframework.context.annotation.Primary |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * 缓存复合配置类 |  | ||||||
|  * |  | ||||||
|  * 该配置类用于定义与缓存相关的主缓存 Bean,通过组合多层缓存实现灵活的缓存策略。 |  | ||||||
|  * 主要职责是创建并初始化 CompositeCache 实例作为 Spring 容器中的核心缓存组件。 |  | ||||||
|  * |  | ||||||
|  * @since 2025-06-21 11:40:10 |  | ||||||
|  * @author gewuyou |  | ||||||
|  */ |  | ||||||
| @Configuration |  | ||||||
| class CacheCompositeConfig { |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 创建主缓存 Bean,使用 CompositeCache 组合多层缓存 |  | ||||||
|      * |  | ||||||
|      * 该方法将 cacheLayers 和 cacheProperties 注入到 CompositeCache 实例中, |  | ||||||
|      * 构建出一个支持多层缓存结构的主缓存组件。该组件会被 Spring 标记为首选 Bean。 |  | ||||||
|      * |  | ||||||
|      * @param cacheLayers 缓存层列表,包含多个 CacheLayer 实例,用于构建缓存层级结构 |  | ||||||
|      * @param cacheProperties 缓存配置对象,包含全局缓存相关属性设置 |  | ||||||
|      * @return 返回构建完成的 Cache 实例,实际类型为 CompositeCache |  | ||||||
|      */ |  | ||||||
|     @Bean("compositeCache") |  | ||||||
|     @Primary |  | ||||||
|     fun compositeCache( |  | ||||||
|         cacheLayers: List<CacheLayer>, |  | ||||||
|         cacheProperties: CacheProperties, |  | ||||||
|     ): Cache { |  | ||||||
|         return CompositeCache(cacheLayers, cacheProperties) |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @ -1,65 +0,0 @@ | |||||||
| package com.gewuyou.forgeboot.cache.autoconfigure.config |  | ||||||
| 
 |  | ||||||
| import com.gewuyou.forgeboot.cache.api.contract.Cache |  | ||||||
| import com.gewuyou.forgeboot.cache.api.generator.KeyGenerator |  | ||||||
| import com.gewuyou.forgeboot.cache.api.policy.CachePolicy |  | ||||||
| import com.gewuyou.forgeboot.cache.api.policy.NullValuePolicy |  | ||||||
| import com.gewuyou.forgeboot.cache.impl.contract.MultiPolicyCache |  | ||||||
| import com.gewuyou.forgeboot.cache.impl.contract.PerEntryTtlCaffeineCache |  | ||||||
| import com.gewuyou.forgeboot.cache.impl.contract.RedisCache |  | ||||||
| import com.gewuyou.forgeboot.cache.impl.utils.RedisKeyScanner |  | ||||||
| import org.springframework.context.annotation.Bean |  | ||||||
| import org.springframework.context.annotation.Configuration |  | ||||||
| import org.springframework.data.redis.core.StringRedisTemplate |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * 缓存实现配置类 |  | ||||||
|  * |  | ||||||
|  * 该配置类定义了缓存相关的 Bean,包括基于 Redis 和 Caffeine 的 NullAwareCache 实例。 |  | ||||||
|  * |  | ||||||
|  * @since 2025-06-21 11:38:18 |  | ||||||
|  * @author gewuyou |  | ||||||
|  */ |  | ||||||
| @Configuration |  | ||||||
| class CacheImplConfig { |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 构建基于 Redis 的 NullAwareCache 缓存实例 |  | ||||||
|      * |  | ||||||
|      * 该方法创建了一个包装 RedisCache 的 NullAwareCache 实例,并结合 NullValuePolicy 控制 null 值的处理策略。 |  | ||||||
|      * |  | ||||||
|      * @param redisTemplate Redis 模板,用于操作 Redis 数据库 |  | ||||||
|      * @param redisKeyScanner 用于扫描 Redis 中的键 |  | ||||||
|      * @param keyGenerator 用于生成缓存键 |  | ||||||
|      * @param nullCachePolicy NullValuePolicy 实例,控制 null 值的缓存行为 |  | ||||||
|      * @return 返回一个基于 Redis 的 Cache 实例 |  | ||||||
|      */ |  | ||||||
|     @Bean("redisNullAwareCache") |  | ||||||
|     fun redisNullAwareCache( |  | ||||||
|         redisTemplate: StringRedisTemplate, |  | ||||||
|         redisKeyScanner: RedisKeyScanner, |  | ||||||
|         keyGenerator: KeyGenerator, |  | ||||||
|         nullCachePolicy: NullValuePolicy, |  | ||||||
|         policies: List<CachePolicy> |  | ||||||
|     ): Cache { |  | ||||||
|         return MultiPolicyCache(RedisCache(redisTemplate, redisKeyScanner, keyGenerator), nullCachePolicy,policies) |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 构建基于 Caffeine 的 NullAwareCache 缓存实例 |  | ||||||
|      * |  | ||||||
|      * 该方法创建了一个使用 PerEntryTtlCaffeineCache 的 NullAwareCache 实例,支持条目级别的 TTL(生存时间)设置。 |  | ||||||
|      * |  | ||||||
|      * @param keyGenerator 用于生成缓存键 |  | ||||||
|      * @param nullCachePolicy NullValuePolicy 实例,控制 null 值的缓存行为 |  | ||||||
|      * @return 返回一个基于 Caffeine 的 Cache 实例 |  | ||||||
|      */ |  | ||||||
|     @Bean("perEntryTtlCaffeineNullAwareCache") |  | ||||||
|     fun perEntryTtlCaffeineNullAwareCache( |  | ||||||
|         keyGenerator: KeyGenerator, |  | ||||||
|         nullCachePolicy: NullValuePolicy, |  | ||||||
|         policies: List<CachePolicy> |  | ||||||
|     ): Cache { |  | ||||||
|         return MultiPolicyCache(PerEntryTtlCaffeineCache(keyGenerator), nullCachePolicy,policies) |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @ -1,43 +0,0 @@ | |||||||
| package com.gewuyou.forgeboot.cache.autoconfigure.config |  | ||||||
| 
 |  | ||||||
| import com.gewuyou.forgeboot.cache.api.contract.Cache |  | ||||||
| import com.gewuyou.forgeboot.cache.api.entities.CacheLayer |  | ||||||
| import org.springframework.beans.factory.annotation.Qualifier |  | ||||||
| import org.springframework.context.annotation.Bean |  | ||||||
| import org.springframework.context.annotation.Configuration |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * 缓存层配置 |  | ||||||
|  * |  | ||||||
|  * 该配置类用于定义多级缓存的层级结构,当前实现中包含两级缓存: |  | ||||||
|  * 第一层为基于 Caffeine 的本地缓存,具有每个条目独立的生存时间(TTL)特性; |  | ||||||
|  * 第二层为基于 Redis 的分布式缓存,用于跨服务共享缓存数据。 |  | ||||||
|  * |  | ||||||
|  * @since 2025-06-21 11:39:35 |  | ||||||
|  * @author gewuyou |  | ||||||
|  */ |  | ||||||
| @Configuration |  | ||||||
| class CacheLayerConfig { |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 定义缓存层级结构,Caffeine 缓存在第一层,Redis 缓存在第二层 |  | ||||||
|      * |  | ||||||
|      * 该方法创建并返回一个包含两个缓存层的列表。每层缓存都与一个具体的缓存实现绑定, |  | ||||||
|      * 并指定其在整体架构中的优先级顺序。第一层使用本地的 Caffeine 缓存以提高访问速度, |  | ||||||
|      * 第二层使用 Redis 缓存来保证数据的共享和持久性。 |  | ||||||
|      * |  | ||||||
|      * @param redisNullAwareCache 第二层缓存,基于 Redis 的 Null-aware 缓存实现 |  | ||||||
|      * @param perEntryTtlCaffeineNullAwareCache 第一层缓存,基于 Caffeine 的 Null-aware 缓存实现,支持每个缓存条目独立的 TTL 设置 |  | ||||||
|      * @return 包含两个缓存层的列表,按优先级排序 |  | ||||||
|      */ |  | ||||||
|     @Bean |  | ||||||
|     fun cacheLayers( |  | ||||||
|         @Qualifier("redisNullAwareCache") redisNullAwareCache: Cache, |  | ||||||
|         @Qualifier("perEntryTtlCaffeineNullAwareCache") perEntryTtlCaffeineNullAwareCache: Cache, |  | ||||||
|     ): List<CacheLayer> { |  | ||||||
|         return listOf( |  | ||||||
|             CacheLayer(perEntryTtlCaffeineNullAwareCache, 1), // 第一层:Caffeine 缓存,速度快,适合高频访问数据 |  | ||||||
|             CacheLayer(redisNullAwareCache, 2) // 第二层:Redis 缓存,用于持久化存储和跨节点共享数据 |  | ||||||
|         ) |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @ -1,57 +0,0 @@ | |||||||
| package com.gewuyou.forgeboot.cache.autoconfigure.config |  | ||||||
| 
 |  | ||||||
| import com.gewuyou.forgeboot.cache.api.config.CacheProperties |  | ||||||
| import com.gewuyou.forgeboot.cache.api.contract.Cache |  | ||||||
| import com.gewuyou.forgeboot.cache.api.generator.KeyGenerator |  | ||||||
| import com.gewuyou.forgeboot.cache.api.manager.CacheManager |  | ||||||
| import com.gewuyou.forgeboot.cache.impl.manager.DefaultCacheManager |  | ||||||
| import com.gewuyou.forgeboot.core.serialization.serializer.ValueSerializer |  | ||||||
| import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean |  | ||||||
| import org.springframework.context.annotation.Bean |  | ||||||
| import org.springframework.context.annotation.Configuration |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * 缓存管理器配置 |  | ||||||
|  * |  | ||||||
|  * 配置类用于定义缓存管理相关的 Bean,主要职责是创建和初始化 CacheManager 实例。 |  | ||||||
|  * 该配置类基于 Spring 的 @Configuration 注解标识为配置类,并通过 @Bean 定义核心 Bean。 |  | ||||||
|  * |  | ||||||
|  * @since 2025-06-21 11:41:05 |  | ||||||
|  * @author gewuyou |  | ||||||
|  */ |  | ||||||
| @Configuration |  | ||||||
| class CacheManagerConfig { |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 创建并配置 CacheManager 缓存管理器 Bean。 |  | ||||||
|      * |  | ||||||
|      * 此方法负责实例化一个 DefaultCacheManager,它依赖以下组件: |  | ||||||
|      * - cacheProperties:提供缓存的全局配置参数。 |  | ||||||
|      * - cache:实现缓存数据存储与访问的核心接口。 |  | ||||||
|      * - serializer:用于序列化和反序列化缓存值。 |  | ||||||
|      * - keyGenerator:生成缓存键的策略接口。 |  | ||||||
|      * |  | ||||||
|      * 返回的 CacheManager 是一个具体实现,用于管理整个应用中的缓存操作。 |  | ||||||
|      * |  | ||||||
|      * @param cacheProperties 缓存配置信息 |  | ||||||
|      * @param cache 缓存存储与访问的具体实现 |  | ||||||
|      * @param serializer 序列化/反序列化工具 |  | ||||||
|      * @param keyGenerator 缓存键生成策略 |  | ||||||
|      * @return 初始化完成的缓存管理器实例 |  | ||||||
|      */ |  | ||||||
|     @Bean |  | ||||||
|     @ConditionalOnMissingBean |  | ||||||
|     fun cacheManager( |  | ||||||
|         cacheProperties: CacheProperties, |  | ||||||
|         cache: Cache, |  | ||||||
|         serializer: ValueSerializer, |  | ||||||
|         keyGenerator: KeyGenerator |  | ||||||
|     ): CacheManager { |  | ||||||
|         return DefaultCacheManager( |  | ||||||
|             cacheProperties, |  | ||||||
|             cache, |  | ||||||
|             serializer, |  | ||||||
|             keyGenerator |  | ||||||
|         ) |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @ -1,53 +0,0 @@ | |||||||
| package com.gewuyou.forgeboot.cache.autoconfigure.config |  | ||||||
| 
 |  | ||||||
| import com.gewuyou.forgeboot.cache.api.config.CacheProperties |  | ||||||
| import com.gewuyou.forgeboot.cache.api.policy.CachePolicy |  | ||||||
| import com.gewuyou.forgeboot.cache.api.policy.NullValuePolicy |  | ||||||
| import com.gewuyou.forgeboot.cache.impl.policy.AllowNullCachePolicy |  | ||||||
| import com.gewuyou.forgeboot.cache.impl.policy.NullValueCachePolicy |  | ||||||
| import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean |  | ||||||
| import org.springframework.context.annotation.Bean |  | ||||||
| import org.springframework.context.annotation.Configuration |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * 缓存策略配置类 |  | ||||||
|  * |  | ||||||
|  * 该配置类用于定义缓存相关的策略 Bean,当前主要包含 NullValuePolicy 的默认实现。 |  | ||||||
|  * 所有需要注册为 Spring Bean 的缓存策略应在本类中进行声明和配置。 |  | ||||||
|  * |  | ||||||
|  * @since 2025-06-21 11:37:50 |  | ||||||
|  * @author gewuyou |  | ||||||
|  */ |  | ||||||
| @Configuration |  | ||||||
| class CachePolicyConfig { |  | ||||||
|     /** |  | ||||||
|      * 创建 NullValuePolicy 类型的 Bean,用于控制是否允许缓存 null 值。 |  | ||||||
|      * |  | ||||||
|      * 当前使用 AllowNullCachePolicy 作为默认实现,表示允许缓存 null 值。 |  | ||||||
|      * 如果应用上下文中已存在同类型的 Bean,则跳过此 Bean 的创建。 |  | ||||||
|      * |  | ||||||
|      * @return 返回一个 NullValuePolicy 接口的实现对象 |  | ||||||
|      */ |  | ||||||
|     @Bean |  | ||||||
|     @ConditionalOnMissingBean |  | ||||||
|     fun nullCachePolicy(cacheProperties: CacheProperties): NullValuePolicy { |  | ||||||
|         return AllowNullCachePolicy(cacheProperties) |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 创建 CachePolicy 类型的 Bean,用于包装基础的 NullValuePolicy 实现。 |  | ||||||
|      * |  | ||||||
|      * 该方法将 NullValuePolicy 实例封装为一个 CachePolicy 接口的实现对象, |  | ||||||
|      * 允许在缓存操作中应用 null 值策略。如果应用上下文中已存在同类型的 Bean, |  | ||||||
|      * 则跳过此 Bean 的创建。 |  | ||||||
|      * |  | ||||||
|      * @param nullValuePolicy 注入的 NullValuePolicy 实例,用于决定是否允许缓存 null 值 |  | ||||||
|      * @return 返回封装后的 CachePolicy 对象 |  | ||||||
|      */ |  | ||||||
|     @Bean("nullValueCachePolicy") |  | ||||||
|     @ConditionalOnMissingBean |  | ||||||
|     fun nullValueCachePolicy(nullValuePolicy: NullValuePolicy): CachePolicy { |  | ||||||
|         return NullValueCachePolicy(nullValuePolicy) |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
| @ -1,36 +0,0 @@ | |||||||
| package com.gewuyou.forgeboot.cache.autoconfigure.config |  | ||||||
| 
 |  | ||||||
| import com.fasterxml.jackson.databind.ObjectMapper |  | ||||||
| import com.gewuyou.forgeboot.core.serialization.serializer.ValueSerializer |  | ||||||
| import com.gewuyou.forgeboot.core.serialization.serializer.impl.serializer.JacksonValueSerializer |  | ||||||
| 
 |  | ||||||
| import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean |  | ||||||
| import org.springframework.context.annotation.Bean |  | ||||||
| import org.springframework.context.annotation.Configuration |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * 缓存序列化程序配置 |  | ||||||
|  * |  | ||||||
|  * 该配置类用于定义缓存所需的序列化器 Bean。 |  | ||||||
|  * |  | ||||||
|  * @since 2025-06-21 11:40:45 |  | ||||||
|  * @author gewuyou |  | ||||||
|  */ |  | ||||||
| @Configuration |  | ||||||
| class CacheSerializerConfig { |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 创建 JacksonValueSerializer 序列化器 Bean |  | ||||||
|      * |  | ||||||
|      * 该方法定义了一个 JacksonValueSerializer 的 Bean,用于将值序列化和反序列化, |  | ||||||
|      * 适用于与 Jackson 库集成进行 JSON 数据格式的处理。 |  | ||||||
|      * |  | ||||||
|      * @param objectMapper Jackson 提供的对象映射器,用于实际的序列化/反序列化操作 |  | ||||||
|      * @return 返回一个 JacksonValueSerializer 实例,作为 ValueSerializer 接口的实现 |  | ||||||
|      */ |  | ||||||
|     @Bean |  | ||||||
|     @ConditionalOnMissingBean |  | ||||||
|     fun serializer(objectMapper: ObjectMapper): ValueSerializer { |  | ||||||
|         return JacksonValueSerializer(objectMapper) |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @ -1,34 +0,0 @@ | |||||||
| package com.gewuyou.forgeboot.cache.autoconfigure.config |  | ||||||
| 
 |  | ||||||
| import com.gewuyou.forgeboot.cache.api.service.CacheWarmUpService |  | ||||||
| import com.gewuyou.forgeboot.cache.impl.runner.CacheWarmUpRunner |  | ||||||
| import org.springframework.context.annotation.Bean |  | ||||||
| import org.springframework.context.annotation.Configuration |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * 缓存预热配置类 |  | ||||||
|  * |  | ||||||
|  * 该配置类用于定义与缓存预热相关的 Bean,确保应用启动时能够自动执行缓存预热逻辑。 |  | ||||||
|  * |  | ||||||
|  * @since 2025-06-21 11:41:34 |  | ||||||
|  * @author gewuyou |  | ||||||
|  */ |  | ||||||
| @Configuration |  | ||||||
| class CacheWarmUpConfig { |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 创建 CacheWarmUpRunner Bean |  | ||||||
|      * |  | ||||||
|      * 该方法将一组 CacheWarmUpService 实例注入到 CacheWarmUpRunner 中, |  | ||||||
|      * 用于在应用启动时运行缓存预热任务。 |  | ||||||
|      * |  | ||||||
|      * @param services 缓存预热服务的列表,每个服务实现具体的预热逻辑 |  | ||||||
|      * @return 返回一个 CacheWarmUpRunner 实例,用于启动缓存预热流程 |  | ||||||
|      */ |  | ||||||
|     @Bean |  | ||||||
|     fun cacheWarmUpRunner( |  | ||||||
|         services: List<CacheWarmUpService> |  | ||||||
|     ): CacheWarmUpRunner { |  | ||||||
|         return CacheWarmUpRunner(services) |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @ -1,35 +0,0 @@ | |||||||
| package com.gewuyou.forgeboot.cache.autoconfigure.config |  | ||||||
| 
 |  | ||||||
| import com.gewuyou.forgeboot.cache.api.service.LockService |  | ||||||
| import com.gewuyou.forgeboot.cache.impl.service.RedisLockService |  | ||||||
| import org.redisson.api.RedissonClient |  | ||||||
| import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean |  | ||||||
| import org.springframework.context.annotation.Bean |  | ||||||
| import org.springframework.context.annotation.Configuration |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * 锁服务配置类 |  | ||||||
|  * |  | ||||||
|  * 该配置类用于定义与锁服务相关的 Bean,确保应用中可以正常使用分布式锁功能。 |  | ||||||
|  * |  | ||||||
|  * @since 2025-06-21 11:42:20 |  | ||||||
|  * @author gewuyou |  | ||||||
|  */ |  | ||||||
| @Configuration |  | ||||||
| class LockServiceConfig { |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 创建 LockService 锁服务 Bean |  | ||||||
|      * |  | ||||||
|      * 该方法定义了一个 LockService 类型的 Bean,用于提供基于 Redisson 的分布式锁实现。 |  | ||||||
|      * 如果 Spring 容器中尚未存在 LockService 实例,则会通过此方法创建一个。 |  | ||||||
|      * |  | ||||||
|      * @param redissonClient Redisson 客户端实例,用于与 Redis 进行交互并创建锁 |  | ||||||
|      * @return 返回一个 LockService 实例,具体实现为 RedisLockService |  | ||||||
|      */ |  | ||||||
|     @Bean |  | ||||||
|     @ConditionalOnMissingBean |  | ||||||
|     fun lockService(redissonClient: RedissonClient): LockService { |  | ||||||
|         return RedisLockService(redissonClient) |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @ -1 +0,0 @@ | |||||||
| com.gewuyou.forgeboot.cache.autoconfigure.CacheAutoConfiguration |  | ||||||
| @ -1,3 +0,0 @@ | |||||||
| /gradlew text eol=lf |  | ||||||
| *.bat text eol=crlf |  | ||||||
| *.jar binary |  | ||||||
							
								
								
									
										40
									
								
								forgeboot-cache/forgeboot-cache-impl/.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										40
									
								
								forgeboot-cache/forgeboot-cache-impl/.gitignore
									
									
									
									
										vendored
									
									
								
							| @ -1,40 +0,0 @@ | |||||||
| 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 |  | ||||||
| @ -1,13 +0,0 @@ | |||||||
| plugins{ |  | ||||||
|     alias(libs.plugins.kotlin.plugin.spring) |  | ||||||
| } |  | ||||||
| dependencies { |  | ||||||
|     compileOnly(project(Modules.Cache.API)) |  | ||||||
|     compileOnly(project(Modules.Core.SERIALIZATION)) |  | ||||||
|     implementation(libs.springBootStarter.aop) |  | ||||||
|     implementation(libs.springBootStarter.redis) |  | ||||||
|     implementation(libs.com.github.benManes.caffeine) |  | ||||||
|     implementation(libs.kotlinxCoroutines.core) |  | ||||||
|     implementation(libs.jackson.databind) |  | ||||||
|     implementation(libs.redisson.springBootStarter) |  | ||||||
| } |  | ||||||
| @ -1,50 +0,0 @@ | |||||||
| package com.gewuyou.forgeboot.cache.impl.aspect |  | ||||||
| 
 |  | ||||||
| import com.gewuyou.forgeboot.cache.api.annotations.CacheEvictEx |  | ||||||
| import com.gewuyou.forgeboot.cache.api.generator.KeyGenerator |  | ||||||
| import com.gewuyou.forgeboot.cache.api.manager.CacheManager |  | ||||||
| import com.gewuyou.forgeboot.cache.impl.support.CacheSpELHelper |  | ||||||
| import org.aspectj.lang.JoinPoint |  | ||||||
| import org.aspectj.lang.annotation.After |  | ||||||
| import org.aspectj.lang.annotation.Aspect |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * 缓存清理扩展切面 |  | ||||||
|  * |  | ||||||
|  * 该切面用于处理带有 [CacheEvictEx] 注解的方法,在方法执行后清除指定的缓存项。 |  | ||||||
|  * |  | ||||||
|  * @property cacheManager 用于管理缓存的组件,提供缓存操作的接口。 |  | ||||||
|  * @property keyGenerator 用于生成缓存键的辅助组件,支持动态键值解析。 |  | ||||||
|  * |  | ||||||
|  * @since 2025-06-18 20:59:18 |  | ||||||
|  * @author gewuyou |  | ||||||
|  */ |  | ||||||
| @Aspect |  | ||||||
| class CacheEvictExAspect( |  | ||||||
|     private val cacheManager: CacheManager, |  | ||||||
|     private val keyGenerator: KeyGenerator |  | ||||||
| ) { |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 处理被 [CacheEvictEx] 注解标记的方法调用后的缓存清理逻辑。 |  | ||||||
|      * |  | ||||||
|      * 该方法会在目标方法执行完成后触发,根据注解配置的命名空间和 SpEL 表达式 |  | ||||||
|      * 构建完整的缓存键,并通过 [cacheManager] 移除对应的缓存项。 |  | ||||||
|      * |  | ||||||
|      * @param joinPoint 封装了目标方法调用上下文的信息,包括方法参数、返回值等。 |  | ||||||
|      * @param cacheEvictEx 注解实例,包含缓存清理所需的配置信息。 |  | ||||||
|      */ |  | ||||||
|     @After("@annotation(cacheEvictEx)") |  | ||||||
|     fun handle(joinPoint: JoinPoint, cacheEvictEx: CacheEvictEx) { |  | ||||||
|         val namespace = cacheEvictEx.namespace |  | ||||||
|         // 解析并构建完整的缓存键 |  | ||||||
|         val fullKey = CacheSpELHelper.parseKey( |  | ||||||
|             namespace, |  | ||||||
|             cacheEvictEx.keySpEL, |  | ||||||
|             joinPoint, |  | ||||||
|             keyGenerator |  | ||||||
|         ) |  | ||||||
|         // 执行缓存项移除操作 |  | ||||||
|         cacheManager.getCache(namespace).remove(fullKey) |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @ -1,55 +0,0 @@ | |||||||
| package com.gewuyou.forgeboot.cache.impl.aspect |  | ||||||
| 
 |  | ||||||
| import com.gewuyou.forgeboot.cache.api.annotations.CachePutEx |  | ||||||
| import com.gewuyou.forgeboot.cache.api.generator.KeyGenerator |  | ||||||
| import com.gewuyou.forgeboot.cache.api.manager.CacheManager |  | ||||||
| import com.gewuyou.forgeboot.cache.impl.support.CacheSpELHelper |  | ||||||
| import com.gewuyou.forgeboot.cache.impl.utils.SpELResolver |  | ||||||
| import org.aspectj.lang.JoinPoint |  | ||||||
| import org.aspectj.lang.annotation.AfterReturning |  | ||||||
| import org.aspectj.lang.annotation.Aspect |  | ||||||
| import java.time.Duration |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * 缓存插入扩展切面 |  | ||||||
|  * |  | ||||||
|  * 该切面用于处理带有 [CachePutEx] 注解的方法,将方法执行结果根据指定的命名空间和键存储到缓存中,并设置过期时间。 |  | ||||||
|  * |  | ||||||
|  * @property cacheManager 缓存管理器,用于获取缓存服务实例。 |  | ||||||
|  * @property keyGenerator 缓存键生成器,用于生成完整的缓存键。 |  | ||||||
|  * |  | ||||||
|  * @since 2025-06-18 20:57:27 |  | ||||||
|  * @author gewuyou |  | ||||||
|  */ |  | ||||||
| @Aspect |  | ||||||
| class CachePutExAspect( |  | ||||||
|     private val cacheManager: CacheManager, |  | ||||||
|     private val keyGenerator: KeyGenerator |  | ||||||
| ) { |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 处理带有 [CachePutEx] 注解的方法返回后逻辑。 |  | ||||||
|      * |  | ||||||
|      * 通过 AOP 获取方法参数、注解配置的命名空间、键表达式和过期时间, |  | ||||||
|      * 使用 [SpELResolver] 解析出最终的缓存键,并调用 [cacheManager] 将结果写入缓存。 |  | ||||||
|      * |  | ||||||
|      * @param joinPoint 切点信息,包含目标方法及其参数。 |  | ||||||
|      * @param cachePutEx 方法上的 [CachePutEx] 注解实例,定义缓存行为配置。 |  | ||||||
|      * @param result 方法执行后的返回值。 |  | ||||||
|      */ |  | ||||||
|     @AfterReturning("@annotation(cachePutEx)", returning = "result") |  | ||||||
|     fun handle(joinPoint: JoinPoint, cachePutEx: CachePutEx, result: Any?) { |  | ||||||
|         if (result == null) return |  | ||||||
|         val namespace = cachePutEx.namespace |  | ||||||
|         // 解析缓存键 |  | ||||||
|         val fullKey = CacheSpELHelper.parseKey( |  | ||||||
|             namespace, |  | ||||||
|             cachePutEx.keySpEL, |  | ||||||
|             joinPoint, |  | ||||||
|             keyGenerator |  | ||||||
|         ) |  | ||||||
|         // 获取缓存过期时间(单位:秒) |  | ||||||
|         val ttl = cachePutEx.ttl |  | ||||||
|         cacheManager.getCache(namespace).put(fullKey, result, Duration.ofSeconds(ttl)) |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @ -1,76 +0,0 @@ | |||||||
| package com.gewuyou.forgeboot.cache.impl.aspect |  | ||||||
| 
 |  | ||||||
| import com.gewuyou.forgeboot.cache.api.annotations.CacheableEx |  | ||||||
| import com.gewuyou.forgeboot.cache.api.generator.KeyGenerator |  | ||||||
| import com.gewuyou.forgeboot.cache.api.manager.CacheManager |  | ||||||
| import com.gewuyou.forgeboot.cache.impl.utils.SpELResolver |  | ||||||
| import org.aspectj.lang.ProceedingJoinPoint |  | ||||||
| import org.aspectj.lang.annotation.Around |  | ||||||
| import org.aspectj.lang.annotation.Aspect |  | ||||||
| import org.aspectj.lang.reflect.MethodSignature |  | ||||||
| import java.time.Duration |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * 可缓存的扩展切面类 |  | ||||||
|  * |  | ||||||
|  * 用于处理带有 @CacheableEx 注解的方法,实现方法结果的缓存逻辑。 |  | ||||||
|  * 通过 AOP 拦截注解方法,根据配置生成缓存键并操作缓存服务。 |  | ||||||
|  * |  | ||||||
|  * @property cacheManager 缓存管理器,用于操作缓存服务 |  | ||||||
|  * @property keyGenerator 缓存键生成器,用于生成完整的缓存键 |  | ||||||
|  */ |  | ||||||
| @Aspect |  | ||||||
| class CacheableExAspect( |  | ||||||
|     private val cacheManager: CacheManager, |  | ||||||
|     private val keyGenerator: KeyGenerator |  | ||||||
| ) { |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 环绕通知方法,处理缓存逻辑 |  | ||||||
|      * |  | ||||||
|      * 执行流程: |  | ||||||
|      * 1. 解析方法参数并生成参数映射表 |  | ||||||
|      * 2. 使用 SpEL 表达式解析器生成缓存键 |  | ||||||
|      * 3. 从缓存中尝试获取已存在的值 |  | ||||||
|      * 4. 如果缓存命中且值不为 null(或允许缓存 null 值),则直接返回缓存结果 |  | ||||||
|      * 5. 否则执行目标方法,并将结果写入缓存 |  | ||||||
|      * |  | ||||||
|      * @param joinPoint 切点信息,包含目标方法及参数等 |  | ||||||
|      * @param cacheableEx 方法上的 @CacheableEx 注解实例,提供缓存配置 |  | ||||||
|      * @return 目标方法的执行结果,可能是缓存值也可能是实际调用结果 |  | ||||||
|      */ |  | ||||||
|     @Around("@annotation(cacheableEx)") |  | ||||||
|     fun handle(joinPoint: ProceedingJoinPoint, cacheableEx: CacheableEx): Any? { |  | ||||||
|         // 提取目标方法对象 |  | ||||||
|         val method = (joinPoint.signature as MethodSignature).method |  | ||||||
| 
 |  | ||||||
|         // 构建参数名称与值的映射关系 |  | ||||||
|         val argsMap = method.parameters.mapIndexed { i, param -> param.name to joinPoint.args[i] }.toMap() |  | ||||||
| 
 |  | ||||||
|         // 使用 SpEL 解析表达式生成缓存键 |  | ||||||
|         val key = SpELResolver.parse(cacheableEx.keySpEL, argsMap) |  | ||||||
| 
 |  | ||||||
|         // 获取缓存值类型、命名空间和过期时间 |  | ||||||
|         val type = cacheableEx.type.java |  | ||||||
|         val namespace = cacheableEx.namespace |  | ||||||
|         val ttl = cacheableEx.ttl |  | ||||||
| 
 |  | ||||||
|         // 生成完整缓存键 |  | ||||||
|         val fullKey = keyGenerator.generateKey(namespace, key) |  | ||||||
|         val cacheService = cacheManager.getCache(namespace) |  | ||||||
|         // 尝试从缓存获取数据 |  | ||||||
|         val cached = cacheService.retrieve(fullKey, type) |  | ||||||
| 
 |  | ||||||
|         if (cached != null) return cached |  | ||||||
| 
 |  | ||||||
|         // 执行原始方法逻辑 |  | ||||||
|         val result = joinPoint.proceed() |  | ||||||
| 
 |  | ||||||
|         // 根据是否允许缓存 null 值进行判断 |  | ||||||
|         if (result == null && !cacheableEx.cacheNull) return null |  | ||||||
| 
 |  | ||||||
|         // 将非 null 结果写入缓存,空值使用占位符 "" |  | ||||||
|         cacheService.put(fullKey, result ?: "", Duration.ofSeconds(ttl)) |  | ||||||
|         return result |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @ -1,91 +0,0 @@ | |||||||
| package com.gewuyou.forgeboot.cache.impl.contract |  | ||||||
| 
 |  | ||||||
| import com.gewuyou.forgeboot.cache.api.config.CacheProperties |  | ||||||
| import com.gewuyou.forgeboot.cache.api.contract.Cache |  | ||||||
| import com.gewuyou.forgeboot.cache.api.entities.CacheLayer |  | ||||||
| import java.time.Duration |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * 复合缓存实现类,通过组合多个缓存层提供统一的缓存访问接口。 |  | ||||||
|  * |  | ||||||
|  * 缓存按照优先级排序,高优先级的缓存层在前。读取时会从高到低依次查找, |  | ||||||
|  * 一旦在某一层找到数据,就会将该数据回填到优先级更高的缓存层中。 |  | ||||||
|  * |  | ||||||
|  * @property layers 缓存层列表,每个缓存层包含一个具体的缓存实例和优先级。 |  | ||||||
|  * @property cacheProperties 配置属性对象,用于获取默认缓存过期时间等配置参数。 |  | ||||||
|  * @constructor 创建一个复合缓存实例,并按优先级对缓存层进行排序。 |  | ||||||
|  */ |  | ||||||
| class CompositeCache( |  | ||||||
|     layers: List<CacheLayer>, |  | ||||||
|     private val cacheProperties: CacheProperties |  | ||||||
| ) : Cache { |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 按照优先级排序后的缓存层列表。 |  | ||||||
|      * 高优先级的缓存层排在前面,用于后续的缓存查找与回填逻辑。 |  | ||||||
|      */ |  | ||||||
|     private val sortedLayers = layers.sortedBy { it.priority } |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 获取指定键对应的缓存值。 |  | ||||||
|      * |  | ||||||
|      * 从最高优先级的缓存层开始查找,一旦找到有效值,则将其回填到 |  | ||||||
|      * 所有优先级高于当前层的缓存中,并返回该值。 |  | ||||||
|      * |  | ||||||
|      * @param key 要获取的缓存键。 |  | ||||||
|      * @return 如果存在缓存值则返回对应值,否则返回 null。 |  | ||||||
|      */ |  | ||||||
|     override fun retrieve(key: String): String? { |  | ||||||
|         for ((index, layer) in sortedLayers.withIndex()) { |  | ||||||
|             val value = layer.cache.retrieve(key) |  | ||||||
|             if (value != null) { |  | ||||||
|                 // 将找到的值回填到所有更高优先级的缓存层中 |  | ||||||
|                 for (i in 0 until index) { |  | ||||||
|                     sortedLayers[i].cache[key, value] = cacheProperties.theDefaultCacheTTL |  | ||||||
|                 } |  | ||||||
|                 return value |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|         return null |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 将指定键值对放入所有缓存层中。 |  | ||||||
|      * |  | ||||||
|      * @param key 要存储的缓存键。 |  | ||||||
|      * @param value 要存储的缓存值。 |  | ||||||
|      * @param ttl 存活时间。 |  | ||||||
|      */ |  | ||||||
|     override fun put(key: String, value: String?, ttl: Duration) { |  | ||||||
|         sortedLayers.forEach { it.cache[key, value] = ttl } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 从所有缓存层中移除指定键的缓存项。 |  | ||||||
|      * |  | ||||||
|      * @param key 要移除的缓存键。 |  | ||||||
|      * @return 如果所有缓存层都成功移除了该键则返回 true,否则返回 false。 |  | ||||||
|      */ |  | ||||||
|     override fun remove(key: String): Boolean { |  | ||||||
|         return sortedLayers.all { it.cache.remove(key) } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 判断指定键是否存在于任意一个缓存层中。 |  | ||||||
|      * |  | ||||||
|      * @param key 要检查的缓存键。 |  | ||||||
|      * @return 如果存在任意一层缓存包含该键则返回 true,否则返回 false。 |  | ||||||
|      */ |  | ||||||
|     override fun exists(key: String): Boolean { |  | ||||||
|         return sortedLayers.any { it.cache.exists(key) } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 清空缓存中的所有数据。 |  | ||||||
|      * |  | ||||||
|      * @param namespace 命名空间,用于限定清空操作的作用域。 |  | ||||||
|      */ |  | ||||||
|     override fun clear(namespace: String) { |  | ||||||
|         sortedLayers.forEach { it.cache.clear(namespace) } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @ -1,88 +0,0 @@ | |||||||
| package com.gewuyou.forgeboot.cache.impl.contract |  | ||||||
| 
 |  | ||||||
| import com.gewuyou.forgeboot.cache.api.config.CacheProperties |  | ||||||
| import com.gewuyou.forgeboot.cache.api.contract.Cache |  | ||||||
| import com.gewuyou.forgeboot.cache.api.generator.KeyGenerator |  | ||||||
| import com.github.benmanes.caffeine.cache.Caffeine |  | ||||||
| import java.time.Duration |  | ||||||
| import java.util.concurrent.TimeUnit |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * 全局 TTL 咖啡因缓存 |  | ||||||
|  * |  | ||||||
|  * 该实现基于 Caffeine 缓存库,所有缓存项使用统一的默认过期时间(TTL)。 |  | ||||||
|  * 不支持针对单个缓存项设置不同的 TTL。 |  | ||||||
|  * |  | ||||||
|  * @property cacheProperties 缓存配置属性,用于获取默认 TTL 设置 |  | ||||||
|  * @property keyGenerator 键生成器,用于构建带命名空间连接符的键前缀 |  | ||||||
|  * @since 2025-06-17 22:32:36 |  | ||||||
|  * @author gewuyou |  | ||||||
|  */ |  | ||||||
| class GlobalTtlCaffeineCache( |  | ||||||
|     cacheProperties: CacheProperties, |  | ||||||
|     private val keyGenerator: KeyGenerator |  | ||||||
| ) : Cache { |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 初始化 Caffeine 缓存实例 |  | ||||||
|      * |  | ||||||
|      * 使用 expireAfterWrite 设置写入后过期时间,时间长度基于 cacheProperties.theDefaultCacheTTL 配置。 |  | ||||||
|      * 最大缓存条目数量限制为 10,000。 |  | ||||||
|      */ |  | ||||||
|     private val cache = Caffeine.newBuilder() |  | ||||||
|         .expireAfterWrite(cacheProperties.theDefaultCacheTTL.toMillis(), TimeUnit.MILLISECONDS) |  | ||||||
|         .maximumSize(10_000) |  | ||||||
|         .build<String, String>() |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 获取指定 key 对应的缓存值 |  | ||||||
|      * |  | ||||||
|      * @param key 缓存键 |  | ||||||
|      * @return 缓存中对应的值,如果不存在则返回 null |  | ||||||
|      */ |  | ||||||
|     override fun retrieve(key: String): String? = cache.getIfPresent(key) |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 将键值对放入缓存中 |  | ||||||
|      * |  | ||||||
|      * 注意:此处忽略传入的 ttl 参数,统一使用 defaultTtl 控制过期时间。 |  | ||||||
|      * |  | ||||||
|      * @param key   缓存键 |  | ||||||
|      * @param value 缓存值,若为 null 则不存储 |  | ||||||
|      * @param ttl   忽略此参数,使用全局默认的过期时间 |  | ||||||
|      */ |  | ||||||
|     override fun put(key: String, value: String?, ttl: Duration) { |  | ||||||
|         if (value != null) cache.put(key, value) |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 移除指定 key 的缓存项 |  | ||||||
|      * |  | ||||||
|      * @param key 要移除的缓存键 |  | ||||||
|      * @return 总是返回 true,表示操作成功 |  | ||||||
|      */ |  | ||||||
|     override fun remove(key: String): Boolean { |  | ||||||
|         cache.invalidate(key) |  | ||||||
|         return true |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 检查指定 key 是否存在于缓存中 |  | ||||||
|      * |  | ||||||
|      * @param key 缓存键 |  | ||||||
|      * @return 如果存在则返回 true,否则返回 false |  | ||||||
|      */ |  | ||||||
|     override fun exists(key: String): Boolean = cache.getIfPresent(key) != null |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 清除指定命名空间下的所有缓存项 |  | ||||||
|      * |  | ||||||
|      * 根据命名空间和连接符拼接出前缀,并清除所有以前缀开头的 key。 |  | ||||||
|      * |  | ||||||
|      * @param namespace 命名空间前缀 |  | ||||||
|      */ |  | ||||||
|     override fun clear(namespace: String) { |  | ||||||
|         val prefix = "$namespace${keyGenerator.getConnectors()}" |  | ||||||
|         cache.asMap().keys.filter { it.startsWith(prefix) }.forEach { cache.invalidate(it) } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @ -1,103 +0,0 @@ | |||||||
| package com.gewuyou.forgeboot.cache.impl.contract |  | ||||||
| 
 |  | ||||||
| import com.gewuyou.forgeboot.cache.api.contract.Cache |  | ||||||
| import com.gewuyou.forgeboot.cache.api.policy.CachePolicy |  | ||||||
| import com.gewuyou.forgeboot.cache.api.policy.NullValuePolicy |  | ||||||
| import java.time.Duration |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * 多策略缓存装饰器 |  | ||||||
|  * |  | ||||||
|  * 支持多个缓存策略,动态应用各种缓存策略(如 Null 值策略、失效策略等)。 |  | ||||||
|  * 该类通过组合多个 CachePolicy 实现对基础缓存操作的增强处理。 |  | ||||||
|  * |  | ||||||
|  * @property delegate 被包装的真实缓存实现,用于执行底层缓存操作 |  | ||||||
|  * @property policies 缓存策略列表,按顺序依次应用于缓存值 |  | ||||||
|  * @since 2025-06-17 21:16:58 |  | ||||||
|  */ |  | ||||||
| class MultiPolicyCache( |  | ||||||
|     private val delegate: Cache, |  | ||||||
|     private val nullValuePolicy: NullValuePolicy, |  | ||||||
|     private val policies: List<CachePolicy>, |  | ||||||
| ) : Cache { |  | ||||||
| 
 |  | ||||||
|     init { |  | ||||||
|         // 排序 |  | ||||||
|         policies.sortedBy { it.getOrder() } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 获取缓存值并应用所有缓存策略 |  | ||||||
|      * |  | ||||||
|      * 按照策略列表顺序依次处理获取到的缓存值: |  | ||||||
|      * - 如果原始值为 null 或 null 占位符,则返回 null |  | ||||||
|      * - 否则返回经过策略处理后的最终值 |  | ||||||
|      * |  | ||||||
|      * @param key 缓存键,用于定位缓存项 |  | ||||||
|      * @return 经过策略处理后的缓存值,如果为 null 或 null 占位符则返回 null |  | ||||||
|      */ |  | ||||||
|     override fun retrieve(key: String): String? { |  | ||||||
|         var value = delegate.retrieve(key) |  | ||||||
|         // 按策略顺序依次处理缓存值 |  | ||||||
|         policies.forEach { value = it.apply(key, value) } |  | ||||||
|         return value |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 存储缓存值并应用所有缓存策略 |  | ||||||
|      * |  | ||||||
|      * 按照策略列表顺序依次处理要存储的值: |  | ||||||
|      * - 如果值为 null,可能被转换为 null 占位符 |  | ||||||
|      * - 最终将处理后的值委托给底层缓存实现进行存储 |  | ||||||
|      * |  | ||||||
|      * @param key 缓存键,用于标识要存储的缓存项 |  | ||||||
|      * @param value 要存储的值,可能为 null |  | ||||||
|      * @param ttl 缓存过期时间,控制该项在缓存中的存活时长 |  | ||||||
|      */ |  | ||||||
|     override fun put(key: String, value: String?, ttl: Duration) { |  | ||||||
|         var processedValue = value |  | ||||||
|         // 按策略顺序依次处理待存储的值 |  | ||||||
|         policies.forEach { processedValue = it.apply(key, processedValue) } |  | ||||||
|         // 如果最终值是 null 且不允许缓存 null,跳过缓存存储 |  | ||||||
|         if (processedValue == null && !nullValuePolicy.allowCacheNull(key)) { |  | ||||||
|             // 不缓存 null 值 |  | ||||||
|             return |  | ||||||
|         } |  | ||||||
|         delegate.put(key, processedValue, ttl) |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 移除指定缓存项 |  | ||||||
|      * |  | ||||||
|      * 将移除操作直接委托给底层缓存实现。 |  | ||||||
|      * |  | ||||||
|      * @param key 要移除的缓存键 |  | ||||||
|      * @return 移除成功返回 true,否则返回 false |  | ||||||
|      */ |  | ||||||
|     override fun remove(key: String): Boolean { |  | ||||||
|         return delegate.remove(key) |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 检查指定缓存项是否存在 |  | ||||||
|      * |  | ||||||
|      * 将存在性检查操作直接委托给底层缓存实现。 |  | ||||||
|      * |  | ||||||
|      * @param key 要检查的缓存键 |  | ||||||
|      * @return 存在返回 true,否则返回 false |  | ||||||
|      */ |  | ||||||
|     override fun exists(key: String): Boolean { |  | ||||||
|         return delegate.exists(key) |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 清除指定命名空间下的所有缓存 |  | ||||||
|      * |  | ||||||
|      * 将清除操作直接委托给底层缓存实现。 |  | ||||||
|      * |  | ||||||
|      * @param namespace 要清除的命名空间 |  | ||||||
|      */ |  | ||||||
|     override fun clear(namespace: String) { |  | ||||||
|         delegate.clear(namespace) |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @ -1,114 +0,0 @@ | |||||||
| package com.gewuyou.forgeboot.cache.impl.contract |  | ||||||
| 
 |  | ||||||
| import com.gewuyou.forgeboot.cache.api.contract.Cache |  | ||||||
| import com.gewuyou.forgeboot.cache.api.generator.KeyGenerator |  | ||||||
| import kotlinx.coroutines.* |  | ||||||
| import java.time.Duration |  | ||||||
| import java.util.concurrent.ConcurrentHashMap |  | ||||||
| import kotlin.time.Duration.Companion.seconds |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * 每个条目 TTL 咖啡因缓存实现类 |  | ||||||
|  * |  | ||||||
|  * 该缓存为每个缓存条目设置独立的生存时间(TTL),基于 Caffeine 缓存策略设计。 |  | ||||||
|  * |  | ||||||
|  * @since 2025-06-17 22:34:50 |  | ||||||
|  * @author gewuyou |  | ||||||
|  */ |  | ||||||
| class PerEntryTtlCaffeineCache( |  | ||||||
|     private val keyGenerator: KeyGenerator |  | ||||||
| ) : Cache { |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 缓存条目数据类,用于存储值和过期时间 |  | ||||||
|      * |  | ||||||
|      * @property value 缓存的字符串值 |  | ||||||
|      * @property expireAt 条目的过期时间戳(毫秒) |  | ||||||
|      */ |  | ||||||
|     private data class CacheEntry(val value: String, val expireAt: Long) |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 使用线程安全的 ConcurrentHashMap 存储缓存条目 |  | ||||||
|      */ |  | ||||||
|     private val map = ConcurrentHashMap<String, CacheEntry>(16) |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 协程作用域,用于执行后台清理任务 |  | ||||||
|      */ |  | ||||||
|     private val cleanupScope = CoroutineScope(Dispatchers.Default + SupervisorJob()) |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 初始化块:启动定期清理任务 |  | ||||||
|      * |  | ||||||
|      * 清理任务每 5 秒运行一次,移除所有已过期的缓存条目。 |  | ||||||
|      */ |  | ||||||
|     init { |  | ||||||
|         cleanupScope.launch { |  | ||||||
|             while (this.isActive) { |  | ||||||
|                 val now = System.currentTimeMillis() |  | ||||||
|                 map.entries.removeIf { it.value.expireAt <= now } |  | ||||||
|                 delay(5.seconds) |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 获取指定键的缓存值 |  | ||||||
|      * |  | ||||||
|      * 如果缓存不存在或已过期,则返回 null 并从缓存中移除该条目。 |  | ||||||
|      * |  | ||||||
|      * @param key 要获取的缓存键 |  | ||||||
|      * @return 缓存值(如果存在且未过期),否则 null |  | ||||||
|      */ |  | ||||||
|     override fun retrieve(key: String): String? { |  | ||||||
|         val entry = map[key] ?: return null |  | ||||||
|         return if (System.currentTimeMillis() > entry.expireAt) { |  | ||||||
|             map.remove(key) |  | ||||||
|             null |  | ||||||
|         } else entry.value |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 将键值对放入缓存,并设置其生存时间 |  | ||||||
|      * |  | ||||||
|      * 如果值为 null,则不会插入任何内容。 |  | ||||||
|      * |  | ||||||
|      * @param key 键 |  | ||||||
|      * @param value 值 |  | ||||||
|      * @param ttl 生存时间(Duration 类型) |  | ||||||
|      */ |  | ||||||
|     override fun put(key: String, value: String?, ttl: Duration) { |  | ||||||
|         if (value != null) { |  | ||||||
|             val expireAt = System.currentTimeMillis() + ttl.toMillis() |  | ||||||
|             map[key] = CacheEntry(value, expireAt) |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 从缓存中移除指定键 |  | ||||||
|      * |  | ||||||
|      * @param key 要移除的键 |  | ||||||
|      * @return 如果成功移除则返回 true,否则 false |  | ||||||
|      */ |  | ||||||
|     override fun remove(key: String): Boolean = map.remove(key) != null |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 检查指定键是否存在有效的缓存条目 |  | ||||||
|      * |  | ||||||
|      * @param key 要检查的键 |  | ||||||
|      * @return 如果存在有效条目则返回 true,否则 false |  | ||||||
|      */ |  | ||||||
|     override fun exists(key: String): Boolean = retrieve(key) != null |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 清除指定命名空间下的所有缓存条目 |  | ||||||
|      * |  | ||||||
|      * 根据命名空间和连接符生成前缀,移除所有以该前缀开头的键。 |  | ||||||
|      * |  | ||||||
|      * @param namespace 命名空间 |  | ||||||
|      */ |  | ||||||
|     override fun clear(namespace: String) { |  | ||||||
|         val prefix = "$namespace${keyGenerator.getConnectors()}" |  | ||||||
|         map.keys.removeIf { it.startsWith(prefix) } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @ -1,80 +0,0 @@ | |||||||
| package com.gewuyou.forgeboot.cache.impl.contract |  | ||||||
| 
 |  | ||||||
| import com.gewuyou.forgeboot.cache.api.contract.Cache |  | ||||||
| import com.gewuyou.forgeboot.cache.api.generator.KeyGenerator |  | ||||||
| import com.gewuyou.forgeboot.cache.impl.utils.RedisKeyScanner |  | ||||||
| import org.springframework.data.redis.core.StringRedisTemplate |  | ||||||
| import java.time.Duration |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * Redis 缓存实现类,用于通过 Redis 存储、获取和管理缓存数据。 |  | ||||||
|  * |  | ||||||
|  * @property redisTemplate Spring 提供的 StringRedisTemplate 实例,用于与 Redis 进行交互 |  | ||||||
|  * @property redisKeyScanner 用于扫描匹配的 Redis 键集合 |  | ||||||
|  * @author gewuyou |  | ||||||
|  * @since 2025-06-17 21:08:36 |  | ||||||
|  */ |  | ||||||
| class RedisCache( |  | ||||||
|     private val redisTemplate: StringRedisTemplate, |  | ||||||
|     private val redisKeyScanner: RedisKeyScanner, |  | ||||||
|     private val keyGenerator: KeyGenerator |  | ||||||
| ) : Cache { |  | ||||||
|     /** |  | ||||||
|      * 获取指定键对应的缓存值。 |  | ||||||
|      * |  | ||||||
|      * @param key 缓存键,非空字符串 |  | ||||||
|      * @return 缓存值,如果不存在则返回 null |  | ||||||
|      */ |  | ||||||
|     override fun retrieve(key: String): String? { |  | ||||||
|         return redisTemplate.opsForValue()[key] |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 将键值对存储到缓存中,并设置过期时间。 |  | ||||||
|      * |  | ||||||
|      * @param key   缓存键,非空字符串 |  | ||||||
|      * @param value 缓存值,可以为 null |  | ||||||
|      * @param ttl   缓存存活时间(Time To Live),单位为秒或毫秒等 |  | ||||||
|      */ |  | ||||||
|     override fun put(key: String, value: String?, ttl: Duration) { |  | ||||||
|         redisTemplate.opsForValue()[key, value!!] = ttl |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 删除指定键的缓存。 |  | ||||||
|      * |  | ||||||
|      * @param key 要删除的缓存键,非空字符串 |  | ||||||
|      * @return 如果删除成功返回 true,否则返回 false |  | ||||||
|      */ |  | ||||||
|     override fun remove(key: String): Boolean { |  | ||||||
|         return redisTemplate.delete(key) |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 判断指定键是否存在于缓存中。 |  | ||||||
|      * |  | ||||||
|      * @param key 缓存键,非空字符串 |  | ||||||
|      * @return 如果存在返回 true,否则返回 false |  | ||||||
|      */ |  | ||||||
|     override fun exists(key: String): Boolean { |  | ||||||
|         return redisTemplate.hasKey(key) |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 清空缓存中的所有数据,基于给定的命名空间和连接符进行模式匹配。 |  | ||||||
|      * |  | ||||||
|      * @param namespace 命名空间,用于限定要清除的键范围 |  | ||||||
|      */ |  | ||||||
|     override fun clear(namespace: String) { |  | ||||||
|         require(namespace.isNotBlank()) { "namespace must not be blank" } |  | ||||||
|         // 构造匹配模式 |  | ||||||
|         val pattern = "$namespace${keyGenerator.getConnectors()}*" |  | ||||||
|         while (true) { |  | ||||||
|             // 扫描当前模式下的所有键 |  | ||||||
|             val keys = redisKeyScanner.scan(pattern) |  | ||||||
|             if (keys.isEmpty()) break |  | ||||||
|             // 批量删除扫描到的键 |  | ||||||
|             redisTemplate.delete(keys) |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @ -1,39 +0,0 @@ | |||||||
| package com.gewuyou.forgeboot.cache.impl.generator |  | ||||||
| 
 |  | ||||||
| import com.gewuyou.forgeboot.cache.api.generator.KeyGenerator |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * 默认缓存键生成器 |  | ||||||
|  * |  | ||||||
|  * 该类负责生成带有命名空间的缓存键,通过将命名空间和键值拼接为 `namespace:key` 的形式。 |  | ||||||
|  * |  | ||||||
|  * @since 2025-06-18 12:40:04 |  | ||||||
|  * @author gewuyou |  | ||||||
|  */ |  | ||||||
| class DefaultKeyGenerator : KeyGenerator { |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 生成缓存键 |  | ||||||
|      * |  | ||||||
|      * 将给定的命名空间和键拼接成一个完整的缓存键,格式为 `namespace:key`。 |  | ||||||
|      * |  | ||||||
|      * @param namespace 命名空间,用于隔离不同的缓存区域 |  | ||||||
|      * @param key       缓存项的具体键值 |  | ||||||
|      * @return 拼接后的完整缓存键 |  | ||||||
|      */ |  | ||||||
|     override fun generateKey(namespace: String, key: String): String { |  | ||||||
|         return "$namespace${this.getConnectors()}$key" |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 获取连接符 |  | ||||||
|      * |  | ||||||
|      * 返回用于拼接命名空间和基础键值的连接符,默认实现可能返回冒号(:)或其他特定字符。 |  | ||||||
|      * 此方法允许子类自定义连接符,以满足不同存储结构或命名规范的需求。 |  | ||||||
|      * |  | ||||||
|      * @return 返回连接符字符串 |  | ||||||
|      */ |  | ||||||
|     override fun getConnectors(): String { |  | ||||||
|         return ":" |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @ -1,74 +0,0 @@ | |||||||
| package com.gewuyou.forgeboot.cache.impl.manager |  | ||||||
| 
 |  | ||||||
| import com.gewuyou.forgeboot.cache.api.config.CacheProperties |  | ||||||
| import com.gewuyou.forgeboot.cache.api.contract.Cache |  | ||||||
| import com.gewuyou.forgeboot.cache.api.generator.KeyGenerator |  | ||||||
| import com.gewuyou.forgeboot.cache.api.manager.CacheManager |  | ||||||
| import com.gewuyou.forgeboot.cache.api.service.CacheService |  | ||||||
| import com.gewuyou.forgeboot.cache.impl.service.DefaultCacheService |  | ||||||
| import com.gewuyou.forgeboot.core.serialization.serializer.ValueSerializer |  | ||||||
| import java.util.concurrent.ConcurrentHashMap |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * 默认缓存管理器 |  | ||||||
|  * |  | ||||||
|  * 该类负责管理不同命名空间下的缓存服务实例,通过懒加载方式创建 CacheService, |  | ||||||
|  * 并提供统一的清除缓存接口。 |  | ||||||
|  * |  | ||||||
|  * @since 2025-06-18 13:39:07 |  | ||||||
|  * @author gewuyou |  | ||||||
|  */ |  | ||||||
| class DefaultCacheManager( |  | ||||||
|     private val cacheProperties: CacheProperties, |  | ||||||
|     private val cache: Cache, |  | ||||||
|     private val serializer: ValueSerializer, |  | ||||||
|     private val keyGenerator: KeyGenerator |  | ||||||
| ) : CacheManager { |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 缓存服务实例的线程安全映射表,键为命名空间,值为对应的 CacheService 实例。 |  | ||||||
|      * 使用 ConcurrentHashMap 确保多线程环境下的安全访问。 |  | ||||||
|      */ |  | ||||||
|     private val serviceMap = ConcurrentHashMap<String, CacheService>() |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 获取指定命名空间的缓存服务。 |  | ||||||
|      * |  | ||||||
|      * 如果该命名空间尚未存在,则使用提供的参数创建一个新的 DefaultCacheService 实例; |  | ||||||
|      * 否则返回已存在的实例。 |  | ||||||
|      * |  | ||||||
|      * @param namespace 缓存命名空间标识符 |  | ||||||
|      * @return 对应命名空间的缓存服务实例 |  | ||||||
|      */ |  | ||||||
|     override fun getCache(namespace: String): CacheService { |  | ||||||
|         return serviceMap.computeIfAbsent(namespace) { |  | ||||||
|             DefaultCacheService( |  | ||||||
|                 serializer = serializer, |  | ||||||
|                 cache = cache, |  | ||||||
|                 namespace = namespace, |  | ||||||
|                 cacheProperties = cacheProperties, |  | ||||||
|                 keyGenerator = keyGenerator |  | ||||||
|             ) |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 清除指定命名空间的缓存内容。 |  | ||||||
|      * |  | ||||||
|      * 如果该命名空间存在对应的缓存服务,则调用其 clear 方法进行清除。 |  | ||||||
|      * |  | ||||||
|      * @param namespace 要清除缓存的命名空间标识符 |  | ||||||
|      */ |  | ||||||
|     override fun clear(namespace: String) { |  | ||||||
|         serviceMap[namespace]?.clear(namespace) |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 清除所有命名空间的缓存内容。 |  | ||||||
|      * |  | ||||||
|      * 遍历 serviceMap 中的所有缓存服务,并分别调用它们的 clear 方法。 |  | ||||||
|      */ |  | ||||||
|     override fun clearAll() { |  | ||||||
|         serviceMap.forEach { (ns, svc) -> svc.clear(ns) } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @ -1,49 +0,0 @@ | |||||||
| package com.gewuyou.forgeboot.cache.impl.policy |  | ||||||
| 
 |  | ||||||
| import com.gewuyou.forgeboot.cache.api.config.CacheProperties |  | ||||||
| import com.gewuyou.forgeboot.cache.api.policy.NullValuePolicy |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * 允许 Null 缓存策略 |  | ||||||
|  * |  | ||||||
|  * 该策略允许缓存 null 值,并提供相应的占位符机制。 |  | ||||||
|  * |  | ||||||
|  * @since 2025-06-20 21:42:24 |  | ||||||
|  * @author gewuyou |  | ||||||
|  */ |  | ||||||
| class AllowNullCachePolicy( |  | ||||||
|     private val cacheProperties: CacheProperties |  | ||||||
| ) : NullValuePolicy { |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 判断是否允许缓存 null 值。 |  | ||||||
|      * |  | ||||||
|      * @param key 缓存项的键 |  | ||||||
|      * @return Boolean 表示是否允许缓存 null 值,始终返回 true |  | ||||||
|      */ |  | ||||||
|     override fun allowCacheNull(key: String): Boolean { |  | ||||||
|         // 始终允许缓存 null 值 |  | ||||||
|         return true |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 获取表示 null 值的占位符。 |  | ||||||
|      * |  | ||||||
|      * @return String 表示 null 值的占位符 |  | ||||||
|      */ |  | ||||||
|     override fun nullPlaceholder(): String { |  | ||||||
|         // 定义一个占位符,表示 null 值 |  | ||||||
|         return cacheProperties.nullValuePlaceholder |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 判断给定值是否为 null 占位符。 |  | ||||||
|      * |  | ||||||
|      * @param value 要检查的值 |  | ||||||
|      * @return Boolean 表示给定值是否为 null 占位符 |  | ||||||
|      */ |  | ||||||
|     override fun isNullPlaceholder(value: String): Boolean { |  | ||||||
|         // 判断值是否为 null 占位符 |  | ||||||
|         return value == cacheProperties.nullValuePlaceholder |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @ -1,52 +0,0 @@ | |||||||
| package com.gewuyou.forgeboot.cache.impl.policy |  | ||||||
| 
 |  | ||||||
| import com.gewuyou.forgeboot.cache.api.policy.NullValuePolicy |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * 禁止 Null 缓存策略 |  | ||||||
|  * |  | ||||||
|  * 该策略实现不允许缓存 null 值的行为,所有与 null 相关的操作都会被禁止并抛出异常。 |  | ||||||
|  * |  | ||||||
|  * @since 2025-06-20 21:43:00 |  | ||||||
|  * @author gewuyou |  | ||||||
|  */ |  | ||||||
| class DisallowNullCachePolicy : NullValuePolicy { |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 判断是否允许缓存 null 值。 |  | ||||||
|      * |  | ||||||
|      * @param key 缓存键,用于标识缓存项 |  | ||||||
|      * @return Boolean 返回 false 表示始终不允许缓存 null 值 |  | ||||||
|      */ |  | ||||||
|     override fun allowCacheNull(key: String): Boolean { |  | ||||||
|         // 始终不允许缓存 null 值 |  | ||||||
|         return false |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 获取 null 值的占位符。 |  | ||||||
|      * |  | ||||||
|      * 由于不允许缓存 null 值,调用此方法会抛出 UnsupportedOperationException。 |  | ||||||
|      * |  | ||||||
|      * @return String 不会返回任何值,总是抛出异常 |  | ||||||
|      * @throws UnsupportedOperationException 因为不允许缓存 null 值 |  | ||||||
|      */ |  | ||||||
|     override fun nullPlaceholder(): String { |  | ||||||
|         // 该策略不会使用占位符,因为不允许缓存 null |  | ||||||
|         throw UnsupportedOperationException("Cannot use null placeholder when null is not allowed in cache.") |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 判断指定值是否是 null 占位符。 |  | ||||||
|      * |  | ||||||
|      * 由于不允许缓存 null 值,此方法无法执行有效判断并会抛出异常。 |  | ||||||
|      * |  | ||||||
|      * @param value 要检查的值 |  | ||||||
|      * @return Boolean 不会返回任何值,总是抛出异常 |  | ||||||
|      * @throws UnsupportedOperationException 因为不允许缓存 null 值 |  | ||||||
|      */ |  | ||||||
|     override fun isNullPlaceholder(value: String): Boolean { |  | ||||||
|         // 无法判断 null 占位符,因为 null 值不被缓存 |  | ||||||
|         throw UnsupportedOperationException("Cannot check null placeholder when null is not allowed in cache.") |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @ -1,49 +0,0 @@ | |||||||
| package com.gewuyou.forgeboot.cache.impl.policy |  | ||||||
| 
 |  | ||||||
| import com.gewuyou.forgeboot.cache.api.policy.CachePolicy |  | ||||||
| import com.gewuyou.forgeboot.cache.api.policy.NullValuePolicy |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * 空值缓存策略 |  | ||||||
|  * 用于处理缓存中空值(null)的存储和占位逻辑 |  | ||||||
|  * |  | ||||||
|  * @property nullValuePolicy 提供空值处理策略的接口实现 |  | ||||||
|  * @constructor 创建一个 NullValueCachePolicy 实例 |  | ||||||
|  * @param nullValuePolicy 指定的空值处理策略对象,不可为 null |  | ||||||
|  * @since 2025-06-21 11:56:54 |  | ||||||
|  * @author gewuyou |  | ||||||
|  */ |  | ||||||
| class NullValueCachePolicy( |  | ||||||
|     private val nullValuePolicy: NullValuePolicy |  | ||||||
| ) : CachePolicy { |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 应用当前策略对指定的缓存值进行处理 |  | ||||||
|      * |  | ||||||
|      * @param key 缓存键,用于判断是否允许缓存空值 |  | ||||||
|      * @param value 需要处理的缓存值,可能为 null |  | ||||||
|      * @return 处理后的缓存值: |  | ||||||
|      *         - 如果值为 null 且允许缓存,则返回 null 占位符 |  | ||||||
|      *         - 如果值为 null 但不允许缓存,则返回 null |  | ||||||
|      *         - 否则返回原始非 null 值 |  | ||||||
|      */ |  | ||||||
|     override fun apply(key: String, value: String?): String? { |  | ||||||
|         return when { |  | ||||||
|             // 当值为空且策略允许缓存空值时,返回占位符 |  | ||||||
|             value == null && nullValuePolicy.allowCacheNull(key) -> nullValuePolicy.nullPlaceholder() |  | ||||||
|             // 当值为空但策略不允许缓存时,直接返回 null |  | ||||||
|             value == null -> null |  | ||||||
|             // 非空值直接返回 |  | ||||||
|             else -> value |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 获取该策略的优先级,用于决定多个策略的执行顺序 |  | ||||||
|      * |  | ||||||
|      * @return 优先级,值越小表示优先级越高 |  | ||||||
|      */ |  | ||||||
|     override fun getOrder(): Int { |  | ||||||
|         return 1 |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @ -1,32 +0,0 @@ | |||||||
| package com.gewuyou.forgeboot.cache.impl.runner |  | ||||||
| 
 |  | ||||||
| import com.gewuyou.forgeboot.cache.api.service.CacheWarmUpService |  | ||||||
| import org.springframework.boot.ApplicationArguments |  | ||||||
| import org.springframework.boot.ApplicationRunner |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * 缓存预热运行程序 |  | ||||||
|  * |  | ||||||
|  * 该类实现 ApplicationRunner 接口,用于在应用启动完成后执行缓存预热操作。 |  | ||||||
|  * 构造函数注入了多个 CacheWarmUpService 实现,每个服务对应一个需要预热的缓存资源。 |  | ||||||
|  * |  | ||||||
|  * @property services 需要执行预热操作的所有缓存服务集合 |  | ||||||
|  * |  | ||||||
|  * @since 2025-06-18 12:36:40 |  | ||||||
|  * @author gewuyou |  | ||||||
|  */ |  | ||||||
| class CacheWarmUpRunner( |  | ||||||
|     private val services: List<CacheWarmUpService> |  | ||||||
| ) : ApplicationRunner { |  | ||||||
|     /** |  | ||||||
|      * 应用启动完成后执行的方法 |  | ||||||
|      * |  | ||||||
|      * 遍历所有注入的 CacheWarmUpService 并调用 warmUp 方法执行缓存预热逻辑。 |  | ||||||
|      * 该方法会在 Spring Boot 应用完成启动后自动触发。 |  | ||||||
|      * |  | ||||||
|      * @param args 应用启动参数(可为空) |  | ||||||
|      */ |  | ||||||
|     override fun run(args: ApplicationArguments) { |  | ||||||
|         services.forEach { it.warmUp() } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @ -1,93 +0,0 @@ | |||||||
| package com.gewuyou.forgeboot.cache.impl.service |  | ||||||
| 
 |  | ||||||
| import com.gewuyou.forgeboot.cache.api.config.CacheProperties |  | ||||||
| import com.gewuyou.forgeboot.cache.api.contract.Cache |  | ||||||
| import com.gewuyou.forgeboot.cache.api.extension.get |  | ||||||
| import com.gewuyou.forgeboot.cache.api.generator.KeyGenerator |  | ||||||
| import com.gewuyou.forgeboot.cache.api.service.CacheService |  | ||||||
| import com.gewuyou.forgeboot.core.serialization.serializer.ValueSerializer |  | ||||||
| import java.time.Duration |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * 默认缓存服务实现类,提供基于前缀的键值对缓存操作。 |  | ||||||
|  * |  | ||||||
|  * 该类实现了通用的缓存功能,包括获取、设置、删除、判断存在性和清空缓存的方法。 |  | ||||||
|  * 所有方法均通过命名空间隔离不同业务的数据,确保缓存管理的安全性和灵活性。 |  | ||||||
|  * |  | ||||||
|  * @property serializer 序列化/反序列化缓存值的工具 |  | ||||||
|  * @property cache 实际存储数据的复合缓存实例 |  | ||||||
|  * @property namespace 命名空间 |  | ||||||
|  * @property cacheProperties 缓存配置属性,包含默认过期时间等 |  | ||||||
|  * @since 2025-06-16 22:56:49 |  | ||||||
|  * @author gewuyou |  | ||||||
|  */ |  | ||||||
| class DefaultCacheService( |  | ||||||
|     private val serializer: ValueSerializer, |  | ||||||
|     private val cache: Cache, |  | ||||||
|     private val namespace: String, |  | ||||||
|     private val cacheProperties: CacheProperties, |  | ||||||
|     private val keyGenerator: KeyGenerator, |  | ||||||
| ) : CacheService { |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 获取指定键的缓存值。 |  | ||||||
|      * |  | ||||||
|      * 在命名空间下拼接 key,并从缓存中获取对应的值。若值存在,则使用序列化器将其转换为指定类型;否则返回 null。 |  | ||||||
|      * |  | ||||||
|      * @param key 缓存键 |  | ||||||
|      * @param type 值的类型 Class |  | ||||||
|      * @return 缓存中的对象,如果不存在则为 null |  | ||||||
|      */ |  | ||||||
|     override fun <T : Any> retrieve(key: String, type: Class<T>): T? { |  | ||||||
|         return cache[keyGenerator.generateKey(namespace,key)]?.let { serializer.deserialize(it, type) } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 设置缓存值。 |  | ||||||
|      * |  | ||||||
|      * 将值序列化后,在命名空间下拼接 key 并写入缓存。支持自定义 TTL(生存时间),若未指定则使用默认 TTL。 |  | ||||||
|      * |  | ||||||
|      * @param key 缓存键 |  | ||||||
|      * @param value 值(支持任意对象) |  | ||||||
|      * @param ttl 缓存时长,null 表示使用默认 TTL |  | ||||||
|      */ |  | ||||||
|     override fun put(key: String, value: Any, ttl: Duration?) { |  | ||||||
|         cache.put(keyGenerator.generateKey(namespace,key), serializer.serialize(value), (ttl ?: cacheProperties.theDefaultCacheTTL)) |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 删除缓存。 |  | ||||||
|      * |  | ||||||
|      * 在命名空间下拼接 key,并尝试从缓存中移除对应条目。 |  | ||||||
|      * |  | ||||||
|      * @param key 缓存键 |  | ||||||
|      * @return 删除成功返回 true |  | ||||||
|      */ |  | ||||||
|     override fun remove(key: String): Boolean { |  | ||||||
|         return cache.remove(keyGenerator.generateKey(namespace,key)) |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 判断缓存是否存在。 |  | ||||||
|      * |  | ||||||
|      * 检查在命名空间下拼接的 key 是否存在于缓存中。 |  | ||||||
|      * |  | ||||||
|      * @param key 缓存键 |  | ||||||
|      * @return 如果存在返回 true,否则返回 false |  | ||||||
|      */ |  | ||||||
|     override fun exists(key: String): Boolean { |  | ||||||
|         return cache.exists(keyGenerator.generateKey(namespace,key)) |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 清空指定命名空间下的所有缓存数据。 |  | ||||||
|      * |  | ||||||
|      * 直接调用底层缓存实现的 clear 方法,传入命名空间参数。 |  | ||||||
|      * |  | ||||||
|      * @param namespace 命名空间 |  | ||||||
|      */ |  | ||||||
|     override fun clear(namespace: String) { |  | ||||||
|         cache.clear(namespace) |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @ -1,106 +0,0 @@ | |||||||
| package com.gewuyou.forgeboot.cache.impl.service |  | ||||||
| 
 |  | ||||||
| import com.gewuyou.forgeboot.cache.api.exception.CacheException |  | ||||||
| import com.gewuyou.forgeboot.cache.api.service.LockService |  | ||||||
| import org.redisson.api.RLock |  | ||||||
| import org.redisson.api.RedissonClient |  | ||||||
| import java.time.Duration |  | ||||||
| import java.util.concurrent.TimeUnit |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * Redis 锁服务实现类 |  | ||||||
|  * |  | ||||||
|  * 该类通过 Redisson 提供分布式锁功能,确保在分布式环境下关键代码块的线程安全执行。 |  | ||||||
|  * |  | ||||||
|  * @property redissonClient Redisson 客户端实例,用于获取和操作分布式锁 |  | ||||||
|  * @since 2025-06-18 21:17:21 |  | ||||||
|  * @author gewuyou |  | ||||||
|  */ |  | ||||||
| class RedisLockService( |  | ||||||
|     private val redissonClient: RedissonClient |  | ||||||
| ) : LockService { |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 在分布式锁保护下执行指定的操作 |  | ||||||
|      * |  | ||||||
|      * 尝试获取指定 key 的分布式锁,若成功则执行 supplier 函数并确保最终释放锁; |  | ||||||
|      * 若未能在指定时间内获取锁,则抛出 CacheException 异常。 |  | ||||||
|      * |  | ||||||
|      * @param key 分布式锁的唯一标识 |  | ||||||
|      * @param timeout 获取锁的最大等待时间 |  | ||||||
|      * @param supplier 需要在锁保护下执行的业务逻辑 |  | ||||||
|      * @return supplier 执行后的返回结果 |  | ||||||
|      * @throws CacheException 如果无法获取到分布式锁 |  | ||||||
|      */ |  | ||||||
|     override fun <T> executeWithLock(key: String, timeout: Duration, supplier: () -> T): T { |  | ||||||
|         // 获取 Redisson 分布式锁实例 |  | ||||||
|         val lock: RLock = redissonClient.getLock(key) |  | ||||||
|         // 尝试在指定时间内获取锁 |  | ||||||
|         val acquired: Boolean = lock.tryLock(timeout.seconds, TimeUnit.SECONDS) |  | ||||||
| 
 |  | ||||||
|         if (!acquired) { |  | ||||||
|             throw CacheException("failed to acquire distributed lock:key=$key") |  | ||||||
|         } |  | ||||||
|         return try { |  | ||||||
|             // 执行受锁保护的业务逻辑 |  | ||||||
|             supplier() |  | ||||||
|         } finally { |  | ||||||
|             // 确保当前线程持有锁的情况下释放锁 |  | ||||||
|             if (lock.isHeldByCurrentThread) { |  | ||||||
|                 lock.unlock() |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 使用读锁在受保护的上下文中执行指定操作 |  | ||||||
|      * |  | ||||||
|      * 获取指定 key 的读锁并在限定时间内执行 supplier。如果无法获得锁则抛出异常。 |  | ||||||
|      * |  | ||||||
|      * @param key 读锁的唯一标识 |  | ||||||
|      * @param timeout 获取锁的最大等待时间 |  | ||||||
|      * @param supplier 需要在读锁保护下执行的业务逻辑 |  | ||||||
|      * @return supplier 执行后的返回结果 |  | ||||||
|      * @throws CacheException 如果无法获取到读锁 |  | ||||||
|      */ |  | ||||||
|     override fun <T> executeWithReadLock(key: String, timeout: Duration, supplier: () -> T): T { |  | ||||||
|         val rwLock = redissonClient.getReadWriteLock(key).readLock() |  | ||||||
|         val acquired = rwLock.tryLock(timeout.seconds, TimeUnit.SECONDS) |  | ||||||
|         if (!acquired) { |  | ||||||
|             throw CacheException("failed to obtain a read lock:$key") |  | ||||||
|         } |  | ||||||
|         return try { |  | ||||||
|             supplier() |  | ||||||
|         } finally { |  | ||||||
|             if (rwLock.isHeldByCurrentThread) { |  | ||||||
|                 rwLock.unlock() |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 使用写锁在受保护的上下文中执行指定操作 |  | ||||||
|      * |  | ||||||
|      * 获取指定 key 的写锁并在限定时间内执行 supplier。如果无法获得锁则抛出异常。 |  | ||||||
|      * |  | ||||||
|      * @param key 写锁的唯一标识 |  | ||||||
|      * @param timeout 获取锁的最大等待时间 |  | ||||||
|      * @param supplier 需要在写锁保护下执行的业务逻辑 |  | ||||||
|      * @return supplier 执行后的返回结果 |  | ||||||
|      * @throws CacheException 如果无法获取到写锁 |  | ||||||
|      */ |  | ||||||
|     override fun <T> executeWithWriteLock(key: String, timeout: Duration, supplier: () -> T): T { |  | ||||||
|         val rwLock = redissonClient.getReadWriteLock(key).writeLock() |  | ||||||
|         val acquired = rwLock.tryLock(timeout.seconds, TimeUnit.SECONDS) |  | ||||||
|         if (!acquired) { |  | ||||||
|             throw CacheException("failed to obtain a write lock:$key") |  | ||||||
|         } |  | ||||||
|         return try { |  | ||||||
|             supplier() |  | ||||||
|         } finally { |  | ||||||
|             if (rwLock.isHeldByCurrentThread) { |  | ||||||
|                 rwLock.unlock() |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @ -1,51 +0,0 @@ | |||||||
| package com.gewuyou.forgeboot.cache.impl.support |  | ||||||
| 
 |  | ||||||
| import com.gewuyou.forgeboot.cache.api.generator.KeyGenerator |  | ||||||
| import com.gewuyou.forgeboot.cache.impl.utils.SpELResolver |  | ||||||
| import org.aspectj.lang.JoinPoint |  | ||||||
| import org.aspectj.lang.reflect.MethodSignature |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * 缓存 SpEL 表达式帮助类 |  | ||||||
|  * 提供基于方法参数的 SpEL 解析和缓存键生成能力 |  | ||||||
|  * |  | ||||||
|  * @since 2025-06-18 21:04:03 |  | ||||||
|  * @author gewuyou |  | ||||||
|  */ |  | ||||||
| object CacheSpELHelper { |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 构建方法参数名称到参数值的映射关系 |  | ||||||
|      * 用于支持 SpEL 表达式解析时的参数上下文 |  | ||||||
|      * |  | ||||||
|      * @param joinPoint AOP 方法连接点,包含方法签名和参数信息 |  | ||||||
|      * @return 参数名到参数值的映射表 |  | ||||||
|      */ |  | ||||||
|     fun buildArgsMap(joinPoint: JoinPoint): Map<String, Any?> { |  | ||||||
|         val method = (joinPoint.signature as MethodSignature).method |  | ||||||
|         // 将方法参数列表转换为(参数名 -> 实际参数值)的键值对集合 |  | ||||||
|         return method.parameters.mapIndexed { i, param -> param.name to joinPoint.args[i] }.toMap() |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 解析 SpEL 表达式并生成最终缓存键 |  | ||||||
|      * |  | ||||||
|      * @param namespace 缓存命名空间,用于隔离不同业务的缓存键 |  | ||||||
|      * @param keySpEL   SpEL 表达式字符串,定义缓存键的动态生成逻辑 |  | ||||||
|      * @param joinPoint AOP 方法连接点,提供运行时参数上下文 |  | ||||||
|      * @param keyGenerator 用户定义的缓存键生成策略 |  | ||||||
|      * @return 最终生成的缓存键字符串 |  | ||||||
|      */ |  | ||||||
|     fun parseKey( |  | ||||||
|         namespace: String, |  | ||||||
|         keySpEL: String, |  | ||||||
|         joinPoint: JoinPoint, |  | ||||||
|         keyGenerator: KeyGenerator |  | ||||||
|     ): String { |  | ||||||
|         val argsMap = buildArgsMap(joinPoint) |  | ||||||
|         // 使用 SpEL 解析器根据参数上下文解析表达式得到原始键值 |  | ||||||
|         val key = SpELResolver.parse(keySpEL, argsMap) |  | ||||||
|         // 委托给键生成器结合命名空间生成最终缓存键 |  | ||||||
|         return keyGenerator.generateKey(namespace, key) |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @ -1,38 +0,0 @@ | |||||||
| package com.gewuyou.forgeboot.cache.impl.utils |  | ||||||
| 
 |  | ||||||
| import org.springframework.data.redis.connection.RedisConnectionFactory |  | ||||||
| import org.springframework.data.redis.core.ScanOptions |  | ||||||
| import java.nio.charset.StandardCharsets |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  *Redis 键扫描器 |  | ||||||
|  * |  | ||||||
|  * @since 2025-06-17 21:32:15 |  | ||||||
|  * @author gewuyou |  | ||||||
|  */ |  | ||||||
| class RedisKeyScanner( |  | ||||||
|     private val redisConnectionFactory: RedisConnectionFactory |  | ||||||
| ) { |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 扫描指定 pattern 下的所有 key,使用非阻塞 SCAN 命令 |  | ||||||
|      * |  | ||||||
|      * @param pattern 通配符,如 "user:*" |  | ||||||
|      * @param count 每次扫描的数量 默认1000 |  | ||||||
|      * @return 匹配到的所有 key 列表 |  | ||||||
|      */ |  | ||||||
|     fun scan(pattern: String, count: Long = 1000): Set<String> { |  | ||||||
|         require(pattern.isNotBlank()) { "Scan pattern must not be blank" } |  | ||||||
|         val keys = mutableSetOf<String>() |  | ||||||
|         redisConnectionFactory.connection.use { connection -> |  | ||||||
|             val options = ScanOptions.scanOptions().match(pattern).count(count).build() |  | ||||||
|             connection.keyCommands().scan(options).use { cursor -> |  | ||||||
|                 while (cursor.hasNext()) { |  | ||||||
|                     val rawKey = cursor.next() |  | ||||||
|                     keys.add(String(rawKey, StandardCharsets.UTF_8)) |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|         return keys |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @ -1,35 +0,0 @@ | |||||||
| package com.gewuyou.forgeboot.cache.impl.utils |  | ||||||
| 
 |  | ||||||
| import org.springframework.expression.ExpressionParser |  | ||||||
| import org.springframework.expression.spel.standard.SpelExpressionParser |  | ||||||
| import org.springframework.expression.spel.support.StandardEvaluationContext |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * SpEL 解析器,用于解析和执行 Spring Expression Language (SpEL) 表达式。 |  | ||||||
|  * |  | ||||||
|  * @since 2025-06-18 20:44:10 |  | ||||||
|  * @author gewuyou |  | ||||||
|  */ |  | ||||||
| object SpELResolver { |  | ||||||
|     /** |  | ||||||
|      * 表达式解析器实例,用于解析 SpEL 表达式。 |  | ||||||
|      */ |  | ||||||
|     private val parser: ExpressionParser = SpelExpressionParser() |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 解析给定的 SpEL 表达式,并使用提供的参数进行求值。 |  | ||||||
|      * |  | ||||||
|      * @param expression SpEL 表达式字符串 |  | ||||||
|      * @param argsMap 包含变量及其对应值的映射表,用于表达式求值 |  | ||||||
|      * @return 解析后的字符串结果,如果表达式返回 null,则返回空字符串 |  | ||||||
|      */ |  | ||||||
|     fun parse(expression: String, argsMap: Map<String, Any?>): String { |  | ||||||
|         // 创建评估上下文并设置变量 |  | ||||||
|         val context = StandardEvaluationContext().apply { |  | ||||||
|             argsMap.forEach { (name, value) -> setVariable(name, value) } |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         // 解析并获取表达式的字符串值 |  | ||||||
|         return parser.parseExpression(expression).getValue(context, String::class.java) ?: "" |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @ -36,30 +36,11 @@ import org.springframework.web.reactive.function.client.ClientRequest | |||||||
| @Configuration | @Configuration | ||||||
| class ForgeContextAutoConfiguration { | class ForgeContextAutoConfiguration { | ||||||
| 
 | 
 | ||||||
|     /** |  | ||||||
|      * 创建 ValueSerializer Bean,用于在缺少其他实现时提供默认的值序列化器。 |  | ||||||
|      * |  | ||||||
|      * 该方法定义了一个 JacksonValueSerializer 实例作为默认的 ValueSerializer 实现, |  | ||||||
|      * 负责使用 Jackson 库对上下文字段值进行序列化和反序列化操作。 |  | ||||||
|      * |  | ||||||
|      * @param objectMapper 提供 JSON 序列化支持的 ObjectMapper 实例 |  | ||||||
|      * @return 构建完成的 ValueSerializer 实例 |  | ||||||
|      */ |  | ||||||
|     @Bean |     @Bean | ||||||
|     @ConditionalOnMissingBean |     @ConditionalOnMissingBean | ||||||
|     fun valueSerializer(objectMapper: ObjectMapper): ValueSerializer { |     fun valueSerializer(objectMapper: ObjectMapper): ValueSerializer{ | ||||||
|         return JacksonValueSerializer(objectMapper) |         return JacksonValueSerializer(objectMapper) | ||||||
|     } |     } | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 创建 ContextHolder Bean,用于在缺少其他实现时提供默认的上下文持有者。 |  | ||||||
|      * |  | ||||||
|      * 该方法定义了一个 ContextHolder 实例作为默认的上下文管理器, |  | ||||||
|      * 负责存储、传递和清理当前线程的上下文字段数据。 |  | ||||||
|      * |  | ||||||
|      * @param valueSerializer 提供值序列化支持的 ValueSerializer 实例 |  | ||||||
|      * @return 构建完成的 ContextHolder 实例 |  | ||||||
|      */ |  | ||||||
|     @Bean |     @Bean | ||||||
|     @ConditionalOnMissingBean |     @ConditionalOnMissingBean | ||||||
|     fun contextHolder(valueSerializer: ValueSerializer): ContextHolder { |     fun contextHolder(valueSerializer: ValueSerializer): ContextHolder { | ||||||
|  | |||||||
							
								
								
									
										3
									
								
								forgeboot-security/.gitattributes
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								forgeboot-security/.gitattributes
									
									
									
									
										vendored
									
									
								
							| @ -1,3 +0,0 @@ | |||||||
| /gradlew text eol=lf |  | ||||||
| *.bat text eol=crlf |  | ||||||
| *.jar binary |  | ||||||
							
								
								
									
										40
									
								
								forgeboot-security/.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										40
									
								
								forgeboot-security/.gitignore
									
									
									
									
										vendored
									
									
								
							| @ -1,40 +0,0 @@ | |||||||
| 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 |  | ||||||
| @ -1,5 +0,0 @@ | |||||||
| extra{ |  | ||||||
|     setProperty(ProjectFlags.IS_ROOT_MODULE,true) |  | ||||||
| } |  | ||||||
| dependencies { |  | ||||||
| } |  | ||||||
| @ -1,3 +0,0 @@ | |||||||
| /gradlew text eol=lf |  | ||||||
| *.bat text eol=crlf |  | ||||||
| *.jar binary |  | ||||||
| @ -1,40 +0,0 @@ | |||||||
| 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 |  | ||||||
| @ -1,3 +0,0 @@ | |||||||
| /gradlew text eol=lf |  | ||||||
| *.bat text eol=crlf |  | ||||||
| *.jar binary |  | ||||||
| @ -1,40 +0,0 @@ | |||||||
| 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 |  | ||||||
| @ -1,8 +0,0 @@ | |||||||
| 
 |  | ||||||
| dependencies { |  | ||||||
|     api(project(Modules.Webmvc.DTO)) |  | ||||||
|     compileOnly(project(Modules.Security.CORE)) |  | ||||||
|     compileOnly(libs.springBootStarter.web) |  | ||||||
|     compileOnly(libs.springBootStarter.security) |  | ||||||
|     kapt(libs.springBoot.configuration.processor) |  | ||||||
| } |  | ||||||
| @ -1,45 +0,0 @@ | |||||||
| package com.gewuyou.forgeboot.security.authenticate.api.config |  | ||||||
| 
 |  | ||||||
| import org.springframework.boot.context.properties.ConfigurationProperties |  | ||||||
| import org.springframework.http.HttpMethod |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * 安全身份验证属性配置类 |  | ||||||
|  * |  | ||||||
|  * 该类用于定义安全认证相关的配置属性,包含路径权限设置、异常响应信息和基础URL配置。 |  | ||||||
|  * 属性值通过@ConfigurationProperties绑定前缀"forgeboot.security.authenticate"的配置项。 |  | ||||||
|  * |  | ||||||
|  * @since 2025-06-11 15:20:27 |  | ||||||
|  * @author gewuyou |  | ||||||
|  */ |  | ||||||
| @ConfigurationProperties(prefix = "forgeboot.security.authenticate") |  | ||||||
| class SecurityAuthenticateProperties { |  | ||||||
|     /** |  | ||||||
|      * 登录请求的HTTP方法,默认为POST |  | ||||||
|      */ |  | ||||||
|     var loginHttpMethod: String = HttpMethod.POST.name() |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 默认认证异常响应内容,当请求缺少认证时返回此字符串 |  | ||||||
|      */ |  | ||||||
|     var defaultExceptionResponse = "Full authentication is required to access this resource" |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 默认认证失败响应内容,当认证失败时返回此字符串 |  | ||||||
|      */ |  | ||||||
|     var defaultAuthenticationFailureResponse = "If the authentication fails, please report the request ID for more information!" |  | ||||||
|     /** |  | ||||||
|      * 认证模块的基础URL前缀 |  | ||||||
|      */ |  | ||||||
|     var baseUrl = "/api/auth" |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 登录接口的URL路径 |  | ||||||
|      */ |  | ||||||
|     var loginUrl = "/login" |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 登出接口的URL路径 |  | ||||||
|      */ |  | ||||||
|     var logoutUrl = "/logout" |  | ||||||
| } |  | ||||||
| @ -1,24 +0,0 @@ | |||||||
| package com.gewuyou.forgeboot.security.authenticate.api.customizer |  | ||||||
| 
 |  | ||||||
| import org.springframework.security.config.annotation.web.builders.HttpSecurity |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * 登录过滤器定制器接口 |  | ||||||
|  * |  | ||||||
|  * 该函数式接口用于自定义Spring Security的登录过滤器配置。 |  | ||||||
|  * 实现此接口的类或lambda表达式可用于调整安全配置中的HttpSecurity设置, |  | ||||||
|  * 特别是在登录认证流程中对请求的安全策略进行定制化处理。 |  | ||||||
|  * |  | ||||||
|  * @since 2025-06-11 18:53:25 |  | ||||||
|  * @author gewuyou |  | ||||||
|  */ |  | ||||||
| fun interface LoginFilterCustomizer { |  | ||||||
|     /** |  | ||||||
|      * 自定义方法,用于配置或修改HttpSecurity对象。 |  | ||||||
|      * |  | ||||||
|      * 此方法将被调用以应用特定的安全性规则到登录过滤器上。 |  | ||||||
|      * |  | ||||||
|      * @param http HttpSecurity对象,提供了配置Web安全性的API |  | ||||||
|      */ |  | ||||||
|     fun customize(http: HttpSecurity) |  | ||||||
| } |  | ||||||
| @ -1,28 +0,0 @@ | |||||||
| package com.gewuyou.forgeboot.security.authenticate.api.enums |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  *登录类型 |  | ||||||
|  * |  | ||||||
|  * @since 2025-06-12 21:11:02 |  | ||||||
|  * @author gewuyou |  | ||||||
|  */ |  | ||||||
| object LoginTypes { |  | ||||||
|     /** |  | ||||||
|      * 默认登录类型标识 |  | ||||||
|      */ |  | ||||||
|     const val DEFAULT = "default" |  | ||||||
|     /** |  | ||||||
|      * 用户名密码登录类型标识 |  | ||||||
|      */ |  | ||||||
|     const val USERNAME_PASSWORD = "username_password" |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * OAuth2 认证登录类型标识 |  | ||||||
|      */ |  | ||||||
|     const val OAUTH2 = "oauth2" |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 短信验证码登录类型标识 |  | ||||||
|      */ |  | ||||||
|     const val SMS = "sms" |  | ||||||
| } |  | ||||||
| @ -1,18 +0,0 @@ | |||||||
| package com.gewuyou.forgeboot.security.authenticate.api.exception |  | ||||||
| 
 |  | ||||||
| import org.springframework.security.core.AuthenticationException |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  *Forge Boot身份验证异常 |  | ||||||
|  * |  | ||||||
|  * @since 2025-06-11 15:49:33 |  | ||||||
|  * @author gewuyou |  | ||||||
|  */ |  | ||||||
| open class ForgeBootAuthenticationException( |  | ||||||
|     msg: String, |  | ||||||
|     cause: Throwable? = null |  | ||||||
| ): AuthenticationException( |  | ||||||
|     msg, |  | ||||||
|     cause |  | ||||||
| ) |  | ||||||
| @ -1,27 +0,0 @@ | |||||||
| package com.gewuyou.forgeboot.security.authenticate.api.handler |  | ||||||
| 
 |  | ||||||
| import jakarta.servlet.http.HttpServletRequest |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * 委派处理程序接口,用于定义委派处理器的行为规范。 |  | ||||||
|  * |  | ||||||
|  * 该接口设计为泛型函数式接口,要求实现类提供一个方法, |  | ||||||
|  * 将给定的 HTTP 请求解析为指定类型的委派对象。 |  | ||||||
|  * |  | ||||||
|  * @param <T> 委派对象的类型,必须是非空类型 |  | ||||||
|  * |  | ||||||
|  * @since 2025-06-11 14:51:48 |  | ||||||
|  * @author gewuyou |  | ||||||
|  */ |  | ||||||
| fun interface DelegatingHandler<T: Any> { |  | ||||||
|     /** |  | ||||||
|      * 根据提供的 HTTP 请求解析出对应的委派对象。 |  | ||||||
|      * |  | ||||||
|      * 此方法通常用于从请求中提取认证信息或上下文数据, |  | ||||||
|      * 并将其转换为具体的业务对象以供后续处理使用。 |  | ||||||
|      * |  | ||||||
|      * @param request 要解析的 HTTP 请求对象,不能为 null |  | ||||||
|      * @return 返回解析得到的委派对象,具体类型由接口泛型 T 决定 |  | ||||||
|      */ |  | ||||||
|     fun resolveDelegate(request: HttpServletRequest): T |  | ||||||
| } |  | ||||||
| @ -1,47 +0,0 @@ | |||||||
| package com.gewuyou.forgeboot.security.authenticate.api.registry |  | ||||||
| 
 |  | ||||||
| import com.gewuyou.forgeboot.security.core.authenticate.entities.request.LoginRequest |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * 登录请求类型注册表 |  | ||||||
|  * |  | ||||||
|  * 用于管理不同登录类型的请求类映射关系,支持动态注册和获取登录请求类型。 |  | ||||||
|  * |  | ||||||
|  * ```kt |  | ||||||
|  * @Bean |  | ||||||
|  * fun loginRequestTypeRegistry(): LoginRequestTypeRegistry { |  | ||||||
|  *     return LoginRequestTypeRegistry().apply { |  | ||||||
|  *         register("default", DefaultLoginRequest::class.java) |  | ||||||
|  *         register("sms", SmsLoginRequest::class.java) |  | ||||||
|  *     } |  | ||||||
|  * } |  | ||||||
|  * ``` |  | ||||||
|  * @since 2025-06-10 16:33:43 |  | ||||||
|  * @author gewuyou |  | ||||||
|  */ |  | ||||||
| class LoginRequestTypeRegistry { |  | ||||||
|     /** |  | ||||||
|      * 内部使用可变Map保存登录类型与对应LoginRequest子类的映射关系 |  | ||||||
|      */ |  | ||||||
|     private val mapping = mutableMapOf<String, Class<out LoginRequest>>() |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 注册指定登录类型对应的请求类 |  | ||||||
|      * |  | ||||||
|      * @param loginType 登录类型的标识字符串 |  | ||||||
|      * @param clazz     继承自LoginRequest的具体请求类 |  | ||||||
|      */ |  | ||||||
|     fun register(loginType: String, clazz: Class<out LoginRequest>) { |  | ||||||
|         mapping[loginType] = clazz |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 根据登录类型获取对应的请求类 |  | ||||||
|      * |  | ||||||
|      * @param loginType 登录类型的标识字符串 |  | ||||||
|      * @return 返回对应的LoginRequest子类,若未找到则返回null |  | ||||||
|      */ |  | ||||||
|     fun getTypeForLoginType(loginType: String): Class<out LoginRequest>? { |  | ||||||
|         return mapping[loginType] |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @ -1,31 +0,0 @@ | |||||||
| package com.gewuyou.forgeboot.security.authenticate.api.resolver |  | ||||||
| 
 |  | ||||||
| import com.gewuyou.forgeboot.security.core.authenticate.entities.request.LoginRequest |  | ||||||
| import jakarta.servlet.http.HttpServletRequest |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * 登录请求解析器接口 |  | ||||||
|  * 用于定义处理登录请求的通用规范,包括内容类型支持判断和请求参数解析功能 |  | ||||||
|  * |  | ||||||
|  * @since 2025-06-10 16:32:32 |  | ||||||
|  * @author gewuyou |  | ||||||
|  */ |  | ||||||
| interface LoginRequestResolver { |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 判断当前解析器是否支持指定的内容类型 |  | ||||||
|      * |  | ||||||
|      * @param contentType 请求内容类型 |  | ||||||
|      * @return Boolean 返回true表示支持该内容类型,否则不支持 |  | ||||||
|      */ |  | ||||||
|     fun supports(contentType: String): Boolean |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 解析HTTP请求为具体的登录请求对象 |  | ||||||
|      * 该方法应从HttpServletRequest中提取并封装登录所需参数 |  | ||||||
|      * |  | ||||||
|      * @param request HTTP请求对象 |  | ||||||
|      * @return LoginRequest 解析后的登录请求实体对象 |  | ||||||
|      */ |  | ||||||
|     fun resolve(request: HttpServletRequest): LoginRequest |  | ||||||
| } |  | ||||||
| @ -1,31 +0,0 @@ | |||||||
| package com.gewuyou.forgeboot.security.authenticate.api.service |  | ||||||
| 
 |  | ||||||
| import org.springframework.security.core.userdetails.UserDetails |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  *用户缓存服务 |  | ||||||
|  * |  | ||||||
|  * @since 2025-02-15 17:15:17 |  | ||||||
|  * @author gewuyou |  | ||||||
|  */ |  | ||||||
| interface UserCacheService { |  | ||||||
|     /** |  | ||||||
|      * 从缓存中获取用户信息 |  | ||||||
|      * @param principal 用户标识 |  | ||||||
|      * @return 用户信息 返回null表示缓存中没有该用户信息或信息已过期 |  | ||||||
|      */ |  | ||||||
|     fun getUserFromCache(principal: String): UserDetails? |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 将用户信息缓存到缓存中 注意,请将过期时间设置得尽可能短,以防止缓存与数据库出现数据不一致 |  | ||||||
|      * @param userDetails 用户信息 |  | ||||||
|      */ |  | ||||||
|     fun putUserToCache(userDetails: UserDetails) |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 从缓存中移除用户信息 |  | ||||||
|      * @param principal 用户标识 |  | ||||||
|      */ |  | ||||||
|     fun removeUserFromCache(principal: String) |  | ||||||
| } |  | ||||||
| @ -1,19 +0,0 @@ | |||||||
| package com.gewuyou.forgeboot.security.authenticate.api.service |  | ||||||
| 
 |  | ||||||
| import org.springframework.security.core.userdetails.UserDetails |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * 用户详情服务 |  | ||||||
|  * |  | ||||||
|  * @author gewuyou |  | ||||||
|  * @since 2024-11-05 19:34:50 |  | ||||||
|  */ |  | ||||||
| fun interface UserDetailsService { |  | ||||||
|     /** |  | ||||||
|      * 根据用户身份标识获取用户 |  | ||||||
|      * @param principal 用户身份标识 通常为用户名 手机号 邮箱等 |  | ||||||
|      * @return 用户详情 不能为空 |  | ||||||
|      */ |  | ||||||
|     fun loadUserByPrincipal(principal: Any): UserDetails |  | ||||||
| } |  | ||||||
| @ -1,11 +0,0 @@ | |||||||
| package com.gewuyou.forgeboot.security.authenticate.api.strategy |  | ||||||
| 
 |  | ||||||
| import org.springframework.security.web.authentication.AuthenticationFailureHandler |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * 身份验证失败策略接口,用于定义不同登录类型的身份验证失败处理机制。 |  | ||||||
|  * |  | ||||||
|  * @since 2025-06-10 23:43:43 |  | ||||||
|  * @author gewuyou |  | ||||||
|  */ |  | ||||||
| interface AuthenticationFailureStrategy : AuthenticationHandlerSupportStrategy, AuthenticationFailureHandler |  | ||||||
| @ -1,16 +0,0 @@ | |||||||
| package com.gewuyou.forgeboot.security.authenticate.api.strategy |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  *身份验证处理程序支持策略 |  | ||||||
|  * |  | ||||||
|  * @since 2025-06-11 00:03:28 |  | ||||||
|  * @author gewuyou |  | ||||||
|  */ |  | ||||||
| fun interface AuthenticationHandlerSupportStrategy{ |  | ||||||
|     /** |  | ||||||
|      * 获取当前策略支持的登录类型标识符。 |  | ||||||
|      * |  | ||||||
|      * @return 返回当前策略支持的登录类型字符串 |  | ||||||
|      */ |  | ||||||
|     fun supportedLoginType(): String |  | ||||||
| } |  | ||||||
| @ -1,11 +0,0 @@ | |||||||
| package com.gewuyou.forgeboot.security.authenticate.api.strategy |  | ||||||
| 
 |  | ||||||
| import org.springframework.security.web.authentication.AuthenticationSuccessHandler |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * 身份验证成功策略接口,用于定义不同登录类型的成功处理策略。 |  | ||||||
|  * |  | ||||||
|  * @since 2025-06-10 23:42:54 |  | ||||||
|  * @author gewuyou |  | ||||||
|  */ |  | ||||||
| interface AuthenticationSuccessStrategy : AuthenticationHandlerSupportStrategy,  AuthenticationSuccessHandler |  | ||||||
| @ -1,26 +0,0 @@ | |||||||
| package com.gewuyou.forgeboot.security.authenticate.api.strategy |  | ||||||
| 
 |  | ||||||
| import com.gewuyou.forgeboot.security.core.authenticate.entities.request.LoginRequest |  | ||||||
| import org.springframework.security.core.Authentication |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  *登录请求转换器策略 |  | ||||||
|  * 请注意,该接口仅用于定义转换器的接口只负责转换登录请求为认证对象,不负责提供认证逻辑。 |  | ||||||
|  * 具体的认证逻辑由具体的认证提供类实现。因此当需要自定义认证逻辑时,请实现具体的认证提供类。 |  | ||||||
|  * @since 2025-02-15 03:23:34 |  | ||||||
|  * @author gewuyou |  | ||||||
|  */ |  | ||||||
| interface LoginRequestConverterStrategy { |  | ||||||
|     /** |  | ||||||
|      * 转换登录请求为认证对象 |  | ||||||
|      * @param loginRequest 登录请求 |  | ||||||
|      * @return 认证对象 |  | ||||||
|      */ |  | ||||||
|     fun convert(loginRequest: LoginRequest): Authentication |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 获取支持的登录类型 |  | ||||||
|      * @return 请求的登录类型 |  | ||||||
|      */ |  | ||||||
|     fun getSupportedLoginType(): String |  | ||||||
| } |  | ||||||
| @ -1,13 +0,0 @@ | |||||||
| package com.gewuyou.forgeboot.security.authenticate.api.strategy |  | ||||||
| 
 |  | ||||||
| import org.springframework.security.web.authentication.logout.LogoutSuccessHandler |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * 注销成功策略接口,用于定义在用户注销成功后的处理逻辑。 |  | ||||||
|  * |  | ||||||
|  * 实现此类的策略应当提供具体地登出后操作,例如清理会话、记录日志等。 |  | ||||||
|  * |  | ||||||
|  * @since 2025-06-10 23:49:35 |  | ||||||
|  * @author gewuyou |  | ||||||
|  */ |  | ||||||
| interface LogoutSuccessStrategy : AuthenticationHandlerSupportStrategy, LogoutSuccessHandler |  | ||||||
| @ -1,3 +0,0 @@ | |||||||
| /gradlew text eol=lf |  | ||||||
| *.bat text eol=crlf |  | ||||||
| *.jar binary |  | ||||||
| @ -1,40 +0,0 @@ | |||||||
| 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 |  | ||||||
| @ -1,9 +0,0 @@ | |||||||
| plugins { |  | ||||||
|     alias(libs.plugins.kotlin.plugin.spring) |  | ||||||
| } |  | ||||||
| dependencies { |  | ||||||
|     compileOnly(libs.springBootStarter.security) |  | ||||||
|     compileOnly(libs.springBootStarter.web) |  | ||||||
|     compileOnly(project(Modules.Security.Authenticate.IMPL)) |  | ||||||
|     implementation(project(Modules.Security.CORE)) |  | ||||||
| } |  | ||||||
| @ -1,309 +0,0 @@ | |||||||
| package com.gewuyou.forgeboot.security.authenticate.autoconfigure |  | ||||||
| 
 |  | ||||||
| import com.fasterxml.jackson.databind.ObjectMapper |  | ||||||
| import com.gewuyou.forgeboot.security.authenticate.api.config.SecurityAuthenticateProperties |  | ||||||
| import com.gewuyou.forgeboot.security.authenticate.api.customizer.LoginFilterCustomizer |  | ||||||
| import com.gewuyou.forgeboot.security.authenticate.api.resolver.LoginRequestResolver |  | ||||||
| import com.gewuyou.forgeboot.security.authenticate.api.strategy.AuthenticationFailureStrategy |  | ||||||
| import com.gewuyou.forgeboot.security.authenticate.api.strategy.AuthenticationSuccessStrategy |  | ||||||
| import com.gewuyou.forgeboot.security.authenticate.api.strategy.LogoutSuccessStrategy |  | ||||||
| import com.gewuyou.forgeboot.security.core.common.extension.cleanUnNeedConfig |  | ||||||
| import com.gewuyou.forgeboot.security.authenticate.impl.filter.UnifiedAuthenticationFilter |  | ||||||
| import com.gewuyou.forgeboot.security.authenticate.impl.handler.AuthenticationExceptionHandler |  | ||||||
| import com.gewuyou.forgeboot.security.authenticate.impl.handler.CompositeAuthenticationFailureHandler |  | ||||||
| import com.gewuyou.forgeboot.security.authenticate.impl.handler.CompositeAuthenticationSuccessHandler |  | ||||||
| import com.gewuyou.forgeboot.security.authenticate.impl.handler.CompositeLogoutSuccessHandler |  | ||||||
| import com.gewuyou.forgeboot.security.authenticate.impl.resolver.CompositeLoginRequestResolver |  | ||||||
| import com.gewuyou.forgeboot.security.authenticate.impl.strategy.context.AuthenticationFailureHandlerContext |  | ||||||
| import com.gewuyou.forgeboot.security.authenticate.impl.strategy.context.AuthenticationSuccessHandlerContext |  | ||||||
| import com.gewuyou.forgeboot.security.authenticate.impl.strategy.context.LoginRequestConverterContext |  | ||||||
| import com.gewuyou.forgeboot.security.authenticate.impl.strategy.context.LogoutSuccessHandlerContext |  | ||||||
| import org.springframework.beans.factory.ObjectProvider |  | ||||||
| import org.springframework.boot.autoconfigure.condition.ConditionalOnClass |  | ||||||
| import org.springframework.boot.context.properties.EnableConfigurationProperties |  | ||||||
| import org.springframework.context.ApplicationContext |  | ||||||
| import org.springframework.context.annotation.Bean |  | ||||||
| import org.springframework.context.annotation.ComponentScan |  | ||||||
| import org.springframework.context.annotation.Configuration |  | ||||||
| import org.springframework.context.annotation.Primary |  | ||||||
| import org.springframework.security.authentication.AuthenticationManager |  | ||||||
| import org.springframework.security.authentication.AuthenticationProvider |  | ||||||
| import org.springframework.security.authentication.ProviderManager |  | ||||||
| import org.springframework.security.config.annotation.web.builders.HttpSecurity |  | ||||||
| import org.springframework.security.web.AuthenticationEntryPoint |  | ||||||
| import org.springframework.security.web.SecurityFilterChain |  | ||||||
| import org.springframework.security.web.authentication.AuthenticationFailureHandler |  | ||||||
| import org.springframework.security.web.authentication.AuthenticationSuccessHandler |  | ||||||
| import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter |  | ||||||
| import org.springframework.security.web.util.matcher.AntPathRequestMatcher |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * 安全身份验证自动配置 |  | ||||||
|  * |  | ||||||
|  * 主要用于配置与安全认证相关的 Bean 和 Spring Security 的过滤器链。 |  | ||||||
|  * |  | ||||||
|  * @since 2025-06-11 15:04:58 |  | ||||||
|  * @author gewuyou |  | ||||||
|  */ |  | ||||||
| @Configuration |  | ||||||
| @EnableConfigurationProperties(SecurityAuthenticateProperties::class) |  | ||||||
| class SecurityAuthenticateAutoConfiguration { |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * Spring Security 认证流程的自动配置类。 |  | ||||||
|      * |  | ||||||
|      * 该内部类负责构建主要的安全过滤器链,处理登录、登出以及异常入口点等核心功能。 |  | ||||||
|      * |  | ||||||
|      * @property logoutSuccessHandler 处理登出成功的处理器 |  | ||||||
|      * @property authenticationExceptionHandler 处理认证异常的入口点 |  | ||||||
|      * @property unifiedAuthenticationFilter 统一的身份验证过滤器 |  | ||||||
|      * @property customizers 可选的登录过滤器定制器集合 |  | ||||||
|      */ |  | ||||||
|     @Configuration(proxyBeanMethods = false) |  | ||||||
|     @ConditionalOnClass(SecurityFilterChain::class) |  | ||||||
|     class SpringSecurityAuthenticateAutoConfiguration( |  | ||||||
|         private val logoutSuccessHandler: CompositeLogoutSuccessHandler, |  | ||||||
|         private val authenticationExceptionHandler: AuthenticationEntryPoint, |  | ||||||
|         private val unifiedAuthenticationFilter: UnifiedAuthenticationFilter, |  | ||||||
|         private val customizers: ObjectProvider<List<LoginFilterCustomizer>>, |  | ||||||
|     ) { |  | ||||||
| 
 |  | ||||||
|         /** |  | ||||||
|          * 构建并返回一个自定义的安全过滤器链。 |  | ||||||
|          * |  | ||||||
|          * 该方法配置了: |  | ||||||
|          * - 清除不必要地默认安全配置 |  | ||||||
|          * - 登出功能及其成功处理器 |  | ||||||
|          * - 异常处理(认证失败入口点) |  | ||||||
|          * - 请求匹配规则和访问控制策略 |  | ||||||
|          * - 添加统一的身份验证过滤器到过滤器链中 |  | ||||||
|          * - 对可排序的登录过滤器定制器进行排序并应用 |  | ||||||
|          * |  | ||||||
|          * @param http HttpSecurity 实例,用于构建安全过滤器链 |  | ||||||
|          * @param properties 安全认证属性配置对象 |  | ||||||
|          * @return 构建完成的 SecurityFilterChain 实例 |  | ||||||
|          */ |  | ||||||
|         @Bean(name = ["forgebootSecurityAuthenticationChain"]) |  | ||||||
|         fun loginFilterChain( |  | ||||||
|             http: HttpSecurity, |  | ||||||
|             properties: SecurityAuthenticateProperties, |  | ||||||
|         ): SecurityFilterChain { |  | ||||||
|             return http |  | ||||||
|                 .cleanUnNeedConfig() |  | ||||||
|                 .logout { |  | ||||||
|                     it.logoutUrl(properties.logoutUrl) |  | ||||||
|                         .logoutSuccessHandler(logoutSuccessHandler) |  | ||||||
|                 } |  | ||||||
|                 .exceptionHandling { |  | ||||||
|                     it.authenticationEntryPoint(authenticationExceptionHandler) |  | ||||||
|                 } |  | ||||||
|                 .securityMatcher(AntPathRequestMatcher(properties.baseUrl)) |  | ||||||
|                 .addFilterBefore(unifiedAuthenticationFilter, UsernamePasswordAuthenticationFilter::class.java) |  | ||||||
|                 .also { |  | ||||||
|                     customizers.ifAvailable?.sortedBy { c -> (c as? OrderedLoginFilterCustomizer)?.order ?: 0 } |  | ||||||
|                         ?.forEach { it.customize(http) } |  | ||||||
|                 } |  | ||||||
|                 .build() |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * ForgeBoot安全组件的自动配置类。 |  | ||||||
|      * |  | ||||||
|      * 负责注册多个用于处理身份验证流程的组合式组件,如解析器、上下文、处理器等。 |  | ||||||
|      */ |  | ||||||
|     @Configuration(proxyBeanMethods = false) |  | ||||||
|     class ForgeBootSecurityAuthenticateAutoConfiguration { |  | ||||||
| 
 |  | ||||||
|         /** |  | ||||||
|          * 创建并返回一个组合式的登录请求解析器。 |  | ||||||
|          * |  | ||||||
|          * 将多个 LoginRequestResolver 实现组合成一个统一的接口调用入口。 |  | ||||||
|          * |  | ||||||
|          * @param resolvers 所有可用的 LoginRequestResolver 实例列表 |  | ||||||
|          * @return 组合后的 CompositeLoginRequestResolver 实例 |  | ||||||
|          */ |  | ||||||
|         @Bean |  | ||||||
|         fun compositeLoginRequestResolver( |  | ||||||
|             resolvers: List<LoginRequestResolver>, |  | ||||||
|         ) = CompositeLoginRequestResolver(resolvers) |  | ||||||
| 
 |  | ||||||
|         /** |  | ||||||
|          * 创建并返回一个登出成功处理的上下文实例。 |  | ||||||
|          * |  | ||||||
|          * 用于根据注册的策略动态选择合适的 LogoutSuccessStrategy。 |  | ||||||
|          * |  | ||||||
|          * @param strategies 所有可用的 LogoutSuccessStrategy 实例列表 |  | ||||||
|          * @return 初始化好的 LogoutSuccessHandlerContext 实例 |  | ||||||
|          */ |  | ||||||
|         @Bean |  | ||||||
|         fun logoutSuccessHandlerContext( |  | ||||||
|             strategies: List<LogoutSuccessStrategy>, |  | ||||||
|         ) = LogoutSuccessHandlerContext(strategies) |  | ||||||
| 
 |  | ||||||
|         /** |  | ||||||
|          * 创建并返回一个组合式的登出成功处理器。 |  | ||||||
|          * |  | ||||||
|          * 使用解析器和上下文来决定最终使用的登出成功策略。 |  | ||||||
|          * |  | ||||||
|          * @param resolver 登录请求解析器 |  | ||||||
|          * @param context 登出成功处理上下文 |  | ||||||
|          * @return 初始化好的 CompositeLogoutSuccessHandler 实例 |  | ||||||
|          */ |  | ||||||
|         @Bean(name = ["logoutSuccessHandler"]) |  | ||||||
|         fun compositeLogoutSuccessHandler( |  | ||||||
|             resolver: CompositeLoginRequestResolver, |  | ||||||
|             context: LogoutSuccessHandlerContext, |  | ||||||
|         ) = CompositeLogoutSuccessHandler(resolver, context) |  | ||||||
| 
 |  | ||||||
|         /** |  | ||||||
|          * 创建并返回一个认证异常处理器。 |  | ||||||
|          * |  | ||||||
|          * 当用户未认证或认证失败时,通过此处理器响应客户端。 |  | ||||||
|          * |  | ||||||
|          * @param objectMapper JSON 序列化工具 |  | ||||||
|          * @param properties 安全认证属性配置 |  | ||||||
|          * @return 初始化好的 AuthenticationExceptionHandler 实例 |  | ||||||
|          */ |  | ||||||
|         @Bean |  | ||||||
|         fun authenticationExceptionHandler( |  | ||||||
|             objectMapper: ObjectMapper, |  | ||||||
|             properties: SecurityAuthenticateProperties, |  | ||||||
|         ): AuthenticationEntryPoint = AuthenticationExceptionHandler(objectMapper, properties) |  | ||||||
| 
 |  | ||||||
|         /** |  | ||||||
|          * 创建并返回一个认证管理器。 |  | ||||||
|          * |  | ||||||
|          * 使用一组 AuthenticationProvider 来支持多种认证方式。 |  | ||||||
|          * |  | ||||||
|          * @param authenticationProviders 所有可用的认证提供者 |  | ||||||
|          * @return 初始化好的 ProviderManager 实例 |  | ||||||
|          */ |  | ||||||
|         @Bean(name = ["authenticationManager"]) |  | ||||||
|         @Primary |  | ||||||
|         fun authenticationManager( |  | ||||||
|             authenticationProviders: List<AuthenticationProvider>, |  | ||||||
|         ): AuthenticationManager = ProviderManager(authenticationProviders) |  | ||||||
| 
 |  | ||||||
|         /** |  | ||||||
|          * 创建并返回一个认证成功处理的上下文。 |  | ||||||
|          * |  | ||||||
|          * 根据当前请求上下文动态选择合适的认证成功策略。 |  | ||||||
|          * |  | ||||||
|          * @param strategies 所有可用的 AuthenticationSuccessStrategy 实例列表 |  | ||||||
|          * @return 初始化好的 AuthenticationSuccessHandlerContext 实例 |  | ||||||
|          */ |  | ||||||
|         @Bean |  | ||||||
|         fun authenticationSuccessHandlerContext( |  | ||||||
|             strategies: List<AuthenticationSuccessStrategy>, |  | ||||||
|         ) = AuthenticationSuccessHandlerContext(strategies) |  | ||||||
| 
 |  | ||||||
|         /** |  | ||||||
|          * 创建并返回一个组合式的认证成功处理器。 |  | ||||||
|          * |  | ||||||
|          * 委托给具体的策略实现来进行响应。 |  | ||||||
|          * |  | ||||||
|          * @param resolver 登录请求解析器 |  | ||||||
|          * @param context 认证成功处理上下文 |  | ||||||
|          * @return 初始化好的 CompositeAuthenticationSuccessHandler 实例 |  | ||||||
|          */ |  | ||||||
|         @Bean(name = ["authenticationSuccessHandler"]) |  | ||||||
|         fun authenticationSuccessHandler( |  | ||||||
|             resolver: CompositeLoginRequestResolver, |  | ||||||
|             context: AuthenticationSuccessHandlerContext, |  | ||||||
|         ): AuthenticationSuccessHandler = CompositeAuthenticationSuccessHandler(resolver, context) |  | ||||||
| 
 |  | ||||||
|         /** |  | ||||||
|          * 创建并返回一个认证失败处理的上下文。 |  | ||||||
|          * |  | ||||||
|          * 根据当前请求上下文动态选择合适的认证失败策略。 |  | ||||||
|          * |  | ||||||
|          * @param strategies 所有可用的 AuthenticationFailureStrategy 实例列表 |  | ||||||
|          * @return 初始化好的 AuthenticationFailureHandlerContext 实例 |  | ||||||
|          */ |  | ||||||
|         @Bean |  | ||||||
|         fun authenticationFailureHandlerContext( |  | ||||||
|             strategies: List<AuthenticationFailureStrategy>, |  | ||||||
|         ) = AuthenticationFailureHandlerContext(strategies) |  | ||||||
| 
 |  | ||||||
|         /** |  | ||||||
|          * 创建并返回一个组合式的认证失败处理器。 |  | ||||||
|          * |  | ||||||
|          * 委托给具体的策略实现来进行响应。 |  | ||||||
|          * |  | ||||||
|          * @param resolver 登录请求解析器 |  | ||||||
|          * @param context 认证失败处理上下文 |  | ||||||
|          * @return 初始化好的 CompositeAuthenticationFailureHandler 实例 |  | ||||||
|          */ |  | ||||||
|         @Bean(name = ["authenticationFailureHandler"]) |  | ||||||
|         fun authenticationFailureHandler( |  | ||||||
|             resolver: CompositeLoginRequestResolver, |  | ||||||
|             context: AuthenticationFailureHandlerContext, |  | ||||||
|         ): AuthenticationFailureHandler = CompositeAuthenticationFailureHandler(resolver, context) |  | ||||||
| 
 |  | ||||||
|         /** |  | ||||||
|          * 创建并返回一个登录请求转换上下文。 |  | ||||||
|          * |  | ||||||
|          * 用于根据当前请求上下文动态选择合适的登录请求转换逻辑。 |  | ||||||
|          * |  | ||||||
|          * @param applicationContext Spring 应用上下文 |  | ||||||
|          * @return 初始化好的 LoginRequestConverterContext 实例 |  | ||||||
|          */ |  | ||||||
|         @Bean |  | ||||||
|         fun loginRequestConverterContext( |  | ||||||
|             applicationContext: ApplicationContext, |  | ||||||
|         ) = LoginRequestConverterContext(applicationContext) |  | ||||||
| 
 |  | ||||||
|         /** |  | ||||||
|          * 创建并返回一个统一的身份验证过滤器。 |  | ||||||
|          * |  | ||||||
|          * 该过滤器是整个认证流程的核心,处理登录请求并触发相应的成功/失败处理器。 |  | ||||||
|          * |  | ||||||
|          * @param properties 安全认证属性配置 |  | ||||||
|          * @param authenticationManager 认证管理器 |  | ||||||
|          * @param authenticationSuccessHandler 成功认证处理器 |  | ||||||
|          * @param authenticationFailureHandler 失败认证处理器 |  | ||||||
|          * @param compositeLoginRequestResolver 组合登录请求解析器 |  | ||||||
|          * @param loginRequestConverterContext 登录请求转换上下文 |  | ||||||
|          * @return 初始化好的 UnifiedAuthenticationFilter 实例 |  | ||||||
|          */ |  | ||||||
|         @Bean |  | ||||||
|         fun unifiedAuthenticationFilter( |  | ||||||
|             properties: SecurityAuthenticateProperties, |  | ||||||
|             authenticationManager: AuthenticationManager, |  | ||||||
|             authenticationSuccessHandler: AuthenticationSuccessHandler, |  | ||||||
|             authenticationFailureHandler: AuthenticationFailureHandler, |  | ||||||
|             compositeLoginRequestResolver: CompositeLoginRequestResolver, |  | ||||||
|             loginRequestConverterContext: LoginRequestConverterContext, |  | ||||||
|         ): UnifiedAuthenticationFilter = |  | ||||||
|             UnifiedAuthenticationFilter( |  | ||||||
|                 AntPathRequestMatcher( |  | ||||||
|                     properties.baseUrl + properties.loginUrl, |  | ||||||
|                     properties.loginHttpMethod |  | ||||||
|                 ), |  | ||||||
|                 authenticationManager, |  | ||||||
|                 authenticationSuccessHandler, |  | ||||||
|                 authenticationFailureHandler, |  | ||||||
|                 compositeLoginRequestResolver, |  | ||||||
|                 loginRequestConverterContext |  | ||||||
|             ) |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     @Configuration(proxyBeanMethods = false) |  | ||||||
|     @ComponentScan( |  | ||||||
|         basePackages = [ |  | ||||||
|             "com.gewuyou.forgeboot.security.authenticate.impl.strategy.impl", |  | ||||||
|             "com.gewuyou.forgeboot.security.authenticate.impl.provider.impl", |  | ||||||
|         ] |  | ||||||
|     ) |  | ||||||
|     class ForgeBootDefaultSecurityAuthenticateAutoConfiguration |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * 用于支持登录过滤器扩展器排序 |  | ||||||
|  * |  | ||||||
|  * 通过 order 属性为 LoginFilterCustomizer 提供排序能力,确保其按预期顺序执行。 |  | ||||||
|  */ |  | ||||||
| interface OrderedLoginFilterCustomizer : LoginFilterCustomizer { |  | ||||||
|     val order: Int |  | ||||||
| } |  | ||||||
| @ -1 +0,0 @@ | |||||||
| com.gewuyou.forgeboot.security.authenticate.autoconfigure.SecurityAuthenticateAutoConfiguration |  | ||||||
| @ -1,6 +0,0 @@ | |||||||
| extra{ |  | ||||||
|     setProperty(ProjectFlags.IS_ROOT_MODULE,true) |  | ||||||
| } |  | ||||||
| dependencies { |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
| @ -1,3 +0,0 @@ | |||||||
| /gradlew text eol=lf |  | ||||||
| *.bat text eol=crlf |  | ||||||
| *.jar binary |  | ||||||
| @ -1,40 +0,0 @@ | |||||||
| 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 |  | ||||||
| @ -1,11 +0,0 @@ | |||||||
| plugins{ |  | ||||||
|     alias(libs.plugins.kotlin.plugin.spring) |  | ||||||
| } |  | ||||||
| dependencies { |  | ||||||
|     api(project(Modules.Security.Authenticate.API)) |  | ||||||
|     implementation(project(Modules.Security.CORE)) |  | ||||||
|     implementation(project(Modules.Core.EXTENSION)) |  | ||||||
|     implementation(project(Modules.Webmvc.DTO)) |  | ||||||
|     compileOnly(libs.springBootStarter.web) |  | ||||||
|     compileOnly(libs.springBootStarter.security) |  | ||||||
| } |  | ||||||
| @ -1,49 +0,0 @@ | |||||||
| package com.gewuyou.forgeboot.security.authenticate.impl.constants |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * Forge Boot安全身份验证响应信息 |  | ||||||
|  * |  | ||||||
|  * 该对象包含用于身份验证过程中的各种预定义错误响应消息。 |  | ||||||
|  * 每个属性代表一种特定的身份验证失败或系统错误情况,供在认证流程中抛出或返回给调用者。 |  | ||||||
|  * |  | ||||||
|  * @since 2025-06-11 17:05:09 |  | ||||||
|  * @author gewuyou |  | ||||||
|  */ |  | ||||||
| object ForgeBootSecurityAuthenticationResponseInformation { |  | ||||||
|     const val INCORRECT_USERNAME_OR_PASSWORD: String = "the username or password is incorrect" |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 当用户未提供密码时使用的响应消息。 |  | ||||||
|      */ |  | ||||||
|     const val PASSWORD_NOT_PROVIDED: String = "the password cannot be empty" |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 当用户的凭证已过期时使用的响应消息。 |  | ||||||
|      */ |  | ||||||
|     const val ACCOUNT_CREDENTIALS_HAVE_EXPIRED: String = "the account credentials have expired" |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 当用户账户被禁用时使用的响应消息。 |  | ||||||
|      */ |  | ||||||
|     const val ACCOUNT_IS_DISABLED: String = "the account is disabled" |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 当用户账户被锁定时使用的响应消息。 |  | ||||||
|      */ |  | ||||||
|     const val ACCOUNT_IS_LOCKED: String = "the account is locked" |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 当发生内部服务器错误时使用的通用错误响应消息。 |  | ||||||
|      */ |  | ||||||
|     const val INTERNAL_SERVER_ERROR: String = "internal server error occurred" |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 当认证主体(principal)未提供时使用的常量字符串。 |  | ||||||
|      * 这通常意味着认证请求缺少必要的身份标识信息。 |  | ||||||
|      */ |  | ||||||
|     const val PRINCIPAL_NOT_PROVIDED = "the authentication principal cannot be empty" |  | ||||||
| 
 |  | ||||||
|     const val LOGIN_SUCCESS: String = "login success" |  | ||||||
| 
 |  | ||||||
|     const val LOGOUT_SUCCESS: String = "logout success" |  | ||||||
| } |  | ||||||
| @ -1,69 +0,0 @@ | |||||||
| package com.gewuyou.forgeboot.security.authenticate.impl.filter |  | ||||||
| 
 |  | ||||||
| import com.gewuyou.forgeboot.security.authenticate.impl.resolver.CompositeLoginRequestResolver |  | ||||||
| import com.gewuyou.forgeboot.security.authenticate.impl.strategy.context.LoginRequestConverterContext |  | ||||||
| import jakarta.servlet.http.HttpServletRequest |  | ||||||
| import jakarta.servlet.http.HttpServletResponse |  | ||||||
| import org.springframework.security.authentication.AuthenticationManager |  | ||||||
| import org.springframework.security.core.Authentication |  | ||||||
| import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter |  | ||||||
| import org.springframework.security.web.authentication.AuthenticationFailureHandler |  | ||||||
| import org.springframework.security.web.authentication.AuthenticationSuccessHandler |  | ||||||
| import org.springframework.security.web.util.matcher.AntPathRequestMatcher |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * 统一的身份验证过滤器 |  | ||||||
|  * |  | ||||||
|  * 该类实现了身份验证流程的核心逻辑,通过组合不同的解析策略和转换上下文, |  | ||||||
|  * 来支持多种登录请求的处理方式。 |  | ||||||
|  * |  | ||||||
|  * @param pathRequestMatcher 请求路径匹配器,用于判断当前请求是否需要处理 |  | ||||||
|  * @param authenticationManager 身份验证管理器,用于执行实际的身份验证操作 |  | ||||||
|  * @param authenticationSuccessHandler 认证成功处理器,用于处理认证成功后的响应 |  | ||||||
|  * @param authenticationFailureHandler 认证失败处理器,用于处理认证失败后的响应 |  | ||||||
|  * @param compositeLoginRequestResolver 组合登录请求解析器,用于解析不同类型的登录请求 |  | ||||||
|  * @param loginRequestConverterContext 登录请求转换上下文,用于选择合适地转换策略 |  | ||||||
|  * |  | ||||||
|  * @since 2025-06-10 20:28:08 |  | ||||||
|  * @author gewuyou |  | ||||||
|  */ |  | ||||||
| class UnifiedAuthenticationFilter( |  | ||||||
|     pathRequestMatcher: AntPathRequestMatcher, |  | ||||||
|     authenticationManager: AuthenticationManager, |  | ||||||
|     authenticationSuccessHandler: AuthenticationSuccessHandler, |  | ||||||
|     authenticationFailureHandler: AuthenticationFailureHandler, |  | ||||||
|     private val compositeLoginRequestResolver: CompositeLoginRequestResolver, |  | ||||||
|     private val loginRequestConverterContext: LoginRequestConverterContext, |  | ||||||
| ) : AbstractAuthenticationProcessingFilter(pathRequestMatcher) { |  | ||||||
| 
 |  | ||||||
|     init { |  | ||||||
|         // 初始化身份验证管理器、成功处理器和失败处理器 |  | ||||||
|         setAuthenticationManager(authenticationManager) |  | ||||||
|         setAuthenticationSuccessHandler(authenticationSuccessHandler) |  | ||||||
|         setAuthenticationFailureHandler(authenticationFailureHandler) |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 尝试进行身份验证 |  | ||||||
|      * |  | ||||||
|      * 此方法负责从请求中提取登录信息,并使用组合解析器和转换上下文来构建认证请求。 |  | ||||||
|      * 最终调用身份验证管理器执行认证操作。 |  | ||||||
|      * |  | ||||||
|      * @param request HTTP请求对象 |  | ||||||
|      * @param response HTTP响应对象 |  | ||||||
|      * @return 返回经过认证的Authentication对象 |  | ||||||
|      */ |  | ||||||
|     override fun attemptAuthentication( |  | ||||||
|         request: HttpServletRequest, |  | ||||||
|         response: HttpServletResponse, |  | ||||||
|     ): Authentication { |  | ||||||
|         // 尝试认证:通过组合解析器解析请求内容,再根据转换上下文选择合适的策略进行认证 |  | ||||||
|         return authenticationManager.authenticate( |  | ||||||
|             // 通过上下文执行转换策略 |  | ||||||
|             loginRequestConverterContext.executeStrategy( |  | ||||||
|                 // 使用组合解析器解析HTTP请求 |  | ||||||
|                 compositeLoginRequestResolver.resolve(request) |  | ||||||
|             ) |  | ||||||
|         ) |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @ -1,37 +0,0 @@ | |||||||
| package com.gewuyou.forgeboot.security.authenticate.impl.handler |  | ||||||
| 
 |  | ||||||
| import com.gewuyou.forgeboot.security.authenticate.api.handler.DelegatingHandler |  | ||||||
| import com.gewuyou.forgeboot.security.authenticate.impl.resolver.CompositeLoginRequestResolver |  | ||||||
| import jakarta.servlet.http.HttpServletRequest |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * 抽象委派处理程序 |  | ||||||
|  * |  | ||||||
|  * 该类为泛型抽象类,用于实现委派处理逻辑,通过解析请求获取登录类型,并使用上下文解析器获取对应的处理上下文。 |  | ||||||
|  * |  | ||||||
|  * @param resolver 用于解析请求并获取登录类型的组件,不可为空 |  | ||||||
|  * @param contextResolver 根据登录类型生成对应上下文对象的函数式接口,不可为空 |  | ||||||
|  * |  | ||||||
|  * @since 2025-06-11 14:53:46 |  | ||||||
|  * @author gewuyou |  | ||||||
|  */ |  | ||||||
| abstract class AbstractDelegatingHandler<T : Any>( |  | ||||||
|     private val resolver: CompositeLoginRequestResolver, |  | ||||||
|     private val contextResolver: (String) -> T, |  | ||||||
| ): DelegatingHandler<T> { |  | ||||||
|     /** |  | ||||||
|      * 解析请求并获取对应的处理上下文 |  | ||||||
|      * |  | ||||||
|      * 该方法会调用注入的 [resolver] 来解析传入的 HTTP 请求,获取当前请求的登录类型, |  | ||||||
|      * 然后通过 [contextResolver] 函数将登录类型转换为具体地处理上下文对象。 |  | ||||||
|      * |  | ||||||
|      * @param request HTTP 请求对象,用于解析登录类型 |  | ||||||
|      * @return 返回与登录类型对应的处理上下文对象 |  | ||||||
|      */ |  | ||||||
|     override fun resolveDelegate(request: HttpServletRequest): T { |  | ||||||
|         // 解析请求获取登录类型 |  | ||||||
|         val loginType = resolver.resolve(request).getType() |  | ||||||
|         // 使用上下文解析器生成对应类型的处理上下文 |  | ||||||
|         return contextResolver(loginType) |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @ -1,37 +0,0 @@ | |||||||
| package com.gewuyou.forgeboot.security.authenticate.impl.handler |  | ||||||
| 
 |  | ||||||
| import com.fasterxml.jackson.databind.ObjectMapper |  | ||||||
| import com.gewuyou.forgeboot.core.extension.log |  | ||||||
| import com.gewuyou.forgeboot.security.authenticate.api.config.SecurityAuthenticateProperties |  | ||||||
| import com.gewuyou.forgeboot.webmvc.dto.R |  | ||||||
| import jakarta.servlet.http.HttpServletRequest |  | ||||||
| import jakarta.servlet.http.HttpServletResponse |  | ||||||
| import org.springframework.http.HttpStatus |  | ||||||
| import org.springframework.http.MediaType |  | ||||||
| import org.springframework.security.core.AuthenticationException |  | ||||||
| import org.springframework.security.web.AuthenticationEntryPoint |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  *身份验证异常处理程序 |  | ||||||
|  * |  | ||||||
|  * @since 2025-01-03 14:50:46 |  | ||||||
|  * @author gewuyou |  | ||||||
|  */ |  | ||||||
| class AuthenticationExceptionHandler( |  | ||||||
|     private val objectMapper: ObjectMapper, |  | ||||||
|     private val securityAuthenticateProperties: SecurityAuthenticateProperties |  | ||||||
| ) : AuthenticationEntryPoint { |  | ||||||
|     override fun commence( |  | ||||||
|         request: HttpServletRequest, |  | ||||||
|         response: HttpServletResponse, |  | ||||||
|         authException: AuthenticationException |  | ||||||
|     ) { |  | ||||||
|         log.error("身份验证异常: ", authException) |  | ||||||
|         response.status = HttpStatus.OK.value() |  | ||||||
|         response.contentType = MediaType.APPLICATION_JSON_VALUE |  | ||||||
|         val writer = response.writer |  | ||||||
|         writer.print(objectMapper.writeValueAsString(R.failure<String>(HttpStatus.UNAUTHORIZED.value(),  authException.message?:securityAuthenticateProperties.defaultExceptionResponse))) |  | ||||||
|         writer.flush() |  | ||||||
|         writer.close() |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @ -1,43 +0,0 @@ | |||||||
| package com.gewuyou.forgeboot.security.authenticate.impl.handler |  | ||||||
| 
 |  | ||||||
| import com.gewuyou.forgeboot.security.authenticate.impl.resolver.CompositeLoginRequestResolver |  | ||||||
| import com.gewuyou.forgeboot.security.authenticate.impl.strategy.context.AuthenticationFailureHandlerContext |  | ||||||
| import jakarta.servlet.http.HttpServletRequest |  | ||||||
| import jakarta.servlet.http.HttpServletResponse |  | ||||||
| import org.springframework.security.web.authentication.AuthenticationFailureHandler |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * 组合身份验证故障处理程序 |  | ||||||
|  * |  | ||||||
|  * 该类通过组合不同的身份验证失败处理器来处理认证失败场景,利用解析器和上下文策略来动态选择实际的处理器。 |  | ||||||
|  * |  | ||||||
|  * @property resolver 用于解析请求并确定适用的身份验证失败处理器的组件 |  | ||||||
|  * @property context 提供身份验证失败处理策略的上下文对象 |  | ||||||
|  * |  | ||||||
|  * @since 2025-06-11 00:11:52 |  | ||||||
|  * @author gewuyou |  | ||||||
|  */ |  | ||||||
| class CompositeAuthenticationFailureHandler( |  | ||||||
|     private val resolver: CompositeLoginRequestResolver, |  | ||||||
|     private val context: AuthenticationFailureHandlerContext, |  | ||||||
| ) : AbstractDelegatingHandler<AuthenticationFailureHandler>( |  | ||||||
|     resolver, context::resolve |  | ||||||
| ), AuthenticationFailureHandler { |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 在身份验证失败时调用的方法 |  | ||||||
|      * |  | ||||||
|      * 此方法会解析出适用于当前请求的具体身份验证失败处理器,并委托其进行失败处理。 |  | ||||||
|      * |  | ||||||
|      * @param request 来自客户端的 HTTP 请求 |  | ||||||
|      * @param response 发送回客户端的 HTTP 响应 |  | ||||||
|      * @param exception 身份验证过程中抛出的异常信息 |  | ||||||
|      */ |  | ||||||
|     override fun onAuthenticationFailure( |  | ||||||
|         request: HttpServletRequest, |  | ||||||
|         response: HttpServletResponse, |  | ||||||
|         exception: org.springframework.security.core.AuthenticationException, |  | ||||||
|     ) { |  | ||||||
|         resolveDelegate(request).onAuthenticationFailure(request, response, exception) |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @ -1,45 +0,0 @@ | |||||||
| package com.gewuyou.forgeboot.security.authenticate.impl.handler |  | ||||||
| 
 |  | ||||||
| import com.gewuyou.forgeboot.security.authenticate.impl.resolver.CompositeLoginRequestResolver |  | ||||||
| import com.gewuyou.forgeboot.security.authenticate.impl.strategy.context.AuthenticationSuccessHandlerContext |  | ||||||
| import jakarta.servlet.http.HttpServletRequest |  | ||||||
| import jakarta.servlet.http.HttpServletResponse |  | ||||||
| import org.springframework.security.core.Authentication |  | ||||||
| import org.springframework.security.web.authentication.AuthenticationSuccessHandler |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * 统一身份验证成功处理程序 |  | ||||||
|  * |  | ||||||
|  * 该类实现了 [AuthenticationSuccessHandler] 接口,用于在身份验证成功后执行相应的处理逻辑。 |  | ||||||
|  * 它通过组合多个具体的处理器来实现灵活的身份验证成功响应策略。 |  | ||||||
|  * |  | ||||||
|  * @property resolver 用于解析登录请求并确定使用哪个具体的成功处理器 |  | ||||||
|  * @property context 提供处理上下文信息,用于解析和执行成功处理逻辑 |  | ||||||
|  * |  | ||||||
|  * @since 2025-06-10 23:48:32 |  | ||||||
|  * @author gewuyou |  | ||||||
|  */ |  | ||||||
| class CompositeAuthenticationSuccessHandler( |  | ||||||
|     private val resolver: CompositeLoginRequestResolver, |  | ||||||
|     private val context: AuthenticationSuccessHandlerContext, |  | ||||||
| ) : AbstractDelegatingHandler<AuthenticationSuccessHandler>( |  | ||||||
|     resolver, context::resolve |  | ||||||
| ), AuthenticationSuccessHandler { |  | ||||||
|     /** |  | ||||||
|      * 身份验证成功时的回调方法 |  | ||||||
|      * |  | ||||||
|      * 此方法会在用户成功通过身份验证后被调用。它使用 [resolveDelegate] 方法根据当前请求解析出 |  | ||||||
|      * 合适的具体处理器,并委托给该处理器执行后续操作。 |  | ||||||
|      * |  | ||||||
|      * @param request HTTP 请求对象,提供客户端的请求信息 |  | ||||||
|      * @param response HTTP 响应对象,用于向客户端发送响应 |  | ||||||
|      * @param authentication 包含身份验证成功的用户信息和权限等数据的对象 |  | ||||||
|      */ |  | ||||||
|     override fun onAuthenticationSuccess( |  | ||||||
|         request: HttpServletRequest, |  | ||||||
|         response: HttpServletResponse, |  | ||||||
|         authentication: Authentication, |  | ||||||
|     ) { |  | ||||||
|         resolveDelegate(request).onAuthenticationSuccess(request, response, authentication) |  | ||||||
|     } |  | ||||||
| } |  | ||||||
Some files were not shown because too many files have changed in this diff Show More
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user