refactor: 重构偏好模块.

This commit is contained in:
lijiahang
2023-12-19 17:48:48 +08:00
parent 581c14d8d7
commit bb83fe447b
24 changed files with 237 additions and 211 deletions

View File

@@ -1,8 +1,13 @@
package com.orion.ops.module.infra.handler.preference.model;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.orion.lang.define.wrapper.Ref;
import com.orion.lang.utils.collect.Maps;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;
/**
* 偏好
@@ -18,8 +23,9 @@ public interface PreferenceModel {
*
* @return map
*/
default Map<String, Object> toMap() {
return JSON.parseObject(JSON.toJSONString(this));
default Map<String, String> toMap() {
JSONObject map = JSON.parseObject(JSON.toJSONString(this));
return Maps.map(map, Function.identity(), v -> JSON.toJSONString(Ref.of(v)));
}
}

View File

@@ -5,8 +5,8 @@ Authorization: {{token}}
{
"type": "SYSTEM",
"config": {
}
"item": "",
"value": ""
}

View File

@@ -1,8 +1,9 @@
package com.orion.ops.module.infra.controller;
import com.orion.lang.define.wrapper.HttpWrapper;
import com.orion.ops.framework.web.core.annotation.RestWrapper;
import com.orion.ops.module.infra.entity.request.preference.PreferenceUpdatePartialRequest;
import com.orion.ops.module.infra.entity.request.preference.PreferenceUpdateRequest;
import com.orion.ops.module.infra.entity.vo.PreferenceVO;
import com.orion.ops.module.infra.service.PreferenceService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
@@ -12,6 +13,7 @@ import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.Map;
/**
* 用户偏好 api
@@ -33,21 +35,22 @@ public class PreferenceController {
private PreferenceService preferenceService;
@PutMapping("/update")
@Operation(summary = "更新用户偏好-整体")
@Operation(summary = "更新用户偏好-单个")
public Integer updatePreference(@Validated @RequestBody PreferenceUpdateRequest request) {
return preferenceService.updatePreference(request, false);
return preferenceService.updatePreference(request);
}
@PutMapping("/update-partial")
@Operation(summary = "更新用户偏好-部分")
public Integer updatePreferencePartial(@Validated @RequestBody PreferenceUpdateRequest request) {
return preferenceService.updatePreference(request, true);
public HttpWrapper<?> updatePreferencePartial(@Validated @RequestBody PreferenceUpdatePartialRequest request) {
preferenceService.updatePreferencePartial(request);
return HttpWrapper.ok();
}
@GetMapping("/get")
@Operation(summary = "查询用户偏好")
@Parameter(name = "type", description = "type", required = true)
public PreferenceVO getPreference(@RequestParam("type") String type) {
public Map<String, Object> getPreference(@RequestParam("type") String type) {
return preferenceService.getPreferenceByType(type);
}

View File

@@ -1,28 +0,0 @@
package com.orion.ops.module.infra.convert;
import com.orion.ops.module.infra.entity.domain.PreferenceDO;
import com.orion.ops.module.infra.entity.request.preference.PreferenceUpdateRequest;
import com.orion.ops.module.infra.entity.vo.PreferenceVO;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.factory.Mappers;
/**
* 用户偏好 内部对象转换器
*
* @author Jiahang Li
* @version 1.0.0
* @since 2023-9-27 18:37
*/
@Mapper
public interface PreferenceConvert {
PreferenceConvert MAPPER = Mappers.getMapper(PreferenceConvert.class);
@Mapping(target = "config", ignore = true)
PreferenceDO to(PreferenceUpdateRequest request);
@Mapping(target = "config", ignore = true)
PreferenceVO to(PreferenceDO domain);
}

View File

