This commit is contained in:
六如
2024-11-07 22:55:06 +08:00
parent 5956af3564
commit 9e05259d92
45 changed files with 534 additions and 1426 deletions

View File

@@ -1,10 +1,9 @@
package com.gitee.sop.support.exception;
import com.gitee.sop.support.context.OpenContext;
import com.gitee.sop.support.message.OpenError;
import com.gitee.sop.support.message.I18nMessage;
import com.gitee.sop.support.message.OpenMessage;
import com.gitee.sop.support.message.OpenMessageFactory;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.Locale;
@@ -13,27 +12,36 @@ import java.util.Locale;
* @author 六如
*/
@Getter
@AllArgsConstructor
public class OpenException extends RuntimeException {
private static final long serialVersionUID = -8059687941272829442L;
private String subCode;
private final String subCode;
private String subMsg;
private final String subMsg;
private String solution;
private final String solution;
public OpenException(OpenError openError, Locale locale, Object... params) {
this.subCode = openError.getSubCode();
OpenMessage openMessage = OpenMessageFactory.getError(openError, locale, params);
this.subMsg = openMessage.getSubMsg();
public OpenException(I18nMessage i18nMessage, Locale locale, Object... params) {
this.subCode = i18nMessage.getConfigKey();
OpenMessage openMessage = OpenMessageFactory.getMessage(i18nMessage, locale, params);
this.subMsg = openMessage.getMsg();
this.solution = openMessage.getSolution();
}
public OpenException(OpenError openError, Object... params) {
public OpenException(I18nMessage openError, Object... params) {
this(openError, OpenContext.getLocale(), params);
}
public OpenException(String subCode, String subMsg, String solution) {
this.subCode = subCode;
this.subMsg = subMsg;
this.solution = solution;
}
public OpenException(String subCode, String subMsg) {
this(subCode, subMsg, "");
}
@Override
public String toString() {
return "<OPEN_ERROR>" + String.join("@@", subCode, subMsg, solution) + "</OPEN_ERROR>";

View File

@@ -8,8 +8,8 @@ import lombok.Data;
*/
@Data
@AllArgsConstructor
public class ServiceMessageImpl implements OpenMessage {
private String subCode;
private String subMsg;
public class DefaultOpenMessage implements OpenMessage {
private String code;
private String msg;
private String solution;
}

View File

@@ -0,0 +1,14 @@
package com.gitee.sop.support.message;
/**
* 定义国际化消息
*
* @author 六如
*/
public interface I18nMessage {
/**
* i18n配置文件key
*/
String getConfigKey();
}

View File

@@ -1,16 +0,0 @@
package com.gitee.sop.support.message;
/**
* 定义错误返回
* @author 六如
*/
public interface OpenError {
/**
* sub_code明细返回码
* @return sub_code明细返回码
*/
String getSubCode();
String modulePrefix();
}

View File

@@ -10,12 +10,12 @@ public interface OpenMessage {
/**
* @return 明细返回码
*/
String getSubCode();
String getCode();
/**
* @return 明细信息
*/
String getSubMsg();
String getMsg();
/**
* @return 解决方案

View File

@@ -1,19 +1,30 @@
package com.gitee.sop.support.message;
import lombok.Data;
import org.springframework.context.support.MessageSourceAccessor;
import org.springframework.context.support.ResourceBundleMessageSource;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Logger;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* 负责构建错误消息
@@ -25,31 +36,113 @@ public class OpenMessageFactory {
static Logger logger = Logger.getLogger(OpenMessageFactory.class.getName());
private static final String SOLUTION = ".solution";
private static final String I18N_ROOT = "i18n";
private OpenMessageFactory() {
}
public static final String SYS_ERR = "系统错误";
private static final String I18N_OPEN_ERROR = "i18n/isp/error";
private static final Set<String> noModuleCache = new HashSet<>();
private static final Map<String, OpenMessage> errorCache = new ConcurrentHashMap<>(64);
/**
* 错误信息的国际化信息
*/
private static MessageSourceAccessor errorMessageSourceAccessor;
public static void initMessage() {
ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
URL i18nFolder = contextClassLoader.getResource(I18N_ROOT);
if (i18nFolder == null) {
return;
}
try {
Path path = Paths.get(i18nFolder.toURI());
try (Stream<Path> walk = Files.walk(path)) {
Optional<Path> i18nRoot = walk.findFirst();
if (!i18nRoot.isPresent()) {
return;
}
File root = i18nRoot.get().toFile();
List<FileTree> fileTrees = buildFileTree(root);
Set<String> isvModuleList = buildIsvModuleList(fileTrees);
OpenMessageFactory.initMessageSource(new ArrayList<>(isvModuleList));
}
} catch (URISyntaxException | IOException e) {
logger.warning("初始化i18n模块错误:" + e.getMessage());
throw new RuntimeException(e);
}
}
private static Set<String> buildIsvModuleList(List<FileTree> fileTreeList) {
if (fileTreeList == null) {
return Collections.emptySet();
}
Set<String> isvModuleList = new HashSet<>();
List<FileTree> leafList = fileTreeList.stream().filter(FileTree::isLeaf).collect(Collectors.toList());
for (FileTree fileTree : leafList) {
LinkedList<String> nameList = new LinkedList<>();
appendNames(nameList, fileTree);
String moduleName = String.join("/", nameList);
isvModuleList.add(moduleName);
}
return isvModuleList;
}
private static void appendNames(LinkedList<String> nameList, FileTree fileTree) {
nameList.addFirst(fileTree.getName());
FileTree parent = fileTree.getParent();
if (parent != null) {
appendNames(nameList, parent);
}
}
private static List<FileTree> buildFileTree(File file) {
List<FileTree> fileTrees = new ArrayList<>();
appendFileTree(fileTrees, file, null);
return fileTrees;
}
private static void appendFileTree(List<FileTree> fileTrees, File file, FileTree parent) {
FileTree i18nTree = new FileTree();
i18nTree.setParent(parent);
fileTrees.add(i18nTree);
if (file.isDirectory()) {
i18nTree.setName(file.getName());
File[] files = file.listFiles();
if (files == null || files.length == 0) {
return;
}
for (File childFile : files) {
appendFileTree(fileTrees, childFile, i18nTree);
}
} else {
// i18n/isp/bizerror_en.properties
String name = file.getName();
int i = name.indexOf("_");
if (i < 0) {
return;
}
String module = name.substring(0, i);
i18nTree.setName(module);
i18nTree.setLeaf(true);
}
}
/**
* 设置国际化资源信息
*/
public static void initMessageSource(List<String> isvModules) {
HashSet<String> baseNamesSet = new HashSet<>();
baseNamesSet.add(I18N_OPEN_ERROR);
if (!isvModules.isEmpty()) {
if (isvModules != null) {
baseNamesSet.addAll(isvModules);
}
@@ -70,25 +163,26 @@ public class OpenMessageFactory {
* @param params 参数
* @return 如果没有配置国际化消息则直接返回errorMeta中的信息
*/
public static OpenMessage getError(OpenError openError, Locale locale, Object... params) {
Assert.notNull(locale, "未设置Locale");
String modulePrefix = openError.modulePrefix();
String subCode = openError.getSubCode();
// isp.error_isp.unknow-error=Service is temporarily unavailable
String subMsg = getErrorMessage(modulePrefix + subCode, locale, params);
public static OpenMessage getMessage(I18nMessage openError, Locale locale, Object... params) {
if (locale == null) {
locale = Locale.SIMPLIFIED_CHINESE;
}
String subCode = openError.getConfigKey();
// isp.unknow-error=Service is temporarily unavailable
String subMsg = getErrorMessage(subCode, locale, params);
if (ObjectUtils.isEmpty(subMsg)) {
subMsg = SYS_ERR;
}
// isp.error_isp.unknow-error.solution=Service is temporarily unavailable
String solution = getErrorMessage(modulePrefix + subCode + SOLUTION, locale, params);
// isp.unknow-error.solution=Service is temporarily unavailable
String solution = getErrorMessage(subCode + SOLUTION, locale, params);
if (ObjectUtils.isEmpty(solution)) {
solution = "";
}
return new ServiceMessageImpl(subCode, subMsg, solution);
return new DefaultOpenMessage(subCode, subMsg, solution);
}
public static void setErrorMessageSourceAccessor(MessageSourceAccessor errorMessageSourceAccessor) {
private static void setErrorMessageSourceAccessor(MessageSourceAccessor errorMessageSourceAccessor) {
OpenMessageFactory.errorMessageSourceAccessor = errorMessageSourceAccessor;
}
@@ -100,7 +194,7 @@ public class OpenMessageFactory {
* @param params 参数
* @return 返回信息
*/
public static String getErrorMessage(String module, Locale locale, Object... params) {
private static String getErrorMessage(String module, Locale locale, Object... params) {
if (noModuleCache.contains(module)) {
return null;
}
@@ -112,5 +206,21 @@ public class OpenMessageFactory {
}
}
@Data
private static class FileTree {
private String name;
private FileTree parent;
private boolean isLeaf;
@Override
public String toString() {
return "FileTree{" +
"name='" + name + '\'' +
'}';
}
}
}

View File

@@ -12,27 +12,16 @@ import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.dubbo.config.annotation.DubboService;
import java.io.File;
import java.io.IOException;
import java.io.Serializable;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.logging.Logger;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@@ -43,10 +32,7 @@ import java.util.stream.Stream;
*/
public class ApiRegister {
Logger log = Logger.getLogger(ApiRegister.class.getName());
private static final Log LOG = LogFactory.getLog(ApiRegister.class);
public static final String I18N_ROOT = "i18n";
private final ApiRegisterService apiRegisterService;
@@ -65,89 +51,7 @@ public class ApiRegister {
this.regApi(appName, interfaceClass, method, open));
}
initMessage();
}
protected void initMessage() {
ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
URL i18nFolder = contextClassLoader.getResource(I18N_ROOT);
if (i18nFolder == null) {
return;
}
try {
Path path = Paths.get(i18nFolder.toURI());
try (Stream<Path> walk = Files.walk(path)) {
Optional<Path> i18nRoot = walk.findFirst();
if (!i18nRoot.isPresent()) {
return;
}
File root = i18nRoot.get().toFile();
List<FileTree> fileTrees = buildFileTree(root);
Set<String> isvModuleList = buildIsvModuleList(fileTrees);
OpenMessageFactory.initMessageSource(new ArrayList<>(isvModuleList));
}
} catch (URISyntaxException | IOException e) {
log.warning("初始化i18n模块错误:" + e.getMessage());
throw new RuntimeException(e);
}
}
private Set<String> buildIsvModuleList(List<FileTree> fileTreeList) {
if (fileTreeList == null) {
return Collections.emptySet();
}
Set<String> isvModuleList = new HashSet<>();
List<FileTree> leafList = fileTreeList.stream().filter(FileTree::isLeaf).collect(Collectors.toList());
for (FileTree fileTree : leafList) {
LinkedList<String> nameList = new LinkedList<>();
appendNames(nameList, fileTree);
String moduleName = String.join("/", nameList);
isvModuleList.add(moduleName);
}
return isvModuleList;
}
private void appendNames(LinkedList<String> nameList, FileTree fileTree) {
nameList.addFirst(fileTree.getName());
FileTree parent = fileTree.getParent();
if (parent != null) {
appendNames(nameList, parent);
}
}
private List<FileTree> buildFileTree(File file) {
List<FileTree> fileTrees = new ArrayList<>();
this.appendFileTree(fileTrees, file, null);
return fileTrees;
}
private void appendFileTree(List<FileTree> fileTrees, File file, FileTree parent) {
FileTree i18nTree = new FileTree();
i18nTree.setParent(parent);
fileTrees.add(i18nTree);
if (file.isDirectory()) {
i18nTree.setName(file.getName());
File[] files = file.listFiles();
if (files == null || files.length == 0) {
return;
}
for (File childFile : files) {
appendFileTree(fileTrees, childFile, i18nTree);
}
} else {
// i18n/isp/bizerror_en.properties
String name = file.getName();
int i = name.indexOf("_");
String module = name.substring(0, i);
i18nTree.setName(module);
i18nTree.setLeaf(true);
}
OpenMessageFactory.initMessage();
}
protected void doWithMethod(Class<?> objClass, RegisterCallback callback) {