sms4j-solon-plugin:重新适配(同步 springboot 的适配代码)

This commit is contained in:
noear 2025-01-04 18:33:57 +08:00
parent 98e779376d
commit 49c5af9f70
9 changed files with 166 additions and 147 deletions

View File

@ -0,0 +1,17 @@
package org.dromara.sms4j.solon;
import org.dromara.sms4j.solon.config.SmsMainConfigure;
import org.dromara.sms4j.solon.config.SupplierConfigure;
import org.noear.solon.core.AppContext;
import org.noear.solon.core.Plugin;
/**
* @author noear 2023/5/16 created
*/
public class Sms4jPlugin implements Plugin {
@Override
public void start(AppContext context) {
context.beanMake(SmsMainConfigure.class);
context.beanMake(SupplierConfigure.class);
}
}

View File

@ -1,17 +0,0 @@
package org.dromara.sms4j.solon;
import org.dromara.sms4j.solon.config.SmsAutowiredConfig;
import org.dromara.sms4j.solon.config.SupplierConfig;
import org.noear.solon.core.AppContext;
import org.noear.solon.core.Plugin;
/**
* @author noear 2023/5/16 created
*/
public class XPluginImpl implements Plugin {
@Override
public void start(AppContext context) {
context.beanMake(SmsAutowiredConfig.class);
context.beanMake(SupplierConfig.class);
}
}

View File

@ -0,0 +1,40 @@
package org.dromara.sms4j.solon.adaptor;
import cn.hutool.core.bean.BeanUtil;
import org.dromara.sms4j.core.datainterface.SmsReadConfig;
import org.dromara.sms4j.provider.config.BaseConfig;
import java.util.*;
public class ConfigCombineMapAdaptor<S, M> extends HashMap {
@Override
public M get(Object key) {
Object o = super.get(key);
if (null == o){
Set configKeySet = this.keySet();
for (Object insideMapKey : configKeySet) {
if (((String)insideMapKey).startsWith(SmsReadConfig.class.getSimpleName())){
Map smsBlendsConfigInsideMap = (Map) this.get(insideMapKey);
SmsReadConfig config = (SmsReadConfig) smsBlendsConfigInsideMap.get(insideMapKey);
BaseConfig supplierConfig = config.getSupplierConfig((String)key);
List<BaseConfig> supplierConfigList = config.getSupplierConfigList();
if (null == supplierConfigList){
supplierConfigList = new ArrayList<>();
}
if (null != supplierConfig){
supplierConfigList.add(supplierConfig);
}
for (BaseConfig baseConfig : supplierConfigList) {
if (key.equals(baseConfig.getConfigId())){
Map<String, Object> configMap = BeanUtil.beanToMap(baseConfig);
this.put(baseConfig.getConfigId(),configMap);
return (M)configMap;
}
}
}
}
return null;
}
return (M)o;
}
}

View File

@ -1,60 +0,0 @@
package org.dromara.sms4j.solon.config;
import lombok.extern.slf4j.Slf4j;
import org.dromara.sms4j.comm.constant.Constant;
import org.dromara.sms4j.comm.delayedTime.DelayedTime;
import org.dromara.sms4j.provider.config.SmsBanner;
import org.dromara.sms4j.provider.config.SmsConfig;
import org.dromara.sms4j.provider.factory.BeanFactory;
import org.noear.solon.annotation.Bean;
import org.noear.solon.annotation.Configuration;
import org.noear.solon.annotation.Inject;
import org.noear.solon.core.AppContext;
import org.noear.solon.core.bean.LifecycleBean;
import java.util.concurrent.Executor;
@Slf4j
@Configuration
public class SmsAutowiredConfig implements LifecycleBean {
@Inject
AppContext context;
private <T> T injectObj(String prefix, T obj) {
//@Inject 只支持在字段参数类型上注入
context.cfg().getProp(prefix).bindTo(obj);
return obj;
}
@Bean
public SmsConfig smsConfig() {
return injectObj("sms", BeanFactory.getSmsConfig());
}
/**
* 注入一个定时器
*/
@Bean
public DelayedTime delayedTime() {
return BeanFactory.getDelayedTime();
}
/**
* 注入线程池
*/
@Bean("smsExecutor")
public Executor taskExecutor(@Inject SmsConfig config) {
return BeanFactory.setExecutor(config);
}
//是在 solon 容器扫描完成之后执行的
@Override
public void start() {
//打印banner
if (BeanFactory.getSmsConfig().getIsPrint()) {
SmsBanner.PrintBanner(Constant.VERSION);
}
}
}

