feat: 增加系统配置

增加系统配置功能
This commit is contained in:
胡少翔
2024-07-30 16:21:10 +08:00
parent 01c1c0807e
commit 5677a6bba0
9 changed files with 166 additions and 21 deletions

View File

@@ -0,0 +1,15 @@
package com.youlai.system.common.constant;
/**
* Redis Key常量
*
* @author Theo
* @since 2024-7-29 11:46:08
*/
public interface RedisKeyConstants {
/**
* 系统配置Redis-key
*/
String SYSTEM_CONFIG_KEY = "system:config";
}

View File

@@ -2,6 +2,7 @@ package com.youlai.system.common.constant;
/** /**
* 符号和特殊符号常用类 * 符号和特殊符号常用类
*
* @author Theo * @author Theo
* @since 2024-7-29 11:46:08 * @since 2024-7-29 11:46:08
*/ */

View File

@@ -23,4 +23,15 @@ public interface SystemConstants {
* 超级管理员角色编码 * 超级管理员角色编码
*/ */
String ROOT_ROLE_CODE = "ROOT"; String ROOT_ROLE_CODE = "ROOT";
/**
* 未删除状态
*/
Integer NOT_DELETED_STATUS = 0;
/**
* 删除状态
*/
Integer DELETED_STATUS = 1;
} }

View File

