1,有时我们在启动项目的时候配置了program arguments但是却读取不到,这时用下面的方式启动则可以,我把所有的相关代码都放在了下面,如果觉得没有用的大家可在自己的项目中删除,只是项目启动的时候有点变化
启动主方法
@MapperScan({ "com.kidy.mapper" })
@SpringBootApplication
public class RunApplication {
public static void main(String[] args) {
startApplication.run("login",RunApplication.class, args);// startApplication 这个类就是我们新建的启动类
}
}
package com.kidy;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.env.*;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
public class startApplication {
public static ConfigurableApplicationContext run(String appName, Class source, String... args) {
SpringApplicationBuilder builder = createSpringApplicationBuilder(appName, source, args);
return builder.run(args);
}
public static SpringApplicationBuilder createSpringApplicationBuilder(String appName, Class source, String... args) {
Assert.hasText(appName, "[appName]服务名不能为空");
// 读取环境变量,使用spring boot的规则
ConfigurableEnvironment environment = new StandardEnvironment();
MutablePropertySources propertySources = environment.getPropertySources();
propertySources.addFirst(new SimpleCommandLinePropertySource(args));
propertySources.addLast(new MapPropertySource(StandardEnvironment.SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME, environment.getSystemProperties()));
propertySources.addLast(new SystemEnvironmentPropertySource(StandardEnvironment.SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME, environment.getSystemEnvironment()));
// 获取配置的环境变量
String[] activeProfiles = environment.getActiveProfiles();
// 判断环境:dev、test、prod
List<String> profiles = Arrays.asList(activeProfiles);
// 预设的环境
List<String> presetProfiles = new ArrayList<>(Arrays.asList(AppConstant.DEV_CODE, AppConstant.SIT_CODE, AppConstant.TEST_CODE, AppConstant.PROD_CODE));
// 交集
presetProfiles.retainAll(profiles);
// 当前使用
List<String> activeProfileList = new ArrayList<>(profiles);
Function<Object[], String> joinFun = StringUtils::arrayToCommaDelimitedString;
SpringApplicationBuilder builder = new SpringApplicationBuilder(source);
String profile;
if (activeProfileList.isEmpty()) {
// 默认dev开发
profile = AppConstant.DEV_CODE;
activeProfileList.add(profile);
builder.profiles(profile);
} else if (activeProfileList.size() == 1) {
profile = activeProfileList.get(0);
builder.profiles(profile);
} else {
// 同时存在dev、test、prod环境时
throw new RuntimeException("同时存在环境变量:[" + StringUtils.arrayToCommaDelimitedString(activeProfiles) + "]");
}
String startJarPath = startApplication.class.getResource("/").getPath().split("!")[0];
String activePros = joinFun.apply(activeProfileList.toArray());
System.out.printf("----启动中,读取到的环境变量:[%s],jar地址:[%s]----%n", activePros, startJarPath);
Properties props = System.getProperties();
props.setProperty("spring.application.name", appName);
props.setProperty("spring.profiles.active", profile);
props.setProperty("info.version", AppConstant.APPLICATION_VERSION);
props.setProperty("info.desc", appName);
props.setProperty("file.encoding", StandardCharsets.UTF_8.name());
props.setProperty("compass-report.env", profile);
props.setProperty("compass-report.name", appName);
props.setProperty("compass-report.is-local", String.valueOf(isLocalDev()));
props.setProperty("compass-report.dev-mode", profile.equals(AppConstant.PROD_CODE) ? "false" : "true");
props.setProperty("compass-report.service.version", AppConstant.APPLICATION_VERSION);
Properties defaultProperties = new Properties();
defaultProperties.setProperty("spring.main.allow-bean-definition-overriding", "true");
defaultProperties.setProperty("spring.sleuth.sampler.percentage", "1.0");
defaultProperties.setProperty("spring.cloud.alibaba.seata.tx-service-group", appName.concat(NacosConstant.NACOS_GROUP_SUFFIX));
defaultProperties.setProperty("spring.cloud.nacos.config.file-extension", NacosConstant.NACOS_CONFIG_FORMAT);
defaultProperties.setProperty("spring.cloud.nacos.config.shared-configs[0].data-id", NacosConstant.sharedDataId());
defaultProperties.setProperty("spring.cloud.nacos.config.shared-configs[0].group", NacosConstant.NACOS_CONFIG_GROUP);
defaultProperties.setProperty("spring.cloud.nacos.config.shared-configs[0].refresh", NacosConstant.NACOS_CONFIG_REFRESH);
defaultProperties.setProperty("spring.cloud.nacos.config.shared-configs[1].data-id", NacosConstant.sharedDataId(profile));
defaultProperties.setProperty("spring.cloud.nacos.config.shared-configs[1].group", NacosConstant.NACOS_CONFIG_GROUP);
defaultProperties.setProperty("spring.cloud.nacos.config.shared-configs[1].refresh", NacosConstant.NACOS_CONFIG_REFRESH);
builder.properties(defaultProperties);
// 加载自定义组件
List<LauncherService> launcherList = new ArrayList<>();
ServiceLoader.load(LauncherService.class).forEach(launcherList::add);
launcherList.stream().sorted(Comparator.comparing(LauncherService::getOrder)).collect(Collectors.toList())
.forEach(launcherService -> launcherService.launcher(builder, appName, profile, isLocalDev()));
return builder;
}
public static boolean isLocalDev() {
String osName = System.getProperty("os.name");
return StringUtils.hasText(osName) && !(AppConstant.OS_NAME_LINUX.equalsIgnoreCase(osName));
}
}
2,下面都是启动类关联的类,亲测有效
/*
* Copyright (c) 2018-2028, DreamLu All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the dreamlu.net developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*/
package com.kidy;
import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.RoundEnvironment;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.Element;
import javax.lang.model.element.TypeElement;
import javax.tools.Diagnostic.Kind;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Set;
/**
* 抽象 处理器
*
* @author L.cm
*/
public abstract class AbstractBladeProcessor extends AbstractProcessor {
@Override
public SourceVersion getSupportedSourceVersion() {
return SourceVersion.latestSupported();
}
/**
* AutoService 注解处理器
* @param annotations 注解 getSupportedAnnotationTypes
* @param roundEnv 扫描到的 注解新
* @return 是否完成
*/
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
try {
return processImpl(annotations, roundEnv);
} catch (Exception e) {
fatalError(e);
return false;
}
}
protected abstract boolean processImpl(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv);
protected void log(String msg) {
if (processingEnv.getOptions().containsKey("debug")) {
processingEnv.getMessager().printMessage(Kind.NOTE, msg);
}
}
protected void error(String msg, Element element, AnnotationMirror annotation) {
processingEnv.getMessager().printMessage(Kind.ERROR, msg, element, annotation);
}
protected void fatalError(Exception e) {
// We don't allow exceptions of any kind to propagate to the compiler
StringWriter writer = new StringWriter();
e.printStackTrace(new PrintWriter(writer));
fatalError(writer.toString());
}
protected void fatalError(String msg) {
processingEnv.getMessager().printMessage(Kind.ERROR, "FATAL ERROR: " + msg);
}
}
///
/*
* Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the dreamlu.net developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: Chill 庄骞 (smallchill@163.com)
*/
package com.kidy;
/**
* 系统常量
*
* @author Chill
*/
public interface AppConstant {
/**
* 应用版本
*/
String APPLICATION_VERSION = "2.8.0.RELEASE";
/**
* 基础包
*/
String BASE_PACKAGES = "org.springblade";
/**
* 应用名前缀
*/
String APPLICATION_NAME_PREFIX = "pmo-";
/**
* 网关模块名称
*/
String APPLICATION_GATEWAY_NAME = APPLICATION_NAME_PREFIX + "gateway";
/**
* 授权模块名称
*/
String APPLICATION_AUTH_NAME = APPLICATION_NAME_PREFIX + "auth";
/**
* 监控模块名称
*/
String APPLICATION_ADMIN_NAME = APPLICATION_NAME_PREFIX + "admin";
/**
* 报表系统名称
*/
String APPLICATION_REPORT_NAME = APPLICATION_NAME_PREFIX + "report";
/**
* 集群监控名称
*/
String APPLICATION_TURBINE_NAME = APPLICATION_NAME_PREFIX + "turbine";
/**
* 链路追踪名称
*/
String APPLICATION_ZIPKIN_NAME = APPLICATION_NAME_PREFIX + "zipkin";
/**
* websocket名称
*/
String APPLICATION_WEBSOCKET_NAME = APPLICATION_NAME_PREFIX + "websocket";
/**
* 首页模块名称
*/
String APPLICATION_DESK_NAME = APPLICATION_NAME_PREFIX + "desk";
/**
* 系统模块名称
*/
String APPLICATION_SYSTEM_NAME = APPLICATION_NAME_PREFIX + "system";
/**
* 用户模块名称
*/
String APPLICATION_USER_NAME = APPLICATION_NAME_PREFIX + "user";
/**
* 租户模块名称
*/
String APPLICATION_TENANT_NAME = APPLICATION_NAME_PREFIX +"tenant";
/**
* 日志模块名称
*/
String APPLICATION_LOG_NAME = APPLICATION_NAME_PREFIX + "log";
/**
* 开发模块名称
*/
String APPLICATION_DEVELOP_NAME = APPLICATION_NAME_PREFIX + "develop";
/**
* 流程设计器模块名称
*/
String APPLICATION_FLOWDESIGN_NAME = APPLICATION_NAME_PREFIX + "flowdesign";
/**
* 工作流模块名称
*/
String APPLICATION_FLOW_NAME = APPLICATION_NAME_PREFIX + "flow";
/**
* 资源模块名称
*/
String APPLICATION_RESOURCE_NAME = APPLICATION_NAME_PREFIX + "resource";
/**
* 接口文档模块名称
*/
String APPLICATION_SWAGGER_NAME = APPLICATION_NAME_PREFIX + "swagger";
/**
* 测试模块名称
*/
String APPLICATION_TEST_NAME = APPLICATION_NAME_PREFIX + "test";
/**
* 演示模块名称
*/
String APPLICATION_DEMO_NAME = APPLICATION_NAME_PREFIX + "demo";
/**
* cad模块名称
*/
String APPLICATION_CAD_NAME = APPLICATION_NAME_PREFIX + "cad";
/**
* 开发环境
*/
String DEV_CODE = "dev";
/**
* 生产环境
*/
String PROD_CODE = "prod";
/**
* 测试环境
*/
String TEST_CODE = "test";
/**
* 测试环境
*/
String SIT_CODE = "sit";
/**
* 代码部署于 linux 上,工作默认为 mac 和 Windows
*/
String OS_NAME_LINUX = "LINUX";
}
///
/*
* Copyright (c) 2018-2028, DreamLu All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the dreamlu.net developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*/
package com.kidy;
import java.lang.annotation.*;
/**
* An annotation for service providers as described in {@link java.util.ServiceLoader}. The {@link
* AutoServiceProcessor} generates the configuration files which
* allows service providers to be loaded with {@link java.util.ServiceLoader#load(Class)}.
*
* <p>Service providers assert that they conform to the service provider specification.
* Specifically, they must:
*
* <ul>
* <li>be a non-inner, non-anonymous, concrete class
* <li>have a publicly accessible no-arg constructor
* <li>implement the interface type returned by {@code value()}
* </ul>
*
* @author google
*/
@Documented
@Retention(RetentionPolicy.SOURCE)
@Target(ElementType.TYPE)
public @interface AutoService {
/**
* Returns the interfaces implemented by this service provider.
*
* @return interface array
*/
Class<?>[] value();
}
///
/*
* Copyright (c) 2018-2028, DreamLu All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the dreamlu.net developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: DreamLu 卢春梦 (596392912@qq.com)
*/
package com.kidy;
import javax.annotation.processing.Filer;
import javax.annotation.processing.ProcessingEnvironment;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedOptions;
import javax.lang.model.element.*;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.util.ElementFilter;
import javax.lang.model.util.Elements;
import javax.lang.model.util.SimpleAnnotationValueVisitor8;
import javax.lang.model.util.Types;
import javax.tools.FileObject;
import javax.tools.StandardLocation;
import java.io.IOException;
import java.io.OutputStream;
import java.lang.annotation.Annotation;
import java.util.*;
import java.util.stream.Collectors;
/**
* java spi 服务自动处理器 参考:google auto
*
* @author L.cm
*/
@SupportedOptions("debug")
public class AutoServiceProcessor extends AbstractBladeProcessor {
/**
* spi 服务集合,key 接口 -> value 实现列表
*/
private final MultiSetMap<String, String> providers = new MultiSetMap<>();
private TypeHelper typeHelper;
@Override
public synchronized void init(ProcessingEnvironment env) {
super.init(env);
this.typeHelper = new TypeHelper(env);
}
@Override
public Set<String> getSupportedAnnotationTypes() {
return Sets.ofImmutableSet(AutoService.class.getName());
}
@Override
protected boolean processImpl(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
if (roundEnv.processingOver()) {
generateConfigFiles();
} else {
processAnnotations(annotations, roundEnv);
}
return true;
}
private void processAnnotations(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
Set<? extends Element> elements = roundEnv.getElementsAnnotatedWith(AutoService.class);
log(annotations.toString());
log(elements.toString());
for (Element e : elements) {
TypeElement providerImplementer = (TypeElement) e;
AnnotationMirror annotationMirror = getAnnotationMirror(e, AutoService.class);
if (annotationMirror == null) {
continue;
}
Set<TypeMirror> typeMirrors = getValueFieldOfClasses(annotationMirror);
if (typeMirrors.isEmpty()) {
error("No service interfaces provided for element!", e, annotationMirror);
continue;
}
for (TypeMirror typeMirror : typeMirrors) {
String providerInterfaceName = typeHelper.getType(typeMirror);
Name providerImplementerName = providerImplementer.getQualifiedName();
log("provider interface: " + providerInterfaceName);
log("provider implementer: " + providerImplementerName);
if (checkImplementer(providerImplementer, typeMirror)) {
providers.put(providerInterfaceName, typeHelper.getType(providerImplementer));
} else {
String message = "ServiceProviders must implement their service provider interface. "
+ providerImplementerName + " does not implement " + providerInterfaceName;
error(message, e, annotationMirror);
}
}
}
}
private void generateConfigFiles() {
Filer filer = processingEnv.getFiler();
for (String providerInterface : providers.keySet()) {
String resourceFile = "META-INF/services/" + providerInterface;
log("Working on resource file: " + resourceFile);
try {
SortedSet<String> allServices = new TreeSet<>();
try {
FileObject existingFile = filer.getResource(StandardLocation.CLASS_OUTPUT, "", resourceFile);
log("Looking for existing resource file at " + existingFile.toUri());
Set<String> oldServices = ServicesFiles.readServiceFile(existingFile.openInputStream());
log("Existing service entries: " + oldServices);
allServices.addAll(oldServices);
} catch (IOException e) {
log("Resource file did not already exist.");
}
Set<String> newServices = new HashSet<>(providers.get(providerInterface));
if (allServices.containsAll(newServices)) {
log("No new service entries being added.");
return;
}
allServices.addAll(newServices);
log("New service file contents: " + allServices);
FileObject fileObject = filer.createResource(StandardLocation.CLASS_OUTPUT, "", resourceFile);
OutputStream out = fileObject.openOutputStream();
ServicesFiles.writeServiceFile(allServices, out);
out.close();
log("Wrote to: " + fileObject.toUri());
} catch (IOException e) {
fatalError("Unable to create " + resourceFile + ", " + e);
return;
}
}
}
/**
* Verifies {@link java.util.spi.LocaleServiceProvider} constraints on the concrete provider class.
* Note that these constraints are enforced at runtime via the ServiceLoader,
* we're just checking them at compile time to be extra nice to our users.
*/
private boolean checkImplementer(TypeElement providerImplementer, TypeMirror providerType) {
// TODO: We're currently only enforcing the subtype relationship
// constraint. It would be nice to enforce them all.
Types types = processingEnv.getTypeUtils();
return types.isSubtype(providerImplementer.asType(), providerType);
}
/**
* 读取 AutoService 上的 value 值
*
* @param annotationMirror AnnotationMirror
* @return value 集合
*/
private Set<TypeMirror> getValueFieldOfClasses(AnnotationMirror annotationMirror) {
return getAnnotationValue(annotationMirror, "value")
.accept(new SimpleAnnotationValueVisitor8<Set<TypeMirror>, Void>() {
@Override
public Set<TypeMirror> visitType(TypeMirror typeMirror, Void v) {
Set<TypeMirror> declaredTypeSet = new HashSet<>(1);
declaredTypeSet.add(typeMirror);
return Collections.unmodifiableSet(declaredTypeSet);
}
@Override
public Set<TypeMirror> visitArray(
List<? extends AnnotationValue> values, Void v) {
return values
.stream()
.flatMap(value -> value.accept(this, null).stream())
.collect(Collectors.toSet());
}
}, null);
}
/**
* Returns a {@link ExecutableElement} and its associated {@link AnnotationValue} if such
* an element was either declared in the usage represented by the provided
* {@link AnnotationMirror}, or if such an element was defined with a default.
*
* @param annotationMirror AnnotationMirror
* @param elementName elementName
* @return AnnotationValue map
* @throws IllegalArgumentException if no element is defined with the given elementName.
*/
public AnnotationValue getAnnotationValue(AnnotationMirror annotationMirror, String elementName) {
Objects.requireNonNull(annotationMirror);
Objects.requireNonNull(elementName);
for (Map.Entry<ExecutableElement, AnnotationValue> entry : getAnnotationValuesWithDefaults(annotationMirror).entrySet()) {
if (entry.getKey().getSimpleName().contentEquals(elementName)) {
return entry.getValue();
}
}
String name = typeHelper.getType(annotationMirror);
throw new IllegalArgumentException(String.format("@%s does not define an element %s()", name, elementName));
}
/**
* Returns the {@link AnnotationMirror}'s map of {@link AnnotationValue} indexed by {@link
* ExecutableElement}, supplying default values from the annotation if the annotation property has
* not been set. This is equivalent to {@link
* Elements#getElementValuesWithDefaults(AnnotationMirror)} but can be called statically without
* an {@link Elements} instance.
*
* <p>The iteration order of elements of the returned map will be the order in which the {@link
* ExecutableElement}s are defined in {@code annotation}'s {@linkplain
* AnnotationMirror#getAnnotationType() type}.
*
* @param annotation AnnotationMirror
* @return AnnotationValue Map
*/
public Map<ExecutableElement, AnnotationValue> getAnnotationValuesWithDefaults(AnnotationMirror annotation) {
Map<ExecutableElement, AnnotationValue> values = new HashMap<>(32);
Map<? extends ExecutableElement, ? extends AnnotationValue> declaredValues = annotation.getElementValues();
for (ExecutableElement method : ElementFilter.methodsIn(annotation.getAnnotationType().asElement().getEnclosedElements())) {
// Must iterate and put in this order, to ensure consistency in generated code.
if (declaredValues.containsKey(method)) {
values.put(method, declaredValues.get(method));
} else if (method.getDefaultValue() != null) {
values.put(method, method.getDefaultValue());
} else {
String name = typeHelper.getType(method);
throw new IllegalStateException(
"Unset annotation value without default should never happen: " + name + '.' + method.getSimpleName() + "()");
}
}
return Collections.unmodifiableMap(values);
}
public AnnotationMirror getAnnotationMirror(Element element, Class<? extends Annotation> annotationClass) {
String annotationClassName = annotationClass.getCanonicalName();
for (AnnotationMirror annotationMirror : element.getAnnotationMirrors()) {
String name = typeHelper.getType(annotationMirror);
if (name.contentEquals(annotationClassName)) {
return annotationMirror;
}
}
return null;
}
}
///
/*
* Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the dreamlu.net developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: Chill 庄骞 (smallchill@163.com)
*/
package com.kidy;
import static com.kidy.AppConstant.APPLICATION_NAME_PREFIX;
/**
* 启动常量
*
* @author Chill
*/
public interface LauncherConstant {
/**
* xxljob
*/
String APPLICATION_XXLJOB_NAME = APPLICATION_NAME_PREFIX + "xxljob";
/**
* xxljob
*/
String APPLICATION_XXLJOB_ADMIN_NAME = APPLICATION_NAME_PREFIX + "xxljob-admin";
/**
* nacos dev 地址
*/
String NACOS_DEV_ADDR = "mse-dc15a0b6-nacos-ans.mse.aliyuncs.com:8848";
/**
* nacos prod 地址
*/
String NACOS_PROD_ADDR = "mse-04d46bb6-nacos-ans.mse.aliyuncs.com:8848";
/**
* nacos test 地址
*/
String NACOS_TEST_ADDR = "mse-dc15a0b6-nacos-ans.mse.aliyuncs.com:8848";
/**
* nacos SIT 地址
*/
String NACOS_SIT_ADDR = "mse-dc15a0b6-nacos-ans.mse.aliyuncs.com:8848";
/**
* sentinel dev 地址
*/
String SENTINEL_DEV_ADDR = "127.0.0.1:8858";
/**
* sentinel prod 地址
*/
String SENTINEL_PROD_ADDR = "127.0.0.1:8858";
/**
* sentinel test 地址
*/
String SENTINEL_TEST_ADDR = "127.0.0.1:8858";
/**
* seata dev 地址
*/
String SEATA_DEV_ADDR = "127.0.0.1:8091";
/**
* seata prod 地址
*/
String SEATA_PROD_ADDR = "127.0.0.1:8091";
/**
* seata test 地址
*/
String SEATA_TEST_ADDR = "127.0.0.1:8091";
/**
* zipkin dev 地址
*/
String ZIPKIN_DEV_ADDR = "http://127.0.0.1:9411";
/**
* zipkin prod 地址
*/
String ZIPKIN_PROD_ADDR = "http://127.0.0.1:9411";
/**
* zipkin test 地址
*/
String ZIPKIN_TEST_ADDR = "http://127.0.0.1:9411";
/**
* elk dev 地址
*/
String ELK_DEV_ADDR = "127.0.0.1:9000";
/**
* elk prod 地址
*/
String ELK_PROD_ADDR = "127.0.0.1:9000";
/**
* elk test 地址
*/
String ELK_TEST_ADDR = "127.0.0.1:9000";
/**
* seata file模式
*/
String FILE_MODE = "file";
/**
* seata nacos模式
*/
String NACOS_MODE = "nacos";
/**
* seata default模式
*/
String DEFAULT_MODE = "default";
/**
* seata group后缀
*/
String GROUP_NAME = "-group";
/**
* seata 服务组格式
*
* @param appName 服务名
* @return group
*/
static String seataServiceGroup(String appName) {
return appName.concat(GROUP_NAME);
}
/**
* 动态获取nacos地址
*
* @param profile 环境变量
* @return addr
*/
static String nacosAddr(String profile) {
switch (profile) {
case (AppConstant.PROD_CODE):
return NACOS_PROD_ADDR;
case (AppConstant.SIT_CODE):
return NACOS_SIT_ADDR;
case (AppConstant.TEST_CODE):
return NACOS_TEST_ADDR;
default:
return NACOS_DEV_ADDR;
}
}
/**
* 获取 nacos的
* @param profile
* @return
*/
static String nacosNamespace(String profile){
switch (profile) {
case (AppConstant.PROD_CODE):
return "8694d67f-b81d-4780-a9c8-9033d0e479cb";
case (AppConstant.SIT_CODE):
return "8694d67f-b81d-4780-a9c8-9033d0e479cb";
case (AppConstant.TEST_CODE):
return "8694d67f-b81d-4780-a9c8-9033d0e479cb";
default:
return "8694d67f-b81d-4780-a9c8-9033d0e479cb";
}
}
/**
* 获取 nacos的 group地址
* @param profile
* @return
*/
static String nacosGroup(String profile){
switch (profile) {
case (AppConstant.PROD_CODE):
return "compass-prod";
case (AppConstant.SIT_CODE):
return "compass-sit";
case (AppConstant.TEST_CODE):
return "compass-sit";
default:
return "compass-sit";
}
}
/**
* 动态获取sentinel地址
*
* @param profile 环境变量
* @return addr
*/
static String sentinelAddr(String profile) {
switch (profile) {
case (AppConstant.PROD_CODE):
return SENTINEL_PROD_ADDR;
case (AppConstant.TEST_CODE):
return SENTINEL_TEST_ADDR;
default:
return SENTINEL_DEV_ADDR;
}
}
/**
* 动态获取seata地址
*
* @param profile 环境变量
* @return addr
*/
static String seataAddr(String profile) {
switch (profile) {
case (AppConstant.PROD_CODE):
return SEATA_PROD_ADDR;
case (AppConstant.TEST_CODE):
return SEATA_TEST_ADDR;
default:
return SEATA_DEV_ADDR;
}
}
/**
* 动态获取zipkin地址
*
* @param profile 环境变量
* @return addr
*/
static String zipkinAddr(String profile) {
switch (profile) {
case (AppConstant.PROD_CODE):
return ZIPKIN_PROD_ADDR;
case (AppConstant.TEST_CODE):
return ZIPKIN_TEST_ADDR;
default:
return ZIPKIN_DEV_ADDR;
}
}
/**
* 动态获取elk地址
*
* @param profile 环境变量
* @return addr
*/
static String elkAddr(String profile) {
switch (profile) {
case (AppConstant.PROD_CODE):
return ELK_PROD_ADDR;
case (AppConstant.TEST_CODE):
return ELK_TEST_ADDR;
default:
return ELK_DEV_ADDR;
}
}
}
///
/*
* Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the dreamlu.net developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*/
package com.kidy;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.core.Ordered;
/**
* launcher 扩展 用于一些组件发现
*
* @author Chill
*/
public interface LauncherService extends Ordered, Comparable<LauncherService> {
/**
* 启动时 处理 SpringApplicationBuilder
*
* @param builder SpringApplicationBuilder
* @param appName SpringApplicationAppName
* @param profile SpringApplicationProfile
* @param isLocalDev SpringApplicationIsLocalDev
*/
void launcher(SpringApplicationBuilder builder, String appName, String profile, boolean isLocalDev);
/**
* 获取排列顺序
*
* @return order
*/
@Override
default int getOrder() {
return 0;
}
/**
* 对比排序
*
* @param o LauncherService
* @return compare
*/
@Override
default int compareTo(LauncherService o) {
return Integer.compare(this.getOrder(), o.getOrder());
}
}
///
/*
* Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the dreamlu.net developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: Chill 庄骞 (smallchill@163.com)
*/
package com.kidy;
import org.springframework.boot.builder.SpringApplicationBuilder;
import java.util.Properties;
/**
* 启动参数拓展
*
* @author smallchil
*/
@AutoService(LauncherService.class)
public class LauncherServiceImpl implements LauncherService {
@Override
public void launcher(SpringApplicationBuilder builder, String appName, String profile, boolean isLocalDev) {
Properties props = System.getProperties();
// 通用注册
PropsUtil.setProperty(props, "spring.cloud.nacos.discovery.server-addr", LauncherConstant.nacosAddr(profile));
PropsUtil.setProperty(props, "spring.cloud.nacos.config.server-addr", LauncherConstant.nacosAddr(profile));
PropsUtil.setProperty(props, "spring.cloud.sentinel.transport.dashboard", LauncherConstant.sentinelAddr(profile));
PropsUtil.setProperty(props, "spring.zipkin.base-url", LauncherConstant.zipkinAddr(profile));
PropsUtil.setProperty(props, "spring.datasource.dynamic.enabled", "false");
// nacos配置命名空间和分组
PropsUtil.setProperty(props, "spring.cloud.nacos.config.namespace", LauncherConstant.nacosNamespace(profile));//d6daf259-bd8d-4e95-841e-7ec6c10cbcc6
//PropsUtil.setProperty(props, "spring.cloud.nacos.config.group", LauncherConstant.nacosGroup(profile));//DEV_GROUP
// nacos注册服务命名空间和分组
PropsUtil.setProperty(props, "spring.cloud.nacos.discovery.namespace", LauncherConstant.nacosNamespace(profile)); //d6daf259-bd8d-4e95-841e-7ec6c10cbcc6
//PropsUtil.setProperty(props, "spring.cloud.nacos.discovery.group", LauncherConstant.nacosGroup(profile)); //DEV_GROUP
// 开启elk日志
// PropsUtil.setProperty(props, "blade.log.elk.destination", LauncherConstant.elkAddr(profile));
// seata注册地址
// PropsUtil.setProperty(props, "seata.service.grouplist.default", LauncherConstant.seataAddr(profile));
// seata注册group格式
// PropsUtil.setProperty(props, "seata.tx-service-group", LauncherConstant.seataServiceGroup(appName));
// seata配置服务group
// PropsUtil.setProperty(props, "seata.service.vgroup-mapping.".concat(LauncherConstant.seataServiceGroup(appName)), LauncherConstant.DEFAULT_MODE);
// seata注册模式配置
// PropsUtil.setProperty(props, "seata.registry.type", LauncherConstant.NACOS_MODE);
// PropsUtil.setProperty(props, "seata.registry.nacos.server-addr", LauncherConstant.nacosAddr(profile));
// PropsUtil.setProperty(props, "seata.config.type", LauncherConstant.NACOS_MODE);
// PropsUtil.setProperty(props, "seata.config.nacos.server-addr", LauncherConstant.nacosAddr(profile));
}
}
///
/*
* Copyright (c) 2018-2028, DreamLu All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the dreamlu.net developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*/
package com.kidy;
import java.util.*;
/**
* MultiSetMap
*
* @author L.cm
*/
public class MultiSetMap<K, V> {
private transient final Map<K, Set<V>> map;
public MultiSetMap() {
map = new HashMap<>();
}
private Set<V> createSet() {
return new HashSet<>();
}
/**
* put to MultiSetMap
*
* @param key 键
* @param value 值
* @return boolean
*/
public boolean put(K key, V value) {
Set<V> set = map.get(key);
if (set == null) {
set = createSet();
if (set.add(value)) {
map.put(key, set);
return true;
} else {
throw new AssertionError("New set violated the set spec");
}
} else if (set.add(value)) {
return true;
} else {
return false;
}
}
/**
* 是否包含某个key
*
* @param key key
* @return 结果
*/
public boolean containsKey(K key) {
return map.containsKey(key);
}
/**
* 是否包含 value 中的某个值
*
* @param value value
* @return 是否包含
*/
public boolean containsVal(V value) {
Collection<Set<V>> values = map.values();
return values.stream().anyMatch(vs -> vs.contains(value));
}
/**
* key 集合
*
* @return keys
*/
public Set<K> keySet() {
return map.keySet();
}
/**
* put list to MultiSetMap
*
* @param key 键
* @param set 值列表
* @return boolean
*/
public boolean putAll(K key, Set<V> set) {
if (set == null) {
return false;
} else {
map.put(key, set);
return true;
}
}
/**
* get List by key
*
* @param key 键
* @return List
*/
public Set<V> get(K key) {
return map.get(key);
}
/**
* clear MultiSetMap
*/
public void clear() {
map.clear();
}
/**
* isEmpty
*
* @return isEmpty
*/
public boolean isEmpty() {
return map.isEmpty();
}
}
///
/*
* Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the dreamlu.net developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: Chill 庄骞 (smallchill@163.com)
*/
package com.kidy;
/**
* Nacos常量.
*
* @author Chill
*/
public interface NacosConstant {
/**
* nacos 地址
*/
String NACOS_ADDR = "127.0.0.1:8848";
/**
* nacos 配置前缀
*/
String NACOS_CONFIG_PREFIX = "compass-upms";
/**
* nacos 配置前缀 compass-upms
*/
String NACOS_CONFIG_COMPASS_PREFIX = "compass-upms";
/**
* nacos 组配置后缀
*/
String NACOS_GROUP_SUFFIX = "-group";
/**
* nacos 配置文件类型
*/
String NACOS_CONFIG_FORMAT = "yaml";
/**
* nacos json配置文件类型
*/
String NACOS_CONFIG_JSON_FORMAT = "json";
/**
* nacos 是否刷新
*/
String NACOS_CONFIG_REFRESH = "true";
/**
* nacos 分组
*/
String NACOS_CONFIG_GROUP = "DEFAULT_GROUP";
/**
* seata 分组
*/
String NACOS_SEATA_GROUP = "SEATA_GROUP";
/**
* 构建服务对应的 dataId
*
* @param appName 服务名
* @return dataId
*/
static String dataId(String appName) {
return appName + "." + NACOS_CONFIG_FORMAT;
}
/**
* 构建服务对应的 dataId
*
* @param appName 服务名
* @param profile 环境变量
* @return dataId
*/
static String dataId(String appName, String profile) {
return dataId(appName, profile, NACOS_CONFIG_FORMAT);
}
/**
* 构建服务对应的 dataId
*
* @param appName 服务名
* @param profile 环境变量
* @param format 文件类型
* @return dataId
*/
static String dataId(String appName, String profile, String format) {
return appName + "-" + profile + "." + format;
}
/**
* 服务默认加载的配置
*
* @return sharedDataIds
*/
static String sharedDataId() {
return NACOS_CONFIG_PREFIX + "." + NACOS_CONFIG_FORMAT;
}
/**
* 服务默认加载的配置
*
* @return sharedDataIds
*/
static String sharedDataId(String appName, String env) {
if (null == env || env.length() == 0) {
return appName + "." + NACOS_CONFIG_FORMAT;
}
return appName + "-" + env + "." + NACOS_CONFIG_FORMAT;
}
/**
* 服务默认加载的配置
*
* @param profile 环境变量
* @return sharedDataIds
*/
static String sharedDataId(String profile) {
return NACOS_CONFIG_PREFIX + "-" + profile + "." + NACOS_CONFIG_FORMAT;
}
/**
* 服务默认加载的配置
*
* @param profile 环境变量
* @return sharedDataIds
*/
static String sharedDataIds(String profile) {
return NACOS_CONFIG_PREFIX + "." + NACOS_CONFIG_FORMAT + "," + NACOS_CONFIG_PREFIX + "-" + profile + "." + NACOS_CONFIG_FORMAT;
}
}
///
/*
* Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the dreamlu.net developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*/
package com.kidy;
import org.springframework.util.StringUtils;
import java.util.Properties;
/**
* 配置工具类
*
* @author Chill
*/
public class PropsUtil {
/**
* 设置配置值,已存在则跳过
*
* @param props property
* @param key key
* @param value value
*/
public static void setProperty(Properties props, String key, String value) {
if (StringUtils.isEmpty(props.getProperty(key))) {
props.setProperty(key, value);
}
}
}
///
/*
* Copyright (c) 2018-2028, DreamLu All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the dreamlu.net developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*/
package com.kidy;
import java.io.*;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
/**
* A helper class for reading and writing Services files.
*
* @author L.cm
*/
class ServicesFiles {
private static final Charset UTF_8 = StandardCharsets.UTF_8;
/**
* Reads the set of service classes from a service file.
*
* @param input not {@code null}. Closed after use.
* @return a not {@code null Set} of service class names.
* @throws IOException
*/
static Set<String> readServiceFile(InputStream input) throws IOException {
HashSet<String> serviceClasses = new HashSet<>();
try (
InputStreamReader isr = new InputStreamReader(input, UTF_8);
BufferedReader r = new BufferedReader(isr)
) {
String line;
while ((line = r.readLine()) != null) {
int commentStart = line.indexOf('#');
if (commentStart >= 0) {
line = line.substring(0, commentStart);
}
line = line.trim();
if (!line.isEmpty()) {
serviceClasses.add(line);
}
}
return serviceClasses;
}
}
/**
* Writes the set of service class names to a service file.
*
* @param output not {@code null}. Not closed after use.
* @param services a not {@code null Collection} of service class names.
* @throws IOException
*/
static void writeServiceFile(Collection<String> services, OutputStream output) throws IOException {
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(output, UTF_8));
for (String service : services) {
writer.write(service);
writer.newLine();
}
writer.flush();
}
}
///
/*
* Copyright (c) 2018-2028, DreamLu All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the dreamlu.net developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*/
package com.kidy;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* 集合 工具类
*
* @author L.cm
*/
public class Sets {
/**
* 不可变 集合
*
* @param es 对象
* @param <E> 泛型
* @return 集合
*/
@SafeVarargs
public static <E> Set<E> ofImmutableSet(E... es) {
Objects.requireNonNull(es);
return Stream.of(es).collect(Collectors.toSet());
}
}
///
/*
* Copyright (c) 2018-2028, DreamLu All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the dreamlu.net developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*/
package com.kidy;
import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.Element;
import javax.lang.model.element.QualifiedNameable;
import javax.lang.model.element.TypeElement;
import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.util.Types;
import java.util.ArrayList;
import java.util.List;
/**
* Type utilities.
*
* @author Stephane Nicoll
* @since 5.0
*/
public class TypeHelper {
private final ProcessingEnvironment env;
private final Types types;
public TypeHelper(ProcessingEnvironment env) {
this.env = env;
this.types = env.getTypeUtils();
}
public String getType(Element element) {
return getType(element != null ? element.asType() : null);
}
public String getType(AnnotationMirror annotation) {
return getType(annotation != null ? annotation.getAnnotationType() : null);
}
public String getType(TypeMirror type) {
if (type == null) {
return null;
}
if (type instanceof DeclaredType) {
DeclaredType declaredType = (DeclaredType) type;
Element enclosingElement = declaredType.asElement().getEnclosingElement();
if (enclosingElement != null && enclosingElement instanceof TypeElement) {
return getQualifiedName(enclosingElement) + "$" + declaredType.asElement().getSimpleName().toString();
} else {
return getQualifiedName(declaredType.asElement());
}
}
return type.toString();
}
private String getQualifiedName(Element element) {
if (element instanceof QualifiedNameable) {
return ((QualifiedNameable) element).getQualifiedName().toString();
}
return element.toString();
}
/**
* Return the super class of the specified {@link Element} or null if this
* {@code element} represents {@link Object}.
*
* @param element Element
* @return Element
*/
public Element getSuperClass(Element element) {
List<? extends TypeMirror> superTypes = this.types.directSupertypes(element.asType());
if (superTypes.isEmpty()) {
// reached java.lang.Object
return null;
}
return this.types.asElement(superTypes.get(0));
}
/**
* Return the interfaces that are <strong>directly</strong> implemented by the
* specified {@link Element} or an empty list if this {@code element} does not
* implement any interface.
*
* @param element Element
* @return Element list
*/
public List<Element> getDirectInterfaces(Element element) {
List<? extends TypeMirror> superTypes = this.types.directSupertypes(element.asType());
List<Element> directInterfaces = new ArrayList<>();
// index 0 is the super class
if (superTypes.size() > 1) {
for (int i = 1; i < superTypes.size(); i++) {
Element e = this.types.asElement(superTypes.get(i));
if (e != null) {
directInterfaces.add(e);
}
}
}
return directInterfaces;
}
public List<? extends AnnotationMirror> getAllAnnotationMirrors(Element e) {
return this.env.getElementUtils().getAllAnnotationMirrors(e);
}
}