ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

后端代码 定时发送邮件--(线上环境一般都是两台),考虑线上服务器多台的问题

2021-12-10 21:00:07  阅读:401  来源: 互联网

标签:String -- mailInfo 发送 mailSet 线上 new 多台 邮件


自己原本的解决方案思路是:将该个代码移到Job项目中(就是只部署到一台服务器上的代码) 或者在数据库表中添加发送邮件的记录,后来发现只有第一个(只部署到一台服务器上)才能实现;第二种发现不管用,一到需求文档要求的时间,就算在数据库记录中记录发送邮件是否失败的记录信息,但是两台服务器那个同一时间开始发送邮件,都会先到数据库中查询是否有发送过的记录数据,发布到线上(两台服务器--负载均衡)环境发现在那个时间数据库记录表中都还没有相关记录。就会出现重复发送邮件的情况--每台服务器都是发送一封。

 

第一种就不用说了,和我第一篇随笔--定时任务代码类似

主要说下第二种思路错误的,如何解决

①首先,先附上发送邮件的代码

//发送邮件
public void TimerSendEmail(){
//获取环境变量
String flag=System.getenv("EmailServer");
if(flag.equals("true")){
String yesterday = new SimpleDateFormat("yyyy-MM-dd").format(DateUtils.dateDecrease(new Date(),1));
try {
System.setProperty("java.net.preferIPv4Stack", "true");
sendMail(yesterday);
} catch (Exception e) {
e.printStackTrace();
}
}else {
logger.info("环境变量" + flag);
}
}

public void sendMail(String yesterday) throws Exception{
// 获取发送方的邮箱账号信息
MailSetEntity mailSet=new MailSetEntity();

mailSet.setAuth("true");
mailSet.setFromAddress("账号");//邮箱的账号
mailSet.setFromAddressPwd("密码");  //邮箱密码
mailSet.setHost("smtp.centaline.com.cn");//邮箱SMTP服务器地址
mailSet.setPort("25");//端口
mailSet.setSmtp("smtp.centaline.com.cn"); //发件人使用发邮件的电子信箱服务器 个人邮箱(smtp.163.com)和企业邮箱设置值不同 "smtp.centaline.com.cn"
mailSet.setDebug(true);

//以下就是自己逻辑代码
// 查询用户角色权限
OrgUserDepartmentQuery roleQuery = new OrgUserDepartmentQuery();
//员工职称列表集合
String positionName = Constant.REGIONAL_MANAGER + "," +Constant.STORE_MANAGER;
roleQuery.setPositionNames(Arrays.asList(positionName.split(",").clone()));

//要发送到的邮箱集合
String addresses ="";
// 设置邮件发送信息
MailInfoEntity mailInfo = new MailInfoEntity();

mailInfo.setSubject(yesterday+"IBS用戶登入、打印記錄及查看業主報告");
String fileFullPath="";
String fileName="";

mailInfo.setContext(yesterday + "内容");

SystemLogSendEmailQuery query=new SystemLogSendEmailQuery();

List<RptSystemLogSendEmailBean> sendEmailRecord=new ArrayList<RptSystemLogSendEmailBean>();
List<PMRolePO> roles = userDao.findUserRoleListByPosition(roleQuery);
// 查找到对应的职称权限
if (roles.size() > 0) {
// 遍历循环生成多个excel
for (PMRolePO role : roles) {
String rightJson = role.getRightJson();
JsonNode jsonpObject = JsonUtils.jsonToObject(rightJson);
if (null != jsonpObject && null != jsonpObject.get(PermissionCodeEnum.WORKSTATS.getValue())) {
JsonNode rightValue = jsonpObject.get(PermissionCodeEnum.WORKSTATS.getValue());
if (PermissionCodeEnum.ALL.getValue().equals(rightValue.textValue())) { // 全部权限
// 全部权限和导出一样,部门编号赋值“”
fileFullPath = filePath.toString() + "/" + yesterday + "" + "報告.xls";
fileName = yesterday + "" + "IBS報告.xls";
// 调用发送邮件之前,先查询是否对应文件的发送记录
// 如果没有,则启动发送邮件方法;如果有,则不调用
query.setFilename(fileName);
query.setSendTime(new SimpleDateFormat("yyyy-MM-dd").format(new Date()));
// 邮件按照配置文件中配置的邮件名
addresses = Constant.PERMISSION_ALL_SEND_TO_MAIL;
query.setEmailAddress(addresses);
query.setDeptPath("");
query.setFlagSuccess(true);
sendEmailRecord = sysItemDao.findSendEmailRecord(query);
if (sendEmailRecord.size() == 0) {
mailInfo.setFileAddress(fileFullPath);
mailInfo.setFileName(fileName);
// 发送邮件给主管人员
sendEmail(mailSet, mailInfo, addresses,"");
}
} else if (PermissionCodeEnum.DEPARTMENT.getValue().equals(rightValue.textValue())) { // 本部权限
fileFullPath = filePath.toString() + "/" + yesterday + role.getDeptPath() + "報告.xls";
fileName = yesterday + role.getDeptPath() + "報告.xls";
// 调用发送邮件之前,先查询是否对应文件的发送记录
// 如果没有,则启动发送邮件方法;如果有,则不调用
query.setFilename(fileName);
query.setSendTime(new SimpleDateFormat("yyyy-MM-dd").format(new Date()));

// 邮件只能发送能和部门编号对应上的excel附件,并且发送给对应的邮箱
if (fileName.indexOf(role.getDeptPath()) != -1) {
addresses = role.getEmail();
}
query.setEmailAddress(addresses);
query.setDeptPath(role.getDeptPath());
query.setFlagSuccess(true);
sendEmailRecord = sysItemDao.findSendEmailRecord(query);
if (sendEmailRecord.size() == 0) {
mailInfo.setFileAddress(fileFullPath);
mailInfo.setFileName(fileName);
// 发送邮件给主管人员
sendEmail(mailSet, mailInfo, addresses,role.getDeptPath());
}
}
}
}
}
}

 

