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

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

作者:互联网

自己原本的解决方案思路是:将该个代码移到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