Skip to content

Commit e5002b8

Browse files
Time-wCharles7c
authored andcommitted
refactor(storage): 优化存储模块
Co-authored-by: QAQ_Z<[email protected]> # message auto-generated for no-merge-commit merge: merge storage into dev 优化存储模块 Created-by: QAQ_Z Commit-by: QAQ_Z Merged-by: Charles_7c Description: <!-- 非常感谢您的 PR!在提交之前,请务必确保您 PR 的代码经过了完整测试,并且通过了代码规范检查。 --> <!-- 在 [] 中输入 x 来勾选) --> ## PR 类型 <!-- 您的 PR 引入了哪种类型的变更? --> <!-- 只支持选择一种类型,如果有多种类型,可以在更新日志中增加 “类型” 列。 --> - [ ] 新 feature - [ ] Bug 修复 - [x] 功能增强 - [ ] 文档变更 - [ ] 代码样式变更 - [x] 重构 - [ ] 性能改进 - [ ] 单元测试 - [ ] CI/CD - [ ] 其他 ## PR 目的 <!-- 描述一下您的 PR 解决了什么问题。如果可以,请链接到相关 issues。 --> - 重新设计了文件上传的预处理和后处理流程 - 优化了文件验证、命名、路径生成等环节 - 增加了单文件上传监听逻辑 - 增加了装饰器模式,支持重写指定存储策略实现的具体方法 ## 解决方案 <!-- 详细描述您是如何解决的问题 --> ## PR 测试 <!-- 如果可以,请为您的 PR 添加或更新单元测试。 --> <!-- 请描述一下您是如何测试 PR 的。例如:创建/更新单元测试或添加相关的截图。 --> ## Changelog | 模块 | Changelog | Related issues | |-----|-----------| -------------- | | continew-starter-storage | 优化存储模块 | | <!-- 如果有多种类型的变更,可以在变更日志表中增加 “类型” 列,该列的值与上方 “PR 类型” 相同。 --> <!-- Related issues 格式为 Closes #<issue号>,或者 Fixes #<issue号>,或者 Resolves #<issue号>。 --> ## 其他信息 <!-- 请描述一下还有哪些注意事项。例如:如果引入了一个不向下兼容的变更,请描述其影响。 --> ## 提交前确认 - [x] PR 代码经过了完整测试,并且通过了代码规范检查 - [ ] 已经完整填写 Changelog,并链接到了相关 issues - [x] PR 代码将要提交到 dev 分支 See merge request: continew/continew-starter!4
1 parent 5ca34ee commit e5002b8

File tree

51 files changed

+2060
-1188
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+2060
-1188
lines changed
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/*
2+
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
3+
* <p>
4+
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
* <p>
8+
* http://www.gnu.org/licenses/lgpl.html
9+
* <p>
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package top.continew.starter.storage.annotation;
18+
19+
import java.lang.annotation.*;
20+
21+
/**
22+
* 平台处理器注解
23+
* <p>
24+
* 该注解用于标记文件前置处理器类,以指定其适用的平台范围。
25+
* 主要用于实现平台特定的文件处理逻辑,如文件名生成、路径转换、格式适配等。
26+
* <p>
27+
*
28+
* @author echo
29+
* @since 2.14.0
30+
*/
31+
@Target(ElementType.TYPE)
32+
@Retention(RetentionPolicy.RUNTIME)
33+
@Documented
34+
public @interface PlatformProcessor {
35+
/**
36+
* 适用的平台列表
37+
*/
38+
String[] platforms();
39+
}

continew-starter-storage/src/main/java/top/continew/starter/storage/autoconfigure/LocalStorageAutoConfiguration.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
import top.continew.starter.core.constant.PropertiesConstants;
2222
import top.continew.starter.storage.autoconfigure.properties.LocalStorageConfig;
2323
import top.continew.starter.storage.autoconfigure.properties.StorageProperties;
24-
import top.continew.starter.storage.router.StorageStrategyRegistrar;
24+
import top.continew.starter.storage.engine.StorageStrategyRegistrar;
2525
import top.continew.starter.storage.strategy.StorageStrategy;
2626
import top.continew.starter.storage.strategy.impl.LocalStorageStrategy;
2727

@@ -43,7 +43,7 @@ public LocalStorageAutoConfiguration(StorageProperties storageProperties) {
4343
}
4444

