错误码的 Starter 的初始化,暂未完成

This commit is contained in:
YunaiV 2020-07-19 22:13:17 +08:00
parent e04c9584e3
commit 0df486a677
22 changed files with 413 additions and 86731 deletions

View File

@ -18,7 +18,7 @@ import java.lang.reflect.Type;
import static cn.iocoder.common.framework.exception.enums.GlobalErrorCodeConstants.BAD_REQUEST;
import static cn.iocoder.common.framework.exception.enums.GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR;
@Activate(group = CommonConstants.PROVIDER)
@Activate(group = CommonConstants.PROVIDER) // TODO 优化点设置下顺序
public class DubboProviderExceptionFilter implements Filter, Filter.Listener {
private Logger logger = LoggerFactory.getLogger(DubboProviderExceptionFilter.class);
@ -39,7 +39,7 @@ public class DubboProviderExceptionFilter implements Filter, Filter.Listener {
exception = this.constraintViolationExceptionHandler((ConstraintViolationException) exception);
// 1. ServiceException 业务异常因为不会有序列化问题所以无需处理
} else if (exception instanceof ServiceException) {
// 1.3 其它异常转换成 ServiceException 业务异常避免可能存在的反序列化问题
// 1.3 其它异常转换成 GlobalException 全局异常避免可能存在的反序列化问题
} else {
exception = this.defaultExceptionHandler(exception, invocation);
assert exception != null;

View File

@ -0,0 +1,46 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>common</artifactId>
<groupId>cn.iocoder.mall</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>mall-spring-boot-starter-system-error-code</artifactId>
<description>
错误码 ErrorCode 的自动配置功能,提供如下功能:
1. 远程读取:项目启动时,从 system-service 服务,读取数据库中的 ErrorCode 错误码,实现错误码的提水可配置;
2. 自动更新:管理员在管理后台修数据库中的 ErrorCode 错误码时,项目自动从 system-service 服务加载最新的 ErrorCode 错误码;
3. 自动写入:项目启动时,将项目本地的错误码写到 system-service 服务中,方便管理员在管理后台编辑;
</description>
<dependencies>
<!-- Mall 相关 -->
<dependency>
<groupId>cn.iocoder.mall</groupId>
<artifactId>system-service-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!-- Spring 核心 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<!-- RPC 相关 -->
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,18 @@
package cn.iocoder.mall.system.errorcode.config;
import cn.iocoder.mall.system.errorcode.core.ErrorCodeAutoGenerator;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
@EnableConfigurationProperties(ErrorCodeProperties.class)
public class ErrorCodeAutoConfiguration {
@Bean
public ErrorCodeAutoGenerator errorCodeAutoGenerator(ErrorCodeProperties errorCodeProperties) {
return new ErrorCodeAutoGenerator(errorCodeProperties.getGroup())
.setErrorCodeConstantsClass(errorCodeProperties.getConstantsClass());
}
}

View File

@ -0,0 +1,34 @@
package cn.iocoder.mall.system.errorcode.config;
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties("mall.error-code")
public class ErrorCodeProperties {
/**
* 应用分组
*/
private String group;
/**
* 错误码枚举类
*/
private String constantsClass;
public String getGroup() {
return group;
}
public ErrorCodeProperties setGroup(String group) {
this.group = group;
return this;
}
public String getConstantsClass() {
return constantsClass;
}
public ErrorCodeProperties setConstantsClass(String constantsClass) {
this.constantsClass = constantsClass;
return this;
}
}

View File

@ -0,0 +1,76 @@
package cn.iocoder.mall.system.errorcode.core;
import cn.iocoder.common.framework.exception.ErrorCode;
import cn.iocoder.common.framework.util.StringUtils;
import cn.iocoder.mall.systemservice.rpc.errorcode.dto.ErrorCodeAutoGenerateDTO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.event.EventListener;
import org.springframework.scheduling.annotation.Async;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;
public class ErrorCodeAutoGenerator {
private Logger logger = LoggerFactory.getLogger(ErrorCodeAutoGenerator.class);
/**
* 应用分组
*/
private final String group;
/**
* 错误码枚举类
*/
private String errorCodeConstantsClass;
public ErrorCodeAutoGenerator(String group) {
this.group = group;
}
public ErrorCodeAutoGenerator setErrorCodeConstantsClass(String errorCodeConstantsClass) {
this.errorCodeConstantsClass = errorCodeConstantsClass;
return this;
}
@EventListener(ApplicationReadyEvent.class)
@Async // 异步保证项目的启动过程毕竟非关键流程
public void execute() {
// 校验 errorCodeConstantsClass 参数
if (!StringUtils.hasText(errorCodeConstantsClass)) {
logger.info("[execute][未配置 mall.error-code.constants-class 配置项,不进行自动写入到 system-service 服务]");
return;
}
Class errorCodeConstantsClazz;
try {
errorCodeConstantsClazz = Class.forName(errorCodeConstantsClass);
} catch (ClassNotFoundException e) {
logger.error("[execute][配置的 ({}) 找不到对应的类]", errorCodeConstantsClass);
return;
}
// 写入 system-service 服务
logger.info("[execute][自动将 ({}) 类的错误码,准备写入到 system-service 服务]", errorCodeConstantsClass);
List<ErrorCodeAutoGenerateDTO> autoGenerateDTO = new ArrayList<>();
Arrays.stream(errorCodeConstantsClazz.getFields()).forEach(new Consumer<Field>() {
@Override
public void accept(Field field) {
if (field.getType() != ErrorCode.class) {
return;
}
try {
ErrorCode errorCode = (ErrorCode) field.get(errorCodeConstantsClazz);
autoGenerateDTO.add(new ErrorCodeAutoGenerateDTO().setGroup(group)
.setCode(errorCode.getCode()).setMessage(errorCode.getMessage()));
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}
});
logger.info("[execute][自动将 ({}) 类的错误码,完成写入到 system-service 服务]", errorCodeConstantsClass);
}
}

View File

@ -0,0 +1,75 @@
package cn.iocoder.mall.system.errorcode.core;
import cn.iocoder.common.framework.util.ServiceExceptionUtil;
import cn.iocoder.common.framework.vo.CommonResult;
import cn.iocoder.mall.systemservice.rpc.errorcode.ErrorCodeRpc;
import cn.iocoder.mall.systemservice.rpc.errorcode.vo.ErrorCodeVO;
import org.apache.dubbo.config.annotation.Reference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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;
public class ErrorCodeRemoteLoader {
private static final int REFRESH_ERROR_CODE_PERIOD = 60 * 1000;
private Logger logger = LoggerFactory.getLogger(ErrorCodeRemoteLoader.class);
/**
* 应用分组
*/
private final String group;
@Reference(version = "${dubbo.consumer.ErrorCodeRpc.version}")
private ErrorCodeRpc errorCodeRpc;
private Date maxUpdateTime;
public ErrorCodeRemoteLoader(String group) {
this.group = group;
}
@EventListener(ApplicationReadyEvent.class)
public void loadErrorCodes() {
// ErrorCodeRpc 加载 ErrorCode 错误码
CommonResult<List<ErrorCodeVO>> listErrorCodesResult = errorCodeRpc.listErrorCodes(group, null);
listErrorCodesResult.checkError();
logger.info("[loadErrorCodes][从 group({}) 全量加载到 {} 个 ErrorCode 错误码]", group, listErrorCodesResult.getData().size());
// 写入到 ServiceExceptionUtil
listErrorCodesResult.getData().forEach(errorCodeVO -> {
ServiceExceptionUtil.put(errorCodeVO.getCode(), errorCodeVO.getMessage());
// 记录下更新时间方便增量更新
maxUpdateTime = max(maxUpdateTime, errorCodeVO.getUpdateTime());
});
}
@Scheduled(fixedDelay = REFRESH_ERROR_CODE_PERIOD)
public void refreshErrorCodes() {
// ErrorCodeRpc 加载 ErrorCode 错误码
CommonResult<List<ErrorCodeVO>> listErrorCodesResult = errorCodeRpc.listErrorCodes(group, maxUpdateTime);
listErrorCodesResult.checkError();
logger.info("[refreshErrorCodes][从 group({}) 增量加载到 {} 个 ErrorCode 错误码]", group, listErrorCodesResult.getData().size());
// 写入到 ServiceExceptionUtil
listErrorCodesResult.getData().forEach(errorCodeVO -> {
ServiceExceptionUtil.put(errorCodeVO.getCode(), errorCodeVO.getMessage());
// 记录下更新时间方便增量更新
maxUpdateTime = max(maxUpdateTime, errorCodeVO.getUpdateTime());
});
}
private static Date max(Date a, Date b) {
if (a == null) {
return b;
}
if (b == null) {
return a;
}
return a.compareTo(b) > 0 ? a : b;
}
}

View File

@ -0,0 +1,2 @@
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
cn.iocoder.mall.system.errorcode.config.ErrorCodeAutoConfiguration

View File

@ -21,6 +21,7 @@
<module>mall-spring-boot-starter-security-user</module>
<module>mall-spring-boot-starter-mybatis</module>
<module>mall-spring-boot-starter-dubbo</module>
<module>mall-spring-boot-starter-system-error-code</module>
</modules>
<dependencyManagement>

File diff suppressed because one or more lines are too long

View File

@ -219,6 +219,12 @@
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>cn.iocoder.mall</groupId>
<artifactId>mall-spring-boot-starter-system-error-code</artifactId> <!-- 错误码 -->
<version>1.0-SNAPSHOT</version>
</dependency>
<!-- Job 相关 -->
<dependency>
<groupId>com.xuxueli</groupId>

View File

@ -3,18 +3,21 @@ package cn.iocoder.mall.systemservice.enums.errorcode;
/**
* 错误码的类型枚举
*
* 考虑到便利性我们会扫描每个项目的错误码枚举类自动添加到错误码数据库中并标记为 {@link #AUTO_GENERATION} 类型
* 经过管理员手动编辑过的错误码会标记为 {@link #MANUAL_OPERATION} 类型并禁止自动同步
*
* @author ding
*/
public enum ErrorCodeTypeEnum {
/**
* 内置错误码
* 自动生成
*/
SYSTEM(1),
AUTO_GENERATION(1),
/**
* 自定义错误码
* 手动处理
*/
CUSTOM(2);
MANUAL_OPERATION(2);
private final Integer type;

View File

@ -0,0 +1,16 @@
package cn.iocoder.mall.systemservice.rpc.errorcode;
import cn.iocoder.common.framework.vo.CommonResult;
import cn.iocoder.mall.systemservice.rpc.errorcode.dto.ErrorCodeAutoGenerateDTO;
import cn.iocoder.mall.systemservice.rpc.errorcode.vo.ErrorCodeVO;
import java.util.Date;
import java.util.List;
public interface ErrorCodeRpc {
CommonResult<List<ErrorCodeVO>> listErrorCodes(String group, Date minUpdateTime);
CommonResult<Boolean> autoGenerateErrorCodes(ErrorCodeAutoGenerateDTO autoGenerateDTO);
}

View File

@ -0,0 +1,25 @@
package cn.iocoder.mall.systemservice.rpc.errorcode.dto;
import lombok.Data;
import lombok.experimental.Accessors;
import java.io.Serializable;
@Data
@Accessors(chain = true)
public class ErrorCodeAutoGenerateDTO implements Serializable {
/**
* 错误码编码
*/
private Integer code;
/**
* 错误码错误提示
*/
private String message;
/**
* 错误码分组
*/
private String group;
}

View File

@ -0,0 +1,49 @@
package cn.iocoder.mall.systemservice.rpc.errorcode.vo;
import lombok.Data;
import lombok.experimental.Accessors;
import java.io.Serializable;
import java.util.Date;
/**
* 错误码 VO
*/
@Data
@Accessors(chain = true)
public class ErrorCodeVO implements Serializable {
/**
* 错误码编号
*/
private Integer id;
/**
* 错误码编码
*/
private Integer code;
/**
* 错误码错误提示
*/
private String message;
/**
* 错误码类型
*/
private Integer type;
/**
* 错误码分组
*/
private String group;
/**
* 错误码备注
*/
private String memo;
/**
* 创建时间
*/
private Date createTime;
/**
* 最后更新时间
*/
private Date updateTime;
}

View File

@ -23,6 +23,11 @@
<artifactId>system-service-api</artifactId>
</dependency>
<dependency>
<groupId>cn.iocoder.mall</groupId>
<artifactId>mall-spring-boot-starter-system-error-code</artifactId> <!-- 错误码 -->
</dependency>
<!-- Registry 和 Config 相关 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>

View File

@ -0,0 +1,9 @@
package cn.iocoder.mall.systemservice.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
@Configuration
@EnableAsync(proxyTargetClass = true) // 开启 Spring Async 异步的功能
public class AsyncConfiguration {
}

View File

@ -3,6 +3,7 @@ package cn.iocoder.mall.systemservice.dal.mysql.dataobject.datadict;
import cn.iocoder.mall.mybatis.core.dataobject.DeletableDO;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
/**
@ -16,6 +17,7 @@ import lombok.experimental.Accessors;
*/
@TableName("system_data_dict")
@Data
@EqualsAndHashCode(callSuper = true)
@Accessors(chain = true)
public class DataDictDO extends DeletableDO {

View File

@ -1,6 +1,7 @@
package cn.iocoder.mall.system.biz.dataobject.errorcode;
package cn.iocoder.mall.systemservice.dal.mysql.dataobject.errorcode;
import cn.iocoder.mall.mybatis.core.dataobject.DeletableDO;
import cn.iocoder.mall.systemservice.enums.errorcode.ErrorCodeTypeEnum;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.EqualsAndHashCode;
@ -14,6 +15,7 @@ import lombok.experimental.Accessors;
@EqualsAndHashCode(callSuper = true)
@Accessors(chain = true)
public class ErrorCodeDO extends DeletableDO {
/**
* 错误码编号
*/
@ -23,25 +25,24 @@ public class ErrorCodeDO extends DeletableDO {
*/
private Integer code;
/**
* 错误码错误信息
* 错误码错误提示
*/
private String message;
/**
* 错误码类型
*
* 外键 {@link ErrorCodeTypeEnum}
*/
private Integer type;
/**
* 错误码分组
*
* 一般情况下可以采用应用名
*/
private Integer group;
/**
* 错误码备注
*/
private String remark;
// TODO FROM 芋艿 to 鱿鱼丝增加一个分组字段方便做归类
// TODO FROM 芋艿 to 鱿鱼丝增加个备注字段方便做备注哈
private String memo;
}

View File

@ -0,0 +1,24 @@
package cn.iocoder.mall.systemservice.rpc.errorcode;
import cn.iocoder.common.framework.vo.CommonResult;
import cn.iocoder.mall.systemservice.rpc.errorcode.dto.ErrorCodeAutoGenerateDTO;
import cn.iocoder.mall.systemservice.rpc.errorcode.vo.ErrorCodeVO;
import org.apache.dubbo.config.annotation.Service;
import java.util.Date;
import java.util.List;
@Service(version = "${dubbo.provider.ErrorCodeRpc.version}")
public class ErrorCodeRpcImpl implements ErrorCodeRpc {
@Override
public CommonResult<List<ErrorCodeVO>> listErrorCodes(String group, Date minUpdateTime) {
return null;
}
@Override
public CommonResult<Boolean> autoGenerateErrorCodes(ErrorCodeAutoGenerateDTO autoGenerateDTO) {
return null;
}
}

View File

@ -52,3 +52,10 @@ dubbo:
version: 1.0.0
SystemAccessLogRpc:
version: 1.0.0
ErrorCodeRpc:
version: 1.0.0
# Mall 配置项
mall:
error-code:
constants-class: cn.iocoder.mall.systemservice.enums.SystemErrorCodeConstants

View File

@ -36,10 +36,6 @@ public interface ErrorCodeMapper extends BaseMapper<ErrorCodeDO> {
return selectList(new QueryWrapperX<ErrorCodeDO>().inIfPresent("id", ids));
}
default ErrorCodeDO selectByMessage(String message) {
return selectOne(new QueryWrapperX<ErrorCodeDO>().eqIfPresent("message", message));
}
default List<ErrorCodeDO> selectByGroup(Integer group) {
return selectList(new QueryWrapperX<ErrorCodeDO>().eqIfPresent("group", group));
}

View File

@ -128,7 +128,6 @@ public class ErrorCodeServiceImpl extends ServiceImpl<ErrorCodeMapper, ErrorCode
if (ErrorCodeTypeEnum.SYSTEM.getType().equals(errorCodeDO.getType())) {
throw ServiceExceptionUtil.exception(SystemErrorCodeEnum.ERROR_CAN_NOT_UPDATE_SYSTEM_TYPE_ERROR);
}
// TODO FROM 芋艿 to 鱿鱼丝不能删除内置错误码
// 更新到数据库标记删除
errorCodeMapper.deleteById(errorCodeDO.getId());
ServiceExceptionUtil.delete(errorCodeDO.getCode(),errorCodeDO.getMessage());