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

pull/3/head
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());