upd: 控制器

This commit is contained in:
骑着蜗牛追导弹 2024-12-06 21:11:38 +08:00
parent 1bbca46b72
commit 3a0a233f6a
15 changed files with 415 additions and 77 deletions

View File

@ -7,8 +7,9 @@ package cn.odboy.constant;
* @date 2024-09-13 * @date 2024-09-13
*/ */
public interface RegexConst { public interface RegexConst {
// 正则表达式用于匹配中国大陆手机号码 /** 正则表达式,用于匹配中国大陆手机号码 */
String PHONE_NUMBER = "^1[3-9]\\d{9}$"; String PHONE_NUMBER = "^1[3-9]\\d{9}$";
// 小写字母和下划线
String LOW_CHAR_LINE = "^[a-z_]+$"; /** 小写字母和下划线 */
String LOW_CHAR_LINE = "^[a-z_]+$";
} }

View File

@ -1,17 +1,19 @@
package cn.odboy.domain; package cn.odboy.domain;
import cn.odboy.base.MyObject; import cn.odboy.base.MyLogicEntity;
import cn.odboy.base.MyNormalEntity;
import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.annotation.TableName;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import lombok.Data;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
/** /**
* <p>
* 配置应用 * 配置应用
* </p>
* *
* @author odboy * @author odboy
* @since 2024-12-05 * @since 2024-12-05
@ -19,18 +21,46 @@ import lombok.Setter;
@Getter @Getter
@Setter @Setter
@TableName("config_app") @TableName("config_app")
public class ConfigApp extends MyObject { public class ConfigApp extends MyNormalEntity {
@TableId(value = "id", type = IdType.AUTO) @TableId(value = "id", type = IdType.AUTO)
private Long id; private Long id;
/**
* 应用名称 /** 应用名称 */
*/ @TableField("app_name")
@TableField("app_name") private String appName;
/** 应用说明 */
@TableField("description")
private String description;
@Data
public static class CreateArgs {
@NotBlank(message = "必填")
private String appName; private String appName;
/**
* 应用说明 @NotBlank(message = "必填")
*/
@TableField("description")
private String description; private String description;
}
@Data
public static class ModifyDescriptionArgs {
@NotNull(message = "必填")
private Long id;
@NotBlank(message = "必填")
private String description;
}
@Data
public static class RemoveArgs{
@NotNull(message = "必填")
private Long id;
}
@Data
public static class ClientInfo{
private String ip;
private Boolean isActive = false;
}
} }

View File

@ -0,0 +1,25 @@
package cn.odboy.domain;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Getter;
import lombok.Setter;
/**
* 配置应用与用户关联关系
*
* @author odboy
* @since 2024-12-06
*/
@Getter
@Setter
@TableName("config_app_user")
public class ConfigAppUser {
/** 应用名称 */
@TableField("app_id")
private Long appId;
/** 应用名称 */
@TableField("user_id")
private Long userId;
}

View File

@ -1,18 +1,21 @@
package cn.odboy.domain; package cn.odboy.domain;
import cn.odboy.base.MyObject; import cn.odboy.base.MyNormalEntity;
import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.annotation.TableName;
import javax.mail.Multipart;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import lombok.Data; import lombok.Data;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import org.springframework.web.multipart.MultipartFile;
/** /**
* <p>
* 配置文件 * 配置文件
* </p>
* *
* @author odboy * @author odboy
* @since 2024-12-05 * @since 2024-12-05
@ -20,26 +23,51 @@ import lombok.Setter;
@Getter @Getter
@Setter @Setter
@TableName("config_file") @TableName("config_file")
public class ConfigFile extends MyObject { public class ConfigFile extends MyNormalEntity {
@TableId(value = "id", type = IdType.AUTO) @TableId(value = "id", type = IdType.AUTO)
private Long id; private Long id;
@TableField("app_name") /** configAppId */
private String appName; @TableField("app_id")
private Long appId;
@TableField("env") /** 环境编码 */
@TableField("env")
private String env;
/** 例如: application-daily.properties */
@TableField("file_name")
private String fileName;
/** 当前配置内容版本 */
@TableField("version")
private Long version;
@Data
public static class CreateArgs {
@NotNull(message = "必填")
private Long appId;
@NotBlank(message = "必填")
private String env; private String env;
/** @NotNull(message = "必填")
* 例如: application-daily.properties private MultipartFile file;
*/ }
@TableField("file_name")
private String fileName;
/** @Data
* 当前配置内容版本 public static class ModifyFileContentArgs {
*/ @NotNull(message = "必填")
@TableField("version") private Long id;
private Long version;
@NotBlank(message = "必填")
private String fileContent;
}
@Data
public class RemoveArgs {
@NotNull(message = "必填")
private Long id;
}
} }