/**
* 发送邮件给主管人员
* @throws Exception
*/
public void sendEmail(MailSetEntity mailSet, MailInfoEntity mailInfo,String addresses,String deptPath) throws Exception {
RptSystemLogSendEmailBean sendMailBean=new RptSystemLogSendEmailBean();
// 发送邮件
try {
// 设置收件人
String[] tos = addresses.split(",");
mailInfo.setTos(tos);

send(mailSet, mailInfo);
logger.info("发送成功 >>>> 报表");
//发送后在数据库表做个记录,如果有发送记录,则不发送了

sendMailBean.setFileAddress(mailInfo.getFileAddress());
sendMailBean.setFilename(mailInfo.getFileName());
sendMailBean.setEmailAddress(addresses);
sendMailBean.setDeptPath(deptPath);
sendMailBean.setFlagSuccess(true);
sysItemDao.addSendEmailRecord(sendMailBean);

} catch (Exception e) {
e.printStackTrace();
//发送后在数据库表做个记录,如果有发送记录,则不发送了
sendMailBean.setFileAddress(mailInfo.getFileAddress());
sendMailBean.setFilename(mailInfo.getFileName());
sendMailBean.setEmailAddress(addresses);
sendMailBean.setDeptPath(deptPath);
sendMailBean.setFlagSuccess(false);
sysItemDao.addSendEmailRecord(sendMailBean);


logger.info("发送邮件失败");
}
}

 

