写在前面

  • 因为是真实的项目环境,很多代码都做了深度封装,直接看会觉得有点头大。建议拉到文章底部,看一下简单实践了解一下再看这篇文章。

    需求背景

  • 运维交付平台需要对发布的产品包进行统一的管理,包含,创建,编辑,删除,当下 删包管理存在gap,人员进行删包操作之后,对应负责人员无感知,需要做一个功能来承担删包管理,通知相关人员。

  • 删包操作影响颇多,影响到部署的用户
  • 影响到 等待升级的升级计划

!! 业务代码比较多,本次只摘录部分邮件发送的核心业务代码以及实现方式。

解决思路

  • ui 界面处理->获取到ui界面上的相关信息->进行删包操作 or 阻断升级操作 ->邮件给到对应人员。

    简易prd

    image.png

    解决流程

  • 依赖使用 ```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
  1. - talk is toomcuh show code。上代码
  2. ```java
  3. public void sendMsgPauseUpgradePlan(Map<String, Object> data) {
  4. try {
  5. List<NoticeUser> noticeUserList = new ArrayList<>();
  6. // 发送
  7. noticeUserList.add(new NoticeUser("shihu@dtstack.com", true, false));
  8. // 抄送
  9. // noticeUserList.add(new NoticeUser("xx@dtstack.com", false, true)); // jiangbo
  10. // noticeUserList.add(new NoticeUser("x@dtstack.com", false, true)); // toutian
  11. // noticeUserList.add(new NoticeUser("x@dtstack.com", false, true)); //xiaodao
  12. // noticeUserList.add(new NoticeUser("x@dtstack.com", false, true)); // huanxi
  13. // noticeUserList.add(new NoticeUser("x@dtstack.com", false, true)); // muyun
  14. // noticeUserList.add(new NoticeUser("x@dtstack.com", false, true)); // mushan
  15. // noticeUserList.add(new NoticeUser("x@dtstack.com", false, true)); // erlong
  16. // noticeUserList.add(new NoticeUser("x@dtstack.com", false, true)); // moxian
  17. // 抄送当日值班人员
  18. // List<String> dutyUserToday = getDutyUserToday();
  19. // for (String email :dutyUserToday) {
  20. // noticeUserList.add(new NoticeUser(email, false, true));
  21. // }
  22. Map<String, Object> dataModel = new HashMap<>();
  23. dataModel.put("packageName",data.get("packageName")); // 产品包名
  24. dataModel.put("module", data.get("moduleName")); // 模块
  25. dataModel.put("tagVersion",data.get("tagVersion") ); // 影响tag
  26. dataModel.put("packageInfo", data.get("packageInfo"));
  27. dataModel.put("customerInfo", data.get("customerInfo"));
  28. dataModel.put("upgradePlanInfo", data.get("upgradePlanInfo"));
  29. String msg = noticeMessageTemplate.getMessage(NoticeMessageTemplate.MessageTemplateEnum.MSG_PAUSE_UPGRADEPLAN_TEMPLATE, dataModel);
  30. NoticeMessage message = new NoticeMessage();
  31. message.setNoticeUserList(noticeUserList);
  32. // message.setTitle(String.format("【%s-%s】升级阻断通知", customer.getCustomerName(), environment.getEnvName()));
  33. message.setTitle("升级阻断通知");
  34. message.setContent(msg);
  35. sendMessage(Collections.singletonList(NoticeType.EMAIL), message);
  36. } catch (Exception e) {
  37. LOG.warn("sendMsgToOpUser error:", e);
  38. }
  39. }
  • 关键代码片段解释 ```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, Map dataModel) 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();
    

    } ```

  • 上面的代码因为层层封装可读性不是特别强,文末会给出最简便的实践方案

    模板与填充

    image.png

  • 上图为前端向后端发送页面数据。可以看到我直接传的json字符串。

  • 后端接收

image.png

  • 业务层调用

image.png

  • 下见发送邮件调用代码 ```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语法,这个语法对后端人员比较友好。

    效果

    image.png

  • 简陋是简陋了一些,满足日常使用即可。

springboot整合Thymleaf邮件模板发送邮件简单实践

http://www.manongjc.com/detail/18-xornhlmafsngnjd.html