设置用户偏好.

This commit is contained in:
lijiahang
2023-10-08 16:55:18 +08:00
parent c7defdb80d
commit fbd815a10e
30 changed files with 942 additions and 36 deletions

View File

@@ -0,0 +1,25 @@
package com.orion.ops.module.infra.handler.preference.model;
import com.alibaba.fastjson.JSON;
import java.util.Map;
/**
* 偏好
*
* @author Jiahang Li
* @version 1.0.0
* @since 2023/10/8 13:54
*/
public interface PreferenceModel {
/**
* 转为 map
*
* @return map
*/
default Map<String, Object> toMap() {
return JSON.parseObject(JSON.toJSONString(this));
}
}

View File

@@ -0,0 +1,21 @@
package com.orion.ops.module.infra.handler.preference.strategy;
import com.orion.ops.module.infra.handler.preference.model.PreferenceModel;
/**
* 偏好处理策略
*
* @author Jiahang Li
* @version 1.0.0
* @since 2023/10/8 13:49
*/
public interface IPreferenceStrategy<Model extends PreferenceModel> {
/**
* 获取默认值
*
* @return 默认值
*/
Model getDefault();
}

View File

@@ -56,7 +56,7 @@ public class PermissionController {
@IgnoreLog(IgnoreLogMode.RET)
@GetMapping("/user")
@Operation(summary = "获取用户权限")
@Operation(summary = "获取用户权限聚合信息")
public UserPermissionVO getUserPermission() {
return permissionService.getUserPermission();
}

View File

@@ -0,0 +1,28 @@
### 更新用户偏好-全部
PUT {{baseUrl}}/infra/preference/update
Content-Type: application/json
Authorization: {{token}}
{
"type": "SYSTEM",
"config": {
}
}
### 更新用户偏好-部分
PUT {{baseUrl}}/infra/preference/update-partial
Content-Type: application/json
Authorization: {{token}}
{
"type": "SYSTEM",
"config": {
}
}
### 查询用户偏好
GET {{baseUrl}}/infra/preference/get?type=SYSTEM
Authorization: {{token}}

View File

@@ -0,0 +1,55 @@
package com.orion.ops.module.infra.controller;
import com.orion.ops.framework.common.annotation.RestWrapper;
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;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
/**
* 用户偏好 api
*
* @author Jiahang Li
* @version 1.0.0
* @since 2023-9-27 18:37
*/
@Tag(name = "infra - 用户偏好服务")
@Slf4j
@Validated
@RestWrapper
@RestController
@RequestMapping("/infra/preference")
@SuppressWarnings({"ELValidationInJSP", "SpringElInspection"})
public class PreferenceController {
@Resource
private PreferenceService preferenceService;
@PutMapping("/update")
@Operation(summary = "更新用户偏好-整体")
public Integer updatePreference(@Validated @RequestBody PreferenceUpdateRequest request) {
return preferenceService.updatePreference(request, false);
}
@PutMapping("/update-partial")
@Operation(summary = "更新用户偏好-部分")
public Integer updatePreferencePartial(@Validated @RequestBody PreferenceUpdateRequest request) {
return preferenceService.updatePreference(request, true);
}
@GetMapping("/get")
@Operation(summary = "查询用户偏好")
@Parameter(name = "type", description = "type", required = true)
public PreferenceVO getPreference(@RequestParam("type") String type) {
return preferenceService.getPreferenceByType(type);
}
}

View File

@@ -0,0 +1,28 @@
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

@@ -7,7 +7,7 @@ import com.orion.ops.module.infra.entity.request.user.SystemUserQueryRequest;
import com.orion.ops.module.infra.entity.request.user.SystemUserUpdateRequest;
import com.orion.ops.module.infra.entity.request.user.SystemUserUpdateStatusRequest;
import com.orion.ops.module.infra.entity.vo.SystemUserVO;
import com.orion.ops.module.infra.entity.vo.UserBaseInfoVO;
import com.orion.ops.module.infra.entity.vo.UserCollectInfoVO;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
@@ -39,6 +39,6 @@ public interface SystemUserConvert {
LoginUser toLoginUser(SystemUserDO domain);
UserBaseInfoVO toBaseInfo(LoginUser user);
UserCollectInfoVO toCollectInfo(LoginUser user);
}

View File

@@ -0,0 +1,28 @@
package com.orion.ops.module.infra.dao;
import com.orion.ops.framework.mybatis.core.mapper.IMapper;
import com.orion.ops.framework.mybatis.core.query.Conditions;
import com.orion.ops.module.infra.entity.domain.PreferenceDO;
import org.apache.ibatis.annotations.Mapper;
/**
* 用户偏好 Mapper 接口
*
* @author Jiahang Li
* @version 1.0.0
* @since 2023-9-27 18:37
*/
@Mapper
public interface PreferenceDAO extends IMapper<PreferenceDO> {
/**
* 通过 userId 删除
*
* @param userId userId
* @return effect
*/
default int deleteByUserId(Long userId) {
return this.delete(Conditions.eq(PreferenceDO::getUserId, userId));
}
}

View File

@@ -0,0 +1,25 @@
package com.orion.ops.module.infra.define;
import com.alibaba.fastjson.JSONObject;
import com.orion.lang.define.cache.CacheKeyBuilder;
import com.orion.lang.define.cache.CacheKeyDefine;
import java.util.concurrent.TimeUnit;
/**
* 用户偏好缓存 key
*
* @author Jiahang Li
* @version 1.0.0
* @since 2023-9-27 18:37
*/
public interface PreferenceCacheKeyDefine {
CacheKeyDefine PREFERENCE = new CacheKeyBuilder()
.key("user:preference:{}:{}")
.desc("用户偏好 ${userId} ${type}")
.type(JSONObject.class)
.timeout(1, TimeUnit.DAYS)
.build();
}

View File

@@ -0,0 +1,45 @@
package com.orion.ops.module.infra.entity.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.orion.ops.framework.mybatis.core.domain.BaseDO;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
/**
* 用户偏好 实体对象
*
* @author Jiahang Li
* @version 1.0.0
* @since 2023-9-27 18:37
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(callSuper = true)
@TableName(value = "preference", autoResultMap = true)
@Schema(name = "PreferenceDO", description = "用户偏好 实体对象")
public class PreferenceDO extends BaseDO {
private static final long serialVersionUID = 1L;
@Schema(description = "id")
@TableId(value = "id", type = IdType.AUTO)
private Long id;
@Schema(description = "用户id")
@TableField("user_id")
private Long userId;
@Schema(description = "类型")
@TableField("type")
private String type;
@Schema(description = "偏好配置")
@TableField("config")
private String config;
}

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 = "PreferenceUpdateRequest", description = "用户偏好 更新请求对象")
public class PreferenceUpdateRequest implements Serializable {
@NotBlank
@Size(max = 12)
@Schema(description = "类型")
private String type;
@NotEmpty
@Schema(description = "偏好配置")
private Map<String, Object> config;
}

View File

@@ -0,0 +1,31 @@
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

@@ -6,6 +6,8 @@ import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Map;
/**
* 用户基本信息 视图响应对象
*
@@ -17,8 +19,8 @@ import lombok.NoArgsConstructor;
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Schema(name = "UserBaseInfoVO", description = "用户基本信息 视图响应对象")
public class UserBaseInfoVO {
@Schema(name = "UserCollectInfoVO", description = "用户聚合信息 视图响应对象")
public class UserCollectInfoVO {
@Schema(description = "id")
private Long id;
@@ -32,4 +34,10 @@ public class UserBaseInfoVO {
@Schema(description = "头像地址")
private String avatar;
@Schema(description = "系统偏好")
private Map<String, Object> systemPreference;
@Schema(description = "提示偏好")
private Map<String, Object> tipsPreference;
}

View File

@@ -22,8 +22,8 @@ import java.util.List;
@Schema(name = "UserPermissionVO", description = "用户权限 视图响应对象")
public class UserPermissionVO {
@Schema(description = "用户基本信息")
private UserBaseInfoVO user;
@Schema(description = "用户聚合信息")
private UserCollectInfoVO user;
@Schema(description = "该用户已启用的角色")
private List<String> roles;

View File

@@ -0,0 +1,66 @@
package com.orion.ops.module.infra.enums;
import com.orion.ops.module.infra.handler.preference.model.PreferenceModel;
import com.orion.ops.module.infra.handler.preference.strategy.IPreferenceStrategy;
import com.orion.spring.SpringHolder;
import lombok.Getter;
/**
* 偏好类型
*
* @author Jiahang Li
* @version 1.0.0
* @since 2023/10/8 11:31
*/
@Getter
public enum PreferenceTypeEnum {
/**
* 系统偏好
*/
SYSTEM("systemPreferenceStrategy"),
/**
* 提示偏好
*/
TIPS("tipsPreferenceStrategy"),
;
PreferenceTypeEnum(String beanName) {
this.type = this.name();
this.beanName = beanName;
}
private final String type;
/**
* 策越 bean 名称
* 可能跨模块所以不用 class
*/
private final String beanName;
public static PreferenceTypeEnum of(String type) {
if (type == null) {
return null;
}
for (PreferenceTypeEnum value : values()) {
if (value.type.equals(type)) {
return value;
}
}
return null;
}
/**
* 获取策略
*
* @param <M> model
* @param <T> type
* @return IPreferenceStrategy
*/
public <M extends PreferenceModel, T extends IPreferenceStrategy<M>> T getStrategy() {
return SpringHolder.getBean(beanName);
}
}

View File

@@ -0,0 +1,52 @@
package com.orion.ops.module.infra.handler.preference.model;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* 系统偏好模型
*
* @author Jiahang Li
* @version 1.0.0
* @since 2023/10/8 13:59
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class AppPreferenceModel implements PreferenceModel {
@Schema(description = "是否使用侧边菜单")
private Boolean menu;
@Schema(description = "是否使用顶部菜单")
private Boolean topMenu;
@Schema(description = "是否显示导航栏")
private Boolean navbar;
@Schema(description = "是否显示页脚")
private Boolean footer;
@Schema(description = "是否开启多页签")
private Boolean tabBar;
@Schema(description = "是否开启色弱模式")
private Boolean colorWeak;
@Schema(description = "菜单宽度")
private Number menuWidth;
@Schema(description = "主机视图")
private String hostView;
@Schema(description = "主机秘钥视图")
private String hostKeyView;
@Schema(description = "主机身份视图")
private String hostIdentityView;
}

View File

@@ -0,0 +1,25 @@
package com.orion.ops.module.infra.handler.preference.model;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* 提示偏好模型
*
* @author Jiahang Li
* @version 1.0.0
* @since 2023/10/8 13:59
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class TipsPreferenceModel implements PreferenceModel {
@Schema(description = "是否提示过系统偏好设置模态框")
private Boolean tippedSystemPreferenceModal;
}

View File

@@ -0,0 +1,36 @@
package com.orion.ops.module.infra.handler.preference.strategy;
import com.orion.ops.module.infra.handler.preference.model.AppPreferenceModel;
import org.springframework.stereotype.Component;
/**
* 系统偏好处理策略
*
* @author Jiahang Li
* @version 1.0.0
* @since 2023/10/8 13:48
*/
@Component
public class SystemPreferenceStrategy implements IPreferenceStrategy<AppPreferenceModel> {
private static final String TABLE = "table";
private static final String CARD = "card";
@Override
public AppPreferenceModel getDefault() {
return AppPreferenceModel.builder()
.menu(true)
.topMenu(false)
.navbar(true)
.footer(true)
.tabBar(true)
.menuWidth(220)
.colorWeak(false)
.hostView(TABLE)
.hostKeyView(CARD)
.hostIdentityView(CARD)
.build();
}
}

View File

@@ -0,0 +1,23 @@
package com.orion.ops.module.infra.handler.preference.strategy;
import com.orion.ops.module.infra.handler.preference.model.TipsPreferenceModel;
import org.springframework.stereotype.Component;
/**
* 提示偏好处理策略
*
* @author Jiahang Li
* @version 1.0.0
* @since 2023/10/8 15:11
*/
@Component
public class TipsPreferenceStrategy implements IPreferenceStrategy<TipsPreferenceModel> {
@Override
public TipsPreferenceModel getDefault() {
return TipsPreferenceModel.builder()
.tippedSystemPreferenceModal(false)
.build();
}
}

View File

@@ -0,0 +1,52 @@
package com.orion.ops.module.infra.service;
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;
import java.util.concurrent.Future;
/**
* 用户偏好 服务类
*
* @author Jiahang Li
* @version 1.0.0
* @since 2023-9-27 18:37
*/
public interface PreferenceService {
/**
* 更新用户偏好
*
* @param request request
* @param partial 是否为部分更新
* @return effect
*/
Integer updatePreference(PreferenceUpdateRequest request, boolean partial);
/**
* 查询用户偏好
*
* @param type type
* @return row
*/
PreferenceVO getPreferenceByType(String type);
/**
* 获取用户偏好
*
* @param userId userId
* @param type type
* @return 偏好
*/
Future<Map<String, Object>> getPreference(Long userId, PreferenceTypeEnum type);
/**
* 删除用户偏好
*
* @param userId userId
*/
void deletePreferenceByUserId(Long userId);
}

View File

@@ -17,6 +17,7 @@ import com.orion.ops.module.infra.enums.FavoriteTypeEnum;
import com.orion.ops.module.infra.service.FavoriteService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
@@ -111,6 +112,7 @@ public class FavoriteServiceImpl implements FavoriteService {
}
@Override
@Async("asyncExecutor")
public void deleteFavoriteByUserId(Long userId) {
if (userId == null) {
return;
@@ -127,6 +129,7 @@ public class FavoriteServiceImpl implements FavoriteService {
}
@Override
@Async("asyncExecutor")
public void deleteFavoriteByUserIdList(List<Long> userIdList) {
if (Lists.isEmpty(userIdList)) {
return;

View File

@@ -16,20 +16,24 @@ import com.orion.ops.module.infra.entity.domain.SystemRoleDO;
import com.orion.ops.module.infra.entity.domain.SystemRoleMenuDO;
import com.orion.ops.module.infra.entity.dto.SystemMenuCacheDTO;
import com.orion.ops.module.infra.entity.vo.SystemMenuVO;
import com.orion.ops.module.infra.entity.vo.UserBaseInfoVO;
import com.orion.ops.module.infra.entity.vo.UserCollectInfoVO;
import com.orion.ops.module.infra.entity.vo.UserPermissionVO;
import com.orion.ops.module.infra.enums.MenuStatusEnum;
import com.orion.ops.module.infra.enums.MenuTypeEnum;
import com.orion.ops.module.infra.enums.PreferenceTypeEnum;
import com.orion.ops.module.infra.enums.RoleStatusEnum;
import com.orion.ops.module.infra.service.PermissionService;
import com.orion.ops.module.infra.service.PreferenceService;
import com.orion.ops.module.infra.service.SystemMenuService;
import lombok.Getter;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.Future;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@@ -66,11 +70,14 @@ public class PermissionServiceImpl implements PermissionService {
@Resource
private SystemMenuService systemMenuService;
@Resource
private PreferenceService preferenceService;
@PostConstruct
@Override
public void initPermissionCache() {
long start = System.currentTimeMillis();
log.info("initRoleMenuCache-start");
log.info("initPermissionCache-start");
roleCache.clear();
menuCache.clear();
roleMenuCache.clear();
@@ -104,7 +111,7 @@ public class PermissionServiceImpl implements PermissionService {
.map(SystemRoleDO::getCode)
.ifPresent(code -> roleMenuCache.put(code, roleMenus));
});
log.info("initRoleMenuCache-end used: {}ms", System.currentTimeMillis() - start);
log.info("initPermissionCache-end used: {}ms", System.currentTimeMillis() - start);
}
@Override
@@ -186,10 +193,16 @@ public class PermissionServiceImpl implements PermissionService {
return systemMenuService.buildSystemMenuTree(menus);
}
@SneakyThrows
@Override
public UserPermissionVO getUserPermission() {
// 获取用户信息
UserBaseInfoVO user = SystemUserConvert.MAPPER.toBaseInfo(SecurityUtils.getLoginUser());
UserCollectInfoVO user = SystemUserConvert.MAPPER.toCollectInfo(SecurityUtils.getLoginUser());
Long id = user.getId();
// 获取用户系统偏好
Future<Map<String, Object>> systemPreference = preferenceService.getPreference(id, PreferenceTypeEnum.SYSTEM);
// 获取用户提示偏好
Future<Map<String, Object>> tipsPreference = preferenceService.getPreference(id, PreferenceTypeEnum.TIPS);
// 获取用户角色
List<String> roles = this.getUserEnabledRoles();
// 获取用户权限
@@ -213,6 +226,9 @@ public class PermissionServiceImpl implements PermissionService {
.collect(Collectors.toList());
}
}
// 获取异步结果
user.setSystemPreference(systemPreference.get());
user.setTipsPreference(tipsPreference.get());
// 组装数据
return UserPermissionVO.builder()
.user(user)

View File

@@ -0,0 +1,165 @@
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.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.security.core.utils.SecurityUtils;
import com.orion.ops.module.infra.dao.PreferenceDAO;
import com.orion.ops.module.infra.define.PreferenceCacheKeyDefine;
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 com.orion.ops.module.infra.enums.PreferenceTypeEnum;
import com.orion.ops.module.infra.service.PreferenceService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Future;
import java.util.stream.Collectors;
/**
* 用户偏好 服务实现类
*
* @author Jiahang Li
* @version 1.0.0
* @since 2023-9-27 18:37
*/
@Slf4j
@Service
public class PreferenceServiceImpl implements PreferenceService {
@Resource
private PreferenceDAO preferenceDAO;
@Override
public Integer updatePreference(PreferenceUpdateRequest request, boolean partial) {
Long userId = SecurityUtils.getLoginUserId();
String type = request.getType();
Valid.valid(PreferenceTypeEnum::of, type);
// 查询
PreferenceDO preference = preferenceDAO.of()
.wrapper(this.buildQueryWrapper(userId, type))
.getOne();
int effect;
if (preference == null) {
// 直接插入
PreferenceDO insertRecord = new PreferenceDO();
insertRecord.setUserId(userId);
insertRecord.setType(type);
insertRecord.setConfig(JSON.toJSONString(request.getConfig()));
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()));
}
effect = preferenceDAO.updateById(updateRecord);
// 删除缓存
RedisStrings.delete(PreferenceCacheKeyDefine.PREFERENCE.format(userId, type));
}
return effect;
}
@Override
public PreferenceVO 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();
}
@Override
@Async("asyncExecutor")
public Future<Map<String, Object>> getPreference(Long userId, PreferenceTypeEnum type) {
Map<String, Object> config = this.getPreferenceByCache(userId, type);
return CompletableFuture.completedFuture(config);
}
@Override
@Async("asyncExecutor")
public void deletePreferenceByUserId(Long userId) {
// 删除
int effect = preferenceDAO.deleteByUserId(userId);
log.info("PreferenceService-deletePreferenceById userId: {}, effect: {}", userId, effect);
// 删除缓存
List<String> deleteKeys = Arrays.stream(PreferenceTypeEnum.values())
.map(s -> PreferenceCacheKeyDefine.PREFERENCE.format(userId, s))
.collect(Collectors.toList());
RedisStrings.delete(deleteKeys);
}
/**
* 通过缓存获取偏好
*
* @param userId userId
* @param type type
* @return config
*/
private Map<String, Object> getPreferenceByCache(Long userId, PreferenceTypeEnum type) {
String typeValue = type.getType();
// 查询缓存 用 string 防止数据类型丢失
String key = PreferenceCacheKeyDefine.PREFERENCE.format(userId, type);
Map<String, Object> config = RedisStrings.getJson(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);
}
// 初始化
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);
}
// 设置缓存
if (setCache) {
RedisStrings.setJson(key, PreferenceCacheKeyDefine.PREFERENCE, config);
}
return config;
}
/**
* 构建查询 wrapper
*
* @param userId userId
* @param type type
* @return wrapper
*/
private LambdaQueryWrapper<PreferenceDO> buildQueryWrapper(Long userId, String type) {
return preferenceDAO.wrapper()
.eq(PreferenceDO::getUserId, userId)
.eq(PreferenceDO::getType, type);
}
}