View File

@ -13,7 +13,9 @@ import org.dromara.sms4j.budingyun.config.BudingV2Factory;
import org.dromara.sms4j.chuanglan.config.ChuangLanFactory; import org.dromara.sms4j.chuanglan.config.ChuangLanFactory;
import org.dromara.sms4j.cloopen.config.CloopenFactory; import org.dromara.sms4j.cloopen.config.CloopenFactory;
import org.dromara.sms4j.comm.constant.Constant; import org.dromara.sms4j.comm.constant.Constant;
import org.dromara.sms4j.comm.enums.ConfigType;
import org.dromara.sms4j.comm.utils.SmsUtils; import org.dromara.sms4j.comm.utils.SmsUtils;
import org.dromara.sms4j.core.datainterface.SmsReadConfig;
import org.dromara.sms4j.core.factory.SmsFactory; import org.dromara.sms4j.core.factory.SmsFactory;
import org.dromara.sms4j.core.proxy.EnvirmentHolder; import org.dromara.sms4j.core.proxy.EnvirmentHolder;
import org.dromara.sms4j.core.proxy.SmsProxyFactory; import org.dromara.sms4j.core.proxy.SmsProxyFactory;
@ -36,15 +38,15 @@ import org.dromara.sms4j.provider.config.SmsConfig;
import org.dromara.sms4j.provider.factory.BaseProviderFactory; import org.dromara.sms4j.provider.factory.BaseProviderFactory;
import org.dromara.sms4j.provider.factory.ProviderFactoryHolder; import org.dromara.sms4j.provider.factory.ProviderFactoryHolder;
import org.dromara.sms4j.qiniu.config.QiNiuFactory; import org.dromara.sms4j.qiniu.config.QiNiuFactory;
import org.dromara.sms4j.solon.holder.SolonSmsDaoHolder; import org.dromara.sms4j.solon.adaptor.ConfigCombineMapAdaptor;
import org.dromara.sms4j.submail.config.SubMailFactory; import org.dromara.sms4j.submail.config.SubMailFactory;
import org.dromara.sms4j.tencent.config.TencentFactory; import org.dromara.sms4j.tencent.config.TencentFactory;
import org.dromara.sms4j.unisms.config.UniFactory; import org.dromara.sms4j.unisms.config.UniFactory;
import org.dromara.sms4j.yixintong.config.YiXintongFactory; import org.dromara.sms4j.yixintong.config.YiXintongFactory;
import org.dromara.sms4j.yunpian.config.YunPianFactory; import org.dromara.sms4j.yunpian.config.YunPianFactory;
import org.dromara.sms4j.zhutong.config.ZhutongFactory; import org.dromara.sms4j.zhutong.config.ZhutongFactory;
import org.noear.solon.core.AppContext;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.ServiceLoader; import java.util.ServiceLoader;
@ -56,56 +58,69 @@ public class SmsBlendsInitializer {
private final SmsConfig smsConfig; private final SmsConfig smsConfig;
private final Map<String, Map<String, Object>> blends; private final Map<String, Map<String, Object>> blends;
private final AppContext context; private final List<SmsReadConfig> extendsSmsConfigs;
public SmsBlendsInitializer(List<BaseProviderFactory<? extends SmsBlend, ? extends SupplierConfig>> factoryList, public SmsBlendsInitializer(List<BaseProviderFactory<? extends SmsBlend, ? extends SupplierConfig>> factoryList,
SmsConfig smsConfig, SmsConfig smsConfig,
Map<String, Map<String, Object>> blends, Map<String, Map<String, Object>> blends,
AppContext context List<SmsReadConfig> extendsSmsConfigs){
){
this.factoryList = factoryList; this.factoryList = factoryList;
this.smsConfig = smsConfig; this.smsConfig = smsConfig;
this.blends = blends; this.blends = blends;
this.context = context; this.extendsSmsConfigs = extendsSmsConfigs;
onApplicationEvent();
this.initDo();
} }
public void onApplicationEvent() { private void initDo() {
this.registerDefaultFactory(); this.registerDefaultFactory();
// 注册短信对象工厂 // 注册短信对象工厂
ProviderFactoryHolder.registerFactory(factoryList); ProviderFactoryHolder.registerFactory(factoryList);
//持有初始化配置信息 //如果手机号校验器存在实现则注册手机号校验器暂不可用
EnvirmentHolder.frozenEnvirmet(smsConfig, blends);
//框架依赖持有缓存扩展
new SolonSmsDaoHolder(context);
//注册执行器实现
SmsProxyFactory.addPreProcessor(new RestrictedProcessor());
SmsProxyFactory.addPreProcessor(new BlackListProcessor());
SmsProxyFactory.addPreProcessor(new BlackListRecordingProcessor());
//如果手机号校验器存在实现则注册手机号校验器
ServiceLoader<PhoneVerify> loader = ServiceLoader.load(PhoneVerify.class); ServiceLoader<PhoneVerify> loader = ServiceLoader.load(PhoneVerify.class);
if (loader.iterator().hasNext()) { if (loader.iterator().hasNext()) {
loader.forEach(f -> SmsProxyFactory.addPreProcessor(new CoreMethodParamValidateProcessor(f))); loader.forEach(f -> SmsProxyFactory.addPreProcessor(new CoreMethodParamValidateProcessor(f)));
} else { } else {
SmsProxyFactory.addPreProcessor(new CoreMethodParamValidateProcessor(null)); SmsProxyFactory.addPreProcessor(new CoreMethodParamValidateProcessor(null));
} }
// 解析供应商配置 //注册执行器实现
for(String configId : blends.keySet()) { if(this.smsConfig.getRestricted()){
Map<String, Object> configMap = blends.get(configId); SmsProxyFactory.addPreProcessor(new RestrictedProcessor());
Object supplierObj = configMap.get(Constant.SUPPLIER_KEY); SmsProxyFactory.addPreProcessor(new BlackListProcessor());
String supplier = supplierObj == null ? "" : String.valueOf(supplierObj); SmsProxyFactory.addPreProcessor(new BlackListRecordingProcessor());
supplier = StrUtil.isEmpty(supplier) ? configId : supplier;
BaseProviderFactory<SmsBlend, SupplierConfig> providerFactory = (BaseProviderFactory<SmsBlend, SupplierConfig>) ProviderFactoryHolder.requireForSupplier(supplier);
if(providerFactory == null) {
log.warn("创建\"{}\"的短信服务失败,未找到供应商为\"{}\"的服务", configId, supplier);
continue;
}
configMap.put("config-id", configId);
SmsUtils.replaceKeysSeparator(configMap, "-", "_");
JSONObject configJson = new JSONObject(configMap);
SupplierConfig supplierConfig = JSONUtil.toBean(configJson, providerFactory.getConfigClass());
SmsFactory.createSmsBlend(supplierConfig);
} }
if (ConfigType.YAML.equals(this.smsConfig.getConfigType())) {
//持有初始化配置信息
Map<String, Map<String, Object>> blendsInclude = new ConfigCombineMapAdaptor<String, Map<String, Object>>();
blendsInclude.putAll(this.blends);
int num = 0;
for (SmsReadConfig smsReadConfig : extendsSmsConfigs) {
String key = SmsReadConfig.class.getSimpleName() + num;
Map<String, Object> insideMap = new HashMap<>();
insideMap.put(key, smsReadConfig);
blendsInclude.put(key, insideMap);
num++;
}
EnvirmentHolder.frozenEnvirmet(smsConfig, blendsInclude);
// 解析供应商配置
for (String configId : blends.keySet()) {
Map<String, Object> configMap = blends.get(configId);
Object supplierObj = configMap.get(Constant.SUPPLIER_KEY);
String supplier = supplierObj == null ? "" : String.valueOf(supplierObj);
supplier = StrUtil.isEmpty(supplier) ? configId : supplier;
BaseProviderFactory<SmsBlend, SupplierConfig> providerFactory = (BaseProviderFactory<SmsBlend, org.dromara.sms4j.api.universal.SupplierConfig>) ProviderFactoryHolder.requireForSupplier(supplier);
if (providerFactory == null) {
log.warn("创建\"{}\"的短信服务失败,未找到供应商为\"{}\"的服务", configId, supplier);
continue;
}
configMap.put("config-id", configId);
SmsUtils.replaceKeysSeparator(configMap, "-", "_");
JSONObject configJson = new JSONObject(configMap);
org.dromara.sms4j.api.universal.SupplierConfig supplierConfig = JSONUtil.toBean(configJson, providerFactory.getConfigClass());
SmsFactory.createSmsBlend(supplierConfig);
}
}
} }
@ -135,8 +150,11 @@ public class SmsBlendsInitializer {
ProviderFactoryHolder.registerFactory(SubMailFactory.instance()); ProviderFactoryHolder.registerFactory(SubMailFactory.instance());
ProviderFactoryHolder.registerFactory(DanMiFactory.instance()); ProviderFactoryHolder.registerFactory(DanMiFactory.instance());
ProviderFactoryHolder.registerFactory(YiXintongFactory.instance()); ProviderFactoryHolder.registerFactory(YiXintongFactory.instance());
if(SmsUtils.isClassExists("com.jdcloud.sdk.auth.CredentialsProvider")) { if (SmsUtils.isClassExists("com.jdcloud.sdk.auth.CredentialsProvider")) {
ProviderFactoryHolder.registerFactory(JdCloudFactory.instance()); if (SmsUtils.isClassExists("com.jdcloud.sdk.auth.CredentialsProvider")) {
ProviderFactoryHolder.registerFactory(JdCloudFactory.instance());
}
log.debug("加载内置运营商完成!");
} }
} }

