🔨 优化偏好处理逻辑.

This commit is contained in:
lijiahang
2025-01-13 09:43:43 +08:00
parent 2a5bda3d00
commit a734ec40ec
13 changed files with 131 additions and 101 deletions

View File

@@ -33,6 +33,7 @@ import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.dromara.visor.common.constant.Const;
import org.dromara.visor.common.constant.ErrorMessage;
import org.dromara.visor.common.constant.ExtraFieldConst;
import org.dromara.visor.common.handler.data.model.GenericsDataModel;
import org.dromara.visor.common.utils.Valid;
import org.dromara.visor.framework.biz.operator.log.core.utils.OperatorLogs;
@@ -179,7 +180,10 @@ public class HostServiceImpl implements HostService {
@Override
public Integer updateHostConfig(HostUpdateConfigRequest request) {
log.info("HostService-updateHostConfig request: {}", JSON.toJSONString(request));
// 设置日志参数
String param = OperatorLogs.toJsonString(JSON.parseObject(request.getConfig()));
OperatorLogs.add(ExtraFieldConst.CONFIG, param);
log.info("HostService-updateHostConfig request: {}", param);
Long id = request.getId();
try {
CURRENT_UPDATE_CONFIG_ID.set(id);

View File

@@ -28,7 +28,7 @@ import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.dromara.visor.framework.log.core.annotation.IgnoreLog;
import org.dromara.visor.framework.web.core.annotation.RestWrapper;
import org.dromara.visor.module.infra.entity.request.preference.PreferenceUpdatePartialRequest;
import org.dromara.visor.module.infra.entity.request.preference.PreferenceUpdateBatchRequest;
import org.dromara.visor.module.infra.entity.request.preference.PreferenceUpdateRequest;
import org.dromara.visor.module.infra.service.PreferenceService;
import org.springframework.validation.annotation.Validated;
@@ -36,7 +36,6 @@ import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
/**
* 用户偏好 api
@@ -58,23 +57,25 @@ public class PreferenceController {
@PutMapping("/update")
@Operation(summary = "更新用户偏好-单个")
public Integer updatePreference(@Validated @RequestBody PreferenceUpdateRequest request) {
return preferenceService.updatePreference(request);
}
@PutMapping("/update-partial")
@Operation(summary = "更新用户偏好-部分")
public Boolean updatePreferencePartial(@Validated @RequestBody PreferenceUpdatePartialRequest request) {
preferenceService.updatePreferencePartial(request);
public Boolean updatePreference(@Validated @RequestBody PreferenceUpdateRequest request) {
preferenceService.updatePreference(request);
return true;
}
@PutMapping("/update-update")
@Operation(summary = "更新用户偏好-多个")
public Boolean updatePreferenceBatch(@Validated @RequestBody PreferenceUpdateBatchRequest request) {
preferenceService.updatePreferenceBatch(request);
return true;
}
@IgnoreLog
@GetMapping("/get")
@Operation(summary = "查询用户偏好")
@Parameter(name = "type", description = "type", required = true)
@Parameter(name = "items", description = "items")
public Map<String, Object> getPreference(@RequestParam("type") String type,
@RequestParam(name = "items", required = false) List<String> items) {
public Object getPreference(@RequestParam("type") String type,
@RequestParam(name = "items", required = false) List<String> items) {
return preferenceService.getPreferenceByType(type, items);
}
@@ -83,8 +84,8 @@ public class PreferenceController {
@Operation(summary = "查询默认偏好")
@Parameter(name = "type", description = "type", required = true)
@Parameter(name = "items", description = "items")
public Map<String, Object> getDefaultPreference(@RequestParam("type") String type,
@RequestParam(name = "items", required = false) List<String> items) {
public Object getDefaultPreference(@RequestParam("type") String type,
@RequestParam(name = "items", required = false) List<String> items) {
return preferenceService.getDefaultPreferenceByType(type, items);
}

View File

@@ -25,7 +25,7 @@ package org.dromara.visor.module.infra.define.cache;
import cn.orionsec.kit.lang.define.cache.key.CacheKeyBuilder;
import cn.orionsec.kit.lang.define.cache.key.CacheKeyDefine;
import cn.orionsec.kit.lang.define.cache.key.struct.RedisCacheStruct;
import cn.orionsec.kit.lang.define.wrapper.Ref;
import org.json.JSONObject;
import java.util.concurrent.TimeUnit;
@@ -39,10 +39,10 @@ import java.util.concurrent.TimeUnit;
public interface PreferenceCacheKeyDefine {
CacheKeyDefine PREFERENCE = new CacheKeyBuilder()
.key("user:preference:{}:{}")
.key("user:prefer:{}:{}")
.desc("用户偏好 ${userId} ${type}")
.type(Ref.class)
.struct(RedisCacheStruct.HASH)
.type(JSONObject.class)
.struct(RedisCacheStruct.STRING)
.timeout(8, TimeUnit.HOURS)
.build();

View File

@@ -35,7 +35,7 @@ import java.io.Serializable;
import java.util.Map;
/**
* 用户偏好 部分更新请求对象
* 用户偏好 批量更新请求对象
*
* @author Jiahang Li
* @version 1.0.0
@@ -45,8 +45,8 @@ import java.util.Map;
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Schema(name = "PreferenceUpdatePartialRequest", description = "用户偏好 部分更新请求对象")
public class PreferenceUpdatePartialRequest implements Serializable {
@Schema(name = "PreferenceUpdateBatchRequest", description = "用户偏好 批量更新请求对象")
public class PreferenceUpdateBatchRequest implements Serializable {
@NotBlank
@Size(max = 16)
@@ -55,6 +55,6 @@ public class PreferenceUpdatePartialRequest implements Serializable {
@NotEmpty
@Schema(description = "偏好配置")
private Map<String, Object> config;
private Map<String, String> config;
}

View File

@@ -57,6 +57,6 @@ public class PreferenceUpdateRequest implements Serializable {
private String item;
@Schema(description = "偏好配置")
private Object value;
private String value;
}

View File

@@ -30,7 +30,6 @@ import lombok.NoArgsConstructor;
import java.util.Collection;
import java.util.List;
import java.util.Map;
/**
* 用户 聚合响应对象
@@ -59,7 +58,7 @@ public class UserAggregateVO {
private UserUpdatePasswordVO updatePassword;
@Schema(description = "系统偏好")
private Map<String, Object> systemPreference;
private Object systemPreference;
@Schema(description = "已经提示的key")
private List<String> tippedKeys;

View File

@@ -26,6 +26,8 @@ import lombok.Getter;
import org.dromara.visor.common.handler.data.GenericsStrategyDefinition;
import org.dromara.visor.common.handler.data.model.GenericsDataModel;
import org.dromara.visor.common.handler.data.strategy.GenericsDataStrategy;
import org.dromara.visor.module.infra.handler.preference.model.SystemPreferenceModel;
import org.dromara.visor.module.infra.handler.preference.model.TerminalPreferenceModel;
import org.dromara.visor.module.infra.handler.preference.strategy.SystemPreferenceStrategy;
import org.dromara.visor.module.infra.handler.preference.strategy.TerminalPreferenceStrategy;
@@ -42,22 +44,26 @@ public enum PreferenceTypeEnum implements GenericsStrategyDefinition {
/**
* 系统偏好
*/
SYSTEM(SystemPreferenceStrategy.class),
SYSTEM(SystemPreferenceModel.class, SystemPreferenceStrategy.class),
/**
* 终端偏好
*/
TERMINAL(TerminalPreferenceStrategy.class),
TERMINAL(TerminalPreferenceModel.class, TerminalPreferenceStrategy.class),
;
PreferenceTypeEnum(Class<? extends GenericsDataStrategy<? extends GenericsDataModel>> strategyClass) {
PreferenceTypeEnum(Class<? extends GenericsDataModel> modelClass,
Class<? extends GenericsDataStrategy<? extends GenericsDataModel>> strategyClass) {
this.type = this.name();
this.modelClass = modelClass;
this.strategyClass = strategyClass;
}
private final String type;
private final Class<? extends GenericsDataModel> modelClass;
private final Class<? extends GenericsDataStrategy<? extends GenericsDataModel>> strategyClass;
public static PreferenceTypeEnum of(String type) {

View File

@@ -86,4 +86,19 @@ public class SystemPreferenceModel implements GenericsDataModel {
*/
private Integer defaultCardPageSize;
/**
* 主机视图
*/
private String hostView;
/**
* 主机密钥视图
*/
private String hostKeyView;
/**
* 主机身份视图
*/
private String hostIdentityView;
}

View File

@@ -22,7 +22,6 @@
*/
package org.dromara.visor.module.infra.handler.preference.strategy;
import cn.orionsec.kit.lang.utils.Exceptions;
import org.dromara.visor.common.handler.data.strategy.AbstractGenericsDataStrategy;
import org.dromara.visor.module.infra.handler.preference.model.SystemPreferenceModel;
import org.springframework.stereotype.Component;
@@ -37,6 +36,8 @@ import org.springframework.stereotype.Component;
@Component
public class SystemPreferenceStrategy extends AbstractGenericsDataStrategy<SystemPreferenceModel> {
private static final String DEFAULT_VIEW = "table";
public SystemPreferenceStrategy() {
super(SystemPreferenceModel.class);
}
@@ -53,12 +54,10 @@ public class SystemPreferenceStrategy extends AbstractGenericsDataStrategy<Syste
.colorWeak(false)
.defaultTablePageSize(10)
.defaultCardPageSize(12)
.hostView(DEFAULT_VIEW)
.hostKeyView(DEFAULT_VIEW)
.hostIdentityView(DEFAULT_VIEW)
.build();
}
@Override
public SystemPreferenceModel parse(String serialModel) {
throw Exceptions.unsupported();
}
}

View File

@@ -22,7 +22,6 @@
*/
package org.dromara.visor.module.infra.handler.preference.strategy;
import cn.orionsec.kit.lang.utils.Exceptions;
import cn.orionsec.kit.lang.utils.collect.Lists;
import cn.orionsec.kit.net.host.ssh.TerminalType;
import com.alibaba.fastjson.JSONObject;
@@ -157,9 +156,4 @@ public class TerminalPreferenceStrategy extends AbstractGenericsDataStrategy<Ter
.build();
}
@Override
public TerminalPreferenceModel parse(String serialModel) {
throw Exceptions.unsupported();
}
}

View File

@@ -22,12 +22,11 @@
*/
package org.dromara.visor.module.infra.service;
import org.dromara.visor.module.infra.entity.request.preference.PreferenceUpdatePartialRequest;
import org.dromara.visor.module.infra.entity.request.preference.PreferenceUpdateBatchRequest;
import org.dromara.visor.module.infra.entity.request.preference.PreferenceUpdateRequest;
import org.dromara.visor.module.infra.enums.PreferenceTypeEnum;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Future;
/**
@@ -43,43 +42,45 @@ public interface PreferenceService {
* 更新用户偏好-单个
*
* @param request request
* @return effect
*/
Integer updatePreference(PreferenceUpdateRequest request);
void updatePreference(PreferenceUpdateRequest request);
/**
* 更新用户偏好-部分
* 更新用户偏好-多个
*
* @param request request
*/
void updatePreferencePartial(PreferenceUpdatePartialRequest request);
void updatePreferenceBatch(PreferenceUpdateBatchRequest request);
/**
* 查询用户偏好
*
* @param type type
* @param items items
* @param <T> T
* @return rows
*/
Map<String, Object> getPreferenceByType(String type, List<String> items);
<T> T getPreferenceByType(String type, List<String> items);
/**
* 查询默认偏好
*
* @param type type
* @param items items
* @param <T> T
* @return rows
*/
Map<String, Object> getDefaultPreferenceByType(String type, List<String> items);
<T> T getDefaultPreferenceByType(String type, List<String> items);
/**
* 获取用户偏好
*
* @param userId userId
* @param type type
* @param <T> T
* @return 偏好
*/
Future<Map<String, Object>> getPreferenceAsync(Long userId, PreferenceTypeEnum type);
<T> Future<T> getPreferenceAsync(Long userId, PreferenceTypeEnum type);
/**
* 删除用户偏好

View File

@@ -23,18 +23,19 @@
package org.dromara.visor.module.infra.service.impl;
import cn.orionsec.kit.lang.function.Functions;
import cn.orionsec.kit.lang.utils.Refs;
import cn.orionsec.kit.lang.utils.Objects1;
import cn.orionsec.kit.lang.utils.collect.Lists;
import cn.orionsec.kit.lang.utils.collect.Maps;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.dromara.visor.common.utils.Valid;
import org.dromara.visor.framework.redis.core.utils.RedisMaps;
import org.dromara.visor.framework.redis.core.utils.RedisStrings;
import org.dromara.visor.framework.security.core.utils.SecurityUtils;
import org.dromara.visor.module.infra.dao.PreferenceDAO;
import org.dromara.visor.module.infra.define.cache.PreferenceCacheKeyDefine;
import org.dromara.visor.module.infra.entity.domain.PreferenceDO;
import org.dromara.visor.module.infra.entity.request.preference.PreferenceUpdatePartialRequest;
import org.dromara.visor.module.infra.entity.request.preference.PreferenceUpdateBatchRequest;
import org.dromara.visor.module.infra.entity.request.preference.PreferenceUpdateRequest;
import org.dromara.visor.module.infra.enums.PreferenceTypeEnum;
import org.dromara.visor.module.infra.service.PreferenceService;
@@ -65,7 +66,7 @@ public class PreferenceServiceImpl implements PreferenceService {
private PreferenceDAO preferenceDAO;
@Override
public Integer updatePreference(PreferenceUpdateRequest request) {
public void updatePreference(PreferenceUpdateRequest request) {
Long userId = SecurityUtils.getLoginUserId();
String type = request.getType();
String item = request.getItem();
@@ -78,33 +79,31 @@ public class PreferenceServiceImpl implements PreferenceService {
.eq(PreferenceDO::getItem, item)
.then()
.getOne();
int effect;
if (preference == null) {
// 插入
PreferenceDO insertRecord = new PreferenceDO();
insertRecord.setUserId(userId);
insertRecord.setType(type);
insertRecord.setItem(item);
insertRecord.setValue(Refs.json(request.getValue()));
effect = preferenceDAO.insert(insertRecord);
insertRecord.setValue(request.getValue());
preferenceDAO.insert(insertRecord);
} else {
// 更新
PreferenceDO updateRecord = new PreferenceDO();
updateRecord.setId(preference.getId());
updateRecord.setValue(Refs.json(request.getValue()));
effect = preferenceDAO.updateById(updateRecord);
updateRecord.setValue(request.getValue());
preferenceDAO.updateById(updateRecord);
}
// 删除缓存
RedisMaps.delete(PreferenceCacheKeyDefine.PREFERENCE.format(userId, type));
return effect;
RedisStrings.delete(PreferenceCacheKeyDefine.PREFERENCE.format(userId, type));
}
@Override
@Transactional(rollbackFor = Exception.class)
public void updatePreferencePartial(PreferenceUpdatePartialRequest request) {
public void updatePreferenceBatch(PreferenceUpdateBatchRequest request) {
Long userId = SecurityUtils.getLoginUserId();
String type = request.getType();
Map<String, Object> config = request.getConfig();
Map<String, String> config = request.getConfig();
Valid.valid(PreferenceTypeEnum::of, type);
// 查询配置
LambdaQueryWrapper<PreferenceDO> wrapper = preferenceDAO.lambda()
@@ -125,7 +124,7 @@ public class PreferenceServiceImpl implements PreferenceService {
.map(s -> {
PreferenceDO update = new PreferenceDO();
update.setId(items.get(s).getId());
update.setValue(Refs.json(config.get(s)));
update.setValue(config.get(s));
return update;
}).collect(Collectors.toList());
preferenceDAO.updateBatch(updateRecords);
@@ -138,46 +137,35 @@ public class PreferenceServiceImpl implements PreferenceService {
insert.setUserId(userId);
insert.setType(type);
insert.setItem(s);
insert.setValue(Refs.json(config.get(s)));
insert.setValue(config.get(s));
return insert;
}).collect(Collectors.toList());
preferenceDAO.insertBatch(insertRecords);
// 删除缓存
RedisMaps.delete(PreferenceCacheKeyDefine.PREFERENCE.format(userId, type));
RedisStrings.delete(PreferenceCacheKeyDefine.PREFERENCE.format(userId, type));
}
@Override
public Map<String, Object> getPreferenceByType(String type, List<String> items) {
public <T> T getPreferenceByType(String type, List<String> items) {
Long userId = SecurityUtils.getLoginUserId();
PreferenceTypeEnum typeEnum = Valid.valid(PreferenceTypeEnum::of, type);
// 查询缓存
Map<String, Object> preference = this.getPreferenceByCache(userId, typeEnum);
if (Lists.isEmpty(items)) {
return preference;
}
Map<String, Object> partial = Maps.newMap();
items.forEach(s -> partial.put(s, preference.get(s)));
return partial;
return this.getPreferenceByCache(userId, typeEnum, items);
}
@Override
public Map<String, Object> getDefaultPreferenceByType(String type, List<String> items) {
public <T> T getDefaultPreferenceByType(String type, List<String> items) {
PreferenceTypeEnum preferenceType = Valid.valid(PreferenceTypeEnum::of, type);
// 获取默认值
Map<String, Object> defaultModel = preferenceType.getDefault().toMap();
Map<String, Object> result = Maps.newMap();
if (Lists.isEmpty(items)) {
defaultModel.forEach((k, v) -> result.put(k, defaultModel.get(k)));
} else {
items.forEach(s -> result.put(s, defaultModel.get(s)));
}
return result;
JSONObject config = JSONObject.parseObject(preferenceType.getDefault().serial());
// 解析
return this.parsePreference(preferenceType, config, items);
}
@Override
@Async("asyncExecutor")
public Future<Map<String, Object>> getPreferenceAsync(Long userId, PreferenceTypeEnum type) {
Map<String, Object> config = this.getPreferenceByCache(userId, type);
public <T> Future<T> getPreferenceAsync(Long userId, PreferenceTypeEnum type) {
T config = this.getPreferenceByCache(userId, type, null);
return CompletableFuture.completedFuture(config);
}
@@ -205,7 +193,7 @@ public class PreferenceServiceImpl implements PreferenceService {
// .map(s -> PreferenceCacheKeyDefine.PREFERENCE.format(userId, s))
// .forEach(deleteKeys::add);
// }
// RedisMaps.delete(deleteKeys);
// RedisStrings.delete(deleteKeys);
}
/**
@@ -213,33 +201,33 @@ public class PreferenceServiceImpl implements PreferenceService {
*
* @param userId userId
* @param type type
* @param items items
* @return config
*/
private Map<String, Object> getPreferenceByCache(Long userId, PreferenceTypeEnum type) {
private <T> T getPreferenceByCache(Long userId, PreferenceTypeEnum type, List<String> items) {
String typeValue = type.getType();
// 查询缓存 用 string 防止数据类型丢失
String key = PreferenceCacheKeyDefine.PREFERENCE.format(userId, type);
Map<String, String> config = RedisMaps.entities(key);
// 查询缓存
String key = PreferenceCacheKeyDefine.PREFERENCE.format(userId, typeValue);
JSONObject config = RedisStrings.getJson(key);
boolean setCache = Maps.isEmpty(config);
// 查询数据库
if (Maps.isEmpty(config)) {
if (config == null || Maps.isEmpty(config)) {
config = preferenceDAO.of()
.createWrapper()
.eq(PreferenceDO::getUserId, userId)
.eq(PreferenceDO::getType, type)
.eq(PreferenceDO::getType, typeValue)
.then()
.stream()
.collect(Collectors.toMap(
PreferenceDO::getItem,
PreferenceDO::getValue,
Functions.right())
);
Functions.right(),
JSONObject::new));
}
// 初始化
if (Maps.isEmpty(config)) {
// 获取默认值
Map<String, Object> defaultConfig = type.getDefault().toMap();
config = Maps.map(defaultConfig, Function.identity(), Refs::json);
config = JSONObject.parseObject(type.getDefault().serial());
// 插入默认值
List<PreferenceDO> entities = config
.entrySet()
@@ -249,17 +237,40 @@ public class PreferenceServiceImpl implements PreferenceService {
entity.setUserId(userId);
entity.setType(typeValue);
entity.setItem(s.getKey());
entity.setValue(s.getValue());
entity.setValue(Objects1.toString(s.getValue()));
return entity;
}).collect(Collectors.toList());
preferenceDAO.insertBatch(entities);
}
// 设置缓存
if (setCache) {
RedisMaps.putAll(key, PreferenceCacheKeyDefine.PREFERENCE, config);
RedisStrings.setJson(key, PreferenceCacheKeyDefine.PREFERENCE, config);
}
// unRef
return Maps.map(config, Function.identity(), Refs::unref);
// 获取偏好
return this.parsePreference(type, config, items);
}
/**
* 解析偏好
*
* @param type type
* @param config config
* @param items items
* @param <T> T
* @return prefer
*/
@SuppressWarnings("unchecked")
private <T> T parsePreference(PreferenceTypeEnum type, JSONObject config, List<String> items) {
// 设置返回的键
if (!Lists.isEmpty(items)) {
JSONObject configItems = new JSONObject();
for (String item : items) {
configItems.put(item, config.get(item));
}
config = configItems;
}
// 解析
return (T) config.toJavaObject(type.getModelClass());
}
}

View File

@@ -90,7 +90,7 @@ public class UserAggregateServiceImpl implements UserAggregateService {
// 获取用户信息
Long userId = SecurityUtils.getLoginUserId();
// 获取用户系统偏好
Future<Map<String, Object>> systemPreference = preferenceService.getPreferenceAsync(userId, PreferenceTypeEnum.SYSTEM);
Future<Object> systemPreference = preferenceService.getPreferenceAsync(userId, PreferenceTypeEnum.SYSTEM);
// 查询用户信息
SystemUserDO user = systemUserDAO.selectById(userId);
// 修改密码信息