写在前面
因为是真实的项目环境,很多代码都做了深度封装,直接看会觉得有点头大。建议拉到文章底部,看一下简单实践了解一下再看这篇文章。
需求背景
运维交付平台需要对发布的产品包进行统一的管理,包含,创建,编辑,删除,当下 删包管理存在gap,人员进行删包操作之后,对应负责人员无感知,需要做一个功能来承担删包管理,通知相关人员。
- 删包操作影响颇多,影响到部署的用户
- 影响到 等待升级的升级计划
!! 业务代码比较多,本次只摘录部分邮件发送的核心业务代码以及实现方式。
解决思路
ui 界面处理->获取到ui界面上的相关信息->进行删包操作 or 阻断升级操作 ->邮件给到对应人员。
简易prd
解决流程
依赖使用 ```java
org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-thymeleaf org.springframework.boot spring-boot-starter-mail org.springframework.boot spring-boot-starter-test
- talk is toomcuh show code。上代码
```java
public void sendMsgPauseUpgradePlan(Map<String, Object> data) {
try {
List<NoticeUser> noticeUserList = new ArrayList<>();
// 发送
noticeUserList.add(new NoticeUser("shihu@dtstack.com", true, false));
// 抄送
// noticeUserList.add(new NoticeUser("xx@dtstack.com", false, true)); // jiangbo
// noticeUserList.add(new NoticeUser("x@dtstack.com", false, true)); // toutian
// noticeUserList.add(new NoticeUser("x@dtstack.com", false, true)); //xiaodao
// noticeUserList.add(new NoticeUser("x@dtstack.com", false, true)); // huanxi
// noticeUserList.add(new NoticeUser("x@dtstack.com", false, true)); // muyun
// noticeUserList.add(new NoticeUser("x@dtstack.com", false, true)); // mushan
// noticeUserList.add(new NoticeUser("x@dtstack.com", false, true)); // erlong
// noticeUserList.add(new NoticeUser("x@dtstack.com", false, true)); // moxian
// 抄送当日值班人员
// List<String> dutyUserToday = getDutyUserToday();
// for (String email :dutyUserToday) {
// noticeUserList.add(new NoticeUser(email, false, true));
// }
Map<String, Object> dataModel = new HashMap<>();
dataModel.put("packageName",data.get("packageName")); // 产品包名
dataModel.put("module", data.get("moduleName")); // 模块
dataModel.put("tagVersion",data.get("tagVersion") ); // 影响tag
dataModel.put("packageInfo", data.get("packageInfo"));
dataModel.put("customerInfo", data.get("customerInfo"));
dataModel.put("upgradePlanInfo", data.get("upgradePlanInfo"));
String msg = noticeMessageTemplate.getMessage(NoticeMessageTemplate.MessageTemplateEnum.MSG_PAUSE_UPGRADEPLAN_TEMPLATE, dataModel);
NoticeMessage message = new NoticeMessage();
message.setNoticeUserList(noticeUserList);
// message.setTitle(String.format("【%s-%s】升级阻断通知", customer.getCustomerName(), environment.getEnvName()));
message.setTitle("升级阻断通知");
message.setContent(msg);
sendMessage(Collections.singletonList(NoticeType.EMAIL), message);
} catch (Exception e) {
LOG.warn("sendMsgToOpUser error:", e);
}
}
- 关键代码片段解释
```java
String msg =
noticeMessageTemplate.getMessage(NoticeMessageTemplate.MessageTemplateEnum.MSG_PAUSE_UPGRADEPLAN_TEMPLATE, dataModel);
—- getMessage 为 封装的匹配模板推送的代码 /**
* 部署申请模板
*/
DEPLOY_APPLY_TEMPLATE("deploy_apply.ftl"),
/**
* 变更申请模板
*/
CHANGE_APPLY_TEMPLATE("change_apply.ftl"),
/**
* 升级申请模板
*/
UPGRADE_APPLY_TEMPLATE("upgrade_apply.ftl"),
/**
* 紧急升级模板
*/
URGENT_UPGRADE_TEMPLATE("urgent_upgrade.ftl"),
/**
* 删包申请模板
*/
DELETE_PACKAGE_TEMPLATE("delete_package.ftl"),
/**
* 运维问题消息模板
*/
ISSUE_TEMPLATE("issue_message.ftl"),
MessageTemplateEnum 为各种发送邮件的枚举类
public String getMessage(MessageTemplateEnum templateEnum, MapdataModel) throws Exception { Template template = templateMap.get(templateEnum.name()); if (null == template) { throw new RuntimeException("Can not find message template by name:" + templateEnum.name()); } StringWriter out = new StringWriter(); template.process(dataModel, out); out.close(); return out.toString();
} ```
上面的代码因为层层封装可读性不是特别强,文末会给出最简便的实践方案
模板与填充
上图为前端向后端发送页面数据。可以看到我直接传的json字符串。
- 后端接收
- 业务层调用
下见发送邮件调用代码 ```java public void sendMsgPauseUpgradePlan(Map
data) { try { List<NoticeUser> noticeUserList = new ArrayList<>(); // 发送 noticeUserList.add(new NoticeUser("shihu@dtstack.com", true, false)); // 抄送
// noticeUserList.add(new NoticeUser(“xx@dtstack.com”, false, true)); // jiangbo // noticeUserList.add(new NoticeUser(“x@dtstack.com”, false, true)); // toutian // noticeUserList.add(new NoticeUser(“x@dtstack.com”, false, true)); //xiaodao // noticeUserList.add(new NoticeUser(“x@dtstack.com”, false, true)); // huanxi // noticeUserList.add(new NoticeUser(“x@dtstack.com”, false, true)); // muyun // noticeUserList.add(new NoticeUser(“x@dtstack.com”, false, true)); // mushan // noticeUserList.add(new NoticeUser(“x@dtstack.com”, false, true)); // erlong // noticeUserList.add(new NoticeUser(“x@dtstack.com”, false, true)); // moxian
// 抄送当日值班人员
// List
dutyUserToday = getDutyUserToday(); // for (String email :dutyUserToday) { // noticeUserList.add(new NoticeUser(email, false, true)); // } Map<String, Object> dataModel = new HashMap<>(); dataModel.put("packageName",data.get("packageName")); // 产品包名 dataModel.put("module", data.get("moduleName")); // 模块 dataModel.put("tagVersion",data.get("tagVersion") ); // 影响tag dataModel.put("packageInfo", data.get("packageInfo")); dataModel.put("customerInfo", data.get("customerInfo")); dataModel.put("upgradePlanInfo", data.get("upgradePlanInfo")); String msg = noticeMessageTemplate.getMessage(NoticeMessageTemplate.MessageTemplateEnum.MSG_PAUSE_UPGRADEPLAN_TEMPLATE, dataModel); NoticeMessage message = new NoticeMessage(); message.setNoticeUserList(noticeUserList);
// message.setTitle(String.format(“【%s-%s】升级阻断通知”, customer.getCustomerName(), environment.getEnvName()));
message.setTitle("升级阻断通知"); message.setContent(msg); sendMessage(Collections.singletonList(NoticeType.EMAIL), message); } catch (Exception e) { LOG.warn("sendMsgToOpUser error:", e); }
}
- 先上代码
- pasueUpgrade_apply.ftl
```java
<div><h1> 阻断升级申请 只是测试,当班人员可无视</h1></div>
<div> 产品包 :${packageName} </div> </br>
<div> 模块 : ${module} </div></br>
<div> 影响tag :${tagVersion} </div></br>
<#assign text>${packageInfo}</#assign> // 这里向后端传入的为json字符串,直接通过这样的方式引入模板并进行遍历
<#assign packageInfo=text?eval />
<#assign text1>${customerInfo}</#assign>
<#assign csutomers=text1?eval />
<#assign text2>${upgradePlanInfo}</#assign>
<#assign upgradePlanInfos=text2?eval />
<p>影响产品包</> <br>
<table>
<thead>
<tr>
<th colspan="4" style="background-color: #BFBFBF;text-align: center">产品包id</th>
<th colspan="4" style="background-color: #BFBFBF;text-align: center">产品包版本</th>
<th colspan="4" style="background-color: #BFBFBF;text-align: center">组件tag</th>
<th colspan="4" style="background-color: #BFBFBF;text-align: center">打包时间</th>
<th colspan="4" style="background-color: #BFBFBF;text-align: center">使用客户数</th>
<th colspan="4" style="background-color: #BFBFBF;text-align: center">产品包状态</th>
</tr>
</thead>
<tbody>
<#-- <#list json.userlist as item>-->
<#list packageInfo as item>
<tr>
<td colspan="4">${item.productPackageVersionId}</td>
<td colspan="4">${item.productPackageVersion}</td>
<td colspan="4">${item.moduleInfo}</td>
<td colspan="4">${item.createTime}</td>
<td colspan="4">${item.customerCount}</td>
<td colspan="4">${item.productPackgaeStatus}</td>
</tr>
</#list>
</tbody>
</table>
<p>受影响客户</p>
<table>
<thead>
<tr>
<th colspan="4" style="background-color: #BFBFBF;text-align: center">客户</th>
<th colspan="4" style="background-color: #BFBFBF;text-align: center">环境</th>
<th colspan="4" style="background-color: #BFBFBF;text-align: center">部署版本</th>
</tr>
</thead>
<tbody>
<#-- <#list json.userlist as item>-->
<#list csutomers as item>
<tr>
<td colspan="4">${item.customerName}</td>
<td colspan="4">${item.envName}</td>
<td colspan="4">${item.version}</td>
</tr>
</#list>
</tbody>
</table>
<p>受影响升级</p>
<table>
<thead>
<tr>
<th colspan="4" style="background-color: #BFBFBF;text-align: center">升级计划ID</th>
<th colspan="4" style="background-color: #BFBFBF;text-align: center">客户</th>
<th colspan="4" style="background-color: #BFBFBF;text-align: center">环境</th>
<th colspan="4" style="background-color: #BFBFBF;text-align: center">升级时间</th>
<th colspan="4" style="background-color: #BFBFBF;text-align: center">申请人员</th>
<th colspan="4" style="background-color: #BFBFBF;text-align: center">执行人员</th>
<th colspan="4" style="background-color: #BFBFBF;text-align: center">状态</th>
</tr>
</thead>
<tbody>
<#-- <#list json.userlist as item>-->
<#list upgradePlanInfos as item>
<tr>
<td colspan="4">${item.upgradePlanId}</td>
<td colspan="4">${item.customerName}</td>
<td colspan="4">${item.envName}</td>
<td colspan="4">${item.cteateTime}</td>
<td colspan="4">${item.upgradePlanApplyUser}</td>
<td colspan="4">${item.upgradePlanOperatorUser}</td>
<td colspan="4">${item.upgradePlanStatus}</td>
</tr>
</#list>
</tbody>
</table>
- 模板可以渲染html代码,所以可以按照h5的编写方法去编写自己需要的模板内容
语法支持不太友好,其支持的是freemarker语法,这个语法对后端人员比较友好。
效果
简陋是简陋了一些,满足日常使用即可。