调整 errorCode 模块的自动生成逻辑

This commit is contained in:
YunaiV 2021-04-19 01:21:35 +08:00
parent 54e26d9e8b
commit 06774a7a0b
20 changed files with 428 additions and 355 deletions

View File

@ -1,26 +1,36 @@
package cn.iocoder.dashboard.framework.errorcode.config;
import cn.iocoder.dashboard.modules.system.service.errorcode.ErrorCodeRemoteLoaderImpl;
import cn.iocoder.dashboard.modules.system.service.errorcode.ErrorCodeAutoGeneratorImpl;
import cn.iocoder.dashboard.framework.errorcode.core.generator.ErrorCodeAutoGenerator;
import cn.iocoder.dashboard.framework.errorcode.core.loader.ErrorCodeLoader;
import cn.iocoder.dashboard.framework.errorcode.core.service.ErrorCodeFrameworkService;
import cn.iocoder.dashboard.framework.errorcode.core.loader.ErrorCodeLoaderImpl;
import cn.iocoder.dashboard.framework.errorcode.core.generator.ErrorCodeAutoGeneratorImpl;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
/**
* 错误码配置类
*/
@Configuration
@EnableConfigurationProperties(ErrorCodeProperties.class)
@EnableScheduling // 开启调度任务的功能因为 ErrorCodeRemoteLoader 通过定时刷新错误码
public class ErrorCodeAutoConfiguration {
@Bean
public ErrorCodeAutoGeneratorImpl errorCodeAutoGenerator(ErrorCodeProperties errorCodeProperties) {
return new ErrorCodeAutoGeneratorImpl(errorCodeProperties.getGroup())
.setErrorCodeConstantsClass(errorCodeProperties.getConstantsClass());
public ErrorCodeAutoGenerator errorCodeAutoGenerator(@Value("${spring.application.name}") String applicationName,
ErrorCodeProperties errorCodeProperties,
ErrorCodeFrameworkService errorCodeFrameworkService) {
return new ErrorCodeAutoGeneratorImpl(applicationName, errorCodeProperties.getConstantsClass(),
errorCodeFrameworkService);
}
@Bean
public ErrorCodeRemoteLoaderImpl errorCodeRemoteLoader(ErrorCodeProperties errorCodeProperties) {
return new ErrorCodeRemoteLoaderImpl(errorCodeProperties.getGroup());
public ErrorCodeLoader errorCodeLoader(@Value("${spring.application.name}") String applicationName,
ErrorCodeFrameworkService errorCodeFrameworkService) {
return new ErrorCodeLoaderImpl(applicationName, errorCodeFrameworkService);
}
}
}

View File

@ -1,25 +1,25 @@
package cn.iocoder.dashboard.framework.errorcode.config;
import lombok.Getter;
import lombok.Setter;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.validation.annotation.Validated;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.NotEmpty;
/**
* 错误码的配置属性类
*
* @author dlyan
*/
@ConfigurationProperties("yudao.error-code")
@Data
@Validated
@Getter
@Setter
public class ErrorCodeProperties {
/**
* 应用分组
*/
@NotNull(message = "应用分组不能为空,请设置 yudao.error-code.group 配置项,推荐直接使用 spring.application.name 配置项")
private String group;
/**
* 错误码枚举类
*/
@NotEmpty(message = "错误码枚举类不能为空")
private String constantsClass;
}
}

View File

@ -1,14 +0,0 @@
package cn.iocoder.dashboard.framework.errorcode.core;
public interface ErrorCodeRemoteLoader {
/**
* 全量加载 ErrorCode 错误码
*/
void loadErrorCodes();
/**
* 增量加载 ErrorCode 错误码
*/
void refreshErrorCodes();
}

View File