@@ -1,9 +1,9 @@
package com.orion.ops.module.infra.define.cache;
import com.alibaba.fastjson.JSONObject;
import com.orion.lang.define.cache.key.CacheKeyBuilder;
import com.orion.lang.define.cache.key.CacheKeyDefine;
import com.orion.lang.define.cache.key.struct.RedisCacheStruct;
import com.orion.lang.define.wrapper.Ref;
import java.util.concurrent.TimeUnit;
@@ -19,8 +19,8 @@ public interface PreferenceCacheKeyDefine {
CacheKeyDefine PREFERENCE = new CacheKeyBuilder()
.key("user:preference:{}:{}")
.desc("用户偏好 ${userId} ${type}")
.type(JSONObject.class)
.struct(RedisCacheStruct.STRING)
.type(Ref.class)
.struct(RedisCacheStruct.HASH)
.timeout(1, TimeUnit.DAYS)
.build();

View File

@@ -38,8 +38,12 @@ public class PreferenceDO extends BaseDO {
@TableField("type")
private String type;
@Schema(description = "偏好配置")
@TableField("config")
private String config;
@Schema(description = "配置")
@TableField("item")
private String item;
@Schema(description = "配置值")
@TableField("value")
private String value;
}

View File

@@ -0,0 +1,38 @@
package com.orion.ops.module.infra.entity.request.preference;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.Size;
import java.io.Serializable;
import java.util.Map;
/**
* 用户偏好 部分更新请求对象
*
* @author Jiahang Li
* @version 1.0.0
* @since 2023-9-27 18:37
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Schema(name = "PreferenceUpdatePartialRequest", description = "用户偏好 部分更新请求对象")
public class PreferenceUpdatePartialRequest implements Serializable {
@NotBlank
@Size(max = 12)
@Schema(description = "类型")
private String type;
@NotEmpty
@Schema(description = "偏好配置")
private Map<String, Object> config;
}

View File

@@ -7,10 +7,8 @@ import lombok.Data;
import lombok.NoArgsConstructor;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.Size;
import java.io.Serializable;
import java.util.Map;
/**
* 用户偏好 更新请求对象
@@ -31,8 +29,12 @@ public class PreferenceUpdateRequest implements Serializable {
@Schema(description = "类型")
private String type;
@NotEmpty
@NotBlank
@Size(max = 32)
@Schema(description = "偏好配置")
private Map<String, Object> config;
private String item;
@Schema(description = "偏好配置")
private Object value;
}

View File

@@ -1,31 +0,0 @@
package com.orion.ops.module.infra.entity.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.util.Map;
/**
* 用户偏好 视图响应对象
*
* @author Jiahang Li
* @version 1.0.0
* @since 2023-9-27 18:37
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Schema(name = "PreferenceVO", description = "用户偏好 视图响应对象")
public class PreferenceVO implements Serializable {
private static final long serialVersionUID = 1L;
@Schema(description = "偏好配置")
private Map<String, Object> config;
}

View File

@@ -17,7 +17,7 @@ public class TerminalPreferenceStrategy implements IPreferenceStrategy<TerminalP
@Override
public TerminalPreferenceModel getDefault() {
return TerminalPreferenceModel.builder()
.darkTheme("dark")
.darkTheme("auto")
.newConnectionType("group")
.displaySetting(TerminalPreferenceModel.DisplaySettingModel.builder()
.fontFamily("_")

View File

@@ -1,7 +1,7 @@
package com.orion.ops.module.infra.service;
import com.orion.ops.module.infra.entity.request.preference.PreferenceUpdatePartialRequest;
import com.orion.ops.module.infra.entity.request.preference.PreferenceUpdateRequest;
import com.orion.ops.module.infra.entity.vo.PreferenceVO;
import com.orion.ops.module.infra.enums.PreferenceTypeEnum;
import java.util.Map;
@@ -17,21 +17,27 @@ import java.util.concurrent.Future;
public interface PreferenceService {
/**
* 更新用户偏好
* 更新用户偏好-单个
*
* @param request request
* @param partial 是否为部分更新
* @return effect
*/
Integer updatePreference(PreferenceUpdateRequest request, boolean partial);
Integer updatePreference(PreferenceUpdateRequest request);
/**
* 更新用户偏好-部分
*
* @param request request
*/
void updatePreferencePartial(PreferenceUpdatePartialRequest request);
/**
* 查询用户偏好
*
* @param type type
* @return row
* @return rows
*/
PreferenceVO getPreferenceByType(String type);
Map<String, Object> getPreferenceByType(String type);
/**
* 获取用户偏好

View File

@@ -1,17 +1,18 @@
package com.orion.ops.module.infra.service.impl;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.orion.lang.define.wrapper.Ref;
import com.orion.lang.function.Functions;
import com.orion.lang.utils.collect.Maps;
import com.orion.ops.framework.common.utils.Valid;
import com.orion.ops.framework.redis.core.utils.RedisStrings;
import com.orion.ops.framework.redis.core.utils.RedisMaps;
import com.orion.ops.framework.security.core.utils.SecurityUtils;
import com.orion.ops.module.infra.dao.PreferenceDAO;
import com.orion.ops.module.infra.define.cache.PreferenceCacheKeyDefine;
import com.orion.ops.module.infra.entity.domain.PreferenceDO;
import com.orion.ops.module.infra.entity.request.preference.PreferenceUpdatePartialRequest;
import com.orion.ops.module.infra.entity.request.preference.PreferenceUpdateRequest;
import com.orion.ops.module.infra.entity.vo.PreferenceVO;
import com.orion.ops.module.infra.enums.PreferenceTypeEnum;
import com.orion.ops.module.infra.service.PreferenceService;
import lombok.extern.slf4j.Slf4j;
@@ -24,6 +25,7 @@ import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Future;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
@@ -41,51 +43,73 @@ public class PreferenceServiceImpl implements PreferenceService {
private PreferenceDAO preferenceDAO;
@Override
public Integer updatePreference(PreferenceUpdateRequest request, boolean partial) {
public Integer updatePreference(PreferenceUpdateRequest request) {
Long userId = SecurityUtils.getLoginUserId();
String type = request.getType();
String item = request.getItem();
Valid.valid(PreferenceTypeEnum::of, type);
// 查询
PreferenceDO preference = preferenceDAO.of()
.wrapper(this.buildQueryWrapper(userId, type))
.createWrapper()
.eq(PreferenceDO::getUserId, userId)
.eq(PreferenceDO::getType, type)
.eq(PreferenceDO::getItem, item)
.then()
.getOne();
int effect;
if (preference == null) {
// 直接插入
// 插入
PreferenceDO insertRecord = new PreferenceDO();
insertRecord.setUserId(userId);
insertRecord.setType(type);
insertRecord.setConfig(JSON.toJSONString(request.getConfig()));
insertRecord.setItem(item);
insertRecord.setValue(this.toJsonValue(request.getValue()));
effect = preferenceDAO.insert(insertRecord);
} else {
// 更新
PreferenceDO updateRecord = new PreferenceDO();
updateRecord.setId(preference.getId());
if (partial) {
// 部分更新
JSONObject config = JSON.parseObject(preference.getConfig());
config.putAll(request.getConfig());
updateRecord.setConfig(JSON.toJSONString(config));
} else {
// 全部更新
updateRecord.setConfig(JSON.toJSONString(request.getConfig()));
}
updateRecord.setValue(this.toJsonValue(request.getValue()));
effect = preferenceDAO.updateById(updateRecord);
// 删除缓存
RedisStrings.delete(PreferenceCacheKeyDefine.PREFERENCE.format(userId, type));
}
// 删除缓存
RedisMaps.delete(PreferenceCacheKeyDefine.PREFERENCE.format(userId, type));
return effect;
}
@Override
public PreferenceVO getPreferenceByType(String type) {
public void updatePreferencePartial(PreferenceUpdatePartialRequest request) {
Long userId = SecurityUtils.getLoginUserId();
String type = request.getType();
Map<String, Object> config = request.getConfig();
Valid.valid(PreferenceTypeEnum::of, type);
// 删除配置
LambdaQueryWrapper<PreferenceDO> wrapper = preferenceDAO.lambda()
.eq(PreferenceDO::getUserId, userId)
.eq(PreferenceDO::getType, type)
.in(PreferenceDO::getItem, config.keySet());
preferenceDAO.delete(wrapper);
// 插入配置
List<PreferenceDO> records = config.entrySet()
.stream()
.map(s -> {
PreferenceDO insertRecord = new PreferenceDO();
insertRecord.setUserId(userId);
insertRecord.setType(type);
insertRecord.setItem(s.getKey());
insertRecord.setValue(this.toJsonValue(s.getValue()));
return insertRecord;
}).collect(Collectors.toList());
preferenceDAO.insertBatch(records);
// 删除缓存
RedisMaps.delete(PreferenceCacheKeyDefine.PREFERENCE.format(userId, type));
}
@Override
public Map<String, Object> getPreferenceByType(String type) {
Long userId = SecurityUtils.getLoginUserId();
PreferenceTypeEnum typeEnum = Valid.valid(PreferenceTypeEnum::of, type);
Map<String, Object> config = this.getPreferenceByCache(userId, typeEnum);
// 返回
return PreferenceVO.builder()
.config(config)
.build();
return this.getPreferenceByCache(userId, typeEnum);
}
@Override
@@ -104,7 +128,7 @@ public class PreferenceServiceImpl implements PreferenceService {
List<String> deleteKeys = Arrays.stream(PreferenceTypeEnum.values())
.map(s -> PreferenceCacheKeyDefine.PREFERENCE.format(userId, s))
.collect(Collectors.toList());
RedisStrings.delete(deleteKeys);
RedisMaps.delete(deleteKeys);
}
/**
@@ -118,47 +142,58 @@ public class PreferenceServiceImpl implements PreferenceService {
String typeValue = type.getType();
// 查询缓存 用 string 防止数据类型丢失
String key = PreferenceCacheKeyDefine.PREFERENCE.format(userId, type);
Map<String, Object> config = RedisStrings.getJson(key);
Map<String, String> config = RedisMaps.entities(key);
boolean setCache = Maps.isEmpty(config);
// 查询数据库
if (Maps.isEmpty(config)) {
config = preferenceDAO.of()
.wrapper(this.buildQueryWrapper(userId, typeValue))
.optionalOne()
.map(PreferenceDO::getConfig)
.map(JSON::parseObject)
.orElse(null);
.createWrapper()
.eq(PreferenceDO::getUserId, userId)
.eq(PreferenceDO::getType, type)
.then()
.stream()
.collect(Collectors.toMap(
PreferenceDO::getItem,
PreferenceDO::getValue,
Functions.right())
);
}
// 初始化
if (Maps.isEmpty(config)) {
// 获取默认值
config = type.getStrategy()
.getDefault()
.toMap();
// 插入
PreferenceDO entity = new PreferenceDO();
entity.setUserId(userId);
entity.setType(typeValue);
entity.setConfig(JSON.toJSONString(config));
preferenceDAO.insert(entity);
// 插入默认值
List<PreferenceDO> entities = config
.entrySet()
.stream()
.map(s -> {
PreferenceDO entity = new PreferenceDO();
entity.setUserId(userId);
entity.setType(typeValue);
entity.setItem(s.getKey());
entity.setValue(s.getValue());
return entity;
}).collect(Collectors.toList());
preferenceDAO.insertBatch(entities);
}
// 设置缓存
if (setCache) {
RedisStrings.setJson(key, PreferenceCacheKeyDefine.PREFERENCE, config);
RedisMaps.putAll(key, PreferenceCacheKeyDefine.PREFERENCE, config);
}
return config;
// unref
return Maps.map(config, Function.identity(), v -> JSON.parseObject(v, Ref.class).getValue());
}
/**
* 构建查询 wrapper
* 转为 json 对象
*
* @param userId userId
* @param type type
* @return wrapper
* @param o o
* @return value
*/
private LambdaQueryWrapper<PreferenceDO> buildQueryWrapper(Long userId, String type) {
return preferenceDAO.wrapper()
.eq(PreferenceDO::getUserId, userId)
.eq(PreferenceDO::getType, type);
private String toJsonValue(Object o) {
return JSON.toJSONString(Ref.of(o));
}
}

View File

@@ -12,12 +12,13 @@
<result column="deleted" property="deleted"/>
<result column="user_id" property="userId"/>
<result column="type" property="type"/>
<result column="config" property="config"/>
<result column="item" property="item"/>
<result column="value" property="value"/>
</resultMap>
<!-- 通用查询结果列 -->
<sql id="Base_Column_List">
id, user_id, type, config, create_time, update_time, creator, updater, deleted
id, user_id, type, item, value, create_time, update_time, creator, updater, deleted
</sql>
</mapper>