在我们系统研发过程中经常需要发送短信、邮件、站内信等,笔者在本文给大家介绍下如何使用Oinone的消息模块。
准备工作
如果通过我们工程脚手架工具生成的则已经引入了无需做更多的配置,如果不是则需要按以下步骤先配置依赖和增加启动模块
pamirs-demo-boot的pom文件中引入pamirs-message-core包依赖
<dependency>
<groupId>pro.shushi.pamirs.core</groupId>
<artifactId>pamirs-message-core</artifactId>
</dependency>
pamirs-demo-boot的application-dev.yml文件中增加配置pamirs.boot.modules增加message,即在启动应用中增加message模块
pamirs:
boot:
modules:
- message
消息参数设置
发送邮件和短信需要设置对应的发送邮箱服务器和短信云,短信目前默认阿里云短信。我们通过代码示例来完成对应邮箱和短信的参数设置
Step1 增加pamirs-message-api依赖
pamirs-demo-core的pom文件中引入pamirs-message-api包依赖
<dependency>
<groupId>pro.shushi.pamirs.core</groupId>
<artifactId>pamirs-message-api</artifactId>
</dependency>
Step2 消息参数设置
请自行替换邮箱服务器和短信通道的账号信息
package pro.shushi.pamirs.demo.core.init;
import org.springframework.stereotype.Component;
import pro.shushi.pamirs.boot.common.api.command.AppLifecycleCommand;
import pro.shushi.pamirs.boot.common.api.init.InstallDataInit;
import pro.shushi.pamirs.boot.common.api.init.UpgradeDataInit;
import pro.shushi.pamirs.demo.api.DemoModule;
import pro.shushi.pamirs.message.enmu.EmailSendSecurityEnum;
import pro.shushi.pamirs.message.enmu.MessageEngineTypeEnum;
import pro.shushi.pamirs.message.enmu.SMSChannelEnum;
import pro.shushi.pamirs.message.model.EmailSenderSource;
import pro.shushi.pamirs.message.model.SmsChannelConfig;
import java.util.Collections;
import java.util.List;
@Component
public class DemoMessageInit implements InstallDataInit, UpgradeDataInit {
private void initEmail(){
EmailSenderSource emailSenderSource = new EmailSenderSource();
emailSenderSource.setName("邮件发送服务");
emailSenderSource.setType(MessageEngineTypeEnum.EMAIL_SEND);
//优先级
emailSenderSource.setSequence(10);
//发送账号 FIXME 自行替换
emailSenderSource.setSmtpUser("");
//发送密码 FIXME 自行替换
emailSenderSource.setSmtpPassword("");
//发送服务器地址和端口
emailSenderSource.setSmtpHost("smtp.exmail.qq.com");
emailSenderSource.setSmtpPort(465);
//" None: SMTP 对话用明文完成。" +
//" TLS (STARTTLS): SMTP对话的开始时要求TLS 加密 (建议)" +
//" SSL/TLS: SMTP对话通过专用端口用 SSL/TLS 加密 (默认是: 465)")
emailSenderSource.setSmtpSecurity(EmailSendSecurityEnum.SSL);
emailSenderSource.createOrUpdate();
}
private void initSms(){
SmsChannelConfig smsChannelConfig = new SmsChannelConfig();
smsChannelConfig.setType(MessageEngineTypeEnum.SMS_SEND);
smsChannelConfig.setChannel(SMSChannelEnum.ALIYUN);
//短信签名名称
smsChannelConfig.setSignName("oinone");
//阿里云账号信息 FIXME 自行替换
smsChannelConfig.setAccessKeyId("");
smsChannelConfig.setAccessKeySecret("");
smsChannelConfig.setEndpoint("https://dysmsapi.aliyuncs.com");
smsChannelConfig.setRegionId("cn-hangzhou");
smsChannelConfig.setTimeZone("GMT");
smsChannelConfig.setSignatureMethod("HMAC-SHA1");
smsChannelConfig.setSignatureVersion("1.0");
smsChannelConfig.setVersion("2017-05-25");
smsChannelConfig.createOrUpdate();
//初始化短信模版
//目前支持阿里云短信通道:获取短信模板,如没有短信模板,需要先创建模板,并审核通过
SmsTemplate smsTemplate = new SmsTemplate();
smsTemplate.setName("通知短信");
smsTemplate.setTemplateType(SMSTemplateTypeEnum.NOTIFY);
smsTemplate.setTemplateCode("SMS_244595482");//从阿里云获取,自行提供 FIXME
smsTemplate.setTemplateContent("尊敬的&{name},你的&{itemName}库存为&{quantity}");
smsTemplate.setChannel(SMSChannelEnum.ALIYUN);
smsTemplate.setStatus(SMSTemplateStatusEnum.SUCCESS);
smsTemplate.createOrUpdate();
}
@Override
public boolean init(AppLifecycleCommand command, String version) {
initEmail();
initSms();
return Boolean.TRUE;
}
@Override
public boolean upgrade(AppLifecycleCommand command, String version, String existVersion) {
initEmail();
initSms();
return Boolean.TRUE;
}
@Override
public List<String> modules() {
return Collections.singletonList(DemoModule.MODULE_MODULE);
}
@Override
public int priority() {
return 0;
}
}
消息发送举例
该例子以各种站内信、邮件、短信方式发送宠物商品库存记录信息为例,构建宠物商品库存信息发送服务并在宠物商品库存模型的表格页面创建发送入口
Step1 创建宠物商品库存信息发送服务接口
在Api工程新建PetItemInventoryMessageService接口,并定义发送站内信、邮件、短信的三个Function
package pro.shushi.pamirs.demo.api.service;
import pro.shushi.pamirs.demo.api.model.PetItemInventroy;
import pro.shushi.pamirs.meta.annotation.Fun;
import pro.shushi.pamirs.meta.annotation.Function;
@Fun(PetItemInventoryMessageService.FUN_NAMESPACE)
public interface PetItemInventoryMessageService {
String FUN_NAMESPACE = "demo.PetItemInventoryMessageService";
@Function
void sendMail(PetItemInventroy data);
@Function
void sendEmail(PetItemInventroy data);
@Function
void sendSms(PetItemInventroy data);
}
Step2 发送站内信
在Core工程新建PetItemInventoryMessageService接口的实现类
package pro.shushi.pamirs.demo.core.service;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import pro.shushi.pamirs.demo.api.enumeration.DemoExpEnumerate;
import pro.shushi.pamirs.demo.api.model.PetItemInventroy;
import pro.shushi.pamirs.demo.api.service.PetItemInventoryMessageService;
import pro.shushi.pamirs.demo.core.session.DemoSession;
import pro.shushi.pamirs.message.engine.MessageEngine;
import pro.shushi.pamirs.message.engine.email.EmailSender;
import pro.shushi.pamirs.message.engine.message.MessageSender;
import pro.shushi.pamirs.message.engine.sms.SMSSender;
import pro.shushi.pamirs.message.enmu.MessageEngineTypeEnum;
import pro.shushi.pamirs.message.enmu.MessageGroupTypeEnum;
import pro.shushi.pamirs.message.enmu.MessageTypeEnum;
import pro.shushi.pamirs.message.enmu.SMSTemplateTypeEnum;
import pro.shushi.pamirs.message.model.PamirsMessage;
import pro.shushi.pamirs.message.model.SmsTemplate;
import pro.shushi.pamirs.message.tmodel.EmailPoster;
import pro.shushi.pamirs.message.tmodel.SystemMessage;
import pro.shushi.pamirs.meta.annotation.Fun;
import pro.shushi.pamirs.meta.annotation.Function;
import pro.shushi.pamirs.meta.annotation.fun.extern.Slf4j;
import pro.shushi.pamirs.meta.common.exception.PamirsException;
import pro.shushi.pamirs.meta.util.JsonUtils;
import pro.shushi.pamirs.user.api.model.PamirsUser;
import javax.mail.MessagingException;
import javax.mail.SendFailedException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@Fun(PetItemInventoryMessageService.FUN_NAMESPACE)
@Slf4j
@Component
public class PetItemInventoryMessageServiceImpl implements PetItemInventoryMessageService {
public static final String INVALID_ADDRESSES_CODE = "Invalid Addresses";
public static final String INVALID_ADDRESSES_MSG = "非法的邮箱地址";
public static final String CAN_NO_CONNECT_TO_SMTP_CODE = "Could not connect to SMTP";
public static final String CAN_NO_CONNECT_TO_SMTP_MSG = "连接邮件服务失败";
@Override
@Function
public void sendMail(PetItemInventroy data) {
//接收对象列表
PamirsUser user = DemoSession.getUser();
List<Long> userIds = new ArrayList<>();
userIds.add(user.getId());
String subject = "商品库存信息";
String body = data.getItemName() + "_" + data.getQuantity();
MessageSender mailSender = (MessageSender) MessageEngine.get(MessageEngineTypeEnum.MAIL_SEND).get(null);
PamirsMessage message = new PamirsMessage()
.setName(subject)
.setSubject(subject)
.setBody(body)
.setMessageType(MessageTypeEnum.NOTIFICATION);
List<PamirsMessage> messages = new ArrayList<>();
messages.add(message);
SystemMessage systemMessage = new SystemMessage();
systemMessage.setPartners(userIds.stream().map(i -> (PamirsUser) new PamirsUser().setId(i)).collect(Collectors.toList()))
.setType(MessageGroupTypeEnum.SYSTEM_MAIL)
.setMessages(messages);
try {
mailSender.sendSystemMail(systemMessage);
} catch (Exception e) {
// TODO: 可增加失败业务处理
throw PamirsException.construct(DemoExpEnumerate.SYSTEM_ERROR, e).appendMsg("站内信发送失败").errThrow();
}
}
@Override
@Function
public void sendEmail(PetItemInventroy data) {
//发送一个邮件
List<String> receiveEmails = new ArrayList<>();
receiveEmails.add("testhaha@shushi.pro");//收件人邮箱,自行替换 FIXME
EmailSender emailSender = null;
EmailPoster emailPoster = null;
emailSender = (EmailSender) MessageEngine.get(MessageEngineTypeEnum.EMAIL_SEND).get(null);
String title = data.getItemName();//"邮件标题";
String body = data.getItemName() + "_" + data.getQuantity();//"邮件内容";
String sender = DemoSession.getUserName();//"发件人";
String replyEmail = "回复邮箱";
emailPoster = new EmailPoster().setSender(sender).setTitle(title).setBody(body).setReplyTo(replyEmail);
EmailPoster finalEmailPoster = emailPoster;
EmailSender finalEmailSender = emailSender;
StringBuilder errorMessages = new StringBuilder();
receiveEmails.stream().distinct().collect(Collectors.toList()).forEach(
email -> {
try {
if (!finalEmailSender.send(finalEmailPoster.setSendTo(email))) {
log.error("发送邮件失败:emailPoster:{}", JsonUtils.toJSONString(finalEmailPoster));
String message = "发送邮件失败,错误信息:" + "系统异常" + ",邮箱:" + email + ";";
errorMessages.append(message);
}
} catch (Exception e) {
log.error("发送邮件失败:emailPoster:{},异常:{}", JsonUtils.toJSONString(finalEmailPoster), e);
String errorMsg = transferEmailThrowMessage(e);
String message = "发送邮件失败,错误信息:" + errorMsg + ",邮箱:" + email + ";";
errorMessages.append(message);
}
}
);
if (StringUtils.isNotBlank(errorMessages.toString())) {
// TODO: 可增加处理邮件发送失败的业务逻辑
}
}
private String transferEmailThrowMessage(Exception e) {
String errorMessage = e.getMessage();
Throwable cause = e.getCause();
if (cause != null) {
if (cause instanceof SendFailedException) {
String message = cause.getMessage();
if (INVALID_ADDRESSES_CODE.equals(message)) {
errorMessage = INVALID_ADDRESSES_MSG;
}
} else if (cause instanceof MessagingException) {
String message = cause.getMessage();
if (StringUtils.isNotBlank(message) && message.contains(CAN_NO_CONNECT_TO_SMTP_CODE)) {
errorMessage = CAN_NO_CONNECT_TO_SMTP_MSG;
}
}
}
return errorMessage;
}
@Override
@Function
public void sendSms(PetItemInventroy data) {
StringBuilder errorMessages = new StringBuilder();
List<String> receivePhoneNumbers = new ArrayList<>();
receivePhoneNumbers.add("13777899044");//接收手机号,自行提供 FIXME
//目前支持阿里云短信通道:获取短信模板,如没有短信模板,需要先创建模板,并审核通过
//如以下示例
SmsTemplate smsTemplate = new SmsTemplate().setTemplateType(SMSTemplateTypeEnum.NOTIFY).setTemplateCode("SMS_246455054").queryOne();//从阿里云获取
// 占位符处理
Map<String, String> vars = new HashMap<>();
vars.put("name", DemoSession.getUserName());
vars.put("itemName", data.getItemName());
vars.put("quantity", data.getQuantity().toString());
SMSSender smsSender = (SMSSender) MessageEngine.get(MessageEngineTypeEnum.SMS_SEND).get(null);
receivePhoneNumbers.stream().distinct().forEach(it -> {
try {
if (!smsSender.smsSend(smsTemplate, it, vars)) {
String message = "发送短信失败,错误信息:" + "系统异常" + ",手机号:" + it + ";";
errorMessages.append(message);
}
} catch (Exception e) {
String message = "发送短信失败,错误信息:" + e.getMessage() + ",手机号:" + it + ";";
errorMessages.append(message);
}
});
if (StringUtils.isNotBlank(errorMessages.toString())) {
// TODO: 可增加失败业务处理
}
}
}
Step3 为宠物商品库存模型的表格页面新增发送入口
把以下代码复制到PetItemInventroyAction类中
@Autowired
private PetItemInventoryMessageService petItemInventoryMessageService;
@Action(displayName = "发送站内信",bindingType = ViewTypeEnum.TABLE,contextType = ActionContextTypeEnum.SINGLE)
public PetItemInventroy sendMail(PetItemInventroy data) {
petItemInventoryMessageService.sendMail(data);
return data;
}
/**
* 发送邮件
*/
@Action(displayName = "发送邮件",bindingType = ViewTypeEnum.TABLE,contextType = ActionContextTypeEnum.SINGLE)
public PetItemInventroy sendEmail(PetItemInventroy data){
petItemInventoryMessageService.sendEmail(data);
return data;
}
/**
* 发送短息
*/
@Action(displayName = "发送短信",bindingType = ViewTypeEnum.TABLE,contextType = ActionContextTypeEnum.SINGLE)
public PetItemInventroy sendSms(PetItemInventroy data){
petItemInventoryMessageService.sendSms(data);
return data;
}
Step4 重启看效果
请分别点击发送邮件、发送短信、发送站内信测试效果,自行测试效果
Oinone社区 作者:史, 昂原创文章,如若转载,请注明出处:https://doc.oinone.top/oio4/9330.html
访问Oinone官网:https://www.oinone.top获取数式Oinone低代码应用平台体验