View File

@ -1,17 +1,13 @@
package cn.odboy.domain; package cn.odboy.domain;
import cn.odboy.base.MyObject; import cn.odboy.base.MyObject;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
/** /**
* <p>
* 配置内容版本 * 配置内容版本
* </p>
* *
* @author odboy * @author odboy
* @since 2024-12-05 * @since 2024-12-05
@ -20,9 +16,15 @@ import lombok.Setter;
@Setter @Setter
@TableName("config_version") @TableName("config_version")
public class ConfigVersion extends MyObject { public class ConfigVersion extends MyObject {
@TableField("file_id") /** 文件id */
private Long fileId; @TableField("file_id")
private Long fileId;
@TableField("file_content") /** 配置文件内容 */
private byte[] fileContent; @TableField("file_content")
private String fileContent;
/** 配置文件内容版本 */
@TableField("version")
private Long version;
} }

View File

@ -0,0 +1,14 @@
package cn.odboy.mapper;
import cn.odboy.domain.ConfigVersion;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
/**
* 配置版本 Mapper 接口
*
* @author odboy
* @since 2024-12-05
*/
@Mapper
public interface ConfigVersionMapper extends BaseMapper<ConfigVersion> {}

View File

@ -0,0 +1,58 @@
package cn.odboy.rest;
import cn.odboy.base.model.SelectOption;
import cn.odboy.domain.ConfigApp;
import cn.odboy.infra.exception.BadRequestException;
import cn.odboy.infra.netty.ConfigClientManage;
import cn.odboy.infra.response.PageArgs;
import cn.odboy.infra.response.PageResult;
import cn.odboy.infra.rest.AnonymousAccess;
import cn.odboy.modules.system.domain.User;
import cn.odboy.modules.system.domain.vo.UserQueryCriteria;
import cn.odboy.service.ConfigAppService;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.stream.Collectors;
/**
* 配置文件 前端控制器
*
* @author odboy
* @since 2024-12-05
*/
@RequiredArgsConstructor
@RestController
@RequestMapping("/api/config/app")
public class ConfigAppController {
private final ConfigAppService configAppService;
@PostMapping("/create")
public ResponseEntity<Object> create(@Validated @RequestBody ConfigApp.CreateArgs args) {
configAppService.create(args);
return new ResponseEntity<>(HttpStatus.OK);
}
@PostMapping("/remove")
public ResponseEntity<Object> remove(@Validated @RequestBody ConfigApp.RemoveArgs args) {
configAppService.remove(args);
return new ResponseEntity<>(HttpStatus.OK);
}
@PostMapping("/modifyDescription")
public ResponseEntity<Object> modifyDescription(@Validated @RequestBody ConfigApp.ModifyDescriptionArgs args) {
configAppService.modifyDescription(args);
return new ResponseEntity<>(HttpStatus.OK);
}
@AnonymousAccess
@GetMapping("/queryClientList")
public ResponseEntity<Object> queryClientList() {
return new ResponseEntity<>(ConfigClientManage.queryClientInfos("daily", "kenaito-config-demo"), HttpStatus.OK);
}
}