/*
* 发送邮件到指定邮箱
* 收件人,抄送人 ,附件地址,附件名称
*/
public static void send(MailSetEntity mailSet, MailInfoEntity mailInfo) throws Exception {
// 1.创建一个程序与邮件服务器会话对象 Session,包含邮件服务器网络连接信息
Properties props = new Properties();
//在初始化邮件的时候加入这些参数,设置下超时时间,默认的是无穷大
props.put("mail.smtp.timeout", 10000);
props.put("mail.smtp.connectiontimeout", 10000);
props.put("mail.smtp.writetimeout", 10000);

// 指定邮件的传输协议,smtp;同时通过验证
props.setProperty("mail.transport.protocol", "smtp");
props.setProperty("mail.host", "smtp.centaline.com.cn");
props.setProperty("mail.smtp.auth", mailSet.getAuth());
Session session = Session.getDefaultInstance(props);
// 开启调试模式
session.setDebug(mailSet.getDebug());

// 2.创建一个Message,它相当于是邮件内容
Message message = new MimeMessage(session);
// 设置邮件消息头
message.setFrom(new InternetAddress(mailSet.getFromAddress()));// 设置发送者
// 创建邮件接收者地址
String[] tos = mailInfo.getTos();
if (tos != null && tos.length != 0) {
InternetAddress[] to = new InternetAddress[tos.length];
// 设置邮件消息的发送者
for (int i = 0; i < tos.length; i++) {
to[i] = new InternetAddress(tos[i]);
}
message.setRecipients(Message.RecipientType.TO, to);// 设置发送方式与接收者
}
// 设置邮件抄送者地址
String[] copyto = mailInfo.getCopyto();
if (copyto != null && copyto.length != 0) {
InternetAddress[] toCC = new InternetAddress[copyto.length];
// 设置邮件消息的发送者
for (int i = 0; i < copyto.length; i++) {
toCC[i] = new InternetAddress(copyto[i]);
}
message.addRecipients(Message.RecipientType.CC, toCC);
}

// 设置主题
message.setSubject(mailInfo.getSubject());
// 设置邮件消息内容、包含附件
Multipart msgPart = new MimeMultipart();
message.setContent(msgPart);

MimeBodyPart body = new MimeBodyPart(); // 正文
MimeBodyPart attach = new MimeBodyPart(); // 附件

msgPart.addBodyPart(body);
msgPart.addBodyPart(attach);

// 设置正文内容
body.setContent(mailInfo.getContext(), "text/html;charset=utf-8");
// 设置附件内容
attach.setDataHandler(new DataHandler(new FileDataSource(mailInfo.getFileAddress())));
attach.setFileName((MimeUtility.encodeText(mailInfo.getFileName())));

message.saveChanges();

// 3.创建 Transport用于将邮件发送
Transport trans = session.getTransport();
trans.connect(mailSet.getSmtp(), mailSet.getFromAddress(), mailSet.getFromAddressPwd());
trans.sendMessage(message, message.getAllRecipients());
trans.close();
}

②我们代码是采用docker +disconf +jenkins

 

 

 dockerfile文件内容:

#代码运行环境 Tomcat

FROM tomcat:8

MAINTAINER zhaoxl

#定义时区参数  --可以保证容器中时间和本地时间一致
ENV TZ=Asia/Shanghai

#后端代码--编译成war  放到固定的webapps文件下

COPY ibsWebService.war /usr/local/tomcat/webapps/ibsWebService.war

 

 

 点击左导的配置

 

 

 

 

这步是关键,后端代码两台,我只想让一台服务实现定点发送邮件,这样就解决了重复发送邮件的问题

在服务器启动镜像语句中添加一个环境变量(名字看你随意),,,并且要放到docker run 后面  最重要的是一定要和其启动镜像其他语句保持 空格 隔开 不然在容器中是拿不到这个环境变量,代码就会不起作用

#启动镜像语句
docker run -e "EmailServer=false" --restart=always --name 镜像名 -d -p 映射端口:8080 -v /home/log/HK/IBS_OFI/webService:/usr/local/tomcat/logs 私库:端口/镜像名:tag名(私库存储前端配置文件和镜像)

(一台服务器设置为true,另外一台设置为false) 这样就解决问题~~~~~~~~~

-e "EmailServer=false"  这个就是你配置的环境的变量 结合以上发送邮件的代码,获取环境变量

//获取环境变量
String flag=System.getenv("EmailServer");
if(flag.equals("true")){   //执行发送邮件代码 }  else{ //不执行发送邮件代码 }

最后一步,验证该环境变量是否获取

1>你可以打个日志输出

private static Logger logger = Logger.getLogger(类名.class);  logger.info("环境变量为'');

2>jenkins 启动发版后

容器列表 docker ps -a 进入容器:docker exec -it 容器ID /bin/sh 或者 docker exec -it 容器ID /bin/bash

输入命令 env 

 

 

这样问题就解决了,完美!

 

标签:String,--,mailInfo,发送,mailSet,线上,new,多台,邮件
来源: https://www.cnblogs.com/bellSmile/p/15673819.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有