parent
e04c9584e3
commit
0df486a677
@ -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>
|
||||
@ -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());
|
||||
}
|
||||
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,2 @@
|
||||
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
|
||||
cn.iocoder.mall.system.errorcode.config.ErrorCodeAutoConfiguration
|
||||
File diff suppressed because one or more lines are too long
@ -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);
|
||||
|
||||
}
|
||||
@ -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;
|
||||
|
||||
}
|
||||
@ -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;
|
||||
|
||||
}
|
||||
@ -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 {
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Reference in new issue