View File

@ -1,18 +1,44 @@
package cn.odboy.rest; package cn.odboy.rest;
import cn.odboy.domain.ConfigApp;
import cn.odboy.domain.ConfigFile;
import cn.odboy.service.ConfigFileService;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
/** /**
* <p>
* 配置文件 前端控制器 * 配置文件 前端控制器
* </p>
* *
* @author odboy * @author odboy
* @since 2024-12-05 * @since 2024-12-05
*/ */
@RequiredArgsConstructor
@RestController @RestController
@RequestMapping("/api/configFile") @RequestMapping("/api/config/file")
public class ConfigFileController { public class ConfigFileController {
private final ConfigFileService configFileService;
@PostMapping("/create")
public ResponseEntity<Object> create(@Validated @RequestBody ConfigFile.CreateArgs args) throws Exception {
configFileService.create(args);
return new ResponseEntity<>(HttpStatus.OK);
}
@PostMapping("/remove")
public ResponseEntity<Object> remove(@Validated @RequestBody ConfigFile.RemoveArgs args) {
configFileService.remove(args);
return new ResponseEntity<>(HttpStatus.OK);
}
@PostMapping("/modifyFileContent")
public ResponseEntity<Object> modifyFileContent(@Validated @RequestBody ConfigFile.ModifyFileContentArgs args) {
configFileService.modifyFileContent(args);
return new ResponseEntity<>(HttpStatus.OK);
}
} }

View File

@ -14,4 +14,9 @@ import com.baomidou.mybatisplus.extension.service.IService;
*/ */
public interface ConfigAppService extends IService<ConfigApp> { public interface ConfigAppService extends IService<ConfigApp> {
void create(ConfigApp.CreateArgs args);
void remove(ConfigApp.RemoveArgs args);
void modifyDescription(ConfigApp.ModifyDescriptionArgs args);
} }

View File

@ -1,22 +1,26 @@
package cn.odboy.service; package cn.odboy.service;
import cn.odboy.config.model.msgtype.ConfigFileInfo; import cn.odboy.config.model.msgtype.ConfigFileInfo;
import cn.odboy.domain.ConfigFile;
import com.baomidou.mybatisplus.extension.service.IService;
import java.util.List; import java.util.List;
/** /**
* <p>
* 配置文件 服务类 * 配置文件 服务类
* </p>
* *
* @author odboy * @author odboy
* @since 2024-12-05 * @since 2024-12-05
*/ */
public interface ConfigFileService { public interface ConfigFileService extends IService<ConfigFile> {
/** /**
* @param env 环境编码 * @param env 环境编码
* @param dataId 数据ID这里是应用名称 * @param dataId 数据ID这里是应用名称
* @return / * @return /
*/ */
List<ConfigFileInfo> getFileList(String env, String dataId); List<ConfigFileInfo> getFileList(String env, String dataId);
List<ConfigFile> queryInAppId(Long appId);
void create(ConfigFile.CreateArgs args) throws Exception;
void remove(ConfigFile.RemoveArgs args);
void modifyFileContent(ConfigFile.ModifyFileContentArgs args);
} }

View File

@ -0,0 +1,17 @@
package cn.odboy.service;
import cn.odboy.domain.ConfigVersion;
import com.baomidou.mybatisplus.extension.service.IService;
import java.util.List;
/**
* 配置版本 服务类
*
* @author odboy
* @since 2024-12-05
*/
public interface ConfigVersionService extends IService<ConfigVersion> {
List<ConfigVersion> queryInFileId(List<Long> fileIds);
void removeBatchByFileId(Long fileId);
}

View File