@ -1,19 +1,25 @@
package cn.iocoder.dashboard.modules.system.controller.errorcode.dto;
package cn.iocoder.dashboard.framework.errorcode.core.dto;
import lombok.Data;
import lombok.experimental.Accessors;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
/**
* 错误码自动生成 DTO
*
* @author dylan
*/
@Data
@Accessors(chain = true)
public class ErrorCodeAutoGenerateDTO implements Serializable {
public class ErrorCodeAutoGenerateReqDTO {
/**
* 应用名
*/
@NotNull(message = "应用名不能为空")
private String applicationName;
/**
* 错误码编码
*/
@ -24,10 +30,5 @@ public class ErrorCodeAutoGenerateDTO implements Serializable {
*/
@NotEmpty(message = "错误码错误提示不能为空")
private String message;
/**
* 错误码分组
*/
@NotNull(message = "错误码分组不能为空")
private String group;
}
}

View File

@ -0,0 +1,28 @@
package cn.iocoder.dashboard.framework.errorcode.core.dto;
import lombok.Data;
import java.util.Date;
/**
* 错误码的 Response DTO
*
* @author 芋道源码
*/
@Data
public class ErrorCodeRespDTO {
/**
* 错误码编码
*/
private Integer code;
/**
* 错误码错误提示
*/
private String message;
/**
* 更新时间
*/
private Date updateTime;
}

View File

@ -1,6 +1,8 @@
package cn.iocoder.dashboard.framework.errorcode.core;
package cn.iocoder.dashboard.framework.errorcode.core.generator;
/**
* 错误码的自动生成器
*
* @author dylan
*/
public interface ErrorCodeAutoGenerator {
@ -9,4 +11,5 @@ public interface ErrorCodeAutoGenerator {
* 将配置类到错误码写入数据库
*/
void execute();
}

View File

@ -0,0 +1,101 @@
package cn.iocoder.dashboard.framework.errorcode.core.generator;
import cn.iocoder.dashboard.common.exception.ErrorCode;
import cn.iocoder.dashboard.framework.errorcode.core.dto.ErrorCodeAutoGenerateReqDTO;
import cn.iocoder.dashboard.framework.errorcode.core.service.ErrorCodeFrameworkService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.event.EventListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.util.StringUtils;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* ErrorCodeAutoGenerator 的实现类
* 目的是扫描指定的 {@link #errorCodeConstantsClass} 写入到 system 的数据库中
*
* @author dylan
*/
@RequiredArgsConstructor
@Slf4j
public class ErrorCodeAutoGeneratorImpl implements ErrorCodeAutoGenerator {
/**
* 应用分组
*/
private final String applicationName;
/**
* 错误码枚举类
*/
private final String errorCodeConstantsClass;
/**
* 错误码 Service
*/
private final ErrorCodeFrameworkService errorCodeService;
@Override
@EventListener(ApplicationReadyEvent.class)
@Async // 异步保证项目的启动过程毕竟非关键流程
public void execute() {
// 第一步获得错误码类
Class<?> errorCodeConstantsClazz = parseErrorCodeConstantsClass();
if (errorCodeConstantsClazz == null) {
return;
}
// 第二步获得错误码数组
List<ErrorCodeAutoGenerateReqDTO> autoGenerateDTOs = parseErrorCode(errorCodeConstantsClazz);
log.info("[execute][解析到错误码数量为 ({}) 个]", autoGenerateDTOs.size());
// 第三步写入到 system 的数据库
errorCodeService.autoGenerateErrorCodes(autoGenerateDTOs);
log.info("[execute][写入到 system 组件完成]");
}
/**
* 解析 errorCodeConstantsClass 变量获得错误码类
*
* @return 错误码类
*/
private Class<?> parseErrorCodeConstantsClass() {
// 校验 errorCodeConstantsClass 参数
if (!StringUtils.hasText(errorCodeConstantsClass)) {
log.info("[execute][未配置 yudao.error-code.constants-class 配置项,不进行自动写入到当前服务中]");
return null;
}
try {
return Class.forName(errorCodeConstantsClass);
} catch (ClassNotFoundException e) {
log.error("[execute][配置的 ({}) 找不到对应的类]", errorCodeConstantsClass);
return null;
}
}
/**
* 解析错误码类获得错误码数组
*
* @return 错误码数组
*/
private List<ErrorCodeAutoGenerateReqDTO> parseErrorCode(Class<?> errorCodeConstantsClazz) {
List<ErrorCodeAutoGenerateReqDTO> autoGenerateDTOs = new ArrayList<>();
Arrays.stream(errorCodeConstantsClazz.getFields()).forEach(field -> {
if (field.getType() != ErrorCode.class) {
return;
}
try {
ErrorCode errorCode = (ErrorCode) field.get(errorCodeConstantsClazz);
autoGenerateDTOs.add(new ErrorCodeAutoGenerateReqDTO().setApplicationName(applicationName)
.setCode(errorCode.getCode()).setMessage(errorCode.getMsg()));
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
});
return autoGenerateDTOs;
}
}

View File

@ -0,0 +1,24 @@
package cn.iocoder.dashboard.framework.errorcode.core.loader;
import cn.iocoder.dashboard.common.exception.util.ServiceExceptionUtil;
/**
* 错误码加载器
*
* 注意错误码最终加载到 {@link cn.iocoder.dashboard.common.exception.util.ServiceExceptionUtil} MESSAGES 变量中
*
* @author dlyan
*/
public interface ErrorCodeLoader {
/**
* 添加错误码
*
* @param code 错误码的编号
* @param msg 错误码的提示
*/
default void putErrorCode(Integer code, String msg) {
ServiceExceptionUtil.put(code, msg);
}
}

View File

@ -0,0 +1,73 @@
package cn.iocoder.dashboard.framework.errorcode.core.loader;
import cn.hutool.core.collection.CollUtil;
import cn.iocoder.dashboard.framework.errorcode.core.dto.ErrorCodeRespDTO;
import cn.iocoder.dashboard.framework.errorcode.core.service.ErrorCodeFrameworkService;
import cn.iocoder.dashboard.util.date.DateUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.event.EventListener;
import org.springframework.scheduling.annotation.Scheduled;
import java.util.Date;
import java.util.List;
/**
* ErrorCodeLoader 的实现类 system 的数据库中加载错误码
*
* 考虑到错误码会刷新所以按照 {@link #REFRESH_ERROR_CODE_PERIOD} 频率增量加载错误码
*
* @author dlyan
*/
@RequiredArgsConstructor
@Slf4j
public class ErrorCodeLoaderImpl implements ErrorCodeLoader {
/**
* 刷新错误码的频率单位毫秒
*/
private static final int REFRESH_ERROR_CODE_PERIOD = 60 * 1000;
/**
* 应用分组
*/
private final String applicationName;
/**
* 错误码 Service
*/
private final ErrorCodeFrameworkService errorCodeService;
/**
* 缓存错误码的最大更新时间用于后续的增量轮询判断是否有更新
*/
private Date maxUpdateTime;
@EventListener(ApplicationReadyEvent.class)
public void loadErrorCodes() {
this.loadErrorCodes0();
}
@Scheduled(fixedDelay = REFRESH_ERROR_CODE_PERIOD, initialDelay = REFRESH_ERROR_CODE_PERIOD)
public void refreshErrorCodes() {
this.loadErrorCodes0();
}
private void loadErrorCodes0() {
// 加载错误码
List<ErrorCodeRespDTO> errorCodeRespDTOs = errorCodeService.getErrorCodeList(applicationName, maxUpdateTime);
if (CollUtil.isEmpty(errorCodeRespDTOs)) {
return;
}
log.info("[loadErrorCodes0][加载到 ({}) 个错误码]", errorCodeRespDTOs.size());
// 刷新错误码的缓存
errorCodeRespDTOs.forEach(errorCodeRespDTO -> {
// 写入到错误码的缓存
putErrorCode(errorCodeRespDTO.getCode(), errorCodeRespDTO.getMessage());
// 记录下更新时间方便增量更新
maxUpdateTime = DateUtils.max(maxUpdateTime, errorCodeRespDTO.getUpdateTime());
});
}
}

View File

@ -0,0 +1,35 @@
package cn.iocoder.dashboard.framework.errorcode.core.service;
import cn.iocoder.dashboard.framework.errorcode.core.dto.ErrorCodeAutoGenerateReqDTO;
import cn.iocoder.dashboard.framework.errorcode.core.dto.ErrorCodeRespDTO;
import javax.validation.Valid;
import java.util.Date;
import java.util.List;
/**
* 错误码 Framework Service 接口
*
* @author 芋道源码
*/
public interface ErrorCodeFrameworkService {
/**
* 自动创建错误码
*
* @param autoGenerateDTOs 错误码信息
*/
void autoGenerateErrorCodes(@Valid List<ErrorCodeAutoGenerateReqDTO> autoGenerateDTOs);
/**
* 增量获得错误码数组
*
* 如果 minUpdateTime 为空时则获取所有错误码
*
* @param applicationName 应用名
* @param minUpdateTime 最小更新时间
* @return 错误码数组
*/
List<ErrorCodeRespDTO> getErrorCodeList(String applicationName, Date minUpdateTime);
}

View File

@ -2,23 +2,16 @@ package cn.iocoder.dashboard.modules.system.controller.errorcode;
import cn.iocoder.dashboard.common.pojo.CommonResult;
import cn.iocoder.dashboard.common.pojo.PageResult;
import cn.iocoder.dashboard.modules.system.controller.errorcode.dto.ErrorCodeAutoGenerateDTO;
import cn.iocoder.dashboard.modules.system.controller.errorcode.dto.ErrorCodeCreateDTO;
import cn.iocoder.dashboard.modules.system.controller.errorcode.dto.ErrorCodePageDTO;
import cn.iocoder.dashboard.modules.system.controller.errorcode.dto.ErrorCodeUpdateDTO;
import cn.iocoder.dashboard.modules.system.controller.errorcode.vo.ErrorCodeVO;
import cn.iocoder.dashboard.modules.system.service.errorcode.ErrorCodeService;
import cn.iocoder.dashboard.modules.system.service.errorcode.impl.ErrorCodeServiceImpl;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.propertyeditors.CustomDateEditor;
import org.springframework.web.bind.ServletRequestDataBinder;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.validation.constraints.NotNull;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import static cn.iocoder.dashboard.common.pojo.CommonResult.success;
@ -29,34 +22,7 @@ import static cn.iocoder.dashboard.common.pojo.CommonResult.success;
public class ErrorCodeController {
@Resource
private ErrorCodeService errorCodeService;
/**
* 获得指定分组下的错误码列表
*
* @param group 错误码分组
* @param minUpdateTime 最小更新时间允许为空
* 通过该参数我们可以增量获取超过 minUpdateTime 时间的错误码
* @return 错误码列表
*/
@ApiOperation("获取指定分组下的状态码")
@GetMapping("/list-group")
public CommonResult<List<ErrorCodeVO>> listErrorCodes(@NotNull(message = "错误码分组不能为空") String group, Date minUpdateTime) {
return success(errorCodeService.listErrorCodes(group, minUpdateTime));
}
/**
* 自动生成错误码
*
* @param autoGenerateDTOs 自动生成信息 DTO
*/
@ApiOperation("自动生成错误码")
@PostMapping("/generate")
public CommonResult<Boolean> autoGenerateErrorCodes(@RequestBody List<ErrorCodeAutoGenerateDTO> autoGenerateDTOs) {
errorCodeService.autoGenerateErrorCodes(autoGenerateDTOs);
return success(Boolean.TRUE);
}
private ErrorCodeServiceImpl errorCodeService;
/**
* 创建错误码
@ -130,11 +96,4 @@ public class ErrorCodeController {
return success(errorCodeService.pageErrorCode(pageDTO));
}
@InitBinder
protected void init(HttpServletRequest request, ServletRequestDataBinder binder) {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
dateFormat.setLenient(false);
binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, false));
}
}

View File

@ -1,15 +1,11 @@
package cn.iocoder.dashboard.modules.system.controller.errorcode.dto;
import cn.iocoder.dashboard.framework.validator.InEnum;
import cn.iocoder.dashboard.modules.system.enums.errorcode.ErrorCodeTypeEnum;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.experimental.Accessors;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
@ApiModel("错误码更新 DTO")
@Data

View File

@ -1,7 +1,8 @@
package cn.iocoder.dashboard.modules.system.convert.errorcode;
import cn.iocoder.dashboard.common.pojo.PageResult;
import cn.iocoder.dashboard.modules.system.controller.errorcode.dto.ErrorCodeAutoGenerateDTO;
import cn.iocoder.dashboard.framework.errorcode.core.dto.ErrorCodeAutoGenerateReqDTO;
import cn.iocoder.dashboard.framework.errorcode.core.dto.ErrorCodeRespDTO;
import cn.iocoder.dashboard.modules.system.controller.errorcode.dto.ErrorCodeCreateDTO;
import cn.iocoder.dashboard.modules.system.controller.errorcode.dto.ErrorCodeUpdateDTO;
import cn.iocoder.dashboard.modules.system.controller.errorcode.vo.ErrorCodeVO;
@ -14,13 +15,10 @@ import org.mapstruct.factory.Mappers;
import java.util.List;
/**
* @author dylan
*/
@Mapper(unmappedSourcePolicy = ReportingPolicy.IGNORE)
public interface ErrorCodeConvert {
public interface SysErrorCodeConvert {
ErrorCodeConvert INSTANCE = Mappers.getMapper(ErrorCodeConvert.class);
SysErrorCodeConvert INSTANCE = Mappers.getMapper(SysErrorCodeConvert.class);
ErrorCodeVO convert (ErrorCodeDO bean);
@ -33,7 +31,8 @@ public interface ErrorCodeConvert {
ErrorCodeDO convert (ErrorCodeUpdateDTO bean);
ErrorCodeDO convert(ErrorCodeAutoGenerateDTO bean);
ErrorCodeDO convert(ErrorCodeAutoGenerateReqDTO bean);
List<ErrorCodeRespDTO> convertList02(List<ErrorCodeDO> list);
}

View File

@ -1,22 +1,34 @@
package cn.iocoder.dashboard.modules.system.dal.dataobject.errorcode;
import cn.iocoder.dashboard.modules.system.enums.errorcode.ErrorCodeTypeEnum;
import com.baomidou.mybatisplus.annotation.TableField;
import cn.iocoder.dashboard.framework.mybatis.core.dataobject.BaseDO;
import cn.iocoder.dashboard.modules.system.enums.errorcode.SysErrorCodeTypeEnum;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import lombok.ToString;
@TableName(value = "sys_error_code")
@Data
@TableName(value = "system_error_code")
@EqualsAndHashCode()
@Accessors(chain = true)
public class ErrorCodeDO {
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class ErrorCodeDO extends BaseDO {
/**
* 错误码编号
*/
@TableId
private Integer id;
/**
* 错误码类型
*
* 枚举 {@link SysErrorCodeTypeEnum}
*/
private Integer type;
/**
* 应用名
*/
private String applicationName;
/**
* 错误码编码
*/
@ -25,21 +37,9 @@ public class ErrorCodeDO {
* 错误码错误提示
*/
private String message;
/**
* 错误码类型
*
* 外键 {@link ErrorCodeTypeEnum}
*/
private Integer type;
/**
* 错误码分组
*
* 一般情况下可以采用应用名
*/
@TableField("`group`") // 避免和数据库关键字冲突
private String group;
/**
* 错误码备注
*/
private String memo;
}

View File

@ -15,6 +15,7 @@ import java.util.List;
@Mapper
public interface ErrorCodeMapper extends BaseMapper<ErrorCodeDO> {
default IPage<ErrorCodeDO> selectPage(ErrorCodePageDTO pageDTO) {
return selectPage(new Page<>(pageDTO.getPageNo(), pageDTO.getPageSize()),
new QueryWrapperX<ErrorCodeDO>().likeIfPresent("`group`", pageDTO.getGroup())
@ -29,8 +30,9 @@ public interface ErrorCodeMapper extends BaseMapper<ErrorCodeDO> {
return selectOne(new QueryWrapper<ErrorCodeDO>().eq("code", code));
}
default List<ErrorCodeDO> selectListByGroup(String group, Date minUpdateTime) {
return selectList(new QueryWrapperX<ErrorCodeDO>().eq("`group`", group)
default List<ErrorCodeDO> selectListByApplicationNameAndUpdateTimeGt(String applicationName, Date minUpdateTime) {
return selectList(new QueryWrapperX<ErrorCodeDO>().eq("application_name", applicationName)
.gtIfPresent("update_time", minUpdateTime));
}
}

View File

@ -1,14 +1,19 @@
package cn.iocoder.dashboard.modules.system.enums.errorcode;
import cn.iocoder.dashboard.common.core.IntArrayValuable;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.Arrays;
/**
* 错误码的类型枚举
*
* @author dylan
*/
public enum ErrorCodeTypeEnum implements IntArrayValuable {
@AllArgsConstructor
@Getter
public enum SysErrorCodeTypeEnum implements IntArrayValuable {
/**
* 自动生成
@ -19,20 +24,16 @@ public enum ErrorCodeTypeEnum implements IntArrayValuable {
*/
MANUAL_OPERATION(2);
public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(ErrorCodeTypeEnum::getType).toArray();
public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(SysErrorCodeTypeEnum::getType).toArray();
/**
* 类型
*/
private final Integer type;
ErrorCodeTypeEnum(Integer type) {
this.type = type;
}
public Integer getType() {
return type;
}
@Override
public int[] array() {
return ARRAYS;
}
}

View File

@ -1,80 +0,0 @@
package cn.iocoder.dashboard.modules.system.service.errorcode;
import cn.iocoder.dashboard.common.exception.ErrorCode;
import cn.iocoder.dashboard.common.pojo.CommonResult;
import cn.iocoder.dashboard.framework.errorcode.core.ErrorCodeAutoGenerator;
import cn.iocoder.dashboard.modules.system.controller.errorcode.dto.ErrorCodeAutoGenerateDTO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.event.EventListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.util.StringUtils;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@RequiredArgsConstructor
@Slf4j
public class ErrorCodeAutoGeneratorImpl implements ErrorCodeAutoGenerator {
/**
* 应用分组
*/
private final String group;
/**
* 错误码枚举类
*/
private String errorCodeConstantsClass;
@Resource
private ErrorCodeService errorCodeService;
public ErrorCodeAutoGeneratorImpl setErrorCodeConstantsClass(String errorCodeConstantsClass) {
this.errorCodeConstantsClass = errorCodeConstantsClass;
return this;
}
@Override
@EventListener(ApplicationReadyEvent.class)
@Async // 异步保证项目的启动过程毕竟非关键流程
public void execute() {
// 校验 errorCodeConstantsClass 参数
if (!StringUtils.hasText(errorCodeConstantsClass)) {
log.info("[execute][未配置 yudao.error-code.constants-class 配置项,不进行自动写入到当前服务中]");
return;
}
Class errorCodeConstantsClazz;
try {
errorCodeConstantsClazz = Class.forName(errorCodeConstantsClass);
} catch (ClassNotFoundException e) {
log.error("[execute][配置的 ({}) 找不到对应的类]", errorCodeConstantsClass);
return;
}
// 写入 system-service 服务
log.info("[execute][自动将 ({}) 类的错误码,准备写入到当前服务]", errorCodeConstantsClass);
List<ErrorCodeAutoGenerateDTO> autoGenerateDTOs = new ArrayList<>();
Arrays.stream(errorCodeConstantsClazz.getFields()).forEach(field -> {
if (field.getType() != ErrorCode.class) {
return;
}
try {
ErrorCode errorCode = (ErrorCode) field.get(errorCodeConstantsClazz);
autoGenerateDTOs.add(new ErrorCodeAutoGenerateDTO().setGroup(group)
.setCode(errorCode.getCode()).setMessage(errorCode.getMessage()));
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
});
CommonResult<Boolean> autoGenerateErrorCodesResult = errorCodeService.autoGenerateErrorCodes1(autoGenerateDTOs);
if (autoGenerateErrorCodesResult.isSuccess()) {
log.info("[execute][自动将 ({}) 类的错误码,成功写入到当前服务]", errorCodeConstantsClass);
} else {
log.error("[execute][自动将 ({}) 类的错误码,失败写入到当前服务,原因为 ({}/{})]", errorCodeConstantsClass,
autoGenerateErrorCodesResult.getCode(), autoGenerateErrorCodesResult.getMsg());
}
}
}

View File

@ -1,71 +0,0 @@
package cn.iocoder.dashboard.modules.system.service.errorcode;
import cn.hutool.core.collection.CollUtil;
import cn.iocoder.dashboard.common.exception.util.ServiceExceptionUtil;
import cn.iocoder.dashboard.common.pojo.CommonResult;
import cn.iocoder.dashboard.framework.errorcode.core.ErrorCodeRemoteLoader;
import cn.iocoder.dashboard.modules.system.controller.errorcode.vo.ErrorCodeVO;
import cn.iocoder.dashboard.util.date.DateUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.event.EventListener;
import org.springframework.scheduling.annotation.Scheduled;
import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
@Slf4j
public class ErrorCodeRemoteLoaderImpl implements ErrorCodeRemoteLoader {
private static final int REFRESH_ERROR_CODE_PERIOD = 60 * 1000;
/**
* 应用分组
*/
private final String group;
@Resource
private ErrorCodeService errorCodeService;
private Date maxUpdateTime;
public ErrorCodeRemoteLoaderImpl(String group) {
this.group = group;
}
@Override
@EventListener(ApplicationReadyEvent.class)
public void loadErrorCodes() {
// ErrorCodeRpc 全量加载 ErrorCode 错误码
CommonResult<List<ErrorCodeVO>> listErrorCodesResult = errorCodeService.listErrorCodes1(group, null);
listErrorCodesResult.checkError();
log.info("[loadErrorCodes][从 group({}) 全量加载到 {} 个 ErrorCode 错误码]", group, listErrorCodesResult.getData().size());
// 写入到 ServiceExceptionUtil
listErrorCodesResult.getData().forEach(errorCodeVO -> {
ServiceExceptionUtil.put(errorCodeVO.getCode(), errorCodeVO.getMessage());
// 记录下更新时间方便增量更新
maxUpdateTime = DateUtils.max(maxUpdateTime, errorCodeVO.getUpdateTime());
});
}
@Override
@Scheduled(fixedDelay = REFRESH_ERROR_CODE_PERIOD, initialDelay = REFRESH_ERROR_CODE_PERIOD)
public void refreshErrorCodes() {
// ErrorCodeRpc 增量加载 ErrorCode 错误码
// TODO 优化点假设删除错误码的配置会存在问题
CommonResult<List<ErrorCodeVO>> listErrorCodesResult = errorCodeService.listErrorCodes1(group, maxUpdateTime);
listErrorCodesResult.checkError();
if (CollUtil.isEmpty(listErrorCodesResult.getData())) {
return;
}
log.info("[refreshErrorCodes][从 group({}) 增量加载到 {} 个 ErrorCode 错误码]", group, listErrorCodesResult.getData().size());
// 写入到 ServiceExceptionUtil
listErrorCodesResult.getData().forEach(errorCodeVO -> {
ServiceExceptionUtil.put(errorCodeVO.getCode(), errorCodeVO.getMessage());
// 记录下更新时间方便增量更新
maxUpdateTime = DateUtils.max(maxUpdateTime, errorCodeVO.getUpdateTime());
});
}
}

View File

@ -0,0 +1,12 @@
package cn.iocoder.dashboard.modules.system.service.errorcode;
import cn.iocoder.dashboard.framework.errorcode.core.service.ErrorCodeFrameworkService;
/**
* 错误码 Service 接口
*
* @author 芋道源码
*/
public interface SysErrorCodeService extends ErrorCodeFrameworkService {
}

View File

@ -1,45 +1,45 @@
package cn.iocoder.dashboard.modules.system.service.errorcode;
package cn.iocoder.dashboard.modules.system.service.errorcode.impl;
import cn.hutool.core.collection.CollUtil;
import cn.iocoder.dashboard.common.exception.util.ServiceExceptionUtil;
import cn.iocoder.dashboard.common.pojo.CommonResult;
import cn.iocoder.dashboard.common.pojo.PageResult;
import cn.iocoder.dashboard.modules.system.controller.errorcode.dto.ErrorCodeAutoGenerateDTO;
import cn.iocoder.dashboard.framework.errorcode.core.dto.ErrorCodeAutoGenerateReqDTO;
import cn.iocoder.dashboard.framework.errorcode.core.dto.ErrorCodeRespDTO;
import cn.iocoder.dashboard.modules.system.controller.errorcode.dto.ErrorCodeCreateDTO;
import cn.iocoder.dashboard.modules.system.controller.errorcode.dto.ErrorCodePageDTO;
import cn.iocoder.dashboard.modules.system.controller.errorcode.dto.ErrorCodeUpdateDTO;
import cn.iocoder.dashboard.modules.system.controller.errorcode.vo.ErrorCodeVO;
import cn.iocoder.dashboard.modules.system.convert.errorcode.ErrorCodeConvert;
import cn.iocoder.dashboard.modules.system.convert.errorcode.SysErrorCodeConvert;
import cn.iocoder.dashboard.modules.system.dal.dataobject.errorcode.ErrorCodeDO;
import cn.iocoder.dashboard.modules.system.dal.mysql.errorcode.ErrorCodeMapper;
import cn.iocoder.dashboard.modules.system.enums.errorcode.ErrorCodeTypeEnum;
import cn.iocoder.dashboard.util.collection.CollectionUtils;
import cn.iocoder.dashboard.modules.system.enums.errorcode.SysErrorCodeTypeEnum;
import cn.iocoder.dashboard.modules.system.service.errorcode.SysErrorCodeService;
import com.baomidou.mybatisplus.core.metadata.IPage;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import javax.validation.Valid;
import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
import java.util.Map;
import static cn.iocoder.dashboard.modules.system.enums.SysErrorCodeConstants.ERROR_CODE_DUPLICATE;
import static cn.iocoder.dashboard.modules.system.enums.SysErrorCodeConstants.ERROR_CODE_NOT_EXISTS;
import static cn.iocoder.dashboard.common.pojo.CommonResult.success;
import static cn.iocoder.dashboard.util.collection.CollectionUtils.convertMap;
import static cn.iocoder.dashboard.util.collection.CollectionUtils.convertSet;
/**
* 错误码 Service
* 错误码 Service 实现类
*/
@Slf4j
@Validated
@Service
public class ErrorCodeService {
@Validated
@Slf4j
public class ErrorCodeServiceImpl implements SysErrorCodeService {
@Autowired
ErrorCodeMapper errorCodeMapper;
@Resource
private ErrorCodeMapper errorCodeMapper;
/**
* 创建错误码
@ -47,13 +47,13 @@ public class ErrorCodeService {
* @param createDTO 创建错误码 DTO
* @return 错误码
*/
public ErrorCodeVO createErrorCode(@Valid ErrorCodeCreateDTO createDTO) {
public ErrorCodeVO createErrorCode(ErrorCodeCreateDTO createDTO) {
checkDuplicateErrorCode(createDTO.getCode(), null);
// 插入到数据库
ErrorCodeDO errorCodeDO = ErrorCodeConvert.INSTANCE.convert(createDTO);
ErrorCodeDO errorCodeDO = SysErrorCodeConvert.INSTANCE.convert(createDTO);
errorCodeMapper.insert(errorCodeDO);
// 返回
return ErrorCodeConvert.INSTANCE.convert(errorCodeDO);
return SysErrorCodeConvert.INSTANCE.convert(errorCodeDO);
}
/**
@ -61,62 +61,17 @@ public class ErrorCodeService {
*
* @param updateDTO 更新错误码 DTO
*/
public void updateErrorCode(@Valid ErrorCodeUpdateDTO updateDTO) {
public void updateErrorCode(ErrorCodeUpdateDTO updateDTO) {
checkDuplicateErrorCode(updateDTO.getCode(), updateDTO.getId());
// 校验更新的错误码是否存在
if (errorCodeMapper.selectById(updateDTO.getId()) == null) {
throw ServiceExceptionUtil.exception(ERROR_CODE_NOT_EXISTS);
}
// 更新到数据库
ErrorCodeDO updateObject = ErrorCodeConvert.INSTANCE.convert(updateDTO);
ErrorCodeDO updateObject = SysErrorCodeConvert.INSTANCE.convert(updateDTO);
errorCodeMapper.updateById(updateObject);
}
@Transactional
public void autoGenerateErrorCodes(@Valid List<ErrorCodeAutoGenerateDTO> autoGenerateDTOs) {
if (CollUtil.isEmpty(autoGenerateDTOs)) {
return;
}
List<ErrorCodeDO> errorCodeDOs = errorCodeMapper.selectListByCodes(
CollectionUtils.convertSet(autoGenerateDTOs, ErrorCodeAutoGenerateDTO::getCode));
Map<Integer, ErrorCodeDO> errorCodeDOMap = CollectionUtils.convertMap(errorCodeDOs, ErrorCodeDO::getCode);
// 遍历 autoGenerateBOs 数组逐个插入或更新考虑到每次量级不大就不走批量了
autoGenerateDTOs.forEach(autoGenerateDTO -> {
ErrorCodeDO errorCodeDO = errorCodeDOMap.get(autoGenerateDTO.getCode());
// 不存在则进行新增
if (errorCodeDO == null) {
errorCodeDO = ErrorCodeConvert.INSTANCE.convert(autoGenerateDTO)
.setType(ErrorCodeTypeEnum.AUTO_GENERATION.getType());
errorCodeMapper.insert(errorCodeDO);
return;
}
// 存在则进行更新更新有三个前置条件
// 条件 1. 只更新自动生成的错误码 Type ErrorCodeTypeEnum.AUTO_GENERATION
if (!ErrorCodeTypeEnum.AUTO_GENERATION.getType().equals(errorCodeDO.getType())) {
return;
}
// 条件 2. 分组 group 必须匹配避免存在错误码冲突的情况
if (!autoGenerateDTO.getGroup().equals(errorCodeDO.getGroup())) {
log.error("[autoGenerateErrorCodes][自动创建({}/{}) 错误码失败,数据库中已经存在({}/{})]",
autoGenerateDTO.getCode(), autoGenerateDTO.getGroup(),
errorCodeDO.getCode(), errorCodeDO.getGroup());
return;
}
// 条件 3. 错误提示语存在差异
if (autoGenerateDTO.getMessage().equals(errorCodeDO.getMessage())) {
return;
}
// 最终匹配进行更新
errorCodeMapper.updateById(new ErrorCodeDO().setId(errorCodeDO.getId()).setMessage(autoGenerateDTO.getMessage()));
});
}
public CommonResult<Boolean> autoGenerateErrorCodes1(@Valid List<ErrorCodeAutoGenerateDTO> autoGenerateDTOs) {
autoGenerateErrorCodes(autoGenerateDTOs);
return success(Boolean.TRUE);
}
/**
* 删除错误码
*
@ -139,7 +94,7 @@ public class ErrorCodeService {
*/
public ErrorCodeVO getErrorCode(Integer errorCodeId) {
ErrorCodeDO errorCodeDO = errorCodeMapper.selectById(errorCodeId);
return ErrorCodeConvert.INSTANCE.convert(errorCodeDO);
return SysErrorCodeConvert.INSTANCE.convert(errorCodeDO);
}
/**
@ -150,7 +105,7 @@ public class ErrorCodeService {
*/
public List<ErrorCodeVO> listErrorCodes(List<Integer> errorCodeIds) {
List<ErrorCodeDO> errorCodeDOs = errorCodeMapper.selectBatchIds(errorCodeIds);
return ErrorCodeConvert.INSTANCE.convertList(errorCodeDOs);
return SysErrorCodeConvert.INSTANCE.convertList(errorCodeDOs);
}
/**
@ -161,7 +116,7 @@ public class ErrorCodeService {
*/
public PageResult<ErrorCodeVO> pageErrorCode(ErrorCodePageDTO pageDTO) {
IPage<ErrorCodeDO> errorCodeDOPage = errorCodeMapper.selectPage(pageDTO);
return ErrorCodeConvert.INSTANCE.convertPage(errorCodeDOPage);
return SysErrorCodeConvert.INSTANCE.convertPage(errorCodeDOPage);
}
/**
@ -186,14 +141,53 @@ public class ErrorCodeService {
}
}
public List<ErrorCodeVO> listErrorCodes(String group, Date minUpdateTime) {
List<ErrorCodeDO> errorCodeDOs = errorCodeMapper.selectListByGroup(group, minUpdateTime);
return ErrorCodeConvert.INSTANCE.convertList(errorCodeDOs);
@Override
@Transactional
public void autoGenerateErrorCodes(List<ErrorCodeAutoGenerateReqDTO> autoGenerateDTOs) {
if (CollUtil.isEmpty(autoGenerateDTOs)) {
return;
}
// 获得错误码
List<ErrorCodeDO> errorCodeDOs = errorCodeMapper.selectListByCodes(
convertSet(autoGenerateDTOs, ErrorCodeAutoGenerateReqDTO::getCode));
Map<Integer, ErrorCodeDO> errorCodeDOMap = convertMap(errorCodeDOs, ErrorCodeDO::getCode);
// 遍历 autoGenerateBOs 数组逐个插入或更新考虑到每次量级不大就不走批量了
autoGenerateDTOs.forEach(autoGenerateDTO -> {
ErrorCodeDO errorCodeDO = errorCodeDOMap.get(autoGenerateDTO.getCode());
// 不存在则进行新增
if (errorCodeDO == null) {
errorCodeDO = SysErrorCodeConvert.INSTANCE.convert(autoGenerateDTO)
.setType(SysErrorCodeTypeEnum.AUTO_GENERATION.getType());
errorCodeMapper.insert(errorCodeDO);
return;
}
// 存在则进行更新更新有三个前置条件
// 条件 1. 只更新自动生成的错误码 Type ErrorCodeTypeEnum.AUTO_GENERATION
if (!SysErrorCodeTypeEnum.AUTO_GENERATION.getType().equals(errorCodeDO.getType())) {
return;
}
// 条件 2. 分组 group 必须匹配避免存在错误码冲突的情况
if (!autoGenerateDTO.getApplicationName().equals(errorCodeDO.getApplicationName())) {
log.error("[autoGenerateErrorCodes][自动创建({}/{}) 错误码失败,数据库中已经存在({}/{})]",
autoGenerateDTO.getCode(), autoGenerateDTO.getApplicationName(),
errorCodeDO.getCode(), errorCodeDO.getApplicationName());
return;
}
// 条件 3. 错误提示语存在差异
if (autoGenerateDTO.getMessage().equals(errorCodeDO.getMessage())) {
return;
}
// 最终匹配进行更新
errorCodeMapper.updateById(new ErrorCodeDO().setId(errorCodeDO.getId()).setMessage(autoGenerateDTO.getMessage()));
});
}
public CommonResult<List<ErrorCodeVO>> listErrorCodes1(String group, Date minUpdateTime) {
List<ErrorCodeDO> errorCodeDOs = errorCodeMapper.selectListByGroup(group, minUpdateTime);
return success(ErrorCodeConvert.INSTANCE.convertList(errorCodeDOs));
@Override
public List<ErrorCodeRespDTO> getErrorCodeList(String applicationName, Date minUpdateTime) {
List<ErrorCodeDO> errorCodeDOs = errorCodeMapper.selectListByApplicationNameAndUpdateTimeGt(
applicationName, minUpdateTime);
return SysErrorCodeConvert.INSTANCE.convertList02(errorCodeDOs);
}
}