feat: 代码一键生成类的引入
代码一键生成类的引入代码一键生成类的引入
This commit is contained in:
+178
@@ -0,0 +1,178 @@
|
||||
package com.aos.element.common.constant;
|
||||
|
||||
|
||||
|
||||
import com.aos.element.basic.basic.constant.ConfigDefaultValue;
|
||||
import com.aos.element.basic.common.util.JustOnceLogger;
|
||||
import com.aos.starter.core.util.SystemUtils;
|
||||
import com.baomidou.mybatisplus.core.toolkit.StringPool;
|
||||
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
|
||||
|
||||
|
||||
|
||||
import lombok.experimental.UtilityClass;
|
||||
|
||||
/**
|
||||
* <p>Company: 成都返空汇网络技术有限公司</p>
|
||||
* <p>Description: 系统常量</p>
|
||||
*
|
||||
* @author dong4j
|
||||
* @version 1.2.3
|
||||
* @email "mailto:dongshijie@fkhwl.com"
|
||||
* @date 2019.12.26 21:40
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@UtilityClass
|
||||
public final class App {
|
||||
/** 用于判断是否为 agent service 应用 */
|
||||
public static final String IS_AGENT_SERVICE = "IS_AGENT_SERVICE";
|
||||
/** FRAMEWORK_VERSION */
|
||||
public static final String FRAMEWORK_VERSION_PREFIX = "V5_";
|
||||
/** 基础包 */
|
||||
public static final String BASE_PACKAGES = ConfigDefaultValue.BASE_PACKAGES;
|
||||
/** 启动标识, 所有项目只能使用 FkhApplication 启动 */
|
||||
public static final String START_FKH_APPLICATION = "start_fkh_application";
|
||||
/** 依赖的 library */
|
||||
public static final String LIBRARY_NAME = "used.librarys";
|
||||
/** server.sh 中的启动参数, 用于获取配置文件路径 */
|
||||
public static final String APP_CONFIG_PATH = "config.path";
|
||||
/** 应用类型 {@link org.springframework.boot.WebApplicationType} */
|
||||
public static final String APP_TYPE = "app.type";
|
||||
/**
|
||||
* 系统自定义应用类型, 比 {@link org.springframework.boot.WebApplicationType}
|
||||
* 多了 SERVICE 类型 (com.fkhwl.starter.launcher.enums.ApplicationType)
|
||||
*/
|
||||
public static final String APPLICATION_TYPE = "APPLICATION_TYPE";
|
||||
/** 启动方式, 用于区分是否通过 server.sh 脚本启动 */
|
||||
public static final String START_TYPE = "start.type";
|
||||
/** 通过 server.sh 启动的类型, 用于区分本地开发和服务端运行 */
|
||||
public static final String START_SHELL = "shell";
|
||||
/** 单元测试启动 */
|
||||
public static final String START_JUNIT = "junit";
|
||||
/** 本地开发时 idea 启动 */
|
||||
public static final String START_IDEA = "idea";
|
||||
/** rest 服务启动完成后将 url 写入到环境变量中, 用于其他组件获取此信息 */
|
||||
public static final String START_URL = "start_url";
|
||||
/** 用于打印 bean 信息 */
|
||||
public static final String DEBUG_MODEL = "debug";
|
||||
/** 以下是环境标识 */
|
||||
public static final String ENV_LOCAL = "local";
|
||||
/** ENV_DEV */
|
||||
public static final String ENV_DEV = "dev";
|
||||
/** ENV_TEST */
|
||||
public static final String ENV_TEST = "test";
|
||||
/** ENV_PREV */
|
||||
public static final String ENV_PREV = "prev";
|
||||
/** ENV_PROD */
|
||||
public static final String ENV_PROD = "prod";
|
||||
/** maven 三要素, 会从中获取应用名, 应用版本(不需要手动配置, 应用打包时会自动创建) */
|
||||
public static final String APP_POM_PROP_NAME = "pom.properties";
|
||||
/** 由 fkh-assist-maven-plugin 自动生成 */
|
||||
public static final String APP_BULID_INFO_FILE_NAME = "build-info.properties";
|
||||
/** GIT_CONFIG_FILE_NAME */
|
||||
public static final String GIT_CONFIG_FILE_NAME = "git.properties";
|
||||
/** WINDOWS_DEFAULT_USER_NAME */
|
||||
private static final String WINDOWS_DEFAULT_USER_NAME = "Administrator";
|
||||
|
||||
/**
|
||||
* <p>Company: 成都返空汇网络技术有限公司 </p>
|
||||
* <p>Description: </p>
|
||||
*
|
||||
* @author dong4j
|
||||
* @version 1.0.0
|
||||
* @email "mailto:dongshijie@fkhwl.com"
|
||||
* @date 2021.01.20 01:43
|
||||
* @since 1.7.1
|
||||
*/
|
||||
@UtilityClass
|
||||
public static final class BuildInfo {
|
||||
/** VERSION */
|
||||
public static final String VERSION = "build.version";
|
||||
/** TIME */
|
||||
public static final String TIME = "build.time";
|
||||
/** USER_NAME */
|
||||
public static final String USER_NAME = "build.user.name";
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Company: 成都返空汇网络技术有限公司 </p>
|
||||
* <p>Description: </p>
|
||||
*
|
||||
* @author dong4j
|
||||
* @version 1.0.0
|
||||
* @email "mailto:dongshijie@fkhwl.com"
|
||||
* @date 2021.01.20 01:50
|
||||
* @since 1.7.1
|
||||
*/
|
||||
@UtilityClass
|
||||
public static final class GitInfo {
|
||||
/** VERSION */
|
||||
public static final String BRANCH = "git.branch";
|
||||
/** BUILD_VERSION */
|
||||
public static final String BUILD_VERSION = "git.build.version";
|
||||
/** 最后提交时间 */
|
||||
public static final String BUILD_TIME = "git.build.time";
|
||||
/** COMMIT_TIME */
|
||||
public static final String COMMIT_TIME = "git.commit.time";
|
||||
/** USER_NAME */
|
||||
public static final String BUILD_USER_NAME = "git.build.user.name";
|
||||
/** COMMIT_USER_NAME */
|
||||
public static final String COMMIT_USER_NAME = "git.commit.user.name";
|
||||
/** COMMIT_MESSAGE */
|
||||
public static final String COMMIT_MESSAGE = "git.commit.message.short";
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Company: 成都返空汇网络技术有限公司 </p>
|
||||
* <p>Description: 组件名常量 </p>
|
||||
*
|
||||
* @author dong4j
|
||||
* @version 1.0.0
|
||||
* @email "mailto:dongshijie@fkhwl.com"
|
||||
* @date 2021.01.16 02:32
|
||||
* @since 1.7.1
|
||||
*/
|
||||
@UtilityClass
|
||||
public static class Components {
|
||||
/** FKH_REST_SPRING_BOOT */
|
||||
public static final String FKH_REST_SPRING_BOOT = "fkh-rest-spring-boot";
|
||||
/** FKH_AGENT_SPRING_BOOT */
|
||||
public static final String FKH_AGENT_SPRING_BOOT = "fkh-agent-spring-boot";
|
||||
}
|
||||
|
||||
/**
|
||||
* 本地开发时, 优先从 JVM 环境变量中读取 {@link SystemUtils#USER_NAMESPACE_VALUE}, 然后是 user.name,
|
||||
* 如果 {@link SystemUtils#USER_NAME} 是 {@link App#WINDOWS_DEFAULT_USER_NAME}, 则读取系统环境变量 FKH_NAME_SPACE).
|
||||
* 如果通过 shell 启动, 会自动设置 FKH_NAME_SPACE 为传入的 env 参数, 不会会加上 fkh- 前缀, 最终找到 fkh-{env} 的 nacos namespace.
|
||||
*/
|
||||
public static final String FKH_NAME_SPACE;
|
||||
|
||||
static {
|
||||
// JVM 参数 user.namespace 优先级最高, 可通过 System.setProperty(SystemUtils.USER_NAMESPACE, "xxxx") 或 JVM 参数设置
|
||||
String currentEnv = SystemUtils.USER_NAMESPACE_VALUE;
|
||||
|
||||
// 第二优先级是 FKH_NAME_SPACE
|
||||
if (StringUtils.isBlank(currentEnv)) {
|
||||
currentEnv = StringUtils.isBlank(SystemUtils.getProperty("FKH_NAME_SPACE"))
|
||||
? StringPool.EMPTY
|
||||
: SystemUtils.getProperty("FKH_NAME_SPACE");
|
||||
}
|
||||
|
||||
// 第三优先级是 user.name, 如果在 windows 未设置计算机名, 此名称将是 Administrator
|
||||
currentEnv = StringUtils.isBlank(currentEnv)
|
||||
? SystemUtils.USER_NAME
|
||||
: currentEnv;
|
||||
|
||||
// 如果是 Administrator 则获取 FKH_NAME_SPACE
|
||||
if (WINDOWS_DEFAULT_USER_NAME.equalsIgnoreCase(currentEnv)) {
|
||||
JustOnceLogger.printOnce(App.class.getName(), "请配置环境变量 「FKH_NAME_SPACE」 或修改本地的计算机名. "
|
||||
+ "如果需要在本地开发时修改 namespace, 请设置 JVM 参数 「user.namespace」"
|
||||
+ "或直接使用 System.setProperty(SystemUtils.USER_NAMESPACE, \"xxxx\"))");
|
||||
currentEnv = "public";
|
||||
}
|
||||
|
||||
FKH_NAME_SPACE = currentEnv;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
package com.aos.starter.core.api;
|
||||
|
||||
import com.aos.element.basic.basic.Result;
|
||||
import com.aos.element.basic.basic.annotation.BusinessLevel;
|
||||
import com.aos.element.basic.basic.annotation.ModelSerial;
|
||||
import com.aos.element.basic.basic.annotation.SystemLevel;
|
||||
import com.aos.starter.core.CoreBundle;
|
||||
import com.aos.starter.core.assertion.BaseExceptionAssert;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* <p>Company: 成都返空汇网络技术有限公司</p>
|
||||
* <p>Description: 通用返回结果 </p>
|
||||
*
|
||||
* @author dong4j
|
||||
* @version 1.2.3
|
||||
* @email "mailto:dongshijie@fkhwl.com"
|
||||
* @date 2020.01.02 11:36
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
@ModelSerial
|
||||
public enum BaseCodes implements BaseExceptionAssert {
|
||||
/** 成功 */
|
||||
SUCCESS(Integer.parseInt(Result.SUCCESS_CODE), Result.SUCCESS_MESSAGE),
|
||||
/** 默认没有数据响应 */
|
||||
@SystemLevel
|
||||
DEFAULT_NULL_DATA(2222, CoreBundle.message("code.default.null.data")),
|
||||
/** 默认的失败响应 */
|
||||
@SystemLevel
|
||||
FAILURE(Integer.parseInt(Result.FAILURE_CODE), Result.FAILURE_MESSAGE),
|
||||
/** 参数校验失败 */
|
||||
@BusinessLevel
|
||||
PARAM_VERIFY_ERROR(4100, CoreBundle.message("code.param.verify.error")),
|
||||
/** 数据不存在 */
|
||||
@SystemLevel
|
||||
DATA_ERROR(4101, CoreBundle.message("code.data.error")),
|
||||
/** 操作失败 */
|
||||
@SystemLevel
|
||||
OPTION_FAILURE(4102, CoreBundle.message("code.option.failure")),
|
||||
/** Config error base codes */
|
||||
@SystemLevel
|
||||
CONFIG_ERROR(7000, CoreBundle.message("code.config.error")),
|
||||
/** Server inner error base codes. */
|
||||
@SystemLevel
|
||||
SERVER_INNER_ERROR(5000, CoreBundle.message("code.server.inner.error")),
|
||||
/** Service invoke error base codes */
|
||||
@SystemLevel
|
||||
SERVICE_INVOKE_ERROR(5001, CoreBundle.message("code.service.invoke.error")),
|
||||
/** Agent exception */
|
||||
@SystemLevel
|
||||
AGENT_INVOKE_EXCEPTION(5002, CoreBundle.message("code.client.invoke.error")),
|
||||
/** Agent enable exception base codes */
|
||||
@SystemLevel
|
||||
AGENT_DISABLE_EXCEPTION(5003, CoreBundle.message("code.agent.disable.error")),
|
||||
/** Rpc error base codes */
|
||||
@SystemLevel
|
||||
RPC_ERROR(5004, CoreBundle.message("code.rpc.invoke.error")),
|
||||
/** Gateway not fund instances error base codes */
|
||||
GATEWAY_NOT_FUND_INSTANCES_ERROR(5005, CoreBundle.message("code.gateway.instances.error")),
|
||||
/** 路由配置错误 */
|
||||
GATEWAY_ROUTER_ERROR(5006, CoreBundle.message("code.gateway.router.error")),
|
||||
/** Agent service not found error base codes */
|
||||
@BusinessLevel
|
||||
AGENT_SERVICE_NOT_FOUND_ERROR(5007, CoreBundle.message("code.agent.not.found.error")),
|
||||
/** 服务器繁忙,请稍后重试 */
|
||||
@SystemLevel
|
||||
SERVER_BUSY(9998, CoreBundle.message("code.server.busy")),
|
||||
/** 服务器异常,无法识别的异常,尽可能对通过判断减少未定义异常抛出 */
|
||||
@SystemLevel
|
||||
SERVER_ERROR(9999, CoreBundle.message("code.server.error"));
|
||||
|
||||
/** 返回码 */
|
||||
private final Integer code;
|
||||
/** 返回消息 */
|
||||
private final String message;
|
||||
}
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
package com.aos.starter.core.assertion;
|
||||
|
||||
import com.aos.starter.core.api.IResultCode;
|
||||
import com.aos.starter.core.exception.BaseException;
|
||||
|
||||
/**
|
||||
* <p>Company: 成都返空汇网络技术有限公司</p>
|
||||
* <p>Description: 全局错误异常断言 </p>
|
||||
*
|
||||
* @author dong4j
|
||||
* @version 1.2.3
|
||||
* @email "mailto:dongshijie@fkhwl.com"
|
||||
* @date 2019.12.24 12:20
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public interface BaseExceptionAssert extends IResultCode, IAssert {
|
||||
/** serialVersionUID */
|
||||
long serialVersionUID = 3077918845714343375L;
|
||||
|
||||
/**
|
||||
* New exceptions base exception.
|
||||
*
|
||||
* @param args the args
|
||||
* @return the base exception
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Override
|
||||
default BaseException newException(Object... args) {
|
||||
return new BaseException(this, args, this.getMessage());
|
||||
}
|
||||
|
||||
/**
|
||||
* New exceptions base exception.
|
||||
*
|
||||
* @param t the t
|
||||
* @param args the args
|
||||
* @return the base exception
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Override
|
||||
default BaseException newException(Throwable t, Object... args) {
|
||||
return new BaseException(this, args, this.getMessage(), t);
|
||||
}
|
||||
|
||||
}
|
||||
+228
@@ -0,0 +1,228 @@
|
||||
package com.aos.starter.core.exception;
|
||||
|
||||
import com.aos.element.basic.basic.exception.BasicException;
|
||||
import com.aos.element.basic.basic.support.StrFormatter;
|
||||
import com.aos.starter.core.api.BaseCodes;
|
||||
import com.aos.starter.core.api.IResultCode;
|
||||
import com.aos.starter.core.util.ResultCodeUtils;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
* <p>Company: 成都返空汇网络技术有限公司</p>
|
||||
* <p>Description: 基础异常类,所有自定义异常类都需要继承本类 </p>
|
||||
*
|
||||
* @author dong4j
|
||||
* @version 1.2.3
|
||||
* @email "mailto:dongshijie@fkhwl.com"
|
||||
* @date 2019.11.26 23:45
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Slf4j
|
||||
@Getter
|
||||
public class BaseException extends BasicException {
|
||||
|
||||
/** serialVersionUID */
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/** 返回码 */
|
||||
protected IResultCode resultCode;
|
||||
/** 异常消息参数 */
|
||||
protected Object[] args;
|
||||
|
||||
/**
|
||||
* Instantiates a new Base exception.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public BaseException() {
|
||||
super(BaseCodes.FAILURE.getMessage());
|
||||
this.resultCode = BaseCodes.FAILURE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates a new Base exception.
|
||||
*
|
||||
* @param msg the msg
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public BaseException(String msg) {
|
||||
super(msg);
|
||||
this.resultCode = BaseCodes.FAILURE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates a new Base exception.
|
||||
*
|
||||
* @param code the code
|
||||
* @param msg the msg
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public BaseException(int code, String msg) {
|
||||
super(msg);
|
||||
this.resultCode = new IResultCode() {
|
||||
private static final long serialVersionUID = 2590640370242410124L;
|
||||
|
||||
@Override
|
||||
public String getMessage() {
|
||||
return msg;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getCode() {
|
||||
return code;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public BaseException(String code, String msg) {
|
||||
super(code, msg);
|
||||
this.resultCode = new IResultCode() {
|
||||
private static final long serialVersionUID = 2590640370242410124L;
|
||||
|
||||
/**
|
||||
* Gets message *
|
||||
*
|
||||
* @return the message
|
||||
* @since 1.6.0
|
||||
*/
|
||||
@Override
|
||||
public String getMessage() {
|
||||
return msg;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getCode() {
|
||||
return ResultCodeUtils.convert(code);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* msg 占位符替换
|
||||
*
|
||||
* @param msg msg
|
||||
* @param args args
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public BaseException(String msg, Object... args) {
|
||||
super(msg, args);
|
||||
this.resultCode = BaseCodes.FAILURE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Base exception
|
||||
*
|
||||
* @param cause cause
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public BaseException(Throwable cause) {
|
||||
super(cause);
|
||||
this.resultCode = BaseCodes.FAILURE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Base exception
|
||||
*
|
||||
* @param msg msg
|
||||
* @param cause cause
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public BaseException(String msg, Throwable cause) {
|
||||
super(msg, cause);
|
||||
this.resultCode = BaseCodes.FAILURE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates a new Base exception.
|
||||
*
|
||||
* @param resultCode the response enum
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public BaseException(@NotNull IResultCode resultCode) {
|
||||
super(resultCode.getMessage());
|
||||
this.resultCode = resultCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Base exception
|
||||
*
|
||||
* @param resultCode result code
|
||||
* @param cause cause
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public BaseException(@NotNull IResultCode resultCode, Throwable cause) {
|
||||
super(resultCode.getMessage(), cause);
|
||||
this.resultCode = resultCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates a new Base exception.
|
||||
*
|
||||
* @param code the code
|
||||
* @param msg the msg
|
||||
* @param cause cause
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public BaseException(int code, String msg, Throwable cause) {
|
||||
super(msg, cause);
|
||||
this.resultCode = new IResultCode() {
|
||||
private static final long serialVersionUID = 2590640370242410124L;
|
||||
|
||||
@Override
|
||||
public String getMessage() {
|
||||
return msg;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates a new Base exception.
|
||||
*
|
||||
* @param resultCode the response enum
|
||||
* @param args the args
|
||||
* @param msg msg 替换占位符后的消息
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public BaseException(IResultCode resultCode, Object[] args, String msg) {
|
||||
super(StrFormatter.mergeFormat(msg, args));
|
||||
this.resultCode = resultCode;
|
||||
this.args = args;
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates a new Base exception.
|
||||
*
|
||||
* @param resultCode the response enum
|
||||
* @param args the args
|
||||
* @param msg msg
|
||||
* @param cause the cause
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public BaseException(IResultCode resultCode, Object[] args, String msg, Throwable cause) {
|
||||
super(StrFormatter.mergeFormat(msg, args), cause);
|
||||
this.resultCode = resultCode;
|
||||
this.args = args;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get code
|
||||
*
|
||||
* @return the string
|
||||
* @since 1.6.0
|
||||
*/
|
||||
@Override
|
||||
public String getCode() {
|
||||
return ResultCodeUtils.generateCode(this.resultCode);
|
||||
}
|
||||
|
||||
}
|
||||
+195
@@ -0,0 +1,195 @@
|
||||
package com.aos.starter.core.jackson;
|
||||
|
||||
import com.aos.element.basic.basic.util.Charsets;
|
||||
import com.fasterxml.jackson.core.JsonEncoding;
|
||||
import com.fasterxml.jackson.core.JsonGenerator;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.core.PrettyPrinter;
|
||||
import com.fasterxml.jackson.core.util.DefaultIndenter;
|
||||
import com.fasterxml.jackson.core.util.DefaultPrettyPrinter;
|
||||
import com.fasterxml.jackson.databind.JavaType;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.ObjectWriter;
|
||||
import com.fasterxml.jackson.databind.SerializationConfig;
|
||||
import com.fasterxml.jackson.databind.SerializationFeature;
|
||||
import com.fasterxml.jackson.databind.exc.InvalidDefinitionException;
|
||||
import com.fasterxml.jackson.databind.ser.FilterProvider;
|
||||
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.springframework.http.HttpOutputMessage;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.converter.AbstractGenericHttpMessageConverter;
|
||||
import org.springframework.http.converter.HttpMessageConversionException;
|
||||
import org.springframework.http.converter.HttpMessageNotWritableException;
|
||||
import org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter;
|
||||
import org.springframework.http.converter.json.MappingJacksonValue;
|
||||
import org.springframework.util.TypeUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
/**
|
||||
* <p>Company: 成都返空汇网络技术有限公司</p>
|
||||
* <p>Description: 分读写的 json 消息 处理器 </p>
|
||||
*
|
||||
* @author dong4j
|
||||
* @version 1.2.3
|
||||
* @email "mailto:dongshijie@fkhwl.com"
|
||||
* @date 2019.12.26 21:38
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public abstract class AbstractReadWriteJackson2HttpMessageConverter extends AbstractJackson2HttpMessageConverter {
|
||||
/** DEFAULT_CHARSET */
|
||||
private static final java.nio.charset.Charset DEFAULT_CHARSET = Charsets.UTF_8;
|
||||
|
||||
/** Write object mapper */
|
||||
private final ObjectMapper writeObjectMapper;
|
||||
/** Sse pretty printer */
|
||||
@Nullable
|
||||
private PrettyPrinter ssePrettyPrinter;
|
||||
|
||||
/**
|
||||
* Instantiates a new Abstract read write jackson 2 http message converter.
|
||||
*
|
||||
* @param readObjectMapper the read object mapper
|
||||
* @param writeObjectMapper the write object mapper
|
||||
* @param supportedMediaType the supported media type
|
||||
* @since 1.0.0
|
||||
*/
|
||||
protected AbstractReadWriteJackson2HttpMessageConverter(ObjectMapper readObjectMapper,
|
||||
ObjectMapper writeObjectMapper,
|
||||
MediaType supportedMediaType) {
|
||||
this(readObjectMapper, writeObjectMapper);
|
||||
this.setSupportedMediaTypes(Collections.singletonList(supportedMediaType));
|
||||
this.initSsePrettyPrinter();
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates a new Abstract read write jackson 2 http message converter.
|
||||
*
|
||||
* @param readObjectMapper the read object mapper
|
||||
* @param writeObjectMapper the write object mapper
|
||||
* @since 1.0.0
|
||||
*/
|
||||
protected AbstractReadWriteJackson2HttpMessageConverter(ObjectMapper readObjectMapper, ObjectMapper writeObjectMapper) {
|
||||
super(readObjectMapper);
|
||||
this.writeObjectMapper = writeObjectMapper;
|
||||
this.initSsePrettyPrinter();
|
||||
}
|
||||
|
||||
/**
|
||||
* Init sse pretty printer
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private void initSsePrettyPrinter() {
|
||||
this.setDefaultCharset(DEFAULT_CHARSET);
|
||||
DefaultPrettyPrinter prettyPrinter = new DefaultPrettyPrinter();
|
||||
prettyPrinter.indentObjectsWith(new DefaultIndenter(" ", "\ndata:"));
|
||||
this.ssePrettyPrinter = prettyPrinter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates a new Abstract read write jackson 2 http message converter.
|
||||
*
|
||||
* @param readObjectMapper the read object mapper
|
||||
* @param writeObjectMapper the write object mapper
|
||||
* @param supportedMediaTypes the supported media types
|
||||
* @since 1.0.0
|
||||
*/
|
||||
protected AbstractReadWriteJackson2HttpMessageConverter(ObjectMapper readObjectMapper,
|
||||
ObjectMapper writeObjectMapper,
|
||||
MediaType... supportedMediaTypes) {
|
||||
this(readObjectMapper, writeObjectMapper);
|
||||
this.setSupportedMediaTypes(Arrays.asList(supportedMediaTypes));
|
||||
}
|
||||
|
||||
/**
|
||||
* Can write boolean
|
||||
*
|
||||
* @param clazz clazz
|
||||
* @param mediaType media type
|
||||
* @return the boolean
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Override
|
||||
public boolean canWrite(@NotNull Class<?> clazz, @Nullable MediaType mediaType) {
|
||||
if (!this.canWrite(mediaType)) {
|
||||
return false;
|
||||
}
|
||||
AtomicReference<Throwable> causeRef = new AtomicReference<>();
|
||||
if (this.objectMapper.canSerialize(clazz, causeRef)) {
|
||||
return true;
|
||||
}
|
||||
this.logWarningIfNecessary(clazz, causeRef.get());
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 最终的序列化逻辑
|
||||
*
|
||||
* @param object object
|
||||
* @param type type
|
||||
* @param outputMessage output message
|
||||
* @throws IOException io exception
|
||||
* @throws HttpMessageNotWritableException http message not writable exception
|
||||
* @see AbstractGenericHttpMessageConverter#write
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Override
|
||||
protected void writeInternal(@NotNull Object object, @Nullable Type type, @NotNull HttpOutputMessage outputMessage)
|
||||
throws IOException, HttpMessageNotWritableException {
|
||||
|
||||
MediaType contentType = outputMessage.getHeaders().getContentType();
|
||||
JsonEncoding encoding = this.getJsonEncoding(contentType);
|
||||
JsonGenerator generator = this.writeObjectMapper.getFactory().createGenerator(outputMessage.getBody(), encoding);
|
||||
try {
|
||||
this.writePrefix(generator, object);
|
||||
|
||||
Object value = object;
|
||||
Class<?> serializationView = null;
|
||||
FilterProvider filters = null;
|
||||
JavaType javaType = null;
|
||||
|
||||
if (object instanceof MappingJacksonValue) {
|
||||
MappingJacksonValue container = (MappingJacksonValue) object;
|
||||
value = container.getValue();
|
||||
serializationView = container.getSerializationView();
|
||||
filters = container.getFilters();
|
||||
}
|
||||
if (type != null && TypeUtils.isAssignable(type, value.getClass())) {
|
||||
javaType = this.getJavaType(type, null);
|
||||
}
|
||||
|
||||
ObjectWriter objectWriter = (serializationView != null
|
||||
? this.writeObjectMapper.writerWithView(serializationView)
|
||||
: this.writeObjectMapper.writer());
|
||||
if (filters != null) {
|
||||
objectWriter = objectWriter.with(filters);
|
||||
}
|
||||
if (javaType != null && javaType.isContainerType()) {
|
||||
objectWriter = objectWriter.forType(javaType);
|
||||
}
|
||||
SerializationConfig config = objectWriter.getConfig();
|
||||
if (contentType != null
|
||||
&& contentType.isCompatibleWith(MediaType.TEXT_EVENT_STREAM)
|
||||
&& config.isEnabled(SerializationFeature.INDENT_OUTPUT)) {
|
||||
objectWriter = objectWriter.with(this.ssePrettyPrinter);
|
||||
}
|
||||
objectWriter.writeValue(generator, value);
|
||||
|
||||
this.writeSuffix(generator, object);
|
||||
generator.flush();
|
||||
} catch (InvalidDefinitionException ex) {
|
||||
throw new HttpMessageConversionException("Type definition error: " + ex.getType(), ex);
|
||||
} catch (JsonProcessingException ex) {
|
||||
throw new HttpMessageNotWritableException("Could not write JSON: " + ex.getOriginalMessage(), ex);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
package com.aos.starter.core.metadata;
|
||||
|
||||
/**
|
||||
* <p>Company: 成都返空汇网络技术有限公司 </p>
|
||||
* <p>Description: 自用常量集中管理 </p>
|
||||
*
|
||||
* @author dong4j
|
||||
* @version 1.3.0
|
||||
* @email "mailto:dongshijie@fkhwl.com"
|
||||
* @date 2020.04.12 12:50
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public interface Constants {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package com.aos.starter.core.node;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* <p>Company: 成都返空汇网络技术有限公司</p>
|
||||
* <p>Description: 节点基类</p>
|
||||
*
|
||||
* @author dong4j
|
||||
* @version 1.2.3
|
||||
* @email "mailto:dongshijie@fkhwl.com"
|
||||
* @date 2020.01.27 14:52
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Data
|
||||
public class BaseNode implements INode {
|
||||
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
protected Integer id;
|
||||
|
||||
/**
|
||||
* 父节点ID
|
||||
*/
|
||||
protected Integer parentId;
|
||||
|
||||
/**
|
||||
* 子孙节点
|
||||
*/
|
||||
@JsonInclude(JsonInclude.Include.NON_EMPTY)
|
||||
protected List<INode> children = new ArrayList<>();
|
||||
|
||||
}
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
package com.aos.starter.core.reflection.invoker;
|
||||
|
||||
import com.aos.starter.core.reflection.ReflectionException;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
/**
|
||||
* <p>Company: 成都返空汇网络技术有限公司 </p>
|
||||
* <p>Description: </p>
|
||||
*
|
||||
* @author dong4j
|
||||
* @version 1.3.0
|
||||
* @email "mailto:dongshijie@fkhwl.com"
|
||||
* @date 2020.04.12 11:46
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class AmbiguousMethodInvoker extends MethodInvoker {
|
||||
/** Exception message */
|
||||
private final String exceptionMessage;
|
||||
|
||||
/**
|
||||
* Ambiguous method invoker
|
||||
*
|
||||
* @param method method
|
||||
* @param exceptionMessage exception message
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public AmbiguousMethodInvoker(Method method, String exceptionMessage) {
|
||||
super(method);
|
||||
this.exceptionMessage = exceptionMessage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoke object
|
||||
*
|
||||
* @param target target
|
||||
* @param args args
|
||||
* @return the object
|
||||
* @throws IllegalAccessException illegal access exception
|
||||
* @throws InvocationTargetException invocation target exception
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Override
|
||||
public Object invoke(Object target, Object[] args) throws IllegalAccessException, InvocationTargetException {
|
||||
throw new ReflectionException(this.exceptionMessage);
|
||||
}
|
||||
}
|
||||
+137
@@ -0,0 +1,137 @@
|
||||
package com.aos.starter.core.reflection.wrapper;
|
||||
|
||||
|
||||
import com.aos.starter.core.reflection.MetaObject;
|
||||
import com.aos.starter.core.reflection.ReflectionException;
|
||||
import com.aos.starter.core.reflection.property.PropertyTokenizer;
|
||||
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* <p>Company: 成都返空汇网络技术有限公司 </p>
|
||||
* <p>Description: </p>
|
||||
*
|
||||
* @author dong4j
|
||||
* @version 1.3.0
|
||||
* @email "mailto:dongshijie@fkhwl.com"
|
||||
* @date 2020.04.12 11:50
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public abstract class BaseWrapper implements ObjectWrapper {
|
||||
|
||||
/** NO_ARGUMENTS */
|
||||
protected static final Object[] NO_ARGUMENTS = new Object[0];
|
||||
/** Meta object */
|
||||
protected final MetaObject metaObject;
|
||||
|
||||
/**
|
||||
* Base wrapper
|
||||
*
|
||||
* @param metaObject meta object
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Contract(pure = true)
|
||||
protected BaseWrapper(MetaObject metaObject) {
|
||||
this.metaObject = metaObject;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve collection object
|
||||
*
|
||||
* @param prop prop
|
||||
* @param object object
|
||||
* @return the object
|
||||
* @since 1.0.0
|
||||
*/
|
||||
protected Object resolveCollection(@NotNull PropertyTokenizer prop, Object object) {
|
||||
if ("".equals(prop.getName())) {
|
||||
return object;
|
||||
} else {
|
||||
return this.metaObject.getValue(prop.getName());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets collection value *
|
||||
*
|
||||
* @param prop prop
|
||||
* @param collection collection
|
||||
* @return the collection value
|
||||
* @since 1.0.0
|
||||
*/
|
||||
protected Object getCollectionValue(PropertyTokenizer prop, Object collection) {
|
||||
if (collection instanceof Map) {
|
||||
return ((Map<?, ?>) collection).get(prop.getIndex());
|
||||
} else {
|
||||
int i = Integer.parseInt(prop.getIndex());
|
||||
if (collection instanceof List) {
|
||||
return ((List<?>) collection).get(i);
|
||||
} else if (collection instanceof Object[]) {
|
||||
return ((Object[]) collection)[i];
|
||||
} else if (collection instanceof char[]) {
|
||||
return ((char[]) collection)[i];
|
||||
} else if (collection instanceof boolean[]) {
|
||||
return ((boolean[]) collection)[i];
|
||||
} else if (collection instanceof byte[]) {
|
||||
return ((byte[]) collection)[i];
|
||||
} else if (collection instanceof double[]) {
|
||||
return ((double[]) collection)[i];
|
||||
} else if (collection instanceof float[]) {
|
||||
return ((float[]) collection)[i];
|
||||
} else if (collection instanceof int[]) {
|
||||
return ((int[]) collection)[i];
|
||||
} else if (collection instanceof long[]) {
|
||||
return ((long[]) collection)[i];
|
||||
} else if (collection instanceof short[]) {
|
||||
return ((short[]) collection)[i];
|
||||
} else {
|
||||
throw new ReflectionException("The '{}' property of {} is not a List or Array.", prop.getName(), collection);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets collection value *
|
||||
*
|
||||
* @param prop prop
|
||||
* @param collection collection
|
||||
* @param value value
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@SuppressWarnings(value = {"unchecked", "rawtypes"})
|
||||
protected void setCollectionValue(PropertyTokenizer prop, Object collection, Object value) {
|
||||
if (collection instanceof Map) {
|
||||
((Map) collection).put(prop.getIndex(), value);
|
||||
} else {
|
||||
int i = Integer.parseInt(prop.getIndex());
|
||||
if (collection instanceof List) {
|
||||
((List) collection).set(i, value);
|
||||
} else if (collection instanceof Object[]) {
|
||||
((Object[]) collection)[i] = value;
|
||||
} else if (collection instanceof char[]) {
|
||||
((char[]) collection)[i] = (Character) value;
|
||||
} else if (collection instanceof boolean[]) {
|
||||
((boolean[]) collection)[i] = (Boolean) value;
|
||||
} else if (collection instanceof byte[]) {
|
||||
((byte[]) collection)[i] = (Byte) value;
|
||||
} else if (collection instanceof double[]) {
|
||||
((double[]) collection)[i] = (Double) value;
|
||||
} else if (collection instanceof float[]) {
|
||||
((float[]) collection)[i] = (Float) value;
|
||||
} else if (collection instanceof int[]) {
|
||||
((int[]) collection)[i] = (Integer) value;
|
||||
} else if (collection instanceof long[]) {
|
||||
((long[]) collection)[i] = (Long) value;
|
||||
} else if (collection instanceof short[]) {
|
||||
((short[]) collection)[i] = (Short) value;
|
||||
} else {
|
||||
throw new ReflectionException("The '{}' property of {} is not a List or Array.", prop.getName(), collection);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+323
@@ -0,0 +1,323 @@
|
||||
package com.aos.starter.core.reflection.wrapper;
|
||||
|
||||
|
||||
import com.aos.starter.core.reflection.DefaultMetaObject;
|
||||
import com.aos.starter.core.reflection.MetaClass;
|
||||
import com.aos.starter.core.reflection.MetaObject;
|
||||
import com.aos.starter.core.reflection.ReflectionException;
|
||||
import com.aos.starter.core.reflection.factory.ObjectFactory;
|
||||
import com.aos.starter.core.reflection.invoker.Invoker;
|
||||
import com.aos.starter.core.reflection.property.PropertyTokenizer;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import cn.hutool.core.exceptions.ExceptionUtil;
|
||||
|
||||
/**
|
||||
* <p>Company: 成都返空汇网络技术有限公司 </p>
|
||||
* <p>Description: </p>
|
||||
*
|
||||
* @author dong4j
|
||||
* @version 1.3.0
|
||||
* @email "mailto:dongshijie@fkhwl.com"
|
||||
* @date 2020.04.12 11:52
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@SuppressWarnings("all")
|
||||
public class BeanWrapper extends BaseWrapper {
|
||||
|
||||
/** Object */
|
||||
private final Object object;
|
||||
/** Meta class */
|
||||
private final MetaClass metaClass;
|
||||
|
||||
/**
|
||||
* Bean wrapper
|
||||
*
|
||||
* @param metaObject meta object
|
||||
* @param object object
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public BeanWrapper(MetaObject metaObject, @NotNull Object object) {
|
||||
super(metaObject);
|
||||
this.object = object;
|
||||
this.metaClass = MetaClass.forClass(object.getClass(), metaObject.getReflectorFactory());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get object
|
||||
*
|
||||
* @param prop prop
|
||||
* @return the object
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Override
|
||||
public Object get(@NotNull PropertyTokenizer prop) {
|
||||
if (prop.getIndex() != null) {
|
||||
Object collection = this.resolveCollection(prop, this.object);
|
||||
return this.getCollectionValue(prop, collection);
|
||||
} else {
|
||||
return this.getBeanProperty(prop, this.object);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set *
|
||||
*
|
||||
* @param prop prop
|
||||
* @param value value
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Override
|
||||
public void set(@NotNull PropertyTokenizer prop, Object value) {
|
||||
if (prop.getIndex() != null) {
|
||||
Object collection = this.resolveCollection(prop, this.object);
|
||||
this.setCollectionValue(prop, collection, value);
|
||||
} else {
|
||||
this.setBeanProperty(prop, this.object, value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Find property string
|
||||
*
|
||||
* @param name name
|
||||
* @param useCamelCaseMapping use camel case mapping
|
||||
* @return the string
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Override
|
||||
public String findProperty(String name, boolean useCamelCaseMapping) {
|
||||
return this.metaClass.findProperty(name, useCamelCaseMapping);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get getter names string [ ]
|
||||
*
|
||||
* @return the string [ ]
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Override
|
||||
public String[] getGetterNames() {
|
||||
return this.metaClass.getGetterNames();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get setter names string [ ]
|
||||
*
|
||||
* @return the string [ ]
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Override
|
||||
public String[] getSetterNames() {
|
||||
return this.metaClass.getSetterNames();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets setter type *
|
||||
*
|
||||
* @param name name
|
||||
* @return the setter type
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Override
|
||||
public Class<?> getSetterType(String name) {
|
||||
PropertyTokenizer prop = new PropertyTokenizer(name);
|
||||
if (prop.hasNext()) {
|
||||
MetaObject metaValue = this.metaObject.metaObjectForProperty(prop.getIndexedName());
|
||||
if (metaValue == DefaultMetaObject.NULL_META_OBJECT) {
|
||||
return this.metaClass.getSetterType(name);
|
||||
} else {
|
||||
return metaValue.getSetterType(prop.getChildren());
|
||||
}
|
||||
} else {
|
||||
return this.metaClass.getSetterType(name);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets getter type *
|
||||
*
|
||||
* @param name name
|
||||
* @return the getter type
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Override
|
||||
public Class<?> getGetterType(String name) {
|
||||
PropertyTokenizer prop = new PropertyTokenizer(name);
|
||||
if (prop.hasNext()) {
|
||||
MetaObject metaValue = this.metaObject.metaObjectForProperty(prop.getIndexedName());
|
||||
if (metaValue == DefaultMetaObject.NULL_META_OBJECT) {
|
||||
return this.metaClass.getGetterType(name);
|
||||
} else {
|
||||
return metaValue.getGetterType(prop.getChildren());
|
||||
}
|
||||
} else {
|
||||
return this.metaClass.getGetterType(name);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Has setter boolean
|
||||
*
|
||||
* @param name name
|
||||
* @return the boolean
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Override
|
||||
public boolean hasSetter(String name) {
|
||||
PropertyTokenizer prop = new PropertyTokenizer(name);
|
||||
if (prop.hasNext()) {
|
||||
if (this.metaClass.hasSetter(prop.getIndexedName())) {
|
||||
MetaObject metaValue = this.metaObject.metaObjectForProperty(prop.getIndexedName());
|
||||
if (metaValue == DefaultMetaObject.NULL_META_OBJECT) {
|
||||
return this.metaClass.hasSetter(name);
|
||||
} else {
|
||||
return metaValue.hasSetter(prop.getChildren());
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return this.metaClass.hasSetter(name);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Has getter boolean
|
||||
*
|
||||
* @param name name
|
||||
* @return the boolean
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Override
|
||||
public boolean hasGetter(String name) {
|
||||
PropertyTokenizer prop = new PropertyTokenizer(name);
|
||||
if (prop.hasNext()) {
|
||||
if (this.metaClass.hasGetter(prop.getIndexedName())) {
|
||||
MetaObject metaValue = this.metaObject.metaObjectForProperty(prop.getIndexedName());
|
||||
if (metaValue == DefaultMetaObject.NULL_META_OBJECT) {
|
||||
return this.metaClass.hasGetter(name);
|
||||
} else {
|
||||
return metaValue.hasGetter(prop.getChildren());
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return this.metaClass.hasGetter(name);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiate property value meta object
|
||||
*
|
||||
* @param name name
|
||||
* @param prop prop
|
||||
* @param objectFactory object factory
|
||||
* @return the meta object
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Override
|
||||
public MetaObject instantiatePropertyValue(String name, @NotNull PropertyTokenizer prop, ObjectFactory objectFactory) {
|
||||
MetaObject metaValue;
|
||||
Class<?> type = this.getSetterType(prop.getName());
|
||||
try {
|
||||
Object newObject = objectFactory.create(type);
|
||||
metaValue = MetaObject.forObject(newObject,
|
||||
this.metaObject.getObjectFactory(),
|
||||
this.metaObject.getObjectWrapperFactory(),
|
||||
this.metaObject.getReflectorFactory());
|
||||
this.set(prop, newObject);
|
||||
} catch (Exception e) {
|
||||
throw new ReflectionException("Cannot set value of property '{}' because '{}' is null "
|
||||
+ "and cannot be instantiated on instance of {}. Cause:", name, name, type.getName(),
|
||||
e.toString(), e);
|
||||
}
|
||||
return metaValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets bean property *
|
||||
*
|
||||
* @param prop prop
|
||||
* @param object object
|
||||
* @param value value
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private void setBeanProperty(PropertyTokenizer prop, Object object, Object value) {
|
||||
try {
|
||||
Invoker method = this.metaClass.getSetInvoker(prop.getName());
|
||||
Object[] params = {value};
|
||||
try {
|
||||
method.invoke(object, params);
|
||||
} catch (Throwable t) {
|
||||
throw ExceptionUtil.unwrap(t);
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
throw new ReflectionException("Could not set property ' of '{}' with value '{}' Cause: {}", prop.getName(), object.getClass(),
|
||||
value, t.toString(), t);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Is collection boolean
|
||||
*
|
||||
* @return the boolean
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Override
|
||||
public boolean isCollection() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add *
|
||||
*
|
||||
* @param element element
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Override
|
||||
public void add(Object element) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add all *
|
||||
*
|
||||
* @param <E> parameter
|
||||
* @param list list
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Override
|
||||
public <E> void addAll(List<E> list) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets bean property *
|
||||
*
|
||||
* @param prop prop
|
||||
* @param object object
|
||||
* @return the bean property
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private Object getBeanProperty(PropertyTokenizer prop, Object object) {
|
||||
try {
|
||||
Invoker method = this.metaClass.getGetInvoker(prop.getName());
|
||||
try {
|
||||
return method.invoke(object, NO_ARGUMENTS);
|
||||
} catch (Throwable t) {
|
||||
throw ExceptionUtil.unwrap(t);
|
||||
}
|
||||
} catch (RuntimeException e) {
|
||||
throw e;
|
||||
} catch (Throwable t) {
|
||||
throw new ReflectionException("Could not get property '{}' from {}. Cause: ", prop.getName(), object.getClass(),
|
||||
t.toString(), t);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+194
@@ -0,0 +1,194 @@
|
||||
package com.aos.starter.core.reflection.wrapper;
|
||||
|
||||
import com.aos.starter.core.reflection.MetaObject;
|
||||
import com.aos.starter.core.reflection.factory.ObjectFactory;
|
||||
import com.aos.starter.core.reflection.property.PropertyTokenizer;
|
||||
|
||||
import org.jetbrains.annotations.Contract;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* <p>Company: 成都返空汇网络技术有限公司 </p>
|
||||
* <p>Description: </p>
|
||||
*
|
||||
* @author dong4j
|
||||
* @version 1.3.0
|
||||
* @email "mailto:dongshijie@fkhwl.com"
|
||||
* @date 2020.04.12 11:52
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class CollectionWrapper implements ObjectWrapper {
|
||||
|
||||
/** Object */
|
||||
private final Collection<Object> object;
|
||||
|
||||
/**
|
||||
* Collection wrapper
|
||||
*
|
||||
* @param metaObject meta object
|
||||
* @param object object
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Contract(pure = true)
|
||||
public CollectionWrapper(MetaObject metaObject, Collection<Object> object) {
|
||||
this.object = object;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get object
|
||||
*
|
||||
* @param prop prop
|
||||
* @return the object
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Override
|
||||
public Object get(PropertyTokenizer prop) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set *
|
||||
*
|
||||
* @param prop prop
|
||||
* @param value value
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Override
|
||||
public void set(PropertyTokenizer prop, Object value) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Find property string
|
||||
*
|
||||
* @param name name
|
||||
* @param useCamelCaseMapping use camel case mapping
|
||||
* @return the string
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Override
|
||||
public String findProperty(String name, boolean useCamelCaseMapping) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get getter names string [ ]
|
||||
*
|
||||
* @return the string [ ]
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Override
|
||||
public String[] getGetterNames() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get setter names string [ ]
|
||||
*
|
||||
* @return the string [ ]
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Override
|
||||
public String[] getSetterNames() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets setter type *
|
||||
*
|
||||
* @param name name
|
||||
* @return the setter type
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Override
|
||||
public Class<?> getSetterType(String name) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets getter type *
|
||||
*
|
||||
* @param name name
|
||||
* @return the getter type
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Override
|
||||
public Class<?> getGetterType(String name) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Has setter boolean
|
||||
*
|
||||
* @param name name
|
||||
* @return the boolean
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Override
|
||||
public boolean hasSetter(String name) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Has getter boolean
|
||||
*
|
||||
* @param name name
|
||||
* @return the boolean
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Override
|
||||
public boolean hasGetter(String name) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiate property value meta object
|
||||
*
|
||||
* @param name name
|
||||
* @param prop prop
|
||||
* @param objectFactory object factory
|
||||
* @return the meta object
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Override
|
||||
public MetaObject instantiatePropertyValue(String name, PropertyTokenizer prop, ObjectFactory objectFactory) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Is collection boolean
|
||||
*
|
||||
* @return the boolean
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Override
|
||||
public boolean isCollection() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add *
|
||||
*
|
||||
* @param element element
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Override
|
||||
public void add(Object element) {
|
||||
this.object.add(element);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add all *
|
||||
*
|
||||
* @param <E> parameter
|
||||
* @param element element
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Override
|
||||
public <E> void addAll(List<E> element) {
|
||||
this.object.addAll(element);
|
||||
}
|
||||
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
package com.aos.starter.core.support;
|
||||
|
||||
import com.aos.element.basic.basic.asserts.Assertions;
|
||||
import com.aos.starter.core.api.IResultCode;
|
||||
|
||||
import lombok.experimental.UtilityClass;
|
||||
|
||||
/**
|
||||
* <p>Company: 成都返空汇网络技术有限公司</p>
|
||||
* <p>Description: 扩展 {@link Assertions}, 添加 {@link IResultCode} 参数
|
||||
* <code>
|
||||
* AssertUtils.notEmpty(map, BaseCodes.DATA_ERROR);
|
||||
* </code>
|
||||
*
|
||||
* @author dong4j
|
||||
* @version 1.2.3
|
||||
* @email "mailto:dongshijie@fkhwl.com"
|
||||
* @date 2019.12.26 21:42
|
||||
* @since 1.2.3
|
||||
* @deprecated 请使用 {@link Assertions} 或 ErrorCodes 的方式代替
|
||||
*/
|
||||
@UtilityClass
|
||||
@Deprecated
|
||||
public class AssertUtils {
|
||||
|
||||
}
|
||||
+341
@@ -0,0 +1,341 @@
|
||||
package com.aos.starter.core.support;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
|
||||
|
||||
import com.aos.starter.core.util.BeanUtils;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.springframework.asm.ClassVisitor;
|
||||
import org.springframework.asm.Type;
|
||||
import org.springframework.cglib.core.AbstractClassGenerator;
|
||||
import org.springframework.cglib.core.ClassEmitter;
|
||||
import org.springframework.cglib.core.CodeEmitter;
|
||||
import org.springframework.cglib.core.Constants;
|
||||
import org.springframework.cglib.core.Converter;
|
||||
import org.springframework.cglib.core.EmitUtils;
|
||||
import org.springframework.cglib.core.KeyFactory;
|
||||
import org.springframework.cglib.core.Local;
|
||||
import org.springframework.cglib.core.MethodInfo;
|
||||
import org.springframework.cglib.core.ReflectUtils;
|
||||
import org.springframework.cglib.core.Signature;
|
||||
import org.springframework.cglib.core.TypeUtils;
|
||||
|
||||
import java.beans.PropertyDescriptor;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.security.ProtectionDomain;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* <p>Company: 成都返空汇网络技术有限公司</p>
|
||||
* <p>Description: spring cglib 修改 </p>
|
||||
* 1. 支持链式 bean
|
||||
* 2. 自定义的 BeanCopier 解决 spring boot 和 cglib ClassLoader classLoader 不一致的问题
|
||||
*
|
||||
* @author dong4j
|
||||
* @version 1.2.3
|
||||
* @email "mailto:dongshijie@fkhwl.com"
|
||||
* @date 2019.12.26 21:46
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@SuppressWarnings("all")
|
||||
public abstract class BaseBeanCopier {
|
||||
/** KEY_FACTORY */
|
||||
private static final BeanCopierKey KEY_FACTORY = (BeanCopierKey) KeyFactory.create(BeanCopierKey.class);
|
||||
/** CONVERTER */
|
||||
private static final Type CONVERTER = TypeUtils.parseType("org.springframework.cglib.core.Converter");
|
||||
/** BEAN_COPIER */
|
||||
private static final Type BEAN_COPIER = TypeUtils.parseType(BaseBeanCopier.class.getName());
|
||||
/** COPY */
|
||||
private static final Signature COPY = new Signature("copy",
|
||||
Type.VOID_TYPE,
|
||||
new Type[] {Constants.TYPE_OBJECT, Constants.TYPE_OBJECT, CONVERTER});
|
||||
/** CONVERT */
|
||||
private static final Signature CONVERT = TypeUtils.parseSignature("Object convert(Object, Class, Object)");
|
||||
|
||||
/**
|
||||
* Create base bean copier.
|
||||
*
|
||||
* @param source the source
|
||||
* @param target the target
|
||||
* @param useConverter the use converter
|
||||
* @return the base bean copier
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static BaseBeanCopier create(Class<?> source, Class<?> target, boolean useConverter) {
|
||||
return BaseBeanCopier.create(source, target, null, useConverter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create base bean copier.
|
||||
*
|
||||
* @param source the source
|
||||
* @param target the target
|
||||
* @param classLoader the class loader
|
||||
* @param useConverter the use converter
|
||||
* @return the base bean copier
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static BaseBeanCopier create(Class<?> source, Class<?> target, ClassLoader classLoader, boolean useConverter) {
|
||||
Generator gen;
|
||||
if (classLoader == null) {
|
||||
gen = new Generator();
|
||||
} else {
|
||||
gen = new Generator(classLoader);
|
||||
}
|
||||
gen.setSource(source);
|
||||
gen.setTarget(target);
|
||||
gen.setUseConverter(useConverter);
|
||||
return gen.create();
|
||||
}
|
||||
|
||||
/**
|
||||
* 拷贝
|
||||
*
|
||||
* @param from 源
|
||||
* @param to 目标
|
||||
* @param converter 转换器
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public abstract void copy(Object from, Object to, Converter converter);
|
||||
|
||||
/**
|
||||
* The interface Bean copier key.
|
||||
*
|
||||
* @author dong4j
|
||||
* @version 1.2.3
|
||||
* @email "mailto:dongshijie@fkhwl.com"
|
||||
* @date 2019.12.26 21:46
|
||||
* @since 1.0.0
|
||||
*/
|
||||
interface BeanCopierKey {
|
||||
/**
|
||||
* 实例化
|
||||
*
|
||||
* @param source 源
|
||||
* @param target 目标
|
||||
* @param useConverter 是否使用转换
|
||||
* @return object object
|
||||
* @since 1.0.0
|
||||
*/
|
||||
Object newInstance(String source, String target, boolean useConverter);
|
||||
}
|
||||
|
||||
/**
|
||||
* The type Generator.
|
||||
*
|
||||
* @author dong4j
|
||||
* @version 1.2.3
|
||||
* @email "mailto:dongshijie@fkhwl.com"
|
||||
* @date 2019.12.26 21:46
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static class Generator extends AbstractClassGenerator<Object> {
|
||||
/** SOURCE */
|
||||
private static final Source SOURCE = new Source(BaseBeanCopier.class.getName());
|
||||
/** Class loader */
|
||||
private final ClassLoader classLoader;
|
||||
/** Source */
|
||||
private Class<?> source;
|
||||
/** Target */
|
||||
private Class<?> target;
|
||||
/** Use converter */
|
||||
private boolean useConverter;
|
||||
|
||||
/**
|
||||
* Instantiates a new Generator.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
Generator() {
|
||||
super(SOURCE);
|
||||
this.classLoader = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates a new Generator.
|
||||
*
|
||||
* @param classLoader the class loader
|
||||
* @since 1.0.0
|
||||
*/
|
||||
Generator(ClassLoader classLoader) {
|
||||
super(SOURCE);
|
||||
this.classLoader = classLoader;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets source.
|
||||
*
|
||||
* @param source the source
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public void setSource(@NotNull Class<?> source) {
|
||||
if (!Modifier.isPublic(source.getModifiers())) {
|
||||
this.setNamePrefix(source.getName());
|
||||
}
|
||||
this.source = source;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets target.
|
||||
*
|
||||
* @param target the target
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public void setTarget(@NotNull Class<?> target) {
|
||||
if (!Modifier.isPublic(target.getModifiers())) {
|
||||
this.setNamePrefix(target.getName());
|
||||
}
|
||||
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets use converter.
|
||||
*
|
||||
* @param useConverter the use converter
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public void setUseConverter(boolean useConverter) {
|
||||
this.useConverter = useConverter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets default class loader *
|
||||
*
|
||||
* @return the default class loader
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Override
|
||||
protected ClassLoader getDefaultClassLoader() {
|
||||
return this.target.getClassLoader();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets protection domain *
|
||||
*
|
||||
* @return the protection domain
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Override
|
||||
protected ProtectionDomain getProtectionDomain() {
|
||||
return ReflectUtils.getProtectionDomain(this.source);
|
||||
}
|
||||
|
||||
/**
|
||||
* First instance object
|
||||
*
|
||||
* @param type type
|
||||
* @return the object
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Override
|
||||
protected Object firstInstance(Class type) {
|
||||
return ReflectUtils.newInstance(type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Next instance object
|
||||
*
|
||||
* @param instance instance
|
||||
* @return the object
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Override
|
||||
protected Object nextInstance(Object instance) {
|
||||
return instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create base bean copier.
|
||||
*
|
||||
* @return the base bean copier
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public BaseBeanCopier create() {
|
||||
Object key = KEY_FACTORY.newInstance(this.source.getName(), this.target.getName(), this.useConverter);
|
||||
return (BaseBeanCopier) super.create(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate class *
|
||||
*
|
||||
* @param v v
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Override
|
||||
public void generateClass(ClassVisitor v) {
|
||||
Type sourceType = Type.getType(this.source);
|
||||
Type targetType = Type.getType(this.target);
|
||||
ClassEmitter ce = new ClassEmitter(v);
|
||||
ce.begin_class(Constants.V1_2,
|
||||
Constants.ACC_PUBLIC,
|
||||
this.getClassName(),
|
||||
BEAN_COPIER,
|
||||
null,
|
||||
Constants.SOURCE_FILE);
|
||||
|
||||
EmitUtils.null_constructor(ce);
|
||||
CodeEmitter e = ce.begin_method(Constants.ACC_PUBLIC, COPY, null);
|
||||
|
||||
// 支持链式 bean
|
||||
PropertyDescriptor[] getters = BeanUtils.getBeanGetters(this.source);
|
||||
PropertyDescriptor[] setters = BeanUtils.getBeanSetters(this.target);
|
||||
Map<String, Object> names = Maps.newHashMapWithExpectedSize(16);
|
||||
for (PropertyDescriptor getter : getters) {
|
||||
names.put(getter.getName(), getter);
|
||||
}
|
||||
|
||||
Local targetLocal = e.make_local();
|
||||
Local sourceLocal = e.make_local();
|
||||
e.load_arg(1);
|
||||
e.checkcast(targetType);
|
||||
e.store_local(targetLocal);
|
||||
e.load_arg(0);
|
||||
e.checkcast(sourceType);
|
||||
e.store_local(sourceLocal);
|
||||
|
||||
for (PropertyDescriptor setter : setters) {
|
||||
PropertyDescriptor getter = (PropertyDescriptor) names.get(setter.getName());
|
||||
if (getter != null) {
|
||||
MethodInfo read = ReflectUtils.getMethodInfo(getter.getReadMethod());
|
||||
MethodInfo write = ReflectUtils.getMethodInfo(setter.getWriteMethod());
|
||||
if (this.useConverter) {
|
||||
Type setterType = write.getSignature().getArgumentTypes()[0];
|
||||
e.load_local(targetLocal);
|
||||
e.load_arg(2);
|
||||
e.load_local(sourceLocal);
|
||||
e.invoke(read);
|
||||
e.box(read.getSignature().getReturnType());
|
||||
EmitUtils.load_class(e, setterType);
|
||||
e.push(write.getSignature().getName());
|
||||
e.invoke_interface(CONVERTER, CONVERT);
|
||||
e.unbox_or_zero(setterType);
|
||||
e.invoke(write);
|
||||
} else if (compatible(getter, setter)) {
|
||||
// 支持链式 bean
|
||||
e.load_local(targetLocal);
|
||||
e.load_local(sourceLocal);
|
||||
e.invoke(read);
|
||||
e.invoke(write);
|
||||
}
|
||||
}
|
||||
}
|
||||
e.return_value();
|
||||
e.end_method();
|
||||
ce.end_class();
|
||||
}
|
||||
|
||||
/**
|
||||
* Compatible boolean
|
||||
*
|
||||
* @param getter getter
|
||||
* @param setter setter
|
||||
* @return the boolean
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private static boolean compatible(@NotNull PropertyDescriptor getter, @NotNull PropertyDescriptor setter) {
|
||||
return setter.getPropertyType().isAssignableFrom(getter.getPropertyType());
|
||||
}
|
||||
}
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
package com.aos.starter.core.support;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* <p>Company: 成都返空汇网络技术有限公司</p>
|
||||
* <p>Description: Bean属性 </p>
|
||||
*
|
||||
* @author dong4j
|
||||
* @version 1.2.3
|
||||
* @email "mailto:dongshijie@fkhwl.com"
|
||||
* @date 2020.01.27 18:10
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public class BeanProperty {
|
||||
/** Name */
|
||||
private final String name;
|
||||
/** Type */
|
||||
private final Class<?> type;
|
||||
}
|
||||
+264
@@ -0,0 +1,264 @@
|
||||
package com.aos.starter.core.support;
|
||||
|
||||
import com.aos.starter.core.util.Tools;
|
||||
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.springframework.util.LinkedCaseInsensitiveMap;
|
||||
|
||||
import java.sql.Time;
|
||||
import java.sql.Timestamp;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* <p>Company: 成都返空汇网络技术有限公司</p>
|
||||
* <p>Description: 链式 map (linkedmap) key 必须为 string </p>
|
||||
*
|
||||
* @author dong4j
|
||||
* @version 1.2.3
|
||||
* @email "mailto:dongshijie@fkhwl.com"
|
||||
* @date 2020.01.27 18:24
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@SuppressWarnings("all")
|
||||
public final class ChainMap extends LinkedCaseInsensitiveMap<Object> {
|
||||
/** serialVersionUID */
|
||||
private static final long serialVersionUID = 3992810369797036508L;
|
||||
|
||||
/**
|
||||
* Chain map
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private ChainMap() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Chain map
|
||||
*
|
||||
* @param size size
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private ChainMap(int size) {
|
||||
super(Tools.capacity(size));
|
||||
}
|
||||
|
||||
/**
|
||||
* Build chain map.
|
||||
*
|
||||
* @return the chain map
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@NotNull
|
||||
@Contract(" -> new")
|
||||
public static ChainMap build() {
|
||||
return new ChainMap();
|
||||
}
|
||||
|
||||
/**
|
||||
* Build chain map.
|
||||
*
|
||||
* @param size the size
|
||||
* @return the chain map
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@NotNull
|
||||
@Contract("_ -> new")
|
||||
public static ChainMap build(int size) {
|
||||
return new ChainMap(size);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置列,当键或值为null时忽略
|
||||
*
|
||||
* @param attr 属性
|
||||
* @param value 值
|
||||
* @return 本身 ignore null
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Contract("null, _ -> this; !null, null -> this")
|
||||
public ChainMap setIgnoreNull(String attr, Object value) {
|
||||
if (null != attr && null != value) {
|
||||
put(attr, value);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 存入 kv
|
||||
*
|
||||
* @param attr 属性
|
||||
* @param value 值
|
||||
* @return 本身 kv
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Contract("_, _ -> this")
|
||||
@NotNull
|
||||
@Override
|
||||
public ChainMap put(@NotNull String attr, Object value) {
|
||||
super.put(attr, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clone chain map
|
||||
*
|
||||
* @return the chain map
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@NotNull
|
||||
@Override
|
||||
public ChainMap clone() {
|
||||
return (ChainMap) super.clone();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets obj.
|
||||
*
|
||||
* @param key the key
|
||||
* @return the obj
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public Object getObj(String key) {
|
||||
return super.get(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得特定类型值
|
||||
*
|
||||
* @param attr 字段名
|
||||
* @return 字段值 str
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public String getStr(String attr) {
|
||||
return Tools.toStr(get(attr), null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得特定类型值
|
||||
*
|
||||
* @param attr 字段名
|
||||
* @return 字段值 int
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@NotNull
|
||||
public Integer getInt(String attr) {
|
||||
return Tools.toInt(get(attr), -1);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得特定类型值
|
||||
*
|
||||
* @param attr 字段名
|
||||
* @return 字段值 long
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@NotNull
|
||||
public Long getLong(String attr) {
|
||||
return Tools.toLong(get(attr), -1L);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得特定类型值
|
||||
*
|
||||
* @param attr 字段名
|
||||
* @return 字段值 float
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public Float getFloat(String attr) {
|
||||
return Tools.toFloat(get(attr), null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets double.
|
||||
*
|
||||
* @param attr the attr
|
||||
* @return the double
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public Double getDouble(String attr) {
|
||||
return Tools.toDouble(get(attr), null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得特定类型值
|
||||
*
|
||||
* @param attr 字段名
|
||||
* @return 字段值 bool
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public Boolean getBool(String attr) {
|
||||
return Tools.toBoolean(get(attr), null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得特定类型值
|
||||
*
|
||||
* @param attr 字段名
|
||||
* @return 字段值 byte [ ]
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public byte[] getBytes(String attr) {
|
||||
return get(attr, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得特定类型值
|
||||
*
|
||||
* @param <T> 值类型
|
||||
* @param attr 字段名
|
||||
* @param defaultValue 默认值
|
||||
* @return 字段值 t
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T get(String attr, T defaultValue) {
|
||||
Object result = get(attr);
|
||||
return (T) (result != null ? result : defaultValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得特定类型值
|
||||
*
|
||||
* @param attr 字段名
|
||||
* @return 字段值 date
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public Date getDate(String attr) {
|
||||
return get(attr, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得特定类型值
|
||||
*
|
||||
* @param attr 字段名
|
||||
* @return 字段值 time
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public Time getTime(String attr) {
|
||||
return get(attr, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得特定类型值
|
||||
*
|
||||
* @param attr 字段名
|
||||
* @return 字段值 timestamp
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public Timestamp getTimestamp(String attr) {
|
||||
return get(attr, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得特定类型值
|
||||
*
|
||||
* @param attr 字段名
|
||||
* @return 字段值 number
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public Number getNumber(String attr) {
|
||||
return get(attr, null);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,311 @@
|
||||
package com.aos.starter.core.util;
|
||||
|
||||
|
||||
import com.aos.element.basic.basic.util.Charsets;
|
||||
import com.aos.element.basic.basic.util.Exceptions;
|
||||
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.spec.IvParameterSpec;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
|
||||
import lombok.experimental.UtilityClass;
|
||||
|
||||
/**
|
||||
* <p>Company: 成都返空汇网络技术有限公司</p>
|
||||
* 完全兼容微信所使用的AES加密方式.
|
||||
* aes的key必须是256byte长 (比如32个字符) ,可以使用AesKit.genAesKey()来生成一组key
|
||||
*
|
||||
* @author dong4j
|
||||
* @version 1.2.3
|
||||
* @email "mailto:dongshijie@fkhwl.com"
|
||||
* @date 2019.12.26 21:39
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@UtilityClass
|
||||
@SuppressWarnings("all")
|
||||
public class AesUtils {
|
||||
|
||||
/** 默认 16 长度 */
|
||||
private static final int DEFAULT_INITIAL_CAPACITY = 1 << 4;
|
||||
/** MAXIMUM_CAPACITY */
|
||||
private static final int MAXIMUM_CAPACITY = 1 << 30;
|
||||
|
||||
/**
|
||||
* 返回 2 的整数倍
|
||||
*
|
||||
* @param cap cap
|
||||
* @return the int
|
||||
* @since 1.9.0
|
||||
*/
|
||||
private static final int relengh(int cap) {
|
||||
int n = cap - 1;
|
||||
n |= n >>> 1;
|
||||
n |= n >>> 2;
|
||||
n |= n >>> 4;
|
||||
n |= n >>> 8;
|
||||
n |= n >>> 16;
|
||||
return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check power of 2
|
||||
*
|
||||
* @param n n
|
||||
* @return the boolean
|
||||
* @since 1.9.0
|
||||
*/
|
||||
private boolean checkPowerOf2(int n) {
|
||||
if (n <= 0) {
|
||||
return false;
|
||||
}
|
||||
int t = n & (n - 1);
|
||||
return t == 0 ? true : false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gen aes key string.
|
||||
*
|
||||
* @return the string
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@NotNull
|
||||
public static String genAesKey() {
|
||||
return RandomUtils.random(DEFAULT_INITIAL_CAPACITY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gen aes key
|
||||
*
|
||||
* @param length length
|
||||
* @return the string
|
||||
* @since 1.9.0
|
||||
*/
|
||||
public static String genAesKey(int length) {
|
||||
return RandomUtils.random(relengh(length));
|
||||
}
|
||||
|
||||
/**
|
||||
* Encrypt byte [ ].
|
||||
*
|
||||
* @param content the content
|
||||
* @param aesTextKey the aes text key
|
||||
* @return the byte [ ]
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static byte[] encrypt(byte[] content, @NotNull String aesTextKey) {
|
||||
return encrypt(content, aesTextKey.getBytes(Charsets.UTF_8));
|
||||
}
|
||||
|
||||
/**
|
||||
* Encrypt byte [ ].
|
||||
*
|
||||
* @param content the content
|
||||
* @param aesKey the aes key
|
||||
* @return the byte [ ]
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static byte[] encrypt(byte[] content, byte[] aesKey) {
|
||||
Assert.isTrue(aesKey.length >= DEFAULT_INITIAL_CAPACITY && checkPowerOf2(aesKey.length),
|
||||
"密钥必须为 2 的幂次方且大于等于 16 位");
|
||||
try {
|
||||
Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
|
||||
SecretKeySpec keySpec = new SecretKeySpec(aesKey, "AES");
|
||||
IvParameterSpec iv = new IvParameterSpec(aesKey, 0, DEFAULT_INITIAL_CAPACITY);
|
||||
cipher.init(Cipher.ENCRYPT_MODE, keySpec, iv);
|
||||
return cipher.doFinal(Pkcs7Encoder.encode(content));
|
||||
} catch (Exception e) {
|
||||
throw Exceptions.unchecked(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Encrypt byte [ ].
|
||||
*
|
||||
* @param content the content
|
||||
* @param aesTextKey the aes text key
|
||||
* @return the byte [ ]
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static byte[] encrypt(@NotNull String content, @NotNull String aesTextKey) {
|
||||
return encrypt(content.getBytes(Charsets.UTF_8), aesTextKey.getBytes(Charsets.UTF_8));
|
||||
}
|
||||
|
||||
/**
|
||||
* Encrypt to str
|
||||
*
|
||||
* @param content content
|
||||
* @param aesTextKey aes text key
|
||||
* @return the string
|
||||
* @since 1.9.0
|
||||
*/
|
||||
public static String encryptToStr(@NotNull String content, @NotNull String aesTextKey) {
|
||||
return Base64Utils.encodeToString(encrypt(content, aesTextKey));
|
||||
}
|
||||
|
||||
/**
|
||||
* Encrypt byte [ ].
|
||||
*
|
||||
* @param content the content
|
||||
* @param charset the charset
|
||||
* @param aesTextKey the aes text key
|
||||
* @return the byte [ ]
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static byte[] encrypt(@NotNull String content, java.nio.charset.Charset charset, @NotNull String aesTextKey) {
|
||||
return encrypt(content.getBytes(charset), aesTextKey.getBytes(Charsets.UTF_8));
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypt to str
|
||||
*
|
||||
* @param content content
|
||||
* @param aesTextKey aes text key
|
||||
* @return the string
|
||||
* @since 1.9.0
|
||||
*/
|
||||
public static String decryptToStr(@NotNull String content, @NotNull String aesTextKey) {
|
||||
return new String(decrypt(content, aesTextKey));
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypt
|
||||
*
|
||||
* @param content content
|
||||
* @param aesTextKey aes text key
|
||||
* @return the byte [ ]
|
||||
* @since 1.9.0
|
||||
*/
|
||||
public static byte[] decrypt(@NotNull String content, @NotNull String aesTextKey) {
|
||||
return decrypt(Base64Utils.decodeFromString(content), aesTextKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypt byte [ ].
|
||||
*
|
||||
* @param content the content
|
||||
* @param aesTextKey the aes text key
|
||||
* @return the byte [ ]
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static byte[] decrypt(byte[] content, @NotNull String aesTextKey) {
|
||||
return decrypt(content, aesTextKey.getBytes(Charsets.UTF_8));
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypt byte [ ].
|
||||
*
|
||||
* @param encrypted the encrypted
|
||||
* @param aesKey the aes key
|
||||
* @return the byte [ ]
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static byte[] decrypt(byte[] encrypted, byte[] aesKey) {
|
||||
Assert.isTrue(aesKey.length >= DEFAULT_INITIAL_CAPACITY && checkPowerOf2(aesKey.length),
|
||||
"密钥必须为 2 的幂次方且大于等于 16 位");
|
||||
try {
|
||||
Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
|
||||
SecretKeySpec keySpec = new SecretKeySpec(aesKey, "AES");
|
||||
IvParameterSpec iv = new IvParameterSpec(Arrays.copyOfRange(aesKey, 0, DEFAULT_INITIAL_CAPACITY));
|
||||
cipher.init(Cipher.DECRYPT_MODE, keySpec, iv);
|
||||
return Pkcs7Encoder.decode(cipher.doFinal(encrypted));
|
||||
} catch (Exception e) {
|
||||
throw Exceptions.unchecked(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypt to str string.
|
||||
*
|
||||
* @param content the content
|
||||
* @param aesTextKey the aes text key
|
||||
* @return the string
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@NotNull
|
||||
@Contract("_, _ -> new")
|
||||
public static String decryptToStr(byte[] content, @NotNull String aesTextKey) {
|
||||
return new String(decrypt(content, aesTextKey.getBytes(Charsets.UTF_8)), Charsets.UTF_8);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypt to str string.
|
||||
*
|
||||
* @param content the content
|
||||
* @param aesTextKey the aes text key
|
||||
* @param charset the charset
|
||||
* @return the string
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@NotNull
|
||||
@Contract("_, _, _ -> new")
|
||||
public static String decryptToStr(byte[] content, @NotNull String aesTextKey, java.nio.charset.Charset charset) {
|
||||
return new String(decrypt(content, aesTextKey.getBytes(Charsets.UTF_8)), charset);
|
||||
}
|
||||
|
||||
/**
|
||||
* 提供基于PKCS7算法的加解密接口.
|
||||
*
|
||||
* @author dong4j
|
||||
* @version 1.2.3
|
||||
* @email "mailto:dongshijie@fkhwl.com"
|
||||
* @date 2019.12.26 21:39
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@UtilityClass
|
||||
static class Pkcs7Encoder {
|
||||
/**
|
||||
* The Block size.
|
||||
*/
|
||||
static final int BLOCK_SIZE = 32;
|
||||
|
||||
/**
|
||||
* Encode byte [ ].
|
||||
*
|
||||
* @param src the src
|
||||
* @return the byte [ ]
|
||||
* @since 1.0.0
|
||||
*/
|
||||
static byte[] encode(byte[] src) {
|
||||
int count = src.length;
|
||||
// 计算需要填充的位数
|
||||
int amountToPad = BLOCK_SIZE - (count % BLOCK_SIZE);
|
||||
// 获得补位所用的字符
|
||||
byte pad = (byte) (amountToPad & 0xFF);
|
||||
byte[] pads = new byte[amountToPad];
|
||||
for (int index = 0; index < amountToPad; index++) {
|
||||
pads[index] = pad;
|
||||
}
|
||||
int length = count + amountToPad;
|
||||
byte[] dest = new byte[length];
|
||||
System.arraycopy(src, 0, dest, 0, count);
|
||||
System.arraycopy(pads, 0, dest, count, amountToPad);
|
||||
return dest;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode byte [ ].
|
||||
*
|
||||
* @param decrypted the decrypted
|
||||
* @return the byte [ ]
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Contract(pure = true)
|
||||
static byte[] decode(byte[] decrypted) {
|
||||
int pad = (int) decrypted[decrypted.length - 1];
|
||||
if (pad < 1 || pad > BLOCK_SIZE) {
|
||||
pad = 0;
|
||||
}
|
||||
if (pad > 0) {
|
||||
return Arrays.copyOfRange(decrypted, 0, decrypted.length - pad);
|
||||
}
|
||||
return decrypted;
|
||||
}
|
||||
}
|
||||
}
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
package com.aos.starter.core.util;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.springframework.util.AntPathMatcher;
|
||||
import org.springframework.util.PathMatcher;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileFilter;
|
||||
import java.io.Serializable;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
/**
|
||||
* <p>Company: 成都返空汇网络技术有限公司</p>
|
||||
* <p>Description: spring AntPath 规则文件过滤 </p>
|
||||
*
|
||||
* @author dong4j
|
||||
* @version 1.2.3
|
||||
* @email "mailto:dongshijie@fkhwl.com"
|
||||
* @date 2019.12.26 21:40
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
public class AntPathFilter implements FileFilter, Serializable {
|
||||
/** serialVersionUID */
|
||||
private static final long serialVersionUID = 812598009067554612L;
|
||||
/** PATH_MATCHER */
|
||||
private static final PathMatcher PATH_MATCHER = new AntPathMatcher();
|
||||
|
||||
/** Pattern */
|
||||
private final String pattern;
|
||||
|
||||
/**
|
||||
* Accept boolean
|
||||
*
|
||||
* @param pathname pathname
|
||||
* @return the boolean
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Override
|
||||
public boolean accept(@NotNull File pathname) {
|
||||
String filePath = pathname.getAbsolutePath();
|
||||
return PATH_MATCHER.match(pattern, filePath);
|
||||
}
|
||||
}
|
||||
+132
@@ -0,0 +1,132 @@
|
||||
package com.aos.starter.core.util;
|
||||
|
||||
|
||||
import com.aos.element.basic.basic.util.Charsets;
|
||||
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import lombok.experimental.UtilityClass;
|
||||
|
||||
/**
|
||||
* <p>Company: 成都返空汇网络技术有限公司</p>
|
||||
* <p>Description: Base64工具 </p>
|
||||
*
|
||||
* @author dong4j
|
||||
* @version 1.2.3
|
||||
* @email "mailto:dongshijie@fkhwl.com"
|
||||
* @date 2019.12.26 21:45
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@UtilityClass
|
||||
@SuppressWarnings("all")
|
||||
public class Base64Utils extends org.springframework.util.Base64Utils {
|
||||
|
||||
/**
|
||||
* 编码
|
||||
*
|
||||
* @param value 字符串
|
||||
* @return {String}
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@NotNull
|
||||
public static String encode(String value) {
|
||||
return Base64Utils.encode(value, Charsets.UTF_8);
|
||||
}
|
||||
|
||||
/**
|
||||
* 编码
|
||||
*
|
||||
* @param value 字符串
|
||||
* @param charset 字符集
|
||||
* @return {String}
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@NotNull
|
||||
@Contract("_, _ -> new")
|
||||
public static String encode(@NotNull String value, java.nio.charset.Charset charset) {
|
||||
byte[] val = value.getBytes(charset);
|
||||
return new String(Base64Utils.encode(val), charset);
|
||||
}
|
||||
|
||||
/**
|
||||
* 编码URL安全
|
||||
*
|
||||
* @param value 字符串
|
||||
* @return {String}
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@NotNull
|
||||
public static String encodeUrlSafe(String value) {
|
||||
return Base64Utils.encodeUrlSafe(value, Charsets.UTF_8);
|
||||
}
|
||||
|
||||
/**
|
||||
* 编码URL安全
|
||||
*
|
||||
* @param value 字符串
|
||||
* @param charset 字符集
|
||||
* @return {String}
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@NotNull
|
||||
@Contract("_, _ -> new")
|
||||
public static String encodeUrlSafe(@NotNull String value, java.nio.charset.Charset charset) {
|
||||
byte[] val = value.getBytes(charset);
|
||||
return new String(Base64Utils.encodeUrlSafe(val), charset);
|
||||
}
|
||||
|
||||
/**
|
||||
* 解码
|
||||
*
|
||||
* @param value 字符串
|
||||
* @return {String}
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@NotNull
|
||||
public static String decode(String value) {
|
||||
return Base64Utils.decode(value, Charsets.UTF_8);
|
||||
}
|
||||
|
||||
/**
|
||||
* 解码
|
||||
*
|
||||
* @param value 字符串
|
||||
* @param charset 字符集
|
||||
* @return {String}
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@NotNull
|
||||
public static String decode(@NotNull String value, java.nio.charset.Charset charset) {
|
||||
byte[] val = value.getBytes(charset);
|
||||
byte[] decodedValue = Base64Utils.decode(val);
|
||||
return new String(decodedValue, charset);
|
||||
}
|
||||
|
||||
/**
|
||||
* 解码URL安全
|
||||
*
|
||||
* @param value 字符串
|
||||
* @return {String}
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@NotNull
|
||||
public static String decodeUrlSafe(String value) {
|
||||
return Base64Utils.decodeUrlSafe(value, Charsets.UTF_8);
|
||||
}
|
||||
|
||||
/**
|
||||
* 解码URL安全
|
||||
*
|
||||
* @param value 字符串
|
||||
* @param charset 字符集
|
||||
* @return {String}
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@NotNull
|
||||
public static String decodeUrlSafe(@NotNull String value, java.nio.charset.Charset charset) {
|
||||
byte[] val = value.getBytes(charset);
|
||||
byte[] decodedValue = Base64Utils.decodeUrlSafe(val);
|
||||
return new String(decodedValue, charset);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,473 @@
|
||||
package com.aos.starter.core.util;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
|
||||
import com.aos.starter.core.convert.CustomConverter;
|
||||
import com.aos.starter.core.exception.BaseException;
|
||||
import com.aos.starter.core.support.BaseBeanCopier;
|
||||
import com.aos.starter.core.support.BeanProperty;
|
||||
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.cglib.beans.BeanGenerator;
|
||||
import org.springframework.cglib.beans.BeanMap;
|
||||
import org.springframework.cglib.core.CodeGenerationException;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import java.beans.PropertyDescriptor;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
import lombok.experimental.UtilityClass;
|
||||
|
||||
/**
|
||||
* <p>Company: 成都返空汇网络技术有限公司</p>
|
||||
* <p>Description: 实体工具类 </p>
|
||||
*
|
||||
* @author dong4j
|
||||
* @version 1.2.3
|
||||
* @email "mailto:dongshijie@fkhwl.com"
|
||||
* @date 2019.12.11 18:47
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@SuppressWarnings("all")
|
||||
@UtilityClass
|
||||
public class BeanUtils extends org.springframework.beans.BeanUtils {
|
||||
|
||||
/**
|
||||
* 实例化对象
|
||||
*
|
||||
* @param <T> 泛型标记
|
||||
* @param clazzStr 类名
|
||||
* @return 对象 t
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@NotNull
|
||||
public static <T> T newInstance(String clazzStr) {
|
||||
try {
|
||||
Class<?> clazz = Class.forName(clazzStr);
|
||||
return newInstance(clazz);
|
||||
} catch (ClassNotFoundException e) {
|
||||
throw new BaseException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 实例化对象
|
||||
*
|
||||
* @param <T> 泛型标记
|
||||
* @param clazz 类
|
||||
* @return 对象 t
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@NotNull
|
||||
public static <T> T newInstance(Class<?> clazz) {
|
||||
return (T) instantiateClass(clazz);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取Bean的属性
|
||||
*
|
||||
* @param bean bean
|
||||
* @param propertyName 属性名
|
||||
* @return 属性值 property
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static Object getProperty(Object bean, String propertyName) {
|
||||
Assert.notNull(bean, "bean Could not null");
|
||||
return BeanMap.create(bean).get(propertyName);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置Bean属性
|
||||
*
|
||||
* @param bean bean
|
||||
* @param propertyName 属性名
|
||||
* @param value 属性值
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static void setProperty(Object bean, String propertyName, Object value) {
|
||||
Assert.notNull(bean, "bean Could not null");
|
||||
BeanMap.create(bean).put(propertyName, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 深复制
|
||||
* 注意: 不支持链式Bean
|
||||
*
|
||||
* @param <T> 泛型标记
|
||||
* @param source 源对象
|
||||
* @return T t
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static <T> T clone(T source) {
|
||||
return (T) BeanUtils.copy(source, source.getClass());
|
||||
}
|
||||
|
||||
/**
|
||||
* copy 对象属性到另一个对象,默认不使用Convert
|
||||
* 注意: 不支持链式Bean,链式用 copyProperties
|
||||
*
|
||||
* @param <T> 泛型标记
|
||||
* @param source 源对象
|
||||
* @param clazz 类名
|
||||
* @return T t
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Contract("null, _ -> null")
|
||||
public static <T> T copy(Object source, Class<T> clazz) {
|
||||
if (source == null) {
|
||||
return null;
|
||||
}
|
||||
return BeanUtils.copy(source, source.getClass(), clazz);
|
||||
}
|
||||
|
||||
/**
|
||||
* copy 对象属性,默认不使用Convert
|
||||
* <p>
|
||||
* 支持 map bean copy
|
||||
* </p>
|
||||
*
|
||||
* @param <T> 泛型标记
|
||||
* @param source 源对象
|
||||
* @param sourceClazz 源类型
|
||||
* @param targetClazz 转换成的类型
|
||||
* @return T t
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Contract("null, _, _ -> null")
|
||||
public static <T> T copy(Object source, Class<?> sourceClazz, Class<T> targetClazz) {
|
||||
BaseBeanCopier copier = BaseBeanCopier.create(sourceClazz, targetClazz, false);
|
||||
T to = newInstance(targetClazz);
|
||||
copier.copy(source, to, null);
|
||||
return to;
|
||||
}
|
||||
|
||||
/**
|
||||
* copy 列表对象,默认不使用Convert
|
||||
* <p>
|
||||
* 支持 map bean copy
|
||||
* </p>
|
||||
*
|
||||
* @param <T> 泛型标记
|
||||
* @param sourceList 源列表
|
||||
* @param targetClazz 转换成的类型
|
||||
* @return T list
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Contract("null, _ -> !null")
|
||||
public static <T> List<T> copy(@Nullable Collection<?> sourceList, Class<T> targetClazz) {
|
||||
if (sourceList == null || sourceList.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
List<T> outList = new ArrayList<>(sourceList.size());
|
||||
Class<?> sourceClazz = null;
|
||||
for (Object source : sourceList) {
|
||||
if (source == null) {
|
||||
continue;
|
||||
}
|
||||
if (sourceClazz == null) {
|
||||
sourceClazz = source.getClass();
|
||||
}
|
||||
T bean = BeanUtils.copy(source, sourceClazz, targetClazz);
|
||||
outList.add(bean);
|
||||
}
|
||||
return outList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 拷贝对象并对不同类型属性进行转换
|
||||
* <p>
|
||||
* 支持 map bean copy
|
||||
* </p>
|
||||
*
|
||||
* @param <T> 泛型标记
|
||||
* @param source 源对象
|
||||
* @param targetClazz 转换成的类
|
||||
* @return T t
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Contract("null, _ -> null")
|
||||
@Nullable
|
||||
public static <T> T copyWithConvert(@Nullable Object source, Class<T> targetClazz) {
|
||||
if (source == null) {
|
||||
return null;
|
||||
}
|
||||
return BeanUtils.copyWithConvert(source, source.getClass(), targetClazz);
|
||||
}
|
||||
|
||||
/**
|
||||
* 拷贝对象并对不同类型属性进行转换
|
||||
* <p>
|
||||
* 支持 map bean copy
|
||||
* </p>
|
||||
*
|
||||
* @param <T> 泛型标记
|
||||
* @param source 源对象
|
||||
* @param sourceClazz 源类
|
||||
* @param targetClazz 转换成的类
|
||||
* @return T t
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Contract("null, _, _ -> null")
|
||||
@Nullable
|
||||
public static <T> T copyWithConvert(@Nullable Object source, Class<?> sourceClazz, Class<T> targetClazz) {
|
||||
if (source == null) {
|
||||
return null;
|
||||
}
|
||||
BaseBeanCopier copier = BaseBeanCopier.create(sourceClazz, targetClazz, true);
|
||||
T to = newInstance(targetClazz);
|
||||
copier.copy(source, to, new CustomConverter(sourceClazz, targetClazz));
|
||||
return to;
|
||||
}
|
||||
|
||||
/**
|
||||
* 拷贝列表并对不同类型属性进行转换
|
||||
* <p>
|
||||
* 支持 map bean copy
|
||||
* </p>
|
||||
*
|
||||
* @param <T> 泛型标记
|
||||
* @param sourceList 源对象列表
|
||||
* @param targetClazz 转换成的类
|
||||
* @return List list
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Contract("null, _ -> !null")
|
||||
public static <T> List<T> copyWithConvert(@Nullable Collection<?> sourceList, Class<T> targetClazz) {
|
||||
if (sourceList == null || sourceList.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
List<T> outList = new ArrayList<>(sourceList.size());
|
||||
Class<?> sourceClazz = null;
|
||||
for (Object source : sourceList) {
|
||||
if (source == null) {
|
||||
continue;
|
||||
}
|
||||
if (sourceClazz == null) {
|
||||
sourceClazz = source.getClass();
|
||||
}
|
||||
T bean = BeanUtils.copyWithConvert(source, sourceClazz, targetClazz);
|
||||
outList.add(bean);
|
||||
}
|
||||
return outList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy the property values of the given source bean into the target class.
|
||||
* <p>Note: The source and target classes do not have to match or even be derived
|
||||
* from each other, as long as the properties match. Any bean properties that the
|
||||
* source bean exposes but the target bean does not will silently be ignored.
|
||||
* <p>This is just a convenience method. For more complex transfer needs,
|
||||
*
|
||||
* @param <T> 泛型标记
|
||||
* @param sourceList the source list bean
|
||||
* @param targetClazz the target bean class
|
||||
* @return List list
|
||||
* @throws BeansException if the copying failed
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Contract("null, _ -> !null")
|
||||
public static <T> List<T> copyProperties(@Nullable Collection<?> sourceList, Class<T> targetClazz) {
|
||||
if (sourceList == null || sourceList.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
List<T> outList = new ArrayList<>(sourceList.size());
|
||||
for (Object source : sourceList) {
|
||||
if (source == null) {
|
||||
continue;
|
||||
}
|
||||
T bean = BeanUtils.copyProperties(source, targetClazz);
|
||||
outList.add(bean);
|
||||
}
|
||||
return outList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy the property values of the given source bean into the target class.
|
||||
* <p>Note: The source and target classes do not have to match or even be derived
|
||||
* from each other, as long as the properties match. Any bean properties that the
|
||||
* source bean exposes but the target bean does not will silently be ignored.
|
||||
* <p>This is just a convenience method. For more complex transfer needs,
|
||||
*
|
||||
* @param <T> 泛型标记
|
||||
* @param source the source bean
|
||||
* @param targetClazz the target bean class
|
||||
* @return T t
|
||||
* @throws BeansException if the copying failed
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Contract("null, _ -> null")
|
||||
@Nullable
|
||||
public static <T> T copyProperties(@Nullable Object source, Class<T> targetClazz) {
|
||||
if (source == null) {
|
||||
return null;
|
||||
}
|
||||
T to = newInstance(targetClazz);
|
||||
BeanUtils.copyProperties(source, to);
|
||||
return to;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将对象装成 map 形式.
|
||||
* 注意: 返回的 Map 不能使用 put 添加键值对, 因为 BeanMap 未做实现, 所以不会添加成功, 必须使用强转为 BeanMap 后才使用 put
|
||||
*
|
||||
* @param bean 源对象
|
||||
* @return {Map}
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Contract("null -> new")
|
||||
@SuppressWarnings("unchecked")
|
||||
public static Map<String, Object> toMap(Object bean) {
|
||||
if (bean == null) {
|
||||
return Maps.newHashMapWithExpectedSize(0);
|
||||
}
|
||||
return BeanMap.create(bean);
|
||||
}
|
||||
|
||||
/**
|
||||
* To string map map
|
||||
*
|
||||
* @param bean bean
|
||||
* @return the map
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Contract("null -> !null")
|
||||
public static Map<String, String> toStringMap(Object bean) {
|
||||
Map<String, Object> map = toMap(bean);
|
||||
|
||||
Map<String, String> stringMap = Maps.newHashMapWithExpectedSize(map.size());
|
||||
map.forEach((k, v) -> {
|
||||
if (ObjectUtils.isNotNull(v)) {
|
||||
stringMap.put(k, String.valueOf(v));
|
||||
}
|
||||
});
|
||||
return stringMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将map 转为 bean
|
||||
*
|
||||
* @param <T> 泛型标记
|
||||
* @param beanMap map
|
||||
* @param valueType 对象类型
|
||||
* @return {T}
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static <T> T toBean(Map<String, Object> beanMap, Class<T> valueType) {
|
||||
Objects.requireNonNull(beanMap, "beanMap Could not null");
|
||||
T bean = BeanUtils.newInstance(valueType);
|
||||
if (beanMap.isEmpty()) {
|
||||
return bean;
|
||||
}
|
||||
BeanMap.create(bean).putAll(beanMap);
|
||||
return bean;
|
||||
}
|
||||
|
||||
/**
|
||||
* 给一个Bean添加字段
|
||||
*
|
||||
* @param superBean 父级Bean
|
||||
* @param props 新增属性
|
||||
* @return {Object}
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static Object generator(@NotNull Object superBean, BeanProperty... props) {
|
||||
Class<?> superclass = superBean.getClass();
|
||||
Object genBean = generator(superclass, props);
|
||||
BeanUtils.copy(superBean, genBean);
|
||||
return genBean;
|
||||
}
|
||||
|
||||
/**
|
||||
* 给一个class添加字段
|
||||
*
|
||||
* @param superclass 父级
|
||||
* @param props 新增属性
|
||||
* @return {Object}
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static Object generator(Class<?> superclass, @NotNull BeanProperty... props) {
|
||||
BeanGenerator generator = new BeanGenerator();
|
||||
generator.setSuperclass(superclass);
|
||||
generator.setUseCache(true);
|
||||
for (BeanProperty prop : props) {
|
||||
generator.addProperty(prop.getName(), prop.getType());
|
||||
}
|
||||
return generator.create();
|
||||
}
|
||||
|
||||
/**
|
||||
* 拷贝对象
|
||||
* 注意: 不支持链式Bean,链式用 copyProperties
|
||||
*
|
||||
* @param source 源对象
|
||||
* @param targetBean 需要赋值的对象
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static void copy(@NotNull Object source, @NotNull Object targetBean) {
|
||||
BaseBeanCopier copier = BaseBeanCopier
|
||||
.create(source.getClass(), targetBean.getClass(), false);
|
||||
|
||||
copier.copy(source, targetBean, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 Bean 的所有 get方法
|
||||
*
|
||||
* @param type 类
|
||||
* @return PropertyDescriptor数组 property descriptor [ ]
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static PropertyDescriptor[] getBeanGetters(Class<?> type) {
|
||||
return getPropertiesHelper(type, true, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get properties helper property descriptor [ ]
|
||||
*
|
||||
* @param type type
|
||||
* @param read read
|
||||
* @param write write
|
||||
* @return the property descriptor [ ]
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private static PropertyDescriptor[] getPropertiesHelper(Class<?> type, boolean read, boolean write) {
|
||||
try {
|
||||
PropertyDescriptor[] all = BeanUtils.getPropertyDescriptors(type);
|
||||
if (read && write) {
|
||||
return all;
|
||||
} else {
|
||||
List<PropertyDescriptor> properties = new ArrayList<>(all.length);
|
||||
for (PropertyDescriptor pd : all) {
|
||||
if (read && pd.getReadMethod() != null) {
|
||||
properties.add(pd);
|
||||
} else if (write && pd.getWriteMethod() != null) {
|
||||
properties.add(pd);
|
||||
}
|
||||
}
|
||||
return properties.toArray(new PropertyDescriptor[0]);
|
||||
}
|
||||
} catch (BeansException ex) {
|
||||
throw new CodeGenerationException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 Bean 的所有 set方法
|
||||
*
|
||||
* @param type 类
|
||||
* @return PropertyDescriptor数组 property descriptor [ ]
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static PropertyDescriptor[] getBeanSetters(Class<?> type) {
|
||||
return getPropertiesHelper(type, false, true);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.aos.starter.core.util;
|
||||
|
||||
import lombok.experimental.UtilityClass;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
* <p>Company: 成都返空汇网络技术有限公司</p>
|
||||
* <p>Description: 类工具类 </p>
|
||||
*
|
||||
* @author dong4j
|
||||
* @version 1.2.3
|
||||
* @email "mailto:dongshijie@fkhwl.com"
|
||||
* @date 2019.12.30 22:37
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Slf4j
|
||||
@UtilityClass
|
||||
@SuppressWarnings("java:S2176")
|
||||
public class ClassUtils extends com.aos.element.basic.basic.util.ClassUtils {
|
||||
|
||||
}
|
||||
+316
@@ -0,0 +1,316 @@
|
||||
package com.aos.starter.core.util;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
|
||||
import com.aos.element.basic.core.util.DataTypeUtils;
|
||||
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import lombok.experimental.UtilityClass;
|
||||
|
||||
/**
|
||||
* <p>Company: 成都返空汇网络技术有限公司</p>
|
||||
* <p>Description: 集合工具类 </p>
|
||||
*
|
||||
* @author dong4j
|
||||
* @version 1.2.3
|
||||
* @email "mailto:dongshijie@fkhwl.com"
|
||||
* @date 2019.12.24 15:24
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@UtilityClass
|
||||
@SuppressWarnings("java:S2176")
|
||||
public class CollectionUtils extends org.springframework.util.CollectionUtils {
|
||||
|
||||
/** THREAD_LOCAL_RANDOM */
|
||||
public static final ThreadLocalRandom THREAD_LOCAL_RANDOM = ThreadLocalRandom.current();
|
||||
|
||||
/**
|
||||
* Return {@code true} if the supplied Collection is not {@code null} or empty.
|
||||
* Otherwise, return {@code false}.
|
||||
*
|
||||
* @param collection the Collection to check
|
||||
* @return whether the given Collection is not empty
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Contract("null -> false")
|
||||
public static boolean isNotEmpty(@Nullable Collection<?> collection) {
|
||||
return !isEmpty(collection);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return {@code true} if the supplied Map is not {@code null} or empty.
|
||||
* Otherwise, return {@code false}.
|
||||
*
|
||||
* @param map the Map to check
|
||||
* @return whether the given Map is not empty
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Contract("null -> false")
|
||||
public static boolean isNotEmpty(@Nullable Map<?, ?> map) {
|
||||
return !isEmpty(map);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the given Array contains the given element.
|
||||
*
|
||||
* @param <T> The generic tag
|
||||
* @param array the Array to check
|
||||
* @param element the element to look for
|
||||
* @return {@code true} if found, {@code false} else
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Contract("null, _ -> false")
|
||||
public static <T> boolean contains(@Nullable T[] array, T element) {
|
||||
if (array == null) {
|
||||
return false;
|
||||
}
|
||||
return Arrays.stream(array).anyMatch(x -> ObjectUtils.nullSafeEquals(x, element));
|
||||
}
|
||||
|
||||
/**
|
||||
* Concatenates 2 arrays
|
||||
*
|
||||
* @param one 数组1
|
||||
* @param other 数组2
|
||||
* @return 新数组 string [ ]
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static String[] concat(String[] one, String[] other) {
|
||||
return concat(one, other, String.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Concatenates 2 arrays
|
||||
*
|
||||
* @param <T> the type parameter
|
||||
* @param one 数组1
|
||||
* @param other 数组2
|
||||
* @param clazz 数组类
|
||||
* @return 新数组 t [ ]
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T> T[] concat(@NotNull T[] one, @NotNull T[] other, Class<T> clazz) {
|
||||
T[] target = (T[]) Array.newInstance(clazz, one.length + other.length);
|
||||
System.arraycopy(one, 0, target, 0, one.length);
|
||||
System.arraycopy(other, 0, target, one.length, other.length);
|
||||
return target;
|
||||
}
|
||||
|
||||
/**
|
||||
* 不可变 Set
|
||||
*
|
||||
* @param <E> 泛型
|
||||
* @param es 对象
|
||||
* @return 集合 set
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static <E> Set<E> ofImmutableSet(E[] es) {
|
||||
Objects.requireNonNull(es, "args es is null.");
|
||||
return Arrays.stream(es).collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
/**
|
||||
* 不可变 List
|
||||
*
|
||||
* @param <E> 泛型
|
||||
* @param es 对象
|
||||
* @return 集合 list
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static <E> List<E> ofImmutableList(E[] es) {
|
||||
Objects.requireNonNull(es, "args es is null.");
|
||||
return Arrays.stream(es).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterable 转换为List集合
|
||||
*
|
||||
* @param <E> 泛型
|
||||
* @param elements Iterable
|
||||
* @return 集合 list
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static <E> List<E> toList(Iterable<E> elements) {
|
||||
Objects.requireNonNull(elements, "elements es is null.");
|
||||
if (elements instanceof Collection) {
|
||||
return new ArrayList<>((Collection<E>) elements);
|
||||
}
|
||||
Iterator<E> iterator = elements.iterator();
|
||||
List<E> list = new ArrayList<>();
|
||||
while (iterator.hasNext()) {
|
||||
list.add(iterator.next());
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将key value 数组转为 map
|
||||
*
|
||||
* @param <K> key
|
||||
* @param <V> value
|
||||
* @param keysValues key value 数组
|
||||
* @return map 集合
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <K, V> Map<K, V> toMap(@NotNull Object... keysValues) {
|
||||
int separate = 2;
|
||||
if (keysValues.length % separate != 0) {
|
||||
throw new IllegalArgumentException("wrong number of arguments for met, keysValues length can not be odd");
|
||||
}
|
||||
Map<K, V> keyValueMap = Maps.newHashMapWithExpectedSize(keysValues.length / 2);
|
||||
for (int i = keysValues.length - separate; i >= 0; i -= separate) {
|
||||
keyValueMap.put((K) keysValues[i], (V) keysValues[i + 1]);
|
||||
}
|
||||
return keyValueMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* 对象是否为数组对象
|
||||
*
|
||||
* @param obj 对象
|
||||
* @return 是否为数组对象 ,如果为{@code null} 返回false
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Contract("null -> false")
|
||||
public static boolean isArray(Object obj) {
|
||||
if (null == obj) {
|
||||
return false;
|
||||
}
|
||||
return obj.getClass().isArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Find value of type t
|
||||
*
|
||||
* @param <T> parameter
|
||||
* @param map map
|
||||
* @param key key
|
||||
* @param type type
|
||||
* @return the t
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Contract("null, _, _ -> null")
|
||||
@Nullable
|
||||
public static <T> T findValueOfType(Map<String, Object> map, String key, @Nullable Class<T> type) {
|
||||
if (map == null || !map.containsKey(key) || StringUtils.isBlank(String.valueOf(map.get(key)))) {
|
||||
return null;
|
||||
}
|
||||
return DataTypeUtils.convert(type, map.get(key));
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过 map 的 value 排序
|
||||
*
|
||||
* @param <K> parameter
|
||||
* @param <V> parameter
|
||||
* @param map map
|
||||
* @param asc asc
|
||||
* @return the map
|
||||
* @version jdk1.8
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static <K, V extends Comparable<? super V>> Map<K, V> sortByValue(@NotNull Map<K, V> map, boolean asc) {
|
||||
Map<K, V> result = new LinkedHashMap<>();
|
||||
Stream<Map.Entry<K, V>> stream = map.entrySet().stream();
|
||||
// 升序
|
||||
if (asc) {
|
||||
stream.sorted(Map.Entry.comparingByValue())
|
||||
.forEachOrdered(e -> result.put(e.getKey(), e.getValue()));
|
||||
} else {
|
||||
// 降序
|
||||
stream.sorted(Map.Entry.<K, V>comparingByValue().reversed())
|
||||
.forEachOrdered(e -> result.put(e.getKey(), e.getValue()));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过 map 的 key 排序
|
||||
*
|
||||
* @param <K> parameter
|
||||
* @param <V> parameter
|
||||
* @param map map
|
||||
* @param asc asc
|
||||
* @return the map
|
||||
* @version jdk1.8
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static <K extends Comparable<? super K>, V> Map<K, V> sortByKey(@NotNull Map<K, V> map, boolean asc) {
|
||||
Map<K, V> result = new LinkedHashMap<>();
|
||||
Stream<Map.Entry<K, V>> stream = map.entrySet().stream();
|
||||
if (asc) {
|
||||
stream.sorted(Map.Entry.comparingByKey())
|
||||
.forEachOrdered(e -> result.put(e.getKey(), e.getValue()));
|
||||
} else {
|
||||
stream.sorted(Map.Entry.<K, V>comparingByKey().reversed())
|
||||
.forEachOrdered(e -> result.put(e.getKey(), e.getValue()));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取多条集合中随机值
|
||||
*
|
||||
* @param <T> parameter
|
||||
* @param list list
|
||||
* @param num num
|
||||
* @return the random list
|
||||
* @Description list 随机取数据
|
||||
* @params list list集合 num 随机取多少条
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public static <T> List<T> getRandomList(@NotNull List<T> list, int num) {
|
||||
List<T> randomList = new ArrayList<>();
|
||||
if (list.size() <= num) {
|
||||
return list;
|
||||
} else {
|
||||
for (int i = 0; i < num; i++) {
|
||||
int intRandom = THREAD_LOCAL_RANDOM.nextInt(list.size() - 1);
|
||||
randomList.add(list.get(intRandom));
|
||||
list.remove(list.get(intRandom));
|
||||
}
|
||||
return randomList;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取集合中随机值
|
||||
*
|
||||
* @param <T> parameter
|
||||
* @param list list
|
||||
* @return the random list
|
||||
* @Description list 随机取数据
|
||||
* @params list list集合 num 随机取多少条
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public static <T> T getRandom(@NotNull List<T> list) {
|
||||
if (isEmpty(list)) {
|
||||
return null;
|
||||
}
|
||||
int size = list.size();
|
||||
if (size == 1) {
|
||||
return list.get(0);
|
||||
}
|
||||
return list.get(THREAD_LOCAL_RANDOM.nextInt(size - 1));
|
||||
}
|
||||
|
||||
}
|
||||
+720
@@ -0,0 +1,720 @@
|
||||
package com.aos.starter.devtools;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
|
||||
import com.aos.element.basic.basic.asserts.Assertions;
|
||||
import com.aos.element.basic.common.util.GsonUtils;
|
||||
import com.aos.element.common.constant.App;
|
||||
import com.aos.element.common.exception.PropertiesException;
|
||||
import com.aos.starter.core.util.DateUtils;
|
||||
import com.aos.starter.core.util.StringUtils;
|
||||
import com.aos.starter.core.util.Tools;
|
||||
import com.baomidou.mybatisplus.annotation.DbType;
|
||||
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
|
||||
import com.baomidou.mybatisplus.core.toolkit.StringPool;
|
||||
import com.baomidou.mybatisplus.extension.toolkit.JdbcUtils;
|
||||
import com.baomidou.mybatisplus.generator.InjectionConfig;
|
||||
import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
|
||||
import com.baomidou.mybatisplus.generator.config.FileOutConfig;
|
||||
import com.baomidou.mybatisplus.generator.config.GlobalConfig;
|
||||
import com.baomidou.mybatisplus.generator.config.ITypeConvert;
|
||||
import com.baomidou.mybatisplus.generator.config.PackageConfig;
|
||||
import com.baomidou.mybatisplus.generator.config.StrategyConfig;
|
||||
import com.baomidou.mybatisplus.generator.config.TemplateConfig;
|
||||
import com.baomidou.mybatisplus.generator.config.converts.MySqlTypeConvert;
|
||||
import com.baomidou.mybatisplus.generator.config.converts.OracleTypeConvert;
|
||||
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
|
||||
import com.baomidou.mybatisplus.generator.config.rules.DateType;
|
||||
import com.baomidou.mybatisplus.generator.config.rules.DbColumnType;
|
||||
import com.baomidou.mybatisplus.generator.config.rules.IColumnType;
|
||||
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
|
||||
|
||||
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
* <p>Company: 成都返空汇网络技术有限公司</p>
|
||||
* <p>Description: </p>
|
||||
*
|
||||
* @author dong4j
|
||||
* @version 1.2.3
|
||||
* @email "mailto:dongshijie@fkhwl.com"
|
||||
* @date 2019.12.26 21:45
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Data
|
||||
@Slf4j
|
||||
@Accessors(chain = true)
|
||||
@SuppressWarnings("all")
|
||||
public class AutoGeneratorCode {
|
||||
/** ROOT_PACKAGE */
|
||||
public static final String ROOT_PACKAGE = App.BASE_PACKAGES + StringPool.DOT;
|
||||
/** 自定义生成文件时需要指定文件后缀 */
|
||||
public static final String VM_SUFFIX = ".vm";
|
||||
/** TEMPLATE_CONTROLLER */
|
||||
public static final String TEMPLATE_CONTROLLER = "/templates/controller.java";
|
||||
/** TEMPLATE_CONTROLLER_EX */
|
||||
public static final String TEMPLATE_CONTROLLER_EX = "/templates/controller-ext.java";
|
||||
/** TEMPLATE_ENTITY_JAVA */
|
||||
public static final String TEMPLATE_ENTITY_JAVA = "/templates/entity.java" + VM_SUFFIX;
|
||||
/** TEMPLATE_VO_JAVA */
|
||||
public static final String TEMPLATE_VO_JAVA = "/templates/vo.java" + VM_SUFFIX;
|
||||
/** TEMPLATE_PAGE_JAVA */
|
||||
public static final String TEMPLATE_PAGE_JAVA = "/templates/page.java" + VM_SUFFIX;
|
||||
/** TEMPLATE_DTO_JAVA */
|
||||
public static final String TEMPLATE_DTO_JAVA = "/templates/dto.java" + VM_SUFFIX;
|
||||
/** TEMPLATE_FORM_JAVA */
|
||||
public static final String TEMPLATE_FORM_JAVA = "/templates/form.java" + VM_SUFFIX;
|
||||
/** TEMPLATE_QUERY_JAVA */
|
||||
public static final String TEMPLATE_QUERY_JAVA = "/templates/query.java" + VM_SUFFIX;
|
||||
/** TEMPLATE_WRAPPER_JAVA */
|
||||
public static final String TEMPLATE_WRAPPER_JAVA = "/templates/wrapper.java" + VM_SUFFIX;
|
||||
/** TEMPLATE_SINGLE_WRAPPER_JAVA */
|
||||
public static final String TEMPLATE_SINGLE_WRAPPER_JAVA = "/templates/single-wrapper.java" + VM_SUFFIX;
|
||||
/** TEMPLATE_OUTER_WRAPPER_JAVA */
|
||||
public static final String TEMPLATE_OUTER_WRAPPER_JAVA = "/templates/outer-wrapper.java" + VM_SUFFIX;
|
||||
/** TEMPLATE_INNER_WRAPPER_JAVA */
|
||||
public static final String TEMPLATE_INNER_WRAPPER_JAVA = "/templates/inner-wrapper.java" + VM_SUFFIX;
|
||||
/** TEMPLATE_MAPPER */
|
||||
public static final String TEMPLATE_MAPPER = "/templates/mapper.java";
|
||||
/** TEMPLATE_XML */
|
||||
public static final String TEMPLATE_XML = "/templates/mapper.xml" + VM_SUFFIX;
|
||||
/** TEMPLATE_SERVICE */
|
||||
public static final String TEMPLATE_SERVICE = "/templates/service.java";
|
||||
/** TEMPLATE_SERVICEIMPL */
|
||||
public static final String TEMPLATE_SERVICEIMPL = "/templates/serviceImpl.java";
|
||||
/** TEMPLATE_GLOBAL_PROPERTIES */
|
||||
public static final String TEMPLATE_GLOBAL_PROPERTIES = "/templates/application.properties" + VM_SUFFIX;
|
||||
/** TEMPLATE_APPLICATION */
|
||||
public static final String TEMPLATE_APPLICATION = "/templates/Application.java" + VM_SUFFIX;
|
||||
/** TEMPLATE_APPLICATION_TEST */
|
||||
public static final String TEMPLATE_APPLICATION_TEST = "/templates/ApplicationTest.java" + VM_SUFFIX;
|
||||
/** TEMPLATE_CLOUD_YML */
|
||||
public static final String TEMPLATE_CLOUD_YML = "/templates/bootstrap.yml" + VM_SUFFIX;
|
||||
/** TEMPLATE_BOOT_YML */
|
||||
public static final String TEMPLATE_BOOT_YML = "/templates/application.yml" + VM_SUFFIX;
|
||||
/** RESOURCE_ROOT_PATH */
|
||||
public static final String RESOURCE_ROOT_PATH = "/src/main/resources/";
|
||||
/** ASSEMBLY_PATH */
|
||||
public static final String ASSEMBLY_PATH = "/src/main/assembly/";
|
||||
/** BIN_PATH */
|
||||
public static final String BIN_PATH = "/src/main/bin/";
|
||||
/** RESOURCE_TEST_PATH */
|
||||
public static final String RESOURCE_TEST_PATH = "/src/test/resources/";
|
||||
/** JAVA_ROOT_PATH */
|
||||
public static final String JAVA_ROOT_PATH = "/src/main/java/";
|
||||
/** JAVA_TEST_PATH */
|
||||
public static final String JAVA_TEST_PATH = "/src/test/java/";
|
||||
/** 设置 model 路径, 最后一级为 src 上一级 */
|
||||
private String modelPath;
|
||||
/** Author */
|
||||
private String author;
|
||||
/** Version */
|
||||
private String version;
|
||||
/** Model name */
|
||||
private String modelName;
|
||||
/** Driver name */
|
||||
private String driverName;
|
||||
/** User name */
|
||||
private String userName;
|
||||
/** Pass word */
|
||||
private String passWord;
|
||||
/** Url */
|
||||
private String url;
|
||||
/** Tables */
|
||||
private String[] tables;
|
||||
/** Prefix */
|
||||
private String[] prefix;
|
||||
/** 自定义实体父类 */
|
||||
private String superEntityClass;
|
||||
/** 自定义 dao 父类 */
|
||||
private String superMapperClass;
|
||||
/** 自定义 service 基类 */
|
||||
private String superServiceClass;
|
||||
/** 自定义 serviceImpl 基类 */
|
||||
private String superServiceImplClass;
|
||||
/** 自定义 controller 父类 */
|
||||
private String superControllerClass;
|
||||
/** 需要生成的 package */
|
||||
private String packageName;
|
||||
/** 需要生成的组件的配置 */
|
||||
private String[] componets;
|
||||
/** Templates */
|
||||
private String[] templates;
|
||||
/** 是否为 web 应用 */
|
||||
private boolean webapp;
|
||||
/** Package config */
|
||||
private PackageConfig packageConfig;
|
||||
/** Templates config */
|
||||
private TemplatesConfig templatesConfig;
|
||||
/** Properties config */
|
||||
private PropertiesConfig propertiesConfig;
|
||||
/** Module type */
|
||||
private ModuleConfig.ModuleType moduleType;
|
||||
|
||||
/**
|
||||
* 生成全局变量
|
||||
*
|
||||
* @return the global config
|
||||
* @since 1.0.0
|
||||
*/
|
||||
GlobalConfig buildGlobalConfig() {
|
||||
// 输出路径
|
||||
GlobalConfig globalConfig = new GlobalConfig()
|
||||
.setDateType(DateType.ONLY_DATE)
|
||||
.setOutputDir(this.modelPath + "/src/main/java")
|
||||
// 开启 ActiveRecord 支持
|
||||
.setActiveRecord(true)
|
||||
// 设置 author
|
||||
.setAuthor(this.author)
|
||||
// 是否覆盖文件
|
||||
.setFileOverride(false)
|
||||
// 是否开始二级缓存
|
||||
.setEnableCache(false)
|
||||
// 是否设置 sql 的 columnlist
|
||||
.setBaseColumnList(true)
|
||||
// 是否设置 resultmap
|
||||
.setBaseResultMap(true)
|
||||
// 设置 controller 名称 (%s 会自动填充表实体属性)
|
||||
.setControllerName("%sController")
|
||||
// 设置 service 名称
|
||||
.setServiceName("%sRepositoryService")
|
||||
// 设置 serviceImpl 名称
|
||||
.setServiceImplName("%sRepositoryServiceImpl")
|
||||
// 设置 mapper 名称
|
||||
.setMapperName("%sDao")
|
||||
// 设置 xml 名称
|
||||
.setXmlName("%sMapper")
|
||||
// 生成后是否打开目录
|
||||
.setOpen(false);
|
||||
log.info("GlobalConfig = {}", GsonUtils.toJson(globalConfig, true));
|
||||
return globalConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build data source config data source config.
|
||||
* 生成 数据源
|
||||
*
|
||||
* @return the data source config
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@SuppressWarnings("PMD.UndefineMagicConstantRule")
|
||||
DataSourceConfig buildDataSourceConfig() {
|
||||
ITypeConvert convert;
|
||||
DbType dbType = JdbcUtils.getDbType(this.url);
|
||||
switch (dbType) {
|
||||
case ORACLE:
|
||||
convert = new OracleTypeConvert() {
|
||||
// 自定义数据库表字段类型转换【可选】
|
||||
@Override
|
||||
public IColumnType processTypeConvert(GlobalConfig globalConfig, String fieldType) {
|
||||
log.info("转换类型: {}", fieldType);
|
||||
// 注意!!processTypeConvert 存在默认类型转换,如果不是你要的效果请自定义返回、非如下直接返回.
|
||||
return super.processTypeConvert(globalConfig, fieldType);
|
||||
}
|
||||
};
|
||||
break;
|
||||
case MYSQL:
|
||||
convert = new MySqlTypeConvert() {
|
||||
@Override
|
||||
public IColumnType processTypeConvert(GlobalConfig globalConfig, String fieldType) {
|
||||
log.info("转换类型: {}", fieldType);
|
||||
String t = fieldType.toLowerCase();
|
||||
// tinyint 转换为 Integer 类型
|
||||
if (t.contains("tinyint")) {
|
||||
log.info("转换类型: {} -> Integer", fieldType);
|
||||
return DbColumnType.INTEGER;
|
||||
}
|
||||
// 注意!!processTypeConvert 存在默认类型转换,如果不是你要的效果请自定义返回、非如下直接返回.
|
||||
return super.processTypeConvert(globalConfig, fieldType);
|
||||
}
|
||||
};
|
||||
break;
|
||||
default:
|
||||
throw new UnsupportedOperationException("暂时不支持其他数据库类型转换");
|
||||
}
|
||||
|
||||
DataSourceConfig dataSourceConfig = new DataSourceConfig().setDriverName(this.driverName)
|
||||
.setUsername(this.userName)
|
||||
.setPassword(this.passWord)
|
||||
.setUrl(this.url)
|
||||
.setTypeConvert(convert);
|
||||
|
||||
log.info("dataSourceConfig = {}", GsonUtils.toJson(dataSourceConfig, true));
|
||||
return dataSourceConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成 策略配置
|
||||
*
|
||||
* @return the strategy config
|
||||
* @since 1.0.0
|
||||
*/
|
||||
StrategyConfig buildStrategyConfig() {
|
||||
StrategyConfig strategyConfig = new StrategyConfig()
|
||||
// 全局大写命名 ORACLE 注意
|
||||
.setCapitalMode(true)
|
||||
// 是否开启 lombok 支持
|
||||
.setEntityLombokModel(true)
|
||||
// 是否开启 @RestContriller 风格
|
||||
.setRestControllerStyle(true)
|
||||
// 此处可以修改为您的表前缀
|
||||
.setTablePrefix(this.prefix)
|
||||
// 表名生成策略 (下划线转驼峰)
|
||||
.setNaming(NamingStrategy.underline_to_camel)
|
||||
// 需要生成的表
|
||||
.setInclude(this.tables)
|
||||
// 自定义实体父类
|
||||
.setSuperEntityClass(this.superEntityClass)
|
||||
// 自定义实体,公共字段
|
||||
.setSuperEntityColumns("id", "deleted", "update_time", "create_time")
|
||||
// 自定义 dao 父类
|
||||
.setSuperMapperClass(this.superMapperClass)
|
||||
// 自定义 service 父类
|
||||
.setSuperServiceClass(this.superServiceClass)
|
||||
// 自定义 service 实现类父类
|
||||
.setSuperServiceImplClass(this.superServiceImplClass)
|
||||
// 自定义 controller 父类
|
||||
.setSuperControllerClass(this.superControllerClass)
|
||||
// 实体是否生成字段常量 (默认 false)
|
||||
.setEntityColumnConstant(true)
|
||||
// 实体是否为构建者模型 (默认 false)
|
||||
.setEntityBuilderModel(false);
|
||||
|
||||
log.info("strategyConfig = {}", GsonUtils.toJson(strategyConfig, true));
|
||||
return strategyConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成 包配置
|
||||
*
|
||||
* @return the package config
|
||||
* @since 1.0.0
|
||||
*/
|
||||
PackageConfig buildPackageConfig() {
|
||||
Assertions.notBlank(this.packageName, "未配置项目 package");
|
||||
String[] names = this.packageName.split("\\.");
|
||||
if (names.length < 1) {
|
||||
throw new PropertiesException("配置错误, 至少配置一个模块名吧!");
|
||||
}
|
||||
this.modelName = names[names.length - 1];
|
||||
this.modelName = Tools.isBlank(this.modelName) ? "auto" : this.modelName;
|
||||
// 首字母大写
|
||||
this.modelName = StringUtils.firstCharToUpper(this.modelName);
|
||||
|
||||
this.packageConfig = new PackageConfig()
|
||||
.setParent(ROOT_PACKAGE + this.packageName)
|
||||
.setMapper("dao");
|
||||
|
||||
log.info("packageConfig = {}", GsonUtils.toJson(this.packageConfig, true));
|
||||
return this.packageConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
* 自定义模板配置,可以 copy 源码 mybatis-plus/src/main/resources/template 下面内容修改,
|
||||
* 放置自己项目的 src/main/resources/template 目录下, 默认名称一下可以不配置,也可以自定义模板名称
|
||||
*
|
||||
* @return the template config
|
||||
* @since 1.0.0
|
||||
*/
|
||||
TemplateConfig buildTemplateConfig() {
|
||||
this.templatesConfig = new TemplatesConfig();
|
||||
if (this.templates == null || this.templates.length == 0) {
|
||||
this.templatesConfig.setController(true)
|
||||
.setDao(true)
|
||||
.setEntity(true)
|
||||
.setImpl(true)
|
||||
.setService(true)
|
||||
.setImpl(true)
|
||||
.setStart(true);
|
||||
} else {
|
||||
// 是否生成其他全局配置
|
||||
for (String template : this.templates) {
|
||||
switch (template) {
|
||||
case TemplatesConfig.CONTROLLER:
|
||||
this.templatesConfig.setController(true);
|
||||
log.info("生成 controller 文件");
|
||||
break;
|
||||
case TemplatesConfig.SERVICE:
|
||||
this.templatesConfig.setService(true);
|
||||
log.info("生成 service 文件");
|
||||
break;
|
||||
case TemplatesConfig.IMPL:
|
||||
this.templatesConfig.setImpl(true);
|
||||
log.info("生成 service impl 文件");
|
||||
break;
|
||||
case TemplatesConfig.DAO:
|
||||
this.templatesConfig.setDao(true);
|
||||
log.info("生成 dao 文件");
|
||||
break;
|
||||
case TemplatesConfig.XML:
|
||||
this.templatesConfig.setXml(true);
|
||||
log.info("生成 mapper.xml 文件");
|
||||
break;
|
||||
case TemplatesConfig.ENTITY:
|
||||
this.templatesConfig.setEntity(true);
|
||||
log.info("生成 entity 文件");
|
||||
break;
|
||||
case TemplatesConfig.VO:
|
||||
this.templatesConfig.setVo(true);
|
||||
log.info("生成 vo 文件");
|
||||
break;
|
||||
case TemplatesConfig.DTO:
|
||||
this.templatesConfig.setDto(true);
|
||||
log.info("生成 dto 文件");
|
||||
break;
|
||||
//noinspection deprecation
|
||||
case TemplatesConfig.WRAPPER:
|
||||
log.error("请使用 TemplatesConfig.CONVERTER 代替");
|
||||
case TemplatesConfig.CONVERTER:
|
||||
this.templatesConfig.setConverter(true);
|
||||
log.info("生成 converter 文件");
|
||||
break;
|
||||
case TemplatesConfig.START:
|
||||
// 生成
|
||||
this.templatesConfig.setStart(true);
|
||||
log.info("生成启动类");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return this.buildTemplate();
|
||||
}
|
||||
|
||||
/**
|
||||
* Build template template config
|
||||
*
|
||||
* @return the template config
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private TemplateConfig buildTemplate() {
|
||||
TemplateConfig templateConfig = new TemplateConfig()
|
||||
.setController(null)
|
||||
.setService(null)
|
||||
.setEntity(null)
|
||||
.setMapper(null)
|
||||
.setServiceImpl(null)
|
||||
.setXml(null);
|
||||
if (this.templatesConfig.isController()) {
|
||||
templateConfig.setController(TEMPLATE_CONTROLLER_EX);
|
||||
}
|
||||
if (this.templatesConfig.isService()) {
|
||||
templateConfig.setService(TEMPLATE_SERVICE);
|
||||
}
|
||||
if (this.templatesConfig.isImpl()) {
|
||||
templateConfig.setServiceImpl(TEMPLATE_SERVICEIMPL);
|
||||
}
|
||||
if (this.templatesConfig.isDao()) {
|
||||
templateConfig.setMapper(TEMPLATE_MAPPER);
|
||||
}
|
||||
if (this.templatesConfig.isEntity()) {
|
||||
log.info("开启自定义 entity 生成");
|
||||
}
|
||||
if (this.templatesConfig.isDto()) {
|
||||
log.info("开启自定义 dto 生成");
|
||||
}
|
||||
if (this.templatesConfig.isVo()) {
|
||||
log.info("开启自定义 vo 生成");
|
||||
}
|
||||
if (this.templatesConfig.isConverter()) {
|
||||
log.info("开启自定义 converter 生成");
|
||||
}
|
||||
if (this.templatesConfig.isXml()) {
|
||||
log.info("开启自定义 xml 生成");
|
||||
}
|
||||
|
||||
log.info("templateConfig = {}", GsonUtils.toJson(templateConfig, true));
|
||||
return templateConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
* 自定义配置
|
||||
*
|
||||
* @return the injection config
|
||||
* @since 1.0.0
|
||||
*/
|
||||
InjectionConfig buildInjectionConfig() {
|
||||
log.info("开始处理自定义配置");
|
||||
// 注入自定义配置,可以在 VM 中使用 cfg.abc 【可无】
|
||||
InjectionConfig injectionConfig = new InjectionConfig() {
|
||||
@Override
|
||||
public void initMap() {
|
||||
Map<String, Object> map = Maps.newHashMapWithExpectedSize(3);
|
||||
map.put("app_name", "${project.artifactId}");
|
||||
map.put("app_version", "${project.version}");
|
||||
// 替换包变量名, 避免被替换
|
||||
map.put("profile_active", "${profile.active}");
|
||||
map.put("package_dto",
|
||||
AutoGeneratorCode.this.packageConfig.getParent()
|
||||
+ StringPool.DOT
|
||||
+ AutoGeneratorCode.this.packageConfig.getEntity()
|
||||
+ StringPool.DOT + "dto");
|
||||
map.put("package_vo",
|
||||
AutoGeneratorCode.this.packageConfig.getParent()
|
||||
+ StringPool.DOT
|
||||
+ AutoGeneratorCode.this.packageConfig.getEntity()
|
||||
+ StringPool.DOT + "vo");
|
||||
map.put("package_form",
|
||||
AutoGeneratorCode.this.packageConfig.getParent()
|
||||
+ StringPool.DOT
|
||||
+ AutoGeneratorCode.this.packageConfig.getEntity()
|
||||
+ StringPool.DOT + "form");
|
||||
map.put("package_po",
|
||||
AutoGeneratorCode.this.packageConfig.getParent()
|
||||
+ StringPool.DOT
|
||||
+ AutoGeneratorCode.this.packageConfig.getEntity()
|
||||
+ StringPool.DOT
|
||||
+ "po");
|
||||
map.put("package_converter", AutoGeneratorCode.this.packageConfig.getParent() + StringPool.DOT + "converter");
|
||||
map.put("version", AutoGeneratorCode.this.getVersion());
|
||||
map.put("date", DateUtils.format(new Date(), "yyyy.MM.dd HH:mm"));
|
||||
map.put("model_name", AutoGeneratorCode.this.modelName);
|
||||
map.put("package_name", AutoGeneratorCode.this.packageConfig.getParent());
|
||||
// 生成 application.properties
|
||||
map.put("gloabl", true);
|
||||
map.put("webapp", AutoGeneratorCode.this.webapp);
|
||||
map.put("pc", AutoGeneratorCode.this.propertiesConfig);
|
||||
this.setMap(map);
|
||||
}
|
||||
};
|
||||
|
||||
// 调用 initMap(), 将 map 注入到 InjectionConfig
|
||||
injectionConfig.initMap();
|
||||
|
||||
List<FileOutConfig> focList = new ArrayList<>();
|
||||
String parentPath = this.packageConfig.getParent().replace(StringPool.DOT, File.separator);
|
||||
this.buildCommonTemplate(focList, parentPath);
|
||||
|
||||
this.buildExpandTemplate(focList, parentPath);
|
||||
|
||||
injectionConfig.setFileOutConfigList(focList);
|
||||
|
||||
return injectionConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成常用的模板
|
||||
*
|
||||
* @param focList foc list
|
||||
* @param parentPath parent path
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private void buildCommonTemplate(List<FileOutConfig> focList, String parentPath) {
|
||||
// 调整 xml 生成目录
|
||||
if (this.templatesConfig.isXml()) {
|
||||
focList.add(buildFileOutConfig(TEMPLATE_XML,
|
||||
this.modelPath + RESOURCE_ROOT_PATH + "mapper",
|
||||
"Mapper.xml",
|
||||
true));
|
||||
}
|
||||
// 调整 entity 的生成目录
|
||||
if (this.templatesConfig.isEntity()) {
|
||||
focList.add(buildFileOutConfig(TEMPLATE_ENTITY_JAVA,
|
||||
this.modelPath + JAVA_ROOT_PATH + parentPath + File.separator + "entity/po",
|
||||
".java",
|
||||
true));
|
||||
// 生成一个 enums 目录
|
||||
File dir = new File(this.modelPath + JAVA_ROOT_PATH + parentPath + File.separator + "enums");
|
||||
if (!dir.mkdirs()) {
|
||||
log.error("[{}] 创建失败", dir);
|
||||
}
|
||||
}
|
||||
// 生成 vo, form, query, page
|
||||
if (this.templatesConfig.isVo()) {
|
||||
focList.add(buildFileOutConfig(TEMPLATE_VO_JAVA,
|
||||
this.modelPath + JAVA_ROOT_PATH + parentPath + File.separator + "entity/vo",
|
||||
"VO.java",
|
||||
true));
|
||||
focList.add(buildFileOutConfig(TEMPLATE_PAGE_JAVA,
|
||||
this.modelPath + JAVA_ROOT_PATH + parentPath + File.separator + "entity/vo",
|
||||
"Page.java",
|
||||
true));
|
||||
|
||||
focList.add(buildFileOutConfig(TEMPLATE_FORM_JAVA,
|
||||
this.modelPath + JAVA_ROOT_PATH + parentPath + File.separator + "entity/form",
|
||||
"Form.java",
|
||||
true));
|
||||
focList.add(buildFileOutConfig(TEMPLATE_QUERY_JAVA,
|
||||
this.modelPath + JAVA_ROOT_PATH + parentPath + File.separator + "entity/form",
|
||||
"Query.java",
|
||||
true));
|
||||
}
|
||||
// 生成 dto
|
||||
if (this.templatesConfig.isDto()) {
|
||||
focList.add(buildFileOutConfig(TEMPLATE_DTO_JAVA,
|
||||
this.modelPath + JAVA_ROOT_PATH + parentPath + File.separator + "entity/dto",
|
||||
"DTO.java",
|
||||
true));
|
||||
}
|
||||
|
||||
// 生成 converter
|
||||
if (this.templatesConfig.isConverter()) {
|
||||
if (ModuleConfig.ModuleType.SINGLE_MODULE.equals(this.moduleType)) {
|
||||
focList.add(buildFileOutConfig(TEMPLATE_SINGLE_WRAPPER_JAVA,
|
||||
this.modelPath + JAVA_ROOT_PATH + parentPath + File.separator + "converter",
|
||||
"Converter.java",
|
||||
true));
|
||||
} else {
|
||||
focList.add(buildFileOutConfig(TEMPLATE_OUTER_WRAPPER_JAVA,
|
||||
this.modelPath + JAVA_ROOT_PATH + parentPath + File.separator + "converter",
|
||||
"ViewConverter.java",
|
||||
true));
|
||||
focList.add(buildFileOutConfig(TEMPLATE_INNER_WRAPPER_JAVA,
|
||||
this.modelPath + JAVA_ROOT_PATH + parentPath + File.separator + "converter",
|
||||
"ServiceConverter.java",
|
||||
true));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成扩展模板
|
||||
*
|
||||
* @param focList foc list
|
||||
* @param parentPath parent path
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private void buildExpandTemplate(List<FileOutConfig> focList, String parentPath) {
|
||||
this.buildPropertiesTemplate();
|
||||
|
||||
if (this.templatesConfig.isStart()) {
|
||||
log.info("生成启动类");
|
||||
focList.add(buildFileOutConfig(TEMPLATE_APPLICATION,
|
||||
this.modelPath + JAVA_ROOT_PATH + parentPath,
|
||||
this.modelName + "Application.java",
|
||||
false));
|
||||
|
||||
log.info("生成单元测试主类");
|
||||
focList.add(buildFileOutConfig(TEMPLATE_APPLICATION_TEST,
|
||||
this.modelPath + JAVA_TEST_PATH + parentPath,
|
||||
this.modelName + "ApplicationTest.java",
|
||||
false));
|
||||
|
||||
if (this.propertiesConfig.isCloudConfig()) {
|
||||
log.info("生成 spring cloud 配置文件");
|
||||
focList.add(buildFileOutConfig(TEMPLATE_CLOUD_YML,
|
||||
this.modelPath + RESOURCE_ROOT_PATH,
|
||||
"bootstrap.yml",
|
||||
false));
|
||||
}
|
||||
if (this.propertiesConfig.isBootConfig()) {
|
||||
log.info("生成 spring boot 配置文件");
|
||||
focList.add(buildFileOutConfig(TEMPLATE_BOOT_YML,
|
||||
this.modelPath + RESOURCE_ROOT_PATH,
|
||||
"application.yml",
|
||||
false));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化配置模板
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private void buildPropertiesTemplate() {
|
||||
this.propertiesConfig = new PropertiesConfig();
|
||||
if (CollectionUtils.isNotEmpty(Collections.singleton(this.componets))) {
|
||||
Arrays.stream(this.componets).forEach(c -> {
|
||||
switch (c) {
|
||||
case PropertiesConfig.ACTIVEMQ:
|
||||
this.propertiesConfig.setActivemq(true);
|
||||
log.info("生成 activemq 相关配置, 需要 fkh-element-activemq 依赖");
|
||||
break;
|
||||
case PropertiesConfig.EMAIL:
|
||||
this.propertiesConfig.setEmail(true);
|
||||
log.info("生成 email 相关配置, 需要 fkh-element-email 依赖");
|
||||
break;
|
||||
case PropertiesConfig.REDIS:
|
||||
this.propertiesConfig.setRedis(true);
|
||||
log.info("生成 redis 相关配置, 需要 fkh-element-redis 依赖, "
|
||||
+ "默认为 standalone 模式, 其他模式配置参照 fkh-element-redis/src/test/resource 配置");
|
||||
break;
|
||||
case PropertiesConfig.ROCKTEMQ:
|
||||
this.propertiesConfig.setRocktemq(true);
|
||||
log.info("生成 rocketmq 相关配置, 需要 fkh-element-rocketmq 依赖");
|
||||
break;
|
||||
case PropertiesConfig.WEBSERVICE:
|
||||
this.propertiesConfig.setWebservice(true);
|
||||
log.info("生成 webservice 相关配置, 需要 fkh-element-webservice 依赖");
|
||||
break;
|
||||
case PropertiesConfig.WEBSOCKET:
|
||||
this.propertiesConfig.setWebsocket(true);
|
||||
log.info("生成 websocklet 相关配置, 需要 fkh-element-websocket 依赖");
|
||||
break;
|
||||
case PropertiesConfig.MYBATIS:
|
||||
this.propertiesConfig.setMybatis(true);
|
||||
log.info("生成 mybatis + jdbc + druid 相关配置, 需要 fkh-element-mybatis 依赖");
|
||||
log.info("如果是多数据源, 需要 ms-mybatis-multi 依赖, 如果不能满足需求, 可以参照 fkh-element-mybatis-multi");
|
||||
break;
|
||||
case PropertiesConfig.DUBBO:
|
||||
this.propertiesConfig.setDubbo(true);
|
||||
log.info("生成 dubbo 相关配置, 需要 ms-dubbo 依赖");
|
||||
break;
|
||||
case PropertiesConfig.ADMIN:
|
||||
this.propertiesConfig.setAdmin(true);
|
||||
log.warn("需要 spring-boot-starter-web, spring-boot-starter-actuator, "
|
||||
+ "spring-boot-admin-starter-client, spring-boot-starter-security 依赖");
|
||||
break;
|
||||
case PropertiesConfig.BOOT_CONFIG:
|
||||
this.propertiesConfig.setBootConfig(true);
|
||||
break;
|
||||
case PropertiesConfig.CLOUD_CONFIG:
|
||||
this.propertiesConfig.setCloudConfig(true);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Build file out config file out config.
|
||||
*
|
||||
* @param template the template
|
||||
* @param finalPath the final path
|
||||
* @param suffix the suffix
|
||||
* @param isSuffix is suffix
|
||||
* @return the file out config
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Contract(value = "_, _, _, _ -> new", pure = true)
|
||||
@NotNull
|
||||
private static FileOutConfig buildFileOutConfig(String template, String finalPath, String suffix, boolean isSuffix) {
|
||||
return new FileOutConfig(template) {
|
||||
@Override
|
||||
public String outputFile(TableInfo tableInfo) {
|
||||
File dir = new File(finalPath);
|
||||
if (!dir.exists()) {
|
||||
boolean result = dir.mkdirs();
|
||||
if (result) {
|
||||
log.info("创建目录: [{}]", dir);
|
||||
}
|
||||
}
|
||||
if (isSuffix) {
|
||||
return dir + File.separator + tableInfo.getEntityName() + suffix;
|
||||
}
|
||||
return dir + File.separator + suffix;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
+361
@@ -0,0 +1,361 @@
|
||||
package com.aos.starter.devtools;
|
||||
|
||||
import com.aos.element.common.constant.App;
|
||||
import com.aos.starter.core.util.Tools;
|
||||
import com.baomidou.mybatisplus.generator.AutoGenerator;
|
||||
|
||||
import org.apache.commons.lang3.SystemUtils;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
import java.util.Properties;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
* <p>Company: 成都返空汇网络技术有限公司</p>
|
||||
* <p>Description: </p>
|
||||
*
|
||||
* @author dong4j
|
||||
* @version 1.2.3
|
||||
* @email "mailto:dongshijie@fkhwl.com"
|
||||
* @date 2019.12.26 21:45
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Slf4j
|
||||
@SuppressWarnings("all")
|
||||
public final class AutoGeneratorCodeBuilder {
|
||||
/** Model path */
|
||||
private String modelPath;
|
||||
/** Author */
|
||||
private String author = App.FKH_NAME_SPACE;
|
||||
/** Version */
|
||||
private String version = "1.0.0";
|
||||
/** Tables */
|
||||
private String[] tables;
|
||||
/** 数据表前缀 */
|
||||
private String[] prefix;
|
||||
/** 自定义实体基类 */
|
||||
private String superEntityClass = App.BASE_PACKAGES + ".starter.common.base.BasePO";
|
||||
/** 自定义 dao 基类 */
|
||||
private String superMapperClass = App.BASE_PACKAGES + ".starter.common.base.BaseDao";
|
||||
/** 自定义 service 基类 */
|
||||
private String superServiceClass = App.BASE_PACKAGES + ".starter.mybatis.service.BaseService";
|
||||
/** 自定义 serviceImpl 基类 */
|
||||
private String superServiceImplClass = App.BASE_PACKAGES + ".starter.mybatis.service.impl.BaseServiceImpl";
|
||||
/** 自动以 controller 父类 */
|
||||
private String superControllerClass = App.BASE_PACKAGES + ".starter.rest.ServletController";
|
||||
/** 需要生成的 package */
|
||||
private String packageName;
|
||||
/** Componets */
|
||||
private String[] componets;
|
||||
/** Template */
|
||||
private String[] template;
|
||||
/** Module type */
|
||||
private ModuleConfig.ModuleType moduleType;
|
||||
/** Webapp */
|
||||
private boolean webapp = false;
|
||||
|
||||
/**
|
||||
* Auto generator code builder
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Contract(pure = true)
|
||||
private AutoGeneratorCodeBuilder() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* An auto generator code auto generator code builder.
|
||||
*
|
||||
* @return the auto generator code builder
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@NotNull
|
||||
@Contract(value = " -> new", pure = true)
|
||||
public static AutoGeneratorCodeBuilder onAutoGeneratorCode() {
|
||||
return new AutoGeneratorCodeBuilder();
|
||||
}
|
||||
|
||||
/**
|
||||
* With model path auto generator code builder.
|
||||
*
|
||||
* @param modelPath the model path
|
||||
* @return the auto generator code builder
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Contract("_ -> this")
|
||||
public AutoGeneratorCodeBuilder withModelPath(String modelPath) {
|
||||
this.modelPath = modelPath;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* With author auto generator code builder
|
||||
*
|
||||
* @param author author
|
||||
* @return the auto generator code builder
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Contract("_ -> this")
|
||||
public AutoGeneratorCodeBuilder withAuthor(String author) {
|
||||
this.author = author;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* With version auto generator code builder
|
||||
*
|
||||
* @param version version
|
||||
* @return the auto generator code builder
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Contract("_ -> this")
|
||||
public AutoGeneratorCodeBuilder withVersion(String version) {
|
||||
this.version = version;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* With tables auto generator code builder.
|
||||
*
|
||||
* @param tables the tables'
|
||||
* @return the auto generator code builder
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Contract("_ -> this")
|
||||
public AutoGeneratorCodeBuilder withTables(String[] tables) {
|
||||
this.tables = tables;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* With prefix auto generator code builder
|
||||
*
|
||||
* @param prefix prefix
|
||||
* @return the auto generator code builder
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Contract("_ -> this")
|
||||
public AutoGeneratorCodeBuilder withPrefix(String[] prefix) {
|
||||
this.prefix = prefix;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* With super entity class auto generator code builder.
|
||||
*
|
||||
* @param superEntityClass the super entity class
|
||||
* @return the auto generator code builder
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Contract("_ -> this")
|
||||
public AutoGeneratorCodeBuilder withSuperEntityClass(String superEntityClass) {
|
||||
this.superEntityClass = superEntityClass;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* With super mapper class auto generator code builder.
|
||||
*
|
||||
* @param superMapperClass the super mapper class
|
||||
* @return the auto generator code builder
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Contract("_ -> this")
|
||||
public AutoGeneratorCodeBuilder withSuperMapperClass(String superMapperClass) {
|
||||
this.superMapperClass = superMapperClass;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* With super service class auto generator code builder
|
||||
*
|
||||
* @param superServiceClass super service class
|
||||
* @return the auto generator code builder
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Contract("_ -> this")
|
||||
public AutoGeneratorCodeBuilder withSuperServiceClass(String superServiceClass) {
|
||||
this.superServiceClass = superServiceClass;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* With super service impl class auto generator code builder
|
||||
*
|
||||
* @param superServiceImplClass super service impl class
|
||||
* @return the auto generator code builder
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Contract("_ -> this")
|
||||
public AutoGeneratorCodeBuilder withSuperServiceImplClass(String superServiceImplClass) {
|
||||
this.superServiceImplClass = superServiceImplClass;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* With super controller class auto generator code builder.
|
||||
*
|
||||
* @param superControllerClass the super controller class
|
||||
* @return the auto generator code builder
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Contract("_ -> this")
|
||||
public AutoGeneratorCodeBuilder withSuperControllerClass(String superControllerClass) {
|
||||
this.superControllerClass = superControllerClass;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* With package name auto generator code builder.
|
||||
*
|
||||
* @param packageName the package name
|
||||
* @return the auto generator code builder
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Contract("_ -> this")
|
||||
public AutoGeneratorCodeBuilder withPackageName(String packageName) {
|
||||
this.packageName = packageName;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* With componets auto generator code builder.
|
||||
*
|
||||
* @param componets the componets
|
||||
* @return the auto generator code builder
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Contract("_ -> this")
|
||||
public AutoGeneratorCodeBuilder withComponets(String... componets) {
|
||||
this.componets = componets;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* With module type auto generator code builder
|
||||
*
|
||||
* @param moduleType module type
|
||||
* @return the auto generator code builder
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Contract("_ -> this")
|
||||
public AutoGeneratorCodeBuilder withModuleType(ModuleConfig.ModuleType moduleType) {
|
||||
this.moduleType = moduleType;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* With webapp auto generator code builder.
|
||||
*
|
||||
* @param webapp the webapp
|
||||
* @return the auto generator code builder
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Contract("_ -> this")
|
||||
public AutoGeneratorCodeBuilder withWebapp(boolean webapp) {
|
||||
this.webapp = webapp;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* With template auto generator code builder
|
||||
*
|
||||
* @param template template
|
||||
* @return the auto generator code builder
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Contract("_ -> this")
|
||||
public AutoGeneratorCodeBuilder withTemplate(String... template) {
|
||||
this.template = template;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public void build() {
|
||||
AutoGeneratorCode autoGeneratorCode = new AutoGeneratorCode();
|
||||
String path = new File(this.modelPath).getAbsolutePath();
|
||||
autoGeneratorCode.setModelPath(path);
|
||||
|
||||
Properties properties = this.getProperties();
|
||||
autoGeneratorCode.setDriverName(properties.getProperty("spring.datasource.driver-class-name"));
|
||||
autoGeneratorCode.setUserName(properties.getProperty("spring.datasource.username"));
|
||||
autoGeneratorCode.setPassWord(properties.getProperty("spring.datasource.password"));
|
||||
autoGeneratorCode.setUrl(properties.getProperty("spring.datasource.url"));
|
||||
autoGeneratorCode.setAuthor(Tools.isBlank(this.author) ? SystemUtils.USER_NAME : this.author);
|
||||
autoGeneratorCode.setVersion(this.version);
|
||||
|
||||
autoGeneratorCode.setTables(this.tables);
|
||||
autoGeneratorCode.setPrefix(this.prefix);
|
||||
autoGeneratorCode.setSuperEntityClass(this.superEntityClass);
|
||||
autoGeneratorCode.setSuperMapperClass(this.superMapperClass);
|
||||
autoGeneratorCode.setSuperServiceClass(this.superServiceClass);
|
||||
autoGeneratorCode.setSuperServiceImplClass(this.superServiceImplClass);
|
||||
autoGeneratorCode.setSuperControllerClass(this.superControllerClass);
|
||||
autoGeneratorCode.setPackageName(this.packageName);
|
||||
autoGeneratorCode.setComponets(this.componets);
|
||||
autoGeneratorCode.setWebapp(this.webapp);
|
||||
autoGeneratorCode.setTemplates(this.template);
|
||||
autoGeneratorCode.setModuleType(this.moduleType);
|
||||
|
||||
AutoGenerator autoGenerator = new AutoGenerator();
|
||||
autoGenerator.setGlobalConfig(autoGeneratorCode.buildGlobalConfig())
|
||||
.setDataSource(autoGeneratorCode.buildDataSourceConfig())
|
||||
.setStrategy(autoGeneratorCode.buildStrategyConfig())
|
||||
.setPackageInfo(autoGeneratorCode.buildPackageConfig())
|
||||
.setTemplate(autoGeneratorCode.buildTemplateConfig())
|
||||
.setCfg(autoGeneratorCode.buildInjectionConfig())
|
||||
.setTemplateEngine(new VelocityTemplateEngine())
|
||||
.execute();
|
||||
|
||||
log.debug("{}", autoGenerator.getCfg().getMap().get("app_name"));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取配置文件
|
||||
*
|
||||
* @return 配置Props properties
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@NotNull
|
||||
private Properties getProperties() {
|
||||
InputStream inputStream;
|
||||
inputStream = this.getClass().getClassLoader().getResourceAsStream("jdbc.properties");
|
||||
if (inputStream == null) {
|
||||
URL url = this.getClass().getClassLoader().getResource("jdbc-default.properties");
|
||||
if (url != null) {
|
||||
try {
|
||||
inputStream = url.openStream();
|
||||
} catch (IOException ignored) {
|
||||
// nothing to do
|
||||
}
|
||||
}
|
||||
}
|
||||
// 读取配置文件
|
||||
Properties props = new Properties();
|
||||
try {
|
||||
props.load(inputStream);
|
||||
} catch (IOException e) {
|
||||
log.error(e.getMessage(), e);
|
||||
} finally {
|
||||
if (inputStream != null) {
|
||||
try {
|
||||
inputStream.close();
|
||||
} catch (IOException ioException) {
|
||||
ioException.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
return props;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package ${cfg.package_name};
|
||||
|
||||
import com.fkhwl.starter.launcher.FkhStarter;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
* <p>Company: 成都返空汇网络技术有限公司</p>
|
||||
* <p>Description: 模板启动类 (Auto))</p>
|
||||
*
|
||||
* @author ${author}
|
||||
* @version ${cfg.version}
|
||||
* @email "mailto:${author}@fkhwl.com"
|
||||
* @date ${cfg.date}
|
||||
* @since ${cfg.version}
|
||||
*/
|
||||
@Slf4j
|
||||
@SpringBootApplication
|
||||
public class ${cfg.model_name}Application extends FkhStarter {
|
||||
|
||||
//region todo-${author} : (${cfg.date}) [根据需求实现以下扩展, 可全部删除]
|
||||
/**
|
||||
* 启动前处理逻辑
|
||||
*
|
||||
* @since ${cfg.version}
|
||||
*/
|
||||
@Override
|
||||
public void before(){
|
||||
log.info("before");
|
||||
}
|
||||
|
||||
/**
|
||||
* 启动完成后处理逻辑
|
||||
*
|
||||
* @since ${cfg.version}
|
||||
*/
|
||||
@Override
|
||||
public void after(){
|
||||
log.info("after");
|
||||
}
|
||||
|
||||
/**
|
||||
* 启动完成后发送自定义事件
|
||||
*
|
||||
* @param context the context
|
||||
* @since ${cfg.version}
|
||||
*/
|
||||
@Override
|
||||
public void publishEvent(@NotNull ConfigurableApplicationContext context) {
|
||||
// Object 替换为自定义事件实体, 需要继承 BaseEvent
|
||||
context.publishEvent(new Object());
|
||||
}
|
||||
//endregion
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package ${cfg.package_name};
|
||||
|
||||
import com.fkhwl.starter.basic.constant.ConfigKey;
|
||||
import com.fkhwl.starter.common.context.SpringContext;
|
||||
import com.fkhwl.starter.test.FkhTest;
|
||||
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
* <p>Company: 成都返空汇网络技术有限公司</p>
|
||||
* <p>Description: 单元测试主类 </p>
|
||||
*
|
||||
* @author ${author}
|
||||
* @version ${cfg.version}
|
||||
* @email "mailto:${author}@fkhwl.com"
|
||||
* @date ${cfg.date}
|
||||
* @since ${cfg.version}
|
||||
*/
|
||||
@Slf4j
|
||||
@FkhTest
|
||||
public class ${cfg.model_name}ApplicationTest {
|
||||
/**
|
||||
* Set up
|
||||
*
|
||||
* @since ${cfg.version}
|
||||
*/
|
||||
@BeforeEach
|
||||
void setUp(){
|
||||
log.info("start ${cfg.model_name}Application test");
|
||||
}
|
||||
|
||||
/**
|
||||
* Tear down
|
||||
*
|
||||
* @since ${cfg.version}
|
||||
*/
|
||||
@AfterEach
|
||||
void tearDown(){
|
||||
log.info("end ${cfg.model_name}Application test");
|
||||
}
|
||||
|
||||
/**
|
||||
* Test
|
||||
*
|
||||
* @since ${cfg.version}
|
||||
*/
|
||||
@Test
|
||||
void test() {
|
||||
log.info("{}", SpringContext.getApplicationContext().getEnvironment().getProperty(ConfigKey.SpringConfigKey.APPLICATION_NAME));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
server:
|
||||
port: 0
|
||||
|
||||
spring:
|
||||
profiles:
|
||||
active: $!{profile_active}
|
||||
@@ -0,0 +1,6 @@
|
||||
server:
|
||||
port: 0
|
||||
|
||||
spring:
|
||||
profiles:
|
||||
active: ${profile_active}
|
||||
@@ -0,0 +1,96 @@
|
||||
package $!{package.Controller};
|
||||
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.fkhwl.starter.basic.Result;
|
||||
import com.fkhwl.starter.rest.ServletController;
|
||||
import com.fkhwl.starter.rest.annotation.RestControllerWrapper;
|
||||
|
||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import io.swagger.annotations.ApiParam;
|
||||
import lombok.AllArgsConstructor;
|
||||
import $!{package.Entity}.dto.$!{entity}DTO;
|
||||
import $!{package.Entity}.form.$!{entity}Query;
|
||||
import $!{package.Entity}.vo.$!{entity}VO;
|
||||
import $!{package.Service}.$!{table.serviceName};
|
||||
#set($wrapperPackage=$package.Entity.replace("entity","converter"))
|
||||
import $!{wrapperPackage}.$!{entity}ViewConverter;
|
||||
|
||||
/**
|
||||
* <p>Company: 成都返空汇网络技术有限公司</p>
|
||||
* <p>Description: $!{table.comment} 控制器 </p>
|
||||
*
|
||||
* @author ${author}
|
||||
* @version ${cfg.version}
|
||||
* @email "mailto:${author}@fkhwl.com"
|
||||
* @date ${cfg.date}
|
||||
* @since ${cfg.version}
|
||||
*/
|
||||
@AllArgsConstructor
|
||||
@RestControllerWrapper
|
||||
@Api(value = "$!{table.comment}", tags = "$!{table.comment}接口")
|
||||
public class $!{table.controllerName} extends $!{superControllerClass} {
|
||||
|
||||
/** $!{entity} service */
|
||||
private final $!{table.serviceName} $!{table.entityPath}Service;
|
||||
|
||||
/**
|
||||
* 分页查询方式 1
|
||||
*
|
||||
* @param query the query
|
||||
* @return the result
|
||||
* @since ${cfg.version}
|
||||
*/
|
||||
@GetMapping("/$!{table.entityPath}s/page_1")
|
||||
@ApiOperation(value = "分页查询实现方式 1", notes = " $!{table.entityPath} 查询条件")
|
||||
public IPage<$!{entity}VO> pages1($!{entity}Query query) {
|
||||
IPage<$!{entity}DTO> page = this.$!{table.entityPath}Service.page(query);
|
||||
return page.convert($!{entity}ViewConverter.INSTANCE::vo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页查询方式 2
|
||||
*
|
||||
* @param query query
|
||||
* @return the result
|
||||
* @since ${cfg.version}
|
||||
*/
|
||||
@GetMapping("/$!{table.entityPath}s/page_2")
|
||||
@ApiOperation(value = "分页查询实现方式 2", notes = " $!{table.entityPath} 查询条件")
|
||||
public IPage<$!{entity}VO> pages2($!{entity}Query query) {
|
||||
IPage<$!{entity}DTO> page = this.$!{table.entityPath}Service.page(query);
|
||||
return $!{entity}ViewConverter.INSTANCE.vo(page);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据条件查询全部数据
|
||||
*
|
||||
* @return the result
|
||||
* @since ${cfg.version}
|
||||
*/
|
||||
@GetMapping("/$!{table.entityPath}s/list")
|
||||
@ApiOperation(value = "获取所有 $!{table.entityPath} 集合")
|
||||
public List<$!{entity}VO> list($!{entity}Query query) {
|
||||
List<$!{entity}DTO> list = this.$!{table.entityPath}Service.list(query);
|
||||
return $!{entity}ViewConverter.INSTANCE.vo(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量删除
|
||||
*
|
||||
* @param user 参数
|
||||
* @return the result
|
||||
* @since ${cfg.version}
|
||||
*/
|
||||
@DeleteMapping
|
||||
@ApiOperation(value = "删除", notes = "传入 ids")
|
||||
public Result<Void> remove(@ApiParam(value = "主键集合", required = true) @RequestBody List<Long> ids) {
|
||||
return this.$!{table.entityPath}Service.removeByIds(ids) ? this.ok() : this.fail("批量删除失败");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user