@ -1,23 +1,66 @@
package cn.odboy.service.impl; package cn.odboy.service.impl;
import cn.hutool.core.bean.BeanUtil;
import cn.odboy.domain.ConfigApp; import cn.odboy.domain.ConfigApp;
import cn.odboy.domain.ConfigFile; import cn.odboy.domain.ConfigFile;
import cn.odboy.domain.ConfigVersion;
import cn.odboy.mapper.ConfigAppMapper; import cn.odboy.mapper.ConfigAppMapper;
import cn.odboy.mapper.ConfigFileMapper;
import cn.odboy.service.ConfigAppService; import cn.odboy.service.ConfigAppService;
import cn.odboy.service.ConfigFileService; import cn.odboy.service.ConfigFileService;
import cn.odboy.service.ConfigVersionService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import java.util.List;
import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
/** /**
* <p>
* 配置应用 服务实现类 * 配置应用 服务实现类
* </p>
* *
* @author odboy * @author odboy
* @since 2024-12-05 * @since 2024-12-05
*/ */
@Service @Service
public class ConfigAppServiceImpl extends ServiceImpl<ConfigAppMapper, ConfigApp> implements ConfigAppService { @RequiredArgsConstructor
public class ConfigAppServiceImpl extends ServiceImpl<ConfigAppMapper, ConfigApp>
implements ConfigAppService {
private final ConfigFileService configFileService;
private final ConfigVersionService configVersionService;
@Override
@Transactional(rollbackFor = Exception.class)
public void create(ConfigApp.CreateArgs args) {
save(BeanUtil.copyProperties(args, ConfigApp.class));
}
@Override
@Transactional(rollbackFor = Exception.class)
public void remove(ConfigApp.RemoveArgs args) {
removeById(args.getId());
List<ConfigFile> configFileList = configFileService.queryInAppId(args.getId());
if (configFileList.isEmpty()) {
return;
}
List<Long> configFileIds =
configFileList.stream().map(ConfigFile::getId).distinct().collect(Collectors.toList());
configFileService.removeBatchByIds(configFileIds);
List<ConfigVersion> configVersionList = configVersionService.queryInFileId(configFileIds);
if (configVersionList.isEmpty()) {
return;
}
List<Long> configVersionIds =
configVersionList.stream()
.map(ConfigVersion::getFileId)
.distinct()
.collect(Collectors.toList());
configVersionService.removeBatchByIds(configVersionIds);
}
@Override
@Transactional(rollbackFor = Exception.class)
public void modifyDescription(ConfigApp.ModifyDescriptionArgs args) {
ConfigApp configApp = BeanUtil.copyProperties(args, ConfigApp.class);
updateById(configApp);
}
} }

View File