@@ -7,6 +7,7 @@ import com.youlai.system.model.form.ConfigForm;
import com.youlai.system.model.query.ConfigPageQuery; import com.youlai.system.model.query.ConfigPageQuery;
import com.youlai.system.model.vo.ConfigVO; import com.youlai.system.model.vo.ConfigVO;
import com.youlai.system.service.SysConfigService; import com.youlai.system.service.SysConfigService;
import io.swagger.v3.oas.annotations.Parameter;
import jakarta.validation.Valid; import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
@@ -18,10 +19,10 @@ import org.springframework.security.access.prepost.PreAuthorize;
/** /**
* 系统配置 前端控制 * 系统配置前端控制
* *
* @author Theo * @author Theo
* @since 2024-07-29 11:17:26 * @since 2024-07-30 11:25
*/ */
@Slf4j @Slf4j
@RestController @RestController
@@ -34,27 +35,43 @@ public class SysConfigController {
@GetMapping("/page") @GetMapping("/page")
@Operation(summary = "系统配置分页列表") @Operation(summary = "系统配置分页列表")
@PreAuthorize("@ss.hasPerm('business:config:query')") @PreAuthorize("@ss.hasPerm('sys:config:query')")
public PageResult<ConfigVO> page(@ParameterObject ConfigPageQuery configPageQuery) { public PageResult<ConfigVO> page(@ParameterObject ConfigPageQuery configPageQuery) {
IPage<ConfigVO> result = sysConfigService.page(configPageQuery); IPage<ConfigVO> result = sysConfigService.page(configPageQuery);
return PageResult.success(result); return PageResult.success(result);
} }
@Operation(summary = "新增系统配置") @Operation(summary = "新增系统配置")
@PostMapping(value = "/save") @PostMapping
@PreAuthorize("@ss.hasPerm('business:config:add')") @PreAuthorize("@ss.hasPerm('sys:config:add')")
public Result<?> save(@RequestBody @Valid ConfigForm configForm) { public Result<?> save(@RequestBody @Valid ConfigForm configForm) {
return Result.judge(sysConfigService.save(configForm)); return Result.judge(sysConfigService.save(configForm));
} }
@PutMapping("/update/{id}") @Operation(summary = "获取系统配置表单数据")
@GetMapping("/{id}/form")
public Result<ConfigForm> getConfigForm(
@Parameter(description = "系统配置ID") @PathVariable Long id
) {
ConfigForm formData = sysConfigService.getConfigFormData(id);
return Result.success(formData);
}
@Operation(summary = "刷新系统配置缓存")
@PatchMapping
@PreAuthorize("@ss.hasPerm('sys:config:refresh')")
public Result<ConfigForm> refreshCache() {
return Result.judge(sysConfigService.refreshCache());
}
@PutMapping(value = "/{id}")
@Operation(summary = "修改系统配置") @Operation(summary = "修改系统配置")
@PreAuthorize("@ss.hasPerm('business:config:update')") @PreAuthorize("@ss.hasPerm('sys:config:update')")
public Result<?> update(@Valid @PathVariable Long id, @RequestBody ConfigForm configForm) { public Result<?> update(@Valid @PathVariable Long id, @RequestBody ConfigForm configForm) {
return Result.judge(sysConfigService.edit(id, configForm)); return Result.judge(sysConfigService.edit(id, configForm));
} }
@DeleteMapping("/delete/{id}") @DeleteMapping("/{id}")
@Operation(summary = "删除系统配置") @Operation(summary = "删除系统配置")
@PreAuthorize("@ss.hasPerm('business:config:delete')") @PreAuthorize("@ss.hasPerm('business:config:delete')")
public Result<?> delete(@PathVariable Long id) { public Result<?> delete(@PathVariable Long id) {

View File

@@ -48,21 +48,18 @@ public class JwtValidationFilter extends OncePerRequestFilter {
@Override @Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
String token = request.getHeader(HttpHeaders.AUTHORIZATION); String token = request.getHeader(HttpHeaders.AUTHORIZATION);
try { try {
if (StrUtil.isNotBlank(token) && token.startsWith(SecurityConstants.JWT_TOKEN_PREFIX)) { if (StrUtil.isNotBlank(token) && token.startsWith(SecurityConstants.JWT_TOKEN_PREFIX)) {
token = token.substring(SecurityConstants.JWT_TOKEN_PREFIX.length()); // 去除 Bearer 前缀 // 去除 Bearer 前缀
token = token.substring(SecurityConstants.JWT_TOKEN_PREFIX.length());
// 解析 Token // 解析 Token
JWT jwt = JWTUtil.parseToken(token); JWT jwt = JWTUtil.parseToken(token);
// 检查 Token 是否有效(验签 + 是否过期) // 检查 Token 是否有效(验签 + 是否过期)
boolean isValidate = jwt.setKey(secretKey).validate(0); boolean isValidate = jwt.setKey(secretKey).validate(0);
if (!isValidate) { if (!isValidate) {
ResponseUtils.writeErrMsg(response, ResultCode.TOKEN_INVALID); ResponseUtils.writeErrMsg(response, ResultCode.TOKEN_INVALID);
return; return;
} }
// 检查 Token 是否已被加入黑名单(注销) // 检查 Token 是否已被加入黑名单(注销)
JSONObject payloads = jwt.getPayloads(); JSONObject payloads = jwt.getPayloads();
String jti = payloads.getStr(JWTPayload.JWT_ID); String jti = payloads.getStr(JWTPayload.JWT_ID);
@@ -71,11 +68,9 @@ public class JwtValidationFilter extends OncePerRequestFilter {
ResponseUtils.writeErrMsg(response, ResultCode.TOKEN_INVALID); ResponseUtils.writeErrMsg(response, ResultCode.TOKEN_INVALID);
return; return;
} }
// Token 有效将其解析为 Authentication 对象,并设置到 Spring Security 上下文中 // Token 有效将其解析为 Authentication 对象,并设置到 Spring Security 上下文中
Authentication authentication = JwtUtils.getAuthentication(payloads); Authentication authentication = JwtUtils.getAuthentication(payloads);
SecurityContextHolder.getContext().setAuthentication(authentication); SecurityContextHolder.getContext().setAuthentication(authentication);
} }
} catch (Exception e) { } catch (Exception e) {
SecurityContextHolder.clearContext(); SecurityContextHolder.clearContext();

View File

@@ -1,9 +1,13 @@
package com.youlai.system.model.form; package com.youlai.system.model.form;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import lombok.Builder; import lombok.Builder;
import lombok.Data; import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/** /**
* 系统配置 表单实体 * 系统配置 表单实体
* *
@@ -12,6 +16,26 @@ import lombok.Data;
*/ */
@Data @Data
@Schema(description = "系统配置Form实体") @Schema(description = "系统配置Form实体")
public class ConfigForm { public class ConfigForm implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
@Schema(description = "主键")
private Long id;
@NotBlank(message = "配置名称不能为空")
@Schema(description = "配置名称")
private String sysName;
@NotBlank(message = "配置key不能为空")
@Schema(description = "配置key")
private String sysKey;
@NotBlank(message = "配置值不能为空")
@Schema(description = "配置值")
private String sysValue;
@Schema(description = "描述、备注")
private String remark;
} }

View File

@@ -10,10 +10,10 @@ import java.io.Serial;
import java.io.Serializable; import java.io.Serializable;
/** /**
* 系统配置视图对象
*
* @author Theo * @author Theo
* @description: 系统配置VO * @since 2024-07-30 14:49
* @Company 利盈智能
* @date 2024-07-29 11:17:26
*/ */
@Data @Data
@Builder @Builder
@@ -21,6 +21,7 @@ import java.io.Serializable;
@Schema(description = "系统配置VO") @Schema(description = "系统配置VO")
public class ConfigVO { public class ConfigVO {
@Schema(description = "主键")
private Long id; private Long id;
@Schema(description = "配置名称") @Schema(description = "配置名称")

View File

@@ -29,6 +29,14 @@ public interface SysConfigService extends IService<SysConfig> {
*/ */
boolean save(ConfigForm sysConfigForm); boolean save(ConfigForm sysConfigForm);
/**
* 获取系统配置表单数据
*
* @param id 系统配置ID
* @return
*/
ConfigForm getConfigFormData(Long id);
/** /**
* 编辑系统配置 * 编辑系统配置
* @param id 系统配置ID * @param id 系统配置ID
@@ -44,4 +52,18 @@ public interface SysConfigService extends IService<SysConfig> {
*/ */
boolean delete(Long ids); boolean delete(Long ids);
/**
* 刷新系统配置缓存
* @return 是否刷新成功
*/
boolean refreshCache();
/**
* 获取系统配置
* @param key 配置key
* @return 配置value
*/
Object getSystemConfig(String key);
} }

View File

@@ -4,15 +4,25 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.youlai.system.common.constant.RedisKeyConstants;
import com.youlai.system.common.constant.SystemConstants;
import com.youlai.system.converter.SysConfigConverter; import com.youlai.system.converter.SysConfigConverter;
import com.youlai.system.model.form.ConfigForm; import com.youlai.system.model.form.ConfigForm;
import com.youlai.system.model.query.ConfigPageQuery; import com.youlai.system.model.query.ConfigPageQuery;
import com.youlai.system.security.util.SecurityUtils;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import com.youlai.system.mapper.SysConfigMapper; import com.youlai.system.mapper.SysConfigMapper;
import com.youlai.system.model.entity.SysConfig; import com.youlai.system.model.entity.SysConfig;
import com.youlai.system.model.vo.ConfigVO; import com.youlai.system.model.vo.ConfigVO;
import com.youlai.system.service.SysConfigService; import com.youlai.system.service.SysConfigService;
import org.springframework.util.Assert;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/** /**
* 系统配置Service接口实现 * 系统配置Service接口实现
@@ -28,6 +38,8 @@ public class SysConfigServiceImpl extends ServiceImpl<SysConfigMapper, SysConfig
private final SysConfigConverter sysConfigConverter; private final SysConfigConverter sysConfigConverter;
private final RedisTemplate<String, Object> redisTemplate;
/** /**
* 分页查询系统配置 * 分页查询系统配置
* @param configPageQuery 查询参数 * @param configPageQuery 查询参数
@@ -37,7 +49,9 @@ public class SysConfigServiceImpl extends ServiceImpl<SysConfigMapper, SysConfig
public IPage<ConfigVO> page(ConfigPageQuery configPageQuery) { public IPage<ConfigVO> page(ConfigPageQuery configPageQuery) {
Page<SysConfig> page = new Page<>(configPageQuery.getPageNum(), configPageQuery.getPageSize()); Page<SysConfig> page = new Page<>(configPageQuery.getPageNum(), configPageQuery.getPageSize());
QueryWrapper<SysConfig> query = new QueryWrapper<>(); QueryWrapper<SysConfig> query = new QueryWrapper<>();
//TODO: 设置查询条件 if(StringUtils.isNotBlank(configPageQuery.getKeywords())) {
query.and(q -> q.like("sys_key", configPageQuery.getKeywords()).or().like("sys_name", configPageQuery.getKeywords()));
}
Page<SysConfig> pageList = this.page(page, query); Page<SysConfig> pageList = this.page(page, query);
return sysConfigConverter.convertToPageVo(pageList); return sysConfigConverter.convertToPageVo(pageList);
} }
@@ -49,10 +63,25 @@ public class SysConfigServiceImpl extends ServiceImpl<SysConfigMapper, SysConfig
*/ */
@Override @Override
public boolean save(ConfigForm configForm) { public boolean save(ConfigForm configForm) {
Assert.isTrue(super.count(new QueryWrapper<SysConfig>().eq("sys_key", configForm.getSysKey())) == 0, "配置key已存在");
SysConfig sysConfig = sysConfigConverter.toEntity(configForm); SysConfig sysConfig = sysConfigConverter.toEntity(configForm);
sysConfig.setCreateBy(SecurityUtils.getUserId());
sysConfig.setIsDeleted(SystemConstants.NOT_DELETED_STATUS);
return this.save(sysConfig); return this.save(sysConfig);
} }
/**
* 获取系统配置表单数据
*
* @param id 系统配置ID
* @return
*/
@Override
public ConfigForm getConfigFormData(Long id) {
SysConfig entity = this.getById(id);
return sysConfigConverter.toForm(entity);
}
/** /**
* 编辑系统配置 * 编辑系统配置
* @param id 系统配置ID * @param id 系统配置ID
@@ -61,8 +90,9 @@ public class SysConfigServiceImpl extends ServiceImpl<SysConfigMapper, SysConfig
*/ */
@Override @Override
public boolean edit(Long id, ConfigForm configForm) { public boolean edit(Long id, ConfigForm configForm) {
//TODO 可能的校验 Assert.isTrue(super.count(new QueryWrapper<SysConfig>().eq("sys_key", configForm.getSysKey()).ne("id", id)) == 0, "配置key已存在");
SysConfig sysConfig = sysConfigConverter.toEntity(configForm); SysConfig sysConfig = sysConfigConverter.toEntity(configForm);
sysConfig.setUpdateBy(SecurityUtils.getUserId());
return this.update(sysConfig, new QueryWrapper<SysConfig>().eq("id", id)); return this.update(sysConfig, new QueryWrapper<SysConfig>().eq("id", id));
} }
@@ -79,4 +109,33 @@ public class SysConfigServiceImpl extends ServiceImpl<SysConfigMapper, SysConfig
return false; return false;
} }
/**
* 刷新系统配置缓存
* @return 是否刷新成功
*/
@Override
public boolean refreshCache() {
redisTemplate.delete(RedisKeyConstants.SYSTEM_CONFIG_KEY);
List<SysConfig> list = this.list();
if (list != null) {
Map<String, String> map = list.stream().collect(Collectors.toMap(SysConfig::getSysKey, SysConfig::getSysValue));
redisTemplate.opsForHash().putAll(RedisKeyConstants.SYSTEM_CONFIG_KEY,map);
return true;
}
return false;
}
/**
* 获取系统配置
* @param key 配置key
* @return 配置value
*/
@Override
public Object getSystemConfig(String key) {
if(StringUtils.isNotBlank(key)){
return redisTemplate.opsForHash().get(RedisKeyConstants.SYSTEM_CONFIG_KEY, key);
}
return null;
}
} }