feat(framework): OssPresignResponseBodyAdvice 支持 List<String> 字段预签名
- @OssPresignUrl 注解现在同时适用于 String 和 List<String> 字段 - 回填时防御不可变 List,自动降级为 ArrayList - FileServiceImpl 预签名访问 URL 去除查询参数,保持持久化路径干净 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -130,8 +130,21 @@ public class OssPresignResponseBodyAdvice implements ResponseBodyAdvice<Object>
|
||||
String signed = signedMap.get(entry.url);
|
||||
if (signed != null) {
|
||||
try {
|
||||
entry.field.set(entry.target, signed);
|
||||
} catch (IllegalAccessException e) {
|
||||
if (entry.isList()) {
|
||||
@SuppressWarnings("unchecked")
|
||||
List<String> list = (List<String>) entry.field.get(entry.target);
|
||||
try {
|
||||
list.set(entry.index(), signed);
|
||||
} catch (UnsupportedOperationException ex) {
|
||||
// 不可变 List(如 List.of()),替换为可变 ArrayList 后重试
|
||||
List<String> mutable = new ArrayList<>(list);
|
||||
mutable.set(entry.index(), signed);
|
||||
entry.field.set(entry.target, mutable);
|
||||
}
|
||||
} else {
|
||||
entry.field.set(entry.target, signed);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.warn("[OssPresignResponseBodyAdvice] 回填签名 URL 失败: field={}", entry.field.getName(), e);
|
||||
}
|
||||
}
|
||||
@@ -195,6 +208,15 @@ public class OssPresignResponseBodyAdvice implements ResponseBodyAdvice<Object>
|
||||
if (value instanceof String url && StrUtil.isNotEmpty(url)) {
|
||||
entries.add(new FieldEntry(obj, field, url));
|
||||
}
|
||||
// 带注解的 List<String> 字段:逐个收集 URL
|
||||
if (value instanceof List<?> list) {
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
Object item = list.get(i);
|
||||
if (item instanceof String url && StrUtil.isNotEmpty(url)) {
|
||||
entries.add(new FieldEntry(obj, field, i, url));
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// 非简单类型字段:递归(递归入口会再次判断 isProjectClass)
|
||||
collectUrls(value, entries, visited, depth + 1);
|
||||
@@ -221,7 +243,8 @@ public class OssPresignResponseBodyAdvice implements ResponseBodyAdvice<Object>
|
||||
return FIELD_CACHE.computeIfAbsent(clazz, c -> {
|
||||
Set<Field> result = new HashSet<>();
|
||||
for (Field field : getAllFields(c)) {
|
||||
if (field.isAnnotationPresent(OssPresignUrl.class) && field.getType() == String.class) {
|
||||
if (field.isAnnotationPresent(OssPresignUrl.class)
|
||||
&& (field.getType() == String.class || List.class.isAssignableFrom(field.getType()))) {
|
||||
result.add(field);
|
||||
}
|
||||
}
|
||||
@@ -340,6 +363,16 @@ public class OssPresignResponseBodyAdvice implements ResponseBodyAdvice<Object>
|
||||
}
|
||||
}
|
||||
|
||||
private record FieldEntry(Object target, Field field, String url) {}
|
||||
private record FieldEntry(Object target, Field field, int index, String url) {
|
||||
|
||||
/** String 字段构造 */
|
||||
FieldEntry(Object target, Field field, String url) {
|
||||
this(target, field, -1, url);
|
||||
}
|
||||
|
||||
boolean isList() {
|
||||
return index >= 0;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -134,7 +134,7 @@ public class FileServiceImpl implements FileService {
|
||||
// 2. 获取文件预签名地址
|
||||
FileClient fileClient = fileConfigService.getMasterFileClient();
|
||||
String uploadUrl = fileClient.presignPutUrl(path);
|
||||
String visitUrl = fileClient.presignGetUrl(path, null);
|
||||
String visitUrl = HttpUtils.removeUrlQuery(fileClient.presignGetUrl(path, null));
|
||||
return new FilePresignedUrlRespVO().setConfigId(fileClient.getId())
|
||||
.setPath(path).setUploadUrl(uploadUrl).setUrl(visitUrl);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user