新的短信服务集成到IDP中¶
最后更新:2024-07-31
1、IDP中已经集成的短信服务¶
截止当前版本,IDP中已经集成的短信服务有:
IDaaS安全认证短信
阿里短信平台
推荐项目交付中使用已有的短信服务,如果已有插件不满足需求,再去集成新的短信服务,集成后再去添加短信网关。
2、插件集成¶
2.1.下载demo¶
运行命令 git clone https://github.com/aliyun-idaas/notify-sms-engine-demo.git
2.2.使用IDEA打开Demo工程,可查看代码¶
图2.1
如图2.1
使用 IDEA 打开 Demo 工程
2.3.工程结构¶
工程使用 maven 进行管理,总体结构与 maven 标准项目相同,需要注意的是增加了一个 lib 目录,里面存放私有库 jar 包,maven仓库无法下载,主要是二方包(如idp相关包)。
2.4.代码开发¶
主要修改点:
2.4.1.修改项目名称¶
工程下载后名称为 notify-sms-plugin-demo,复制代码目录为 notify-sms-plugin-xxx,xxx为具体网关名,根据对接的短信网关真实名称确定,如 notify-sms-plugin-aliyun、notify-sms-plugin-cmcc等,我这里以对接
i253云通讯平台(i235)
为例。
项目名称修改为notify-sms-plugin-i235
打开目录中 pom.xml,修改 artifactId 的值为你的目录名
图2.2
2.4.2.修改包名¶
使用 IDEA 打开改好项目名的项目,修改包名中 demo 为新的包名,如 aliyun、cmcc、i253 等,我这里是对接i253云通讯平台(i235)
短信,包名由demo改为 i235
图2.3
2.4.3.修改类名¶
修改类名格式:XxxSmsEngine、XxxSmsSender 或者 SmsXxxEngine、SmsXxxSender样式
修改SMSEngine和SMSSender类名分别为SmsI253Engine、SmsI253Sende图2.4
2.4.4.修改METADATA信息¶
主要需要修改 MINOR_TYPE、name方法(网关显示名称)、以及metadata文件夹下SMS_DEMO.json 文件名
修改XxxSmsEngine 类中 MINOR_TYPE 需要修改为 SMS_XXX 格式,如 SMS_ALIYUN、SMS_235、SMS_ESB
要求全大写,根据对接的网关名称确定。
修改后修改 src/main/resources/metadata 中 SMS_DEMO.json 为 {MINOR_TYPE}.json,如 SMS_ESB.json。
网关显示名称修改为该短信网关真实的网关名称,如阿里短信平台、中国移动、中国联通、ESB、253等,修改 XxxSmsEngine 类中 name 方法的返回值,返回网关名称,以
i253云通讯平台(i235)
为例:图2.5
2.4.5.填写参数信息¶
修改前端映射文件¶
先确定需要对接的短信网关中需要传递的参数有哪些,其中又有哪些参数是固定的,哪些是需要用户填写的。如根据 235短信网关接口文档(https://zz.253.com/api_doc/guo-nei-duan-xin/dan-fa-qun-fa-jie-kou.html)通过 SMS_235.json 文件配置下面变量:
1、name:网关名称,用户填写(必填);
2、description:网关描述,用户填写(非必填);
3、smsUrl:SMS URL,用户填写(必填);
4、apiUsername:API账户,用户填写(必填);
5、apiPassword:API密码,用户填写(必填);
6、title:短信标题,用户填写(必填);
7、extCode:Api扩展字段,用户填写(非必填);
我们需要修改 src/resources/metadata 文件夹下面的SMS_DEMO.json 文件这里修改文件夹名称为插件SMS_235 为短信网关 minorType名称
SMS_235.json:前端会按照该 json 信息渲染界面,和上面字段一一对应。
示例:
图2.6
图2.7
2.4.6.SmsEngine类编写¶
build方法组装SmsSender¶
核心方法通过实现SmsMsgEngineMetadata
的build
方法组装SmsSender,以i253为例,build方法的json字段就是前端传入的值,通过 doValidate(json) 方法解析和验证json,解析json后需要在修改下图 图2.11
红框处的代码,改成上面自己业务定义的json字段,通过 config.optString(“apiUsername”) 获取前端传的值,然后再通过set方法 传入到Sender类,这样我们的SmsMsgSender就构造好了。
图2.11
修改验证参数KEYS¶
在Engine类 找到KEYS数组字段(这里字段均为上面json中定义的字段中的key值,如SMS_235.json ),通过添加或者修改自己需要验证的字段如 图2.12
,如没有需要验证非空字段KEYS设置为空数组即可
图2.12
修改加密字段 ENCRYPT_FIELDS¶
在Engine类 找到ENCRYPT_FIELDS数组字段(这里字段均为上面json中定义的字段中的key值,如SMS_235.json ),通过添加或者修改自己需要加密的字段如 图2.13
,如没有字段加密,ENCRYPT_FIELDS设置为空数组即可
图2.13
Sms253Engine示例:
package com.idsmanager.idp.notify.sms.i253;
import com.idsmanager.idp.notify.infrastructure.InvalidConfigException;
import com.idsmanager.idp.notify.sms.infrastructure.SMS;
import com.idsmanager.idp.notify.sms.infrastructure.SmsMsgEngineMetadata;
import com.idsmanager.idp.notify.sms.infrastructure.SmsMsgSender;
import com.idsmanager.idp.notify.util.JsonFiledSecurityUtils;
import net.sf.json.JSONObject;
import org.apache.commons.lang.StringUtils;
@SMS
public class Sms253Engine extends SmsMsgEngineMetadata {
private static final String SMS_253 = "SMS_253";
private static final String[] ENCRYPT_FIELDS = {"apiPassword"};
private static final String[] KEYS = new String[]{"apiUsername", "apiPassword", "title"};
@Override
public String name() {
return "i253云通讯平台";
}
@Override
public final String minorType() {
return SMS_253;
}
@Override
public String[] encryptFields() {
return ENCRYPT_FIELDS;
}
@Override
public void validate(String json) throws InvalidConfigException {
doValidate(json);
}
@Override
public SmsMsgSender build(String json) throws InvalidConfigException {
JSONObject config = doValidate(json);
JsonFiledSecurityUtils.decryptField(config, encryptFields());
Sms253Sender sender = new Sms253Sender();
sender.setName(config.optString("name"));
sender.setDescription(config.optString("description"));
sender.setSmsUrl(config.optString("smsUrl"));
sender.setApiUsername(config.optString("apiUsername"));
sender.setApiPassword(config.optString("apiPassword"));
sender.setTitle(config.optString("title"));
sender.setExtCode(config.optString("extCode"));
sender.setInternatMsg(config.optBoolean("isInternatMsg"));
String url = config.optString("url");
url = StringUtils.isBlank(url) ? "https://sms.253.com/m"
+ "sg/send" : url;
sender.setSmsUrl(url);
return sender;
}
private JSONObject doValidate(String json) throws InvalidConfigException {
JSONObject config = null;
try {
config = JSONObject.fromObject(json);
} catch (Throwable e) {
throw new InvalidConfigException("解析配置失败,无效JSON字符串", e);
}
for (String key : KEYS) {
ensureParamNotNull(key, config.optString(key));
}
return config;
}
}
2.4.7.编写Sender的发送逻辑¶
根据 253 短信网关短信发送文档(https://zz.253.com/api_doc/guo-nei-duan-xin/dan-fa-qun-fa-jie-kou.html);
253 短信网关使用 http 接口发送信息,请求、响应值均为 json 格式。所以我们在发送类通过 IDP 传递给 Notify 的短信接收者、短信内容组装235请求信息,调用235 发送接口调用发送短信。
修改 SMSSender 类中 sendMessage (具体发送逻辑)方法,该方法参数 message 的值为具体要发送的短信内容,如“尊敬的用户xxx,您本次的验证码是:133554, 2分钟内有效。如非本人操作,请忽略本短信并联系管理员。
”;
根据 253接口文档,需要在这个内容的最前面拼接上 title;参数 phoneNumbers 为短信接收手机号,该参数为数组类型,截止文档编写时,该参数均只会传递一个值,需要注意该手机号为带有国际区号的手机号,需要根据对接的短信网关决定是否删掉该区号,内容示例“86-18888888888”。短信发送成功,函数要求返回 ApiResult.SUCCESS,失败要求返回 ApiResult.FAILURE 或 new ApiResult(NotifyErrorCode.SEND_UNKNOWN_ERROR, “具体的失败原因”);
其他短信网关具体的逻辑参考对应厂商文档来。
235发送示例:
/*
* Copyright (c) 2016 BeiJing JZYT Technology Co. Ltd
* www.idsmanager.com
* All rights reserved.
*
* This software is the confidential and proprietary information of
* BeiJing JZYT Technology Co. Ltd ("Confidential Information").
* You shall not disclose such Confidential Information and shall use
* it only in accordance with the terms of the license agreement you
* entered into with BeiJing JZYT Technology Co. Ltd.
*/
package com.idsmanager.idp.notify.sms.i253;
import com.google.common.collect.ImmutableMap;
import com.idsmanager.idp.notify.commons.infrastructure.ApiResult;
import com.idsmanager.idp.notify.commons.infrastructure.dto.msg.RContentBasedMsgSendReq;
import com.idsmanager.idp.notify.commons.infrastructure.dto.msg.TemplateBasedMsgSendReq;
import com.idsmanager.idp.notify.logger.NotifyPluginLogger;
import com.idsmanager.idp.notify.sms.domain.SmsMsgTemplate;
import com.idsmanager.idp.notify.sms.infrastructure.SmsMsgSender;
import com.idsmanager.micro.commons.utils.httpclient.HttpClientExecutor;
import com.idsmanager.micro.commons.utils.httpclient.HttpClientPostExecutor;
import com.idsmanager.micro.commons.utils.httpclient.IDSHttpResponse;
import org.apache.commons.lang.StringUtils;
import static com.idsmanager.idp.notify.commons.NotifyErrorCode.SEND_UNKNOWN_ERROR;
/**
* 2017/2/28
* <p/>
* <p/>
* 使用 www.253.com 的短信发送
*
* @author Shengzhao Li
*/
public class Sms253Sender extends SmsMsgSender {
/**
* 253 发送短信的 URL, 固定
*/
public static final String DEFAULT_SMS_URL = "https://sms.253.com/msg/send";
/**
* 逗号
*/
private static final String COMMA = ",";
/**
* 国内手机号码区号前缀,使用短信微服务的标准前缀
*/
private static final String CN_PHONE_REGION_CODE = "86-";
/**
* 标识符 "-"
*/
private static final String RUNG = "-";
/**
* 发送 短信的 URL, 使用默认值即可
*/
private String name = "";
private String description = "";
/**
* 发送 短信的 URL, 使用默认值即可
*/
private String smsUrl = DEFAULT_SMS_URL;
/**
* API 调用 的账号
*/
private String apiUsername = "";
/**
* API 调用的 密码
*/
private String apiPassword = "";
/**
* 发送消息时的标题,如: 【IDP2】
* 在 253中定义 , 可选
*/
private String title = "【云IDaaS平台】";
/**
* API调用时的扩展码(ex), 可选
*/
private String extCode;
/**
* 网关是否支持国际化
*/
private boolean internatMsg = false;
/**
* 发送超时时间
*/
private int maxConnectionSeconds;
public Sms253Sender() {
}
public String getSmsUrl() {
return smsUrl;
}
public void setSmsUrl(String smsUrl) {
this.smsUrl = smsUrl;
}
public String getApiUsername() {
return apiUsername;
}
public void setApiUsername(String apiUsername) {
this.apiUsername = apiUsername;
}
public String getApiPassword() {
return apiPassword;
}
public void setApiPassword(String apiPassword) {
this.apiPassword = apiPassword;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public int getMaxConnectionSeconds() {
return maxConnectionSeconds;
}
public void setMaxConnectionSeconds(int maxConnectionSeconds) {
this.maxConnectionSeconds = maxConnectionSeconds;
}
public String getExtCode() {
return extCode;
}
public void setExtCode(String extCode) {
this.extCode = extCode;
}
public boolean isInternatMsg() {
return internatMsg;
}
public void setInternatMsg(boolean internatMsg) {
this.internatMsg = internatMsg;
}
public String getName() {
return name;
}
public Sms253Sender setName(String name) {
this.name = name;
return this;
}
public String getDescription() {
return description;
}
public Sms253Sender setDescription(String description) {
this.description = description;
return this;
}
@Override
public ApiResult sendMsgByTemplate(TemplateBasedMsgSendReq req, String content, SmsMsgTemplate template) {
return sendMessage(content, req.getReceiver().getRecipients());
}
@Override
public ApiResult sendMsgByRContent(RContentBasedMsgSendReq req) {
return sendMessage(req.getContent(), req.getReceiver().getRecipients());
}
/**
* 参见API文档: https://www.253.com/api-docs-1.html
*
* @param message SMS content
* @param phoneNumbers Phone numbers
* @return SMSResult
*/
public ApiResult sendMessage(String message, String... phoneNumbers) {
if (StringUtils.isEmpty(message) || phoneNumbers == null) {
NotifyPluginLogger.debug("Param checking failed, message: {}, phoneNumbers: {}", message, phoneNumbers);
return new ApiResult(0x0000, "message is empty or phoneNumber is null");
}
StringBuilder builder = convertPhoneNumbers(phoneNumbers);
HttpClientExecutor clientExecutor = createHttpClientExecutor(builder, message);
return clientExecutor.execute(this::responseToResult);
}
protected ApiResult responseToResult(IDSHttpResponse response) {
ApiResult result;
if (response.isResponse200()) {
final String responseText = response.responseAsString();
final String code = checkingResponseSuccessful(responseText);
if (Sms253ErrorEnum.SMS253NEW_SUCCESS.getErrorCode().equals(code)
|| (code != null && code.startsWith("0\n"))) {
NotifyPluginLogger.debug("Send sms success response code [200] response text [{}]", responseText);
result = ApiResult.SUCCESS;
} else {
NotifyPluginLogger.info("Send sms failed response code [200] response text [{}]", responseText);
result = new ApiResult(SEND_UNKNOWN_ERROR, "253云通讯平台发送短信失败,响应码:【" + code + "】," +
"错误信息:【" + Sms253ErrorEnum.load(code).getErrorMsg() + "】", ImmutableMap.of("responseText", responseText));
}
} else {
int httpStatus = response.httpResponse().getStatusLine().getStatusCode();
try {
NotifyPluginLogger.info("Send sms failed response code [{}] response text [{}]", response.httpResponse().getStatusLine().getStatusCode(),
response.responseAsString());
} catch (IllegalStateException e) {
NotifyPluginLogger.info("Send sms failed response code [{}]", httpStatus, e);
}
result = new ApiResult(SEND_UNKNOWN_ERROR, "发送短信失败,调用253服务时HTTP状态码错误[" + httpStatus + "]");
}
return result;
}
protected HttpClientExecutor createHttpClientExecutor(StringBuilder sb, String message) {
HttpClientExecutor executor = new HttpClientPostExecutor(this.smsUrl);
executor.addRequestParam("un", this.apiUsername)
.addRequestParam("pw", this.apiPassword)
.addRequestParam("phone", sb.toString())
.addRequestParam("ex", this.extCode)
.addRequestParam("msg", getFullMessage(message))
.addRequestParam("rd", "1");
executor.maxConnectionSeconds(maxConnectionSeconds);
return executor;
}
/*
* 获取完成的 发送消息, 检查是否有标题(subject)
* */
protected String getFullMessage(String message) {
if (StringUtils.isNotEmpty(this.title)) {
return this.title + message;
}
return message;
}
/*
* 判断第二个响应的数据是否为 0
*
* "响应状态为0 表明那个成功提交到服务器"
* 详细参见 https://www.253.com/api-docs.html
* */
protected String checkingResponseSuccessful(String responseText) {
String[] split = responseText.split(COMMA);
return split.length > 1 ? split[1] : "-1";
}
/*
* 将 手机号转化为 用 逗号, 分隔
*
*/
protected StringBuilder convertPhoneNumbers(String[] phoneNumbers) {
final int length = phoneNumbers.length;
StringBuilder sb = new StringBuilder();
for (int i = 0; i < length; i++) {
sb.append(appendPhoneNumber(phoneNumbers[i]));
if (i + 1 < length) {
sb.append(COMMA);
}
}
return sb;
}
private String appendPhoneNumber(String phoneNumbers) {
if (!this.internatMsg) {
phoneNumbers = phoneNumbers.contains(RUNG) ? phoneNumbers.replace(newStr(phoneNumbers), "") : phoneNumbers;
} else {
phoneNumbers = phoneNumbers.contains(RUNG) ? phoneNumbers.replace(RUNG, "") : phoneNumbers;
}
return phoneNumbers;
}
private String newStr(String phoneNumber) {
return phoneNumber.substring(0, phoneNumber.indexOf(RUNG) + 1);
}
}
2.4.8.插件审计日志和日志打印¶
日志打印¶
日志打印,Notify提供日志打印工具类 NotifyPluginLogger
,可以通过此类打印日志,打印的日志会记录到:
/data/applications/idp4-microservice/notify/logs/时间/idaas-notifyPlugin-log-0.log;
如:我们发送调用第三方短信服务商 发送短信时,通过NotifyPluginLogger.error打印对应返回的响应信息sendReq,如下:
NotifyPluginLogger.error("[{}] Send mas fail response response text [{}]", RIDHolder.id(), JSON.toJSONString(sendReq));
调用发送短信,显示发送失败:
连上服务器,打开idaas-notifyPlugin-log-0.log 日志文件排查问题,打开日志文件通过发送时间定位到具体日志信息找到问题:
以上就可以查看Notify插件打印的具体日志信息;
切记:
一定要用
NotifyPluginLogger
工具类打印日志,这样日志文件才会在idaas-notifyPlugin-log-0.log 输出,不然会打印到idaas-notify-log-0.log 文件,不方便排查问题;日志方法如果是错误的地方使用 NotifyPluginLogger.error 方法打印,调试的日志使用NotifyPluginLogger.info打印;
打印对象一定要通过JSON.toJSONString(sendReq) 转换一下,否则日志展示出来的就是对象地址信息
审计日志¶
审计日志打印,可以使用工具类 ApiResultHelper
返回,比如
#发送短信成功
return ApiResultHelper.success(NotifyErrorCode.SUCCESS, "发送短信成功");
#发送短信失败,把获取到的第三方错误返回
String result = sendPost(smsUrl, phoneNumbers);
SmsResponse sendReq = JSON.parseObject(result, SmsResponse.class);
if (!sendReq.isSuccess()){
return ApiResultHelper.error(FAILURE, sendReq);
}
上述sendReq 是调用第三方短信服务商短信接口获取的响应,我们通过:
return ApiResultHelper.error(FAILURE, sendReq);
传入响应的对象信息:sendReq,当发送短信失败,就可以通过审计日志中查看问题;
发送短信失败:
打开“审计”->“操作日志”->“管理日志”
展开日志信息,再展开详细信息,即可看到第三方短信服务商,响应的错误信息:
以上日志工具类在插件demo都有使用,可以结合文档使用;
2.5.插件新增依赖包¶
由于 Notify 没有实现类隔离,需要注意在插件开发过程中如果需要引入新的 maven 依赖,请先检查引入的依赖是否在下列列表中,如果在列表中,请使用列表中的版本,并将 scope 修改为 provided。如果有新增依赖包插件打包的时候需要打开assembly配置,实际参考** 2.6.2.有第三方lib依赖**
antlr:antlr:2.7.7
ch.qos.logback:logback-classic:1.2.12
ch.qos.logback:logback-core:1.2.12
cn.jpush.api:jpush-client:3.2.9
com.alibaba.cloud:spring-cloud-alibaba-commons:2021.0.6.0
com.alibaba.cloud:spring-cloud-starter-alibaba-nacos-config:2021.0.6.0
com.alibaba.cloud:spring-cloud-starter-alibaba-nacos-discovery:2021.0.6.0
com.alibaba.nacos:nacos-auth-plugin:2.2.0
com.alibaba.nacos:nacos-client:2.2.0
com.alibaba.nacos:nacos-encryption-plugin:2.2.0
com.alibaba.security:typesafe-config-shade:1.3.3-jdk7
com.alibaba.spring:spring-context-support:1.0.11
com.alibaba:fastjson:1.2.83
com.aliyun.rapt.commons:rapt-utils:0.4.4
com.aliyun.security:rapt-circuitbreaker:1.0.4.4
com.aliyun.security:rapt-logger:1.0.4.4
com.aliyun.security:rapt-support:1.0.4.4
com.aliyun.securitysdk:rass-api:2.7
com.aliyun.securitysdk:rass-core:2.7.0
com.aliyun.securitysdk:rass-lite:2.7.0
com.aliyun.securitysdk:rass-resource:2.3.4.0-apsara
com.aliyun.securitysdk:rass-spring-context:2.7.0
com.aliyun:aliyun-java-sdk-core:4.4.3
com.aliyun:aliyun-java-sdk-idaas-doraemon:1.2.4
com.beust:jcommander:1.82
com.fasterxml.jackson.core:jackson-annotations:2.13.5
com.fasterxml.jackson.core:jackson-core:2.13.5
com.fasterxml.jackson.core:jackson-databind:2.13.5
com.fasterxml.jackson.dataformat:jackson-dataformat-smile:2.13.5
com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.13.5
com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.13.5
com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.13.5
com.fasterxml.jackson.module:jackson-module-afterburner:2.13.5
com.fasterxml.jackson.module:jackson-module-jsonSchema:2.6.5
com.fasterxml.jackson.module:jackson-module-parameter-names:2.13.5
com.fasterxml:classmate:1.5.1
com.github.jai-imageio:jai-imageio-core:1.4.0
com.github.ua-parser:uap-java:1.5.2
com.google.code.findbugs:jsr305:3.0.2
com.google.code.gson:gson:2.9.1
com.google.errorprone:error_prone_annotations:2.11.0
com.google.guava:failureaccess:1.0.1
com.google.guava:guava:31.1-jre
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava
com.google.j2objc:j2objc-annotations:1.3
com.google.zxing:core:3.5.0
com.google.zxing:javase:3.5.0
com.idsmanager.boot:micro-commons:1.3.0
com.idsmanager.notify:notify-api:4.21.3
com.idsmanager.notify:notify-autoconfiguration:4.21.3
com.idsmanager.notify:notify-core:4.21.3
com.idsmanager.notify:notify-email-api:4.21.3
com.idsmanager.notify:notify-email-local:4.21.3
com.idsmanager.notify:notify-email-remote:4.21.3
com.idsmanager.notify:notify-email-web:4.21.3
com.idsmanager.notify:notify-mobile-api:4.21.3
com.idsmanager.notify:notify-mobile-engine-jpush:4.21.3
com.idsmanager.notify:notify-mobile-local:4.21.3
com.idsmanager.notify:notify-mobile-web:4.21.3
com.idsmanager.notify:notify-rocket-mq:4.21.3
com.idsmanager.notify:notify-sms-api:4.21.3
com.idsmanager.notify:notify-sms-engine-253:4.21.3
com.idsmanager.notify:notify-sms-engine-253-new:4.21.3
com.idsmanager.notify:notify-sms-engine-aliyun:4.21.3
com.idsmanager.notify:notify-sms-engine-cmcc:4.21.3
com.idsmanager.notify:notify-sms-engine-cmcc-ws:1.0
com.idsmanager.notify:notify-sms-engine-unicom:4.21.3
com.idsmanager.notify:notify-sms-local:4.21.3
com.idsmanager.notify:notify-sms-remote:4.21.3
com.idsmanager.notify:notify-sms-web:4.21.3
com.idsmanager.notify:notify-website-api:4.21.3
com.idsmanager.notify:notify-website-local:4.21.3
com.idsmanager.notify:notify-website-web:4.21.3
com.idsmanager:idp-commons:1.0-SNAPSHOT
com.jayway.jsonpath:json-path:2.7.0
com.mysql:mysql-connector-j:8.0.33
com.net.sxt:jxtWS:1.0
com.sun.activation:jakarta.activation:1.2.2
com.sun.istack:istack-commons-runtime:3.0.12
com.vaadin.external.google:android-json:0.0.20131108.vaadin1
com.zaxxer:HikariCP:4.0.3
commons-beanutils:commons-beanutils:1.8.0
commons-beanutils:commons-beanutils:1.9.4
commons-codec:commons-codec:1.15
commons-collections:commons-collections:3.2.2
commons-discovery:commons-discovery:0.2
commons-io:commons-io:2.11.0
commons-lang:commons-lang:2.5
commons-lang:commons-lang:2.6
commons-logging:commons-logging:1.1.1
commons-logging:commons-logging:1.2
commons-net:commons-net:3.8.0
io.github.classgraph:classgraph:4.8.149
io.micrometer:micrometer-core:1.9.17
io.prometheus:simpleclient:0.15.0
io.prometheus:simpleclient_tracer_common:0.15.0
io.prometheus:simpleclient_tracer_otel:0.15.0
io.prometheus:simpleclient_tracer_otel_agent:0.15.0
io.springfox:springfox-bean-validators:2.4.0
io.springfox:springfox-core:2.4.0
io.springfox:springfox-spi:2.4.0
io.swagger.core.v3:swagger-annotations:2.2.8
io.swagger.core.v3:swagger-core:2.2.8
io.swagger.core.v3:swagger-models:2.2.8
io.swagger:swagger-annotations:1.5.6
jakarta.activation:jakarta.activation-api:1.2.2
jakarta.annotation:jakarta.annotation-api:1.3.5
jakarta.persistence:jakarta.persistence-api:2.2.3
jakarta.transaction:jakarta.transaction-api:1.3.3
jakarta.validation:jakarta.validation-api:2.0.2
jakarta.xml.bind:jakarta.xml.bind-api:2.3.3
javax.activation:activation:1.1
javax.activation:javax.activation-api:1.2.0
javax.mail:mail:1.4.7
javax.persistence:javax.persistence-api:2.2
javax.validation:validation-api:2.0.1.Final
javax.xml.bind:jaxb-api:2.3.1
jaxen:jaxen:1.2.0
net.bytebuddy:byte-buddy:1.12.23
net.bytebuddy:byte-buddy-agent:1.12.23
net.logstash.logback:logstash-logback-encoder:4.5.1
net.minidev:accessors-smart:2.4.11
net.minidev:json-smart:2.4.11
net.sf.ezmorph:ezmorph:1.0.6
net.sf.json-lib:json-lib:jdk15:2.4
org.apache.axis:axis:1.4
org.apache.axis:axis-jaxrpc:1.4
org.apache.axis:axis-saaj:1.4
org.apache.commons:commons-collections4:4.4
org.apache.commons:commons-lang3:3.12.0
org.apache.httpcomponents:httpasyncclient:4.1.5
org.apache.httpcomponents:httpclient:4.5.14
org.apache.httpcomponents:httpcore:4.4.16
org.apache.httpcomponents:httpcore-nio:4.4.16
org.apache.logging.log4j:log4j-api:2.17.2
org.apache.logging.log4j:log4j-to-slf4j:2.17.2
org.apache.skywalking:apm-toolkit-logback-1.x:8.14.0
org.apache.skywalking:apm-toolkit-trace:8.14.0
org.apache.tomcat.embed:tomcat-embed-core:9.0.83
org.apache.tomcat.embed:tomcat-embed-el:9.0.83
org.apache.tomcat.embed:tomcat-embed-websocket:9.0.83
org.apiguardian:apiguardian-api:1.1.2
org.aspectj:aspectjweaver:1.9.7
org.assertj:assertj-core:3.22.0
org.bouncycastle:bcmail-jdk15:1.46
org.bouncycastle:bcpkix-jdk18on:1.73
org.bouncycastle:bcprov-jdk15:1.46
org.bouncycastle:bcprov-jdk15on:1.70
org.bouncycastle:bcprov-jdk18on:1.73
org.bouncycastle:bcutil-jdk18on:1.73
org.checkerframework:checker-qual:3.12.0
org.codehaus.groovy:groovy-all:2.4.21
org.dom4j:dom4j:2.1.3
org.glassfish.jaxb:jaxb-runtime:2.3.9
org.glassfish.jaxb:txw2:2.3.9
org.hamcrest:hamcrest:2.2
org.hdrhistogram:HdrHistogram:2.1.12
org.hibernate.common:hibernate-commons-annotations:5.1.2.Final
org.hibernate.javax.persistence:hibernate-jpa-2.1-api:1.0.2.Final
org.hibernate.validator:hibernate-validator:6.2.5.Final
org.hibernate:hibernate-core:5.6.15.Final
org.ini4j:ini4j:0.5.4
org.jacoco:org.jacoco.agent:runtime:0.8.3
org.jboss.logging:jboss-logging:3.4.3.Final
org.jboss.spec.javax.transaction:jboss-transaction-api_1.2_spec:1.1.1.Final
org.jboss:jandex:2.4.2.Final
org.junit.jupiter:junit-jupiter:5.8.2
org.junit.jupiter:junit-jupiter-api:5.8.2
org.junit.jupiter:junit-jupiter-engine:5.8.2
org.junit.jupiter:junit-jupiter-params:5.8.2
org.junit.platform:junit-platform-commons:1.8.2
org.junit.platform:junit-platform-engine:1.8.2
org.latencyutils:LatencyUtils:2.0.3
org.mockito:mockito-core:4.5.1
org.mockito:mockito-junit-jupiter:4.5.1
org.objenesis:objenesis:3.2
org.opentest4j:opentest4j:1.2.0
org.ow2.asm:asm:9.3
org.skyscreamer:jsonassert:1.5.1
org.slf4j:jul-to-slf4j:1.7.36
org.slf4j:slf4j-api:1.7.36
org.springdoc:springdoc-openapi-common:1.6.15
org.springdoc:springdoc-openapi-ui:1.6.15
org.springdoc:springdoc-openapi-webmvc-core:1.6.15
org.springframework.boot:spring-boot:2.7.18
org.springframework.boot:spring-boot-actuator:2.7.18
org.springframework.boot:spring-boot-actuator-autoconfigure:2.7.18
org.springframework.boot:spring-boot-autoconfigure:2.7.18
org.springframework.boot:spring-boot-starter:2.7.18
org.springframework.boot:spring-boot-starter-actuator:2.7.18
org.springframework.boot:spring-boot-starter-aop:2.7.18
org.springframework.boot:spring-boot-starter-data-jpa:2.7.18
org.springframework.boot:spring-boot-starter-jdbc:2.7.18
org.springframework.boot:spring-boot-starter-json:2.7.18
org.springframework.boot:spring-boot-starter-logging:2.7.18
org.springframework.boot:spring-boot-starter-test:2.7.18
org.springframework.boot:spring-boot-starter-tomcat:2.7.18
org.springframework.boot:spring-boot-starter-validation:2.7.18
org.springframework.boot:spring-boot-starter-web:2.7.18
org.springframework.boot:spring-boot-test:2.7.18
org.springframework.boot:spring-boot-test-autoconfigure:2.7.18
org.springframework.cloud:spring-cloud-commons:3.1.8
org.springframework.cloud:spring-cloud-context:3.1.8
org.springframework.cloud:spring-cloud-starter:3.1.8
org.springframework.cloud:spring-cloud-starter-bootstrap:3.1.8
org.springframework.data:spring-data-commons:2.7.18
org.springframework.data:spring-data-jpa:2.7.18
org.springframework.plugin:spring-plugin-core:1.2.0.RELEASE
org.springframework.plugin:spring-plugin-metadata:1.2.0.RELEASE
org.springframework.security:spring-security-crypto:5.7.11
org.springframework.security:spring-security-rsa:1.0.12.RELEASE
org.springframework:spring-aop:5.3.34
org.springframework:spring-aspects:5.3.34
org.springframework:spring-beans:5.3.34
org.springframework:spring-context:5.3.34
org.springframework:spring-core:5.3.34
org.springframework:spring-expression:5.3.34
org.springframework:spring-jcl:5.3.34
org.springframework:spring-jdbc:5.3.34
org.springframework:spring-orm:5.3.34
org.springframework:spring-test:5.3.34
org.springframework:spring-tx:5.3.34
org.springframework:spring-web:5.3.34
org.springframework:spring-webmvc:5.3.34
org.webjars:swagger-ui:4.17.1
org.webjars:webjars-locator-core:0.50
org.xmlunit:xmlunit-core:2.9.1
org.yaml:snakeyaml:1.30
wsdl4j:wsdl4j:1.6.3
2.6.插件打包¶
DEMO插件工程使用Maven进行管理,在开发插件后,需要使用Maven命令来进行打包生成应用插件jar, 在工程的pom.xml文件所在目录,使用Maven 命令:
mvn clean package
运行成功后在target目录有以notify-sms-plugin-xxx-{version}-jar-with-plugin.jar
的文件生成即是插件jar。
考虑到Notify插件开发时有可能依赖其他第三方lib来完成插件开发(即在pom.xml中会加入第三方依赖dependency),在打包时需要分两种情况来处理,具体如下:
2.6.1.无任务第三方lib依赖¶
若无任何第三方lib依赖,直接如上所说使用Maven命令运行,使用生成的notify-sms-plugin-xxx-{version}-jar-with-plugin.jar
文件即可, 以i235为例打包后插件为:notify-sms-plugin-i235-1.0.0-jar-with-plugin.jar。
2.6.2.有第三方lib依赖¶
对于有第三方lib依赖的Notify插件,需要配置使用Maven的assembly插件来将指定的lib一起打包到一个jar中。
假设我们需要依赖一个叫 jjwt的第三方lib库,
首先在 pom.xml中加入依赖,如下图:
再在src/mian/assembly
目录增加assembly-plugin.xml
插件配置(在DEMO工程中已经有此插件配置,注释取消即可),如下图:
标签中的内容格式为:{groupId}:{artifactId}。
最后再使用Maven的打包命令生成对应的插件jar文件即可,如下图:
**注意:**此时生成的插件完整jar文件为:notify-sms-plugin-xxx-{version}-jar-with-plugin.jar
,即图中的notify-sms-plugin-demo-1.0.0-jar-with-plugin.jar
文件(此时的notify-sms-plugin-demo-1.0.0.jar
只包含工程本身代码,在没有额外第三方依赖,也就是只依赖了Notify核心包,这个插件包也是可以使用的)。
2.7.插件上传¶
使用ssh文件上传工具,这里我使用的xftp,登录到服务器上,到Notify插件目录(插件目录是Notify工作目录下的plugins文件夹下${workdir}/plugins),假如Notify的工作目录为:/data/applications/idp4-microservice/notify
对应的Notify插件目录:/data/applications/idp4-microservice/notify/plugins
,这里对应上传notify-sms-plugin-demo-1.0.0-jar-with-plugin.jar
插件到对应目录。
注意:若已经有相同的插件存在,需要移除之前的插件,若版本号升级,没有删除之前相同的插件,可能导致新上传的插件不可用。
如以下notify-sms-engine-esb-v2-1.0.0.jar
和notify-sms-engine-esb-v2-2.0.0.jar
两个插件,如果同时存在可能导致新版本插件无法加载。
2.8.运行调试¶
可以采用java的远程调试功能来调试插件;
3.UI Schema规范¶
具体请查看 IDaaS插件前端集成文档