提交 | 用户 | 时间
|
e7c126
|
1 |
package com.iailab.module.infra.service.file; |
H |
2 |
|
|
3 |
import cn.hutool.core.io.resource.ResourceUtil; |
|
4 |
import cn.hutool.core.util.IdUtil; |
|
5 |
import com.iailab.framework.common.pojo.PageResult; |
|
6 |
import com.iailab.framework.common.util.json.JsonUtils; |
|
7 |
import com.iailab.framework.common.util.validation.ValidationUtils; |
|
8 |
import com.iailab.module.infra.controller.admin.file.vo.config.FileConfigPageReqVO; |
|
9 |
import com.iailab.module.infra.controller.admin.file.vo.config.FileConfigSaveReqVO; |
|
10 |
import com.iailab.module.infra.convert.file.FileConfigConvert; |
|
11 |
import com.iailab.module.infra.dal.dataobject.file.FileConfigDO; |
|
12 |
import com.iailab.module.infra.dal.mysql.file.FileConfigMapper; |
|
13 |
import com.iailab.module.infra.framework.file.core.client.FileClient; |
|
14 |
import com.iailab.module.infra.framework.file.core.client.FileClientConfig; |
|
15 |
import com.iailab.module.infra.framework.file.core.client.FileClientFactory; |
|
16 |
import com.iailab.module.infra.framework.file.core.enums.FileStorageEnum; |
|
17 |
import com.google.common.cache.CacheLoader; |
|
18 |
import com.google.common.cache.LoadingCache; |
|
19 |
import lombok.Getter; |
|
20 |
import lombok.extern.slf4j.Slf4j; |
|
21 |
import org.springframework.stereotype.Service; |
|
22 |
import org.springframework.transaction.annotation.Transactional; |
|
23 |
import org.springframework.validation.annotation.Validated; |
|
24 |
|
|
25 |
import javax.annotation.Resource; |
|
26 |
import javax.validation.Validator; |
|
27 |
import java.time.Duration; |
|
28 |
import java.util.Map; |
|
29 |
import java.util.Objects; |
|
30 |
|
|
31 |
import static com.iailab.framework.common.exception.util.ServiceExceptionUtil.exception; |
|
32 |
import static com.iailab.framework.common.util.cache.CacheUtils.buildAsyncReloadingCache; |
|
33 |
import static com.iailab.module.infra.enums.ErrorCodeConstants.FILE_CONFIG_DELETE_FAIL_MASTER; |
|
34 |
import static com.iailab.module.infra.enums.ErrorCodeConstants.FILE_CONFIG_NOT_EXISTS; |
|
35 |
|
|
36 |
/** |
|
37 |
* 文件配置 Service 实现类 |
|
38 |
* |
|
39 |
* @author iailab |
|
40 |
*/ |
|
41 |
@Service |
|
42 |
@Validated |
|
43 |
@Slf4j |
|
44 |
public class FileConfigServiceImpl implements FileConfigService { |
|
45 |
|
|
46 |
private static final Long CACHE_MASTER_ID = 0L; |
|
47 |
|
|
48 |
/** |
|
49 |
* {@link FileClient} 缓存,通过它异步刷新 fileClientFactory |
|
50 |
*/ |
|
51 |
@Getter |
|
52 |
private final LoadingCache<Long, FileClient> clientCache = buildAsyncReloadingCache(Duration.ofSeconds(10L), |
|
53 |
new CacheLoader<Long, FileClient>() { |
|
54 |
|
|
55 |
@Override |
|
56 |
public FileClient load(Long id) { |
|
57 |
FileConfigDO config = Objects.equals(CACHE_MASTER_ID, id) ? |
|
58 |
fileConfigMapper.selectByMaster() : fileConfigMapper.selectById(id); |
|
59 |
if (config != null) { |
|
60 |
fileClientFactory.createOrUpdateFileClient(config.getId(), config.getStorage(), config.getConfig()); |
|
61 |
} |
|
62 |
return fileClientFactory.getFileClient(null == config ? id : config.getId()); |
|
63 |
} |
|
64 |
|
|
65 |
}); |
|
66 |
|
|
67 |
@Resource |
|
68 |
private FileClientFactory fileClientFactory; |
|
69 |
|
|
70 |
@Resource |
|
71 |
private FileConfigMapper fileConfigMapper; |
|
72 |
|
|
73 |
@Resource |
|
74 |
private Validator validator; |
|
75 |
|
|
76 |
@Override |
|
77 |
public Long createFileConfig(FileConfigSaveReqVO createReqVO) { |
|
78 |
FileConfigDO fileConfig = FileConfigConvert.INSTANCE.convert(createReqVO) |
|
79 |
.setConfig(parseClientConfig(createReqVO.getStorage(), createReqVO.getConfig())) |
|
80 |
.setMaster(false); // 默认非 master |
|
81 |
fileConfigMapper.insert(fileConfig); |
|
82 |
return fileConfig.getId(); |
|
83 |
} |
|
84 |
|
|
85 |
@Override |
|
86 |
public void updateFileConfig(FileConfigSaveReqVO updateReqVO) { |
|
87 |
// 校验存在 |
|
88 |
FileConfigDO config = validateFileConfigExists(updateReqVO.getId()); |
|
89 |
// 更新 |
|
90 |
FileConfigDO updateObj = FileConfigConvert.INSTANCE.convert(updateReqVO) |
|
91 |
.setConfig(parseClientConfig(config.getStorage(), updateReqVO.getConfig())); |
|
92 |
fileConfigMapper.updateById(updateObj); |
|
93 |
|
|
94 |
// 清空缓存 |
|
95 |
clearCache(config.getId(), null); |
|
96 |
} |
|
97 |
|
|
98 |
@Override |
|
99 |
@Transactional(rollbackFor = Exception.class) |
|
100 |
public void updateFileConfigMaster(Long id) { |
|
101 |
// 校验存在 |
|
102 |
validateFileConfigExists(id); |
|
103 |
// 更新其它为非 master |
|
104 |
fileConfigMapper.updateBatch(new FileConfigDO().setMaster(false)); |
|
105 |
// 更新 |
|
106 |
fileConfigMapper.updateById(new FileConfigDO().setId(id).setMaster(true)); |
|
107 |
|
|
108 |
// 清空缓存 |
|
109 |
clearCache(null, true); |
|
110 |
} |
|
111 |
|
|
112 |
private FileClientConfig parseClientConfig(Integer storage, Map<String, Object> config) { |
|
113 |
// 获取配置类 |
|
114 |
Class<? extends FileClientConfig> configClass = FileStorageEnum.getByStorage(storage) |
|
115 |
.getConfigClass(); |
|
116 |
FileClientConfig clientConfig = JsonUtils.parseObject2(JsonUtils.toJsonString(config), configClass); |
|
117 |
// 参数校验 |
|
118 |
ValidationUtils.validate(validator, clientConfig); |
|
119 |
// 设置参数 |
|
120 |
return clientConfig; |
|
121 |
} |
|
122 |
|
|
123 |
@Override |
|
124 |
public void deleteFileConfig(Long id) { |
|
125 |
// 校验存在 |
|
126 |
FileConfigDO config = validateFileConfigExists(id); |
|
127 |
if (Boolean.TRUE.equals(config.getMaster())) { |
|
128 |
throw exception(FILE_CONFIG_DELETE_FAIL_MASTER); |
|
129 |
} |
|
130 |
// 删除 |
|
131 |
fileConfigMapper.deleteById(id); |
|
132 |
|
|
133 |
// 清空缓存 |
|
134 |
clearCache(id, null); |
|
135 |
} |
|
136 |
|
|
137 |
/** |
|
138 |
* 清空指定文件配置 |
|
139 |
* |
|
140 |
* @param id 配置编号 |
|
141 |
* @param master 是否主配置 |
|
142 |
*/ |
|
143 |
private void clearCache(Long id, Boolean master) { |
|
144 |
if (id != null) { |
|
145 |
clientCache.invalidate(id); |
|
146 |
} |
|
147 |
if (Boolean.TRUE.equals(master)) { |
|
148 |
clientCache.invalidate(CACHE_MASTER_ID); |
|
149 |
} |
|
150 |
} |
|
151 |
|
|
152 |
private FileConfigDO validateFileConfigExists(Long id) { |
|
153 |
FileConfigDO config = fileConfigMapper.selectById(id); |
|
154 |
if (config == null) { |
|
155 |
throw exception(FILE_CONFIG_NOT_EXISTS); |
|
156 |
} |
|
157 |
return config; |
|
158 |
} |
|
159 |
|
|
160 |
@Override |
|
161 |
public FileConfigDO getFileConfig(Long id) { |
|
162 |
return fileConfigMapper.selectById(id); |
|
163 |
} |
|
164 |
|
|
165 |
@Override |
|
166 |
public PageResult<FileConfigDO> getFileConfigPage(FileConfigPageReqVO pageReqVO) { |
|
167 |
return fileConfigMapper.selectPage(pageReqVO); |
|
168 |
} |
|
169 |
|
|
170 |
@Override |
|
171 |
public String testFileConfig(Long id) throws Exception { |
|
172 |
// 校验存在 |
|
173 |
validateFileConfigExists(id); |
|
174 |
// 上传文件 |
|
175 |
byte[] content = ResourceUtil.readBytes("file/erweima.jpg"); |
|
176 |
return getFileClient(id).upload(content, IdUtil.fastSimpleUUID() + ".jpg", "image/jpeg"); |
|
177 |
} |
|
178 |
|
|
179 |
@Override |
|
180 |
public FileClient getFileClient(Long id) { |
|
181 |
return clientCache.getUnchecked(id); |
|
182 |
} |
|
183 |
|
|
184 |
@Override |
|
185 |
public FileClient getMasterFileClient() { |
|
186 |
return clientCache.getUnchecked(CACHE_MASTER_ID); |
|
187 |
} |
|
188 |
|
|
189 |
} |