@ -1,28 +1,81 @@
package cn.odboy.service.impl; package cn.odboy.service.impl;
import cn.hutool.core.util.StrUtil;
import cn.odboy.config.model.msgtype.ConfigFileInfo; import cn.odboy.config.model.msgtype.ConfigFileInfo;
import cn.odboy.domain.ConfigFile;
import cn.odboy.domain.ConfigVersion;
import cn.odboy.mapper.ConfigFileMapper; import cn.odboy.mapper.ConfigFileMapper;
import cn.odboy.service.ConfigFileService; import cn.odboy.service.ConfigFileService;
import cn.odboy.service.ConfigVersionService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import java.nio.charset.StandardCharsets;
import java.util.List;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List; import org.springframework.web.multipart.MultipartFile;
/** /**
* <p>
* 配置文件 服务实现类 * 配置文件 服务实现类
* </p>
* *
* @author odboy * @author odboy
* @since 2024-12-05 * @since 2024-12-05
*/ */
@Service @Service
@RequiredArgsConstructor @RequiredArgsConstructor
public class ConfigFileServiceImpl implements ConfigFileService { public class ConfigFileServiceImpl extends ServiceImpl<ConfigFileMapper, ConfigFile>
private final ConfigFileMapper configFileMapper; implements ConfigFileService {
private final ConfigVersionService configVersionService;
@Override @Override
public List<ConfigFileInfo> getFileList(String env, String dataId) { public List<ConfigFileInfo> getFileList(String env, String dataId) {
return configFileMapper.selectByEnvAndAppName(env, dataId); return getBaseMapper().selectByEnvAndAppName(env, dataId);
} }
@Override
public List<ConfigFile> queryInAppId(Long appId) {
return list(new LambdaQueryWrapper<ConfigFile>().in(ConfigFile::getAppId, appId));
}
@Override
@Transactional(rollbackFor = Exception.class)
public void create(ConfigFile.CreateArgs args) throws Exception {
MultipartFile file = args.getFile();
Long version = 1L;
ConfigFile configFile = new ConfigFile();
configFile.setEnv(args.getEnv());
configFile.setAppId(args.getAppId());
configFile.setFileName(file.getOriginalFilename());
configFile.setVersion(version);
save(configFile);
ConfigVersion configVersion = new ConfigVersion();
configVersion.setFileId(configFile.getId());
configVersion.setFileContent(StrUtil.str(file.getBytes(), StandardCharsets.UTF_8));
configVersion.setVersion(version);
configVersionService.save(configVersion);
}
@Override
@Transactional(rollbackFor = Exception.class)
public void remove(ConfigFile.RemoveArgs args) {
removeById(args.getId());
configVersionService.removeBatchByFileId(args.getId());
}
@Override
@Transactional(rollbackFor = Exception.class)
public void modifyFileContent(ConfigFile.ModifyFileContentArgs args) {
ConfigFile originConfigFile = getById(args.getId());
long newVersion = originConfigFile.getVersion() + 1;
ConfigFile updVersion = new ConfigFile();
updVersion.setId(originConfigFile.getId());
updVersion.setVersion(newVersion);
updateById(updVersion);
ConfigVersion lastConfigVersion = new ConfigVersion();
lastConfigVersion.setFileId(originConfigFile.getId());
lastConfigVersion.setFileContent(args.getFileContent());
lastConfigVersion.setVersion(newVersion);
configVersionService.save(lastConfigVersion);
}
} }

View File

@ -0,0 +1,31 @@
package cn.odboy.service.impl;
import cn.odboy.domain.ConfigVersion;
import cn.odboy.mapper.ConfigVersionMapper;
import cn.odboy.service.ConfigVersionService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import java.util.List;
import org.springframework.stereotype.Service;
/**
* 配置版本 服务实现类
*
* @author odboy
* @since 2024-12-05
*/
@Service
public class ConfigVersionServiceImpl extends ServiceImpl<ConfigVersionMapper, ConfigVersion>
implements ConfigVersionService {
@Override
public List<ConfigVersion> queryInFileId(List<Long> fileIds) {
return list(new LambdaQueryWrapper<ConfigVersion>().in(ConfigVersion::getFileId, fileIds));
}
@Override
public void removeBatchByFileId(Long fileId) {
remove(new LambdaQueryWrapper<ConfigVersion>()
.eq(ConfigVersion::getFileId, fileId)
);
}
}

View File

@ -2,12 +2,13 @@
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.odboy.mapper.ConfigFileMapper"> <mapper namespace="cn.odboy.mapper.ConfigFileMapper">
<select id="selectByEnvAndAppName" resultType="cn.odboy.config.model.msgtype.ConfigFileInfo"> <select id="selectByEnvAndAppName" resultType="cn.odboy.config.model.msgtype.ConfigFileInfo">
SELECT t1.file_name, SELECT t2.file_name,
t2.file_content t3.file_content
FROM config_file t1 FROM config_app t1
LEFT JOIN config_version t2 ON t1.id = t2.file_id LEFT JOIN config_file t2 ON t1.id = t2.app_id
AND t1.version = t2.version LEFT JOIN config_version t3 ON t1.id = t3.file_id
WHERE t1.env = #{env} AND t2.version = t3.version
WHERE t2.env = #{env}
AND t1.app_name = #{dataId} AND t1.app_name = #{dataId}
</select> </select>
</mapper> </mapper>