4545
/**
46-
* 注册配置策略
46+
* 注册本地存储策略
4747
*
4848
* @param strategies 策略列表
4949
*/
Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,9 @@
1919
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
2020
import org.springframework.context.annotation.Bean;
2121
import top.continew.starter.core.constant.PropertiesConstants;
22-
import top.continew.starter.storage.autoconfigure.properties.S3StorageConfig;
22+
import top.continew.starter.storage.autoconfigure.properties.OssStorageConfig;
2323
import top.continew.starter.storage.autoconfigure.properties.StorageProperties;
24-
import top.continew.starter.storage.router.StorageStrategyRegistrar;
24+
import top.continew.starter.storage.engine.StorageStrategyRegistrar;
2525
import top.continew.starter.storage.strategy.StorageStrategy;
2626
import top.continew.starter.storage.strategy.impl.OssStorageStrategy;
2727

@@ -33,24 +33,24 @@
3333
* @author echo
3434
* @since 2.14.0
3535
*/
36-
@ConditionalOnProperty(prefix = PropertiesConstants.STORAGE, name = "s3")
37-
public class S3StorageAutoConfiguration implements StorageStrategyRegistrar {
36+
@ConditionalOnProperty(prefix = PropertiesConstants.STORAGE, name = "oss")
37+
public class OssStorageAutoConfiguration implements StorageStrategyRegistrar {
3838

3939
private final StorageProperties properties;
4040

41-
public S3StorageAutoConfiguration(StorageProperties properties) {
41+
public OssStorageAutoConfiguration(StorageProperties properties) {
4242
this.properties = properties;
4343
}
4444

4545
/**
46-
* 注册配置策略
46+
* 注册 OSS 存储策略
4747
*
4848
* @param strategies 策略列表
4949
*/
5050
@Override
5151
@Bean
5252
public void register(List<StorageStrategy> strategies) {
53-
for (S3StorageConfig config : properties.getS3()) {
53+
for (OssStorageConfig config : properties.getOss()) {
5454
if (config.isEnabled()) {
5555
strategies.add(new OssStorageStrategy(config));
5656
}

continew-starter-storage/src/main/java/top/continew/starter/storage/autoconfigure/StorageAutoConfiguration.java

Lines changed: 69 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -19,29 +19,29 @@
1919
import jakarta.annotation.PostConstruct;
2020
import org.slf4j.Logger;
2121
import org.slf4j.LoggerFactory;
22-
import org.springframework.beans.factory.annotation.Autowired;
2322
import org.springframework.boot.autoconfigure.AutoConfiguration;
24-
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
2523
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
2624
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
2725
import org.springframework.boot.autoconfigure.web.servlet.MultipartProperties;
2826
import org.springframework.boot.context.properties.EnableConfigurationProperties;
27+
import org.springframework.context.ApplicationContext;
2928
import org.springframework.context.annotation.Bean;
30-
import org.springframework.context.annotation.Configuration;
3129
import org.springframework.context.annotation.Import;
30+
import top.continew.starter.storage.annotation.PlatformProcessor;
3231
import top.continew.starter.storage.autoconfigure.properties.StorageProperties;
3332
import top.continew.starter.storage.core.FileStorageService;
34-
import top.continew.starter.storage.core.ProcessorRegistry;
35-
import top.continew.starter.storage.core.StrategyProxyFactory;
36-
import top.continew.starter.storage.prehandle.*;
37-
import top.continew.starter.storage.prehandle.impl.*;
38-
import top.continew.starter.storage.router.StorageStrategyRegistrar;
39-
import top.continew.starter.storage.router.StorageStrategyRouter;
33+
import top.continew.starter.storage.engine.StorageDecoratorManager;
34+
import top.continew.starter.storage.processor.registry.ProcessorRegistry;
35+
import top.continew.starter.storage.processor.preprocess.*;
36+
import top.continew.starter.storage.processor.preprocess.impl.*;
37+
import top.continew.starter.storage.engine.StorageStrategyRegistrar;
38+
import top.continew.starter.storage.engine.StorageStrategyRouter;
39+
import top.continew.starter.storage.service.FileProcessor;
4040
import top.continew.starter.storage.service.FileRecorder;
4141
import top.continew.starter.storage.service.impl.DefaultFileRecorder;
42-
import top.continew.starter.storage.strategy.StorageStrategyOverride;
4342

4443
import java.util.List;
44+
import java.util.Map;
4545

4646
/**
4747
* 存储自动配置
@@ -51,15 +51,17 @@
5151
*/
5252
@AutoConfiguration
5353
@EnableConfigurationProperties(StorageProperties.class)
54-
@Import({ProcessorRegistry.class, StrategyProxyFactory.class})
54+
@Import({ProcessorRegistry.class})
5555
public class StorageAutoConfiguration {
5656

5757
private static final Logger log = LoggerFactory.getLogger(StorageAutoConfiguration.class);
5858

5959
private final StorageProperties properties;
60+
private final ApplicationContext applicationContext;
6061

61-
public StorageAutoConfiguration(StorageProperties properties) {
62+
public StorageAutoConfiguration(StorageProperties properties, ApplicationContext applicationContext) {
6263
this.properties = properties;
64+
this.applicationContext = applicationContext;
6365
}
6466

6567
/**
@@ -70,17 +72,27 @@ public StorageAutoConfiguration(StorageProperties properties) {
7072
*/
7173
@Bean
7274
public StorageStrategyRouter strategyRouter(List<StorageStrategyRegistrar> registrars) {
73-
return new StorageStrategyRouter(registrars);
75+
return new StorageStrategyRouter(registrars, properties, storageDecoratorManager());
7476
}
7577

7678
/**
77-
* S3存储自动配置
79+
* 存储装饰器管理器
7880
*
79-
* @return {@link S3StorageAutoConfiguration }
81+
* @return {@link StorageDecoratorManager }
8082
*/
8183
@Bean
82-
public S3StorageAutoConfiguration s3StorageAutoConfiguration() {
83-
return new S3StorageAutoConfiguration(properties);
84+
public StorageDecoratorManager storageDecoratorManager() {
85+
return new StorageDecoratorManager(applicationContext);
86+
}
87+
88+
/**
89+
* oss存储自动配置
90+
*
91+
* @return {@link OssStorageAutoConfiguration }
92+
*/
93+
@Bean
94+
public OssStorageAutoConfiguration ossStorageAutoConfiguration() {
95+
return new OssStorageAutoConfiguration(properties);
8496
}
8597

8698
/**
@@ -99,16 +111,15 @@ public LocalStorageAutoConfiguration localStorageAutoConfiguration() {
99111
* @param router 路由
100112
* @param storageProperties 存储属性
101113
* @param processorRegistry 处理器注册表
102-
* @param proxyFactory 代理工厂
114+
* @param fileRecorder 文件记录器
103115
* @return {@link FileStorageService }
104116
*/
105117
@Bean
106118
public FileStorageService fileStorageService(StorageStrategyRouter router,
107119
StorageProperties storageProperties,
108120
ProcessorRegistry processorRegistry,
109-
StrategyProxyFactory proxyFactory,
110121
FileRecorder fileRecorder) {
111-
return new FileStorageService(router, storageProperties, processorRegistry, proxyFactory, fileRecorder);
122+
return new FileStorageService(router, storageProperties, processorRegistry, fileRecorder);
112123
}
113124

114125
/**
@@ -122,125 +133,74 @@ public FileRecorder fileRecorder() {
122133
return new DefaultFileRecorder();
123134
}
124135

136+
/**
137+
* 处理器注册中心
138+
*/
139+
@Bean
140+
public ProcessorRegistry processorRegistry() {
141+
ProcessorRegistry registry = new ProcessorRegistry();
142+
143+
// 自动发现并注册所有 FileProcessor 实现
144+
Map<String, FileProcessor> processors = applicationContext.getBeansOfType(FileProcessor.class);
145+
processors.values().forEach(processor -> {
146+
// 检查是否有平台注解
147+
PlatformProcessor annotation = processor.getClass().getAnnotation(PlatformProcessor.class);
148+
if (annotation != null) {
149+
for (String platform : annotation.platforms()) {
150+
registry.register(processor, platform);
151+
}
152+
} else {
153+
// 注册为全局处理器
154+
registry.register(processor);
155+
}
156+
});
157+
return registry;
158+
}
159+
125160
/**
126161
* 默认文件名生成器
127-
*
128-
* @param registry 登记处
129-
* @return {@link FileNameGenerator }
130162
*/
131163
@Bean
132-
@ConditionalOnMissingBean(name = "defaultFileNameGenerator")
133-
public FileNameGenerator defaultFileNameGenerator(ProcessorRegistry registry) {
134-
DefaultFileNameGenerator generator = new DefaultFileNameGenerator();
135-
registry.registerGlobalNameGenerator(generator);
136-
return generator;
164+
@ConditionalOnMissingBean(FileNameGenerator.class)
165+
public FileNameGenerator defaultFileNameGenerator() {
166+
return new DefaultFileNameGenerator();
137167
}
138168

139169
/**
140-
* 默认文件路径生成器
141-
*
142-
* @param registry 注册
143-
* @return {@link FilePathGenerator }
170+
* 默认路径生成器
144171
*/
145172
@Bean
146-
@ConditionalOnMissingBean(name = "defaultFilePathGenerator")
147-
public FilePathGenerator defaultFilePathGenerator(ProcessorRegistry registry) {
148-
DefaultFilePathGenerator generator = new DefaultFilePathGenerator();
149-
registry.registerGlobalPathGenerator(generator);
150-
return generator;
173+
@ConditionalOnMissingBean(FilePathGenerator.class)
174+
public FilePathGenerator defaultFilePathGenerator() {
175+
return new DefaultFilePathGenerator();
151176
}
152177

153178
/**
154179
* 默认缩略图处理器
155-
*
156-
* @param registry 注册
157-
* @return {@link ThumbnailProcessor }
158180
*/
159181
@Bean
160-
@ConditionalOnMissingBean(name = "defaultThumbnailProcessor")
182+
@ConditionalOnMissingBean(ThumbnailProcessor.class)
161183
@ConditionalOnClass(name = "net.coobird.thumbnailator.Thumbnails")
162-
public ThumbnailProcessor defaultThumbnailProcessor(ProcessorRegistry registry) {
163-
DefaultThumbnailProcessor processor = new DefaultThumbnailProcessor();
164-
registry.registerGlobalThumbnailProcessor(processor);
165-
return processor;
184+
public ThumbnailProcessor defaultThumbnailProcessor() {
185+
return new DefaultThumbnailProcessor();
166186
}
167187

168188
/**
169189
* 文件大小验证器
170-
*
171-
* @param registry 注册
172-
* @return {@link FileValidator }
173190
*/
174191
@Bean
175192
@ConditionalOnMissingBean(name = "fileSizeValidator")
176-
public FileValidator fileSizeValidator(ProcessorRegistry registry, MultipartProperties multipartProperties) {
177-
FileSizeValidator validator = new FileSizeValidator(multipartProperties);
178-
registry.registerGlobalValidator(validator);
179-
return validator;
193+
public FileValidator fileSizeValidator(MultipartProperties multipartProperties) {
194+
return new FileSizeValidator(multipartProperties);
180195
}
181196

182197
/**
183198
* 文件类型验证器
184-
*
185-
* @param registry 注册
186-
* @return {@link FileValidator }
187199
*/
188200
@Bean
189201
@ConditionalOnMissingBean(name = "fileTypeValidator")
190-
public FileValidator fileTypeValidator(ProcessorRegistry registry) {
191-
FileTypeValidator validator = new FileTypeValidator();
192-
registry.registerGlobalValidator(validator);
193-
return validator;
194-
}
195-
196-
/**
197-
* 策略重写自动注册
198-
*/
199-
@Configuration
200-
@ConditionalOnBean(StorageStrategyOverride.class)
201-
public static class StrategyOverrideConfiguration {
202-
203-
/**
204-
* 注册覆盖
205-
*/
206-
@Autowired
207-
public void registerOverrides(List<StorageStrategyOverride<?>> overrides, StrategyProxyFactory proxyFactory) {
208-
for (StorageStrategyOverride<?> override : overrides) {
209-
proxyFactory.registerOverride(override);
210-
}
211-
}
212-
}
213-
214-
/**
215-
* 处理器自动注册
216-
*/
217-
@Configuration
218-
public static class ProcessorAutoConfiguration {
219-
@Autowired(required = false)
220-
public void registerGlobalProcessors(List<FileNameGenerator> nameGenerators,
221-
List<FilePathGenerator> pathGenerators,
222-
List<ThumbnailProcessor> thumbnailProcessors,
223-
List<FileValidator> validators,
224-
List<UploadCompleteProcessor> completeProcessors,
225-
ProcessorRegistry registry) {
226-
227-
// 注册全局处理器
228-
if (nameGenerators != null) {
229-
nameGenerators.forEach(registry::registerGlobalNameGenerator);
230-
}
231-
if (pathGenerators != null) {
232-
pathGenerators.forEach(registry::registerGlobalPathGenerator);
233-
}
234-
if (thumbnailProcessors != null) {
235-
thumbnailProcessors.forEach(registry::registerGlobalThumbnailProcessor);
236-
}
237-
if (validators != null) {
238-
validators.forEach(registry::registerGlobalValidator);
239-
}
240-
if (completeProcessors != null) {
241-
completeProcessors.forEach(registry::registerGlobalCompleteProcessor);
242-
}
243-
}
202+
public FileValidator fileTypeValidator() {
203+
return new FileTypeValidator();
244204
}
245205

246206
@PostConstruct

0 commit comments

Comments
 (0)