View File

@@ -22,6 +22,7 @@ import com.orion.ops.module.infra.entity.vo.SystemUserVO;
import com.orion.ops.module.infra.enums.UserStatusEnum;
import com.orion.ops.module.infra.service.AuthenticationService;
import com.orion.ops.module.infra.service.FavoriteService;
import com.orion.ops.module.infra.service.PreferenceService;
import com.orion.ops.module.infra.service.SystemUserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
@@ -52,6 +53,9 @@ public class SystemUserServiceImpl implements SystemUserService {
@Resource
private FavoriteService favoriteService;
@Resource
private PreferenceService preferenceService;
@Resource
private RedisTemplate<String, String> redisTemplate;
@@ -169,6 +173,8 @@ public class SystemUserServiceImpl implements SystemUserService {
redisTemplate.delete(UserCacheKeyDefine.USER_INFO.format(id));
// 删除用户收藏
favoriteService.deleteFavoriteByUserId(id);
// 删除用户偏好
preferenceService.deletePreferenceByUserId(id);
return effect;
}

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.orion.ops.module.infra.dao.PreferenceDAO">
<!-- 通用查询映射结果 -->
<resultMap id="BaseResultMap" type="com.orion.ops.module.infra.entity.domain.PreferenceDO">
<id column="id" property="id"/>
<result column="create_time" property="createTime"/>
<result column="update_time" property="updateTime"/>
<result column="creator" property="creator"/>
<result column="updater" property="updater"/>
<result column="deleted" property="deleted"/>
<result column="user_id" property="userId"/>
<result column="type" property="type"/>
<result column="config" property="config"/>
</resultMap>
<!-- 通用查询结果列 -->
<sql id="Base_Column_List">
id, user_id, type, config, create_time, update_time, creator, updater, deleted
</sql>
</mapper>