View File

@ -0,0 +1,34 @@
package org.dromara.sms4j.solon.config;
import lombok.extern.slf4j.Slf4j;
import org.dromara.sms4j.comm.constant.Constant;
import org.dromara.sms4j.provider.config.SmsBanner;
import org.dromara.sms4j.provider.config.SmsConfig;
import org.dromara.sms4j.provider.factory.BeanFactory;
import org.noear.solon.annotation.Bean;
import org.noear.solon.annotation.Configuration;
import org.noear.solon.annotation.Init;
import org.noear.solon.annotation.Inject;
import org.noear.solon.core.AppContext;
@Slf4j
@Configuration
public class SmsMainConfigure {
@Inject
AppContext context;
@Bean
public SmsConfig smsConfig() {
return context.cfg().getProp("sms")
.bindTo(BeanFactory.getSmsConfig());
}
//是在 solon 容器扫描完成之后执行的
@Init
public void init() {
//打印banner
if (BeanFactory.getSmsConfig().getIsPrint()) {
SmsBanner.PrintBanner(Constant.VERSION);
}
}
}

View File

@ -2,8 +2,10 @@ package org.dromara.sms4j.solon.config;
import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.ObjectUtil;
import org.dromara.sms4j.api.SmsBlend; import org.dromara.sms4j.api.SmsBlend;
import org.dromara.sms4j.api.universal.SupplierConfig;
import org.dromara.sms4j.comm.constant.Constant; import org.dromara.sms4j.comm.constant.Constant;
import org.dromara.sms4j.comm.enums.ConfigType; import org.dromara.sms4j.comm.enums.ConfigType;
import org.dromara.sms4j.core.datainterface.SmsReadConfig;
import org.dromara.sms4j.provider.config.SmsConfig; import org.dromara.sms4j.provider.config.SmsConfig;
import org.dromara.sms4j.provider.factory.BaseProviderFactory; import org.dromara.sms4j.provider.factory.BaseProviderFactory;
import org.noear.solon.annotation.Bean; import org.noear.solon.annotation.Bean;
@ -18,11 +20,11 @@ import java.util.List;
import java.util.Map; import java.util.Map;
/** /**
* smsConfig参数意义为确保注入时smsConfig已经存在 * smsConfig 参数意义为确保注入时 smsConfig 已经存在
*/ */
@Condition(onProperty = "${sms.configType}=yaml") @Condition(onProperty = "${sms.configType}=yaml")
@Configuration @Configuration
public class SupplierConfig { public class SupplierConfigure {
@Inject @Inject
AppContext context; AppContext context;
@ -33,44 +35,43 @@ public class SupplierConfig {
} }
@Bean("blends") @Bean("blends")
@Condition(onProperty = "${sms.configType} = yaml")
public Map<String, Map<String, Object>> blends() { public Map<String, Map<String, Object>> blends() {
return injectObj("sms.blends", new LinkedHashMap<>()); return context.cfg().getProp("sms.blends").bindTo(new LinkedHashMap<>());
} }
@Bean @Bean
@Condition(onBean = SmsConfig.class) @Condition(onBean = SmsConfig.class)
public List<BaseProviderFactory> factoryList(@Inject("blends") Map<String, Map<String, Object>> blends, SmsConfig smsConfig) throws Exception { public List<BaseProviderFactory<? extends SmsBlend, ? extends SupplierConfig>> factoryList(
@Inject("blends") Map<String, Map<String, Object>> blends,
SmsConfig smsConfig) throws Exception {
//注入自定义实现工厂 //注入自定义实现工厂
List<BaseProviderFactory> factoryList = new ArrayList<>(); List<BaseProviderFactory<? extends SmsBlend, ? extends SupplierConfig>> factoryList = new ArrayList<>();
if (ConfigType.YAML.equals(smsConfig.getConfigType())) { if (ConfigType.YAML.equals(smsConfig.getConfigType())) {
for (String configId : blends.keySet()) { for (String configId : blends.keySet()) {
Map<String, Object> configMap = blends.get(configId); Map<String, Object> configMap = blends.get(configId);
Object factoryPath = configMap.get(Constant.FACTORY_PATH); Object factoryPath = configMap.get(Constant.FACTORY_PATH);
if (ObjectUtil.isNotEmpty(factoryPath)) { if (ObjectUtil.isNotEmpty(factoryPath)) {
//反射创建实例 //反射创建实例
Class<BaseProviderFactory<? extends SmsBlend, ? extends org.dromara.sms4j.api.universal.SupplierConfig>> newClass = (Class<BaseProviderFactory<? extends SmsBlend, ? extends org.dromara.sms4j.api.universal.SupplierConfig>>) Class.forName(factoryPath.toString()); Class<BaseProviderFactory<? extends SmsBlend, ? extends SupplierConfig>> newClass = (Class<BaseProviderFactory<? extends SmsBlend, ? extends SupplierConfig>>) Class.forName(factoryPath.toString());
BaseProviderFactory<? extends SmsBlend, ? extends org.dromara.sms4j.api.universal.SupplierConfig> factory = newClass.newInstance(); BaseProviderFactory<? extends SmsBlend, ? extends SupplierConfig> factory = newClass.newInstance();
factoryList.add(factory); factoryList.add(factory);
} }
} }
} }
return factoryList; return factoryList;
} }
@Bean @Bean
public SmsBlendsInitializer smsBlendsInitializer(List<BaseProviderFactory> factoryList, public SmsBlendsInitializer smsBlendsInitializer(List<BaseProviderFactory<? extends SmsBlend, ? extends SupplierConfig>> factoryList,
SmsConfig smsConfig, SmsConfig smsConfig,
@Inject("blends") Map<String, Map<String, Object>> blends) { @Inject("blends") Map<String, Map<String, Object>> blends,
@Inject(required = false) List<SmsReadConfig> extendsSmsConfigs) {
//todo: solon 不支持泛型的 List[Bean] 注入 if (extendsSmsConfigs == null) {
List<BaseProviderFactory<? extends SmsBlend, ? extends org.dromara.sms4j.api.universal.SupplierConfig>> factoryList2 = new ArrayList<>(factoryList.size()); extendsSmsConfigs = new ArrayList<>();
for (BaseProviderFactory factory : factoryList) {
factoryList2.add((BaseProviderFactory<? extends SmsBlend, ? extends org.dromara.sms4j.api.universal.SupplierConfig>) factory);
} }
return new SmsBlendsInitializer(factoryList, smsConfig, blends, extendsSmsConfigs);
return new SmsBlendsInitializer(factoryList2, smsConfig, blends, context);
} }
} }

View File

@ -1,22 +1,10 @@
package org.dromara.sms4j.solon.holder; package org.dromara.sms4j.solon.holder;
import org.dromara.sms4j.api.dao.SmsDao; import org.dromara.sms4j.api.dao.SmsDao;
import org.dromara.sms4j.api.dao.SmsDaoDefaultImpl; import org.noear.solon.Solon;
import org.dromara.sms4j.comm.utils.SmsUtils;
import org.noear.solon.core.AppContext;
public class SolonSmsDaoHolder{
private static SmsDao smsDao;
public SolonSmsDaoHolder(AppContext context) {
context.getBeanAsync(SmsDao.class, bean -> smsDao = bean);
}
public class SolonSmsDaoHolder {
public static SmsDao getSmsDao() { public static SmsDao getSmsDao() {
if (SmsUtils.isEmpty(smsDao)){ return Solon.context().getBean(SmsDao.class);
smsDao = SmsDaoDefaultImpl.getInstance();
}
return smsDao;
} }
} }

View File

@ -1,4 +1,2 @@
#??????? solon.plugin=org.dromara.sms4j.solon.Sms4jPlugin
solon.plugin=org.dromara.sms4j.solon.XPluginImpl
#?????????????????0
solon.plugin.priority=1 solon.plugin.priority=1