Springboot程序异常邮件通知

闲话少许,上码。
---> 开发ide:idea
---> jdk:1.8

一.建立一个普通Springboot项目,加入以下依赖:

		<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
         <!-- lombok插件,需要idea安装lombok插件并引入以下依赖 -->
 		 <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>${lombok.version}</version>
        </dependency>
  		 <!-- email -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-mail</artifactId>
        </dependency>
        <!-- freemarker -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-freemarker</artifactId>
        </dependency>

二.配置application.yml

  # 邮件配置
spring:
  mail:
    host: smtp.126.com #用什么邮箱发送就用对应的host
    username: [email protected] #你要发送邮件的邮箱
    password: #此处填写你邮箱的授权码,注意:不是密码哦
    properties:
      mail:
        smtp:
          auth: true
          starttls:
            enable: true
            required: true
  mvc:
    throw-exception-if-no-handler-found: true
#    static-path-pattern: /static/**
  # freemarker
  freemarker:
    template-loader-path:
      - classpath:/templates
    suffix: .ftl
    enabled: true
    cache: false
    charset: UTF-8
    content-type: text/html
    allow-request-override: false
    check-template-location: true
    expose-request-attributes: false
    expose-session-attributes: false
    expose-spring-macro-helpers: false

# 异常通知地址 多个邮箱以逗号分隔
alarm:
  email: [email protected],[email protected]

三.建立Email类

package com.lhyt.modules.sys.mail;

import lombok.Data;

import java.io.Serializable;
import java.util.HashMap;

/**
 * Email封装对象
 *
 * @author wangdy
 * @date 2019/4/19 22:14
 */
@Data //该注解会自动生成 getter setter 方法
public class Email implements Serializable {

    private static final long serialVersionUID = 1L;

    // 必填参数
    private String[] email;// 接收方邮件数组
    private String subject;// 主题,邮件标题
    private String content;// 邮件内容文本
    // 以模板发送邮件的时候填写以下参数的值
    private String template;// 邮件模板
    private HashMap<String, Object> kvMap;// 自定义参数,用于模板发送时显示内容

    public Email() {
        super();
    }

    public Email(String[] email, String subject, String content, String template, HashMap<String, Object> kvMap) {
        super();
        this.email = email;
        this.subject = subject;
        this.content = content;
        this.template = template;
        this.kvMap = kvMap;
    }
}

四.定义接口,实现类

接口
package com.lhyt.modules.sys.service;

import com.lhyt.modules.sys.mail.Email;

/**
 * 邮件发送服务
 *
 * @author wangdy
 * @date 2019/4/19 22:16
 */
public interface IMailService {

    /**
     * 纯文本发送
     *
     * @param mail
     */
    public void send(Email mail);

    /**
     * 模版发送 freemarker
     *
     * @param mail
     */
    public void sendFreemarker(Email mail);
}
接口的实现类
package com.lhyt.modules.sys.service.impl;

import com.lhyt.modules.sys.mail.Email;
import com.lhyt.modules.sys.service.IMailService;
import freemarker.template.Configuration;
import freemarker.template.Template;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Service;
import org.springframework.ui.freemarker.FreeMarkerTemplateUtils;

import javax.mail.internet.MimeMessage;
import java.util.HashMap;
import java.util.Map;

@Service
public class MailServiceImpl implements IMailService {

    private static final Logger logger = LoggerFactory.getLogger(MailServiceImpl.class);

    @Autowired
    private JavaMailSender mailSender;
    @Autowired
    public Configuration configuration;//freemarker---FreeMarkerConfigurer

    @Value("${spring.mail.username}")
    public String USER_NAME;//发送者

    //文本分割
    static {
        System.setProperty("mail.mime.splitlongparameters", "false");
    }

    @Override
    public void send(Email mail) {
        try {
            logger.info("发送普通文本邮件:{}", mail.getContent());
            SimpleMailMessage message = new SimpleMailMessage();
            message.setFrom(USER_NAME);
            message.setTo(mail.getEmail());
            message.setSubject(mail.getSubject());
            message.setText(mail.getContent());
            mailSender.send(message);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void sendFreemarker(Email mail) {
        try {
            MimeMessage message = mailSender.createMimeMessage();
            MimeMessageHelper helper = new MimeMessageHelper(message, true);
            //这里可以自定义发信名称比如:工作流
            helper.setFrom(USER_NAME, "系统邮件通知");
            helper.setTo(mail.getEmail());
            helper.setSubject(mail.getSubject());
            Map<String, Object> model = new HashMap<>();
            model.put("mail", mail);
            model.put("exception", mail.getKvMap());
            Template template = configuration.getTemplate(mail.getTemplate());
            String text = FreeMarkerTemplateUtils.processTemplateIntoString(template, model);
            helper.setText(text, true);
            mailSender.send(message);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

五.定义异常处理类

package com.lhyt.common.exception;

import com.lhyt.common.utils.R;
import com.lhyt.modules.sys.mail.Email;
import com.lhyt.modules.sys.service.IMailService;
import org.apache.shiro.authz.AuthorizationException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.NoHandlerFoundException;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.HashMap;

/**
 * 异常处理器
 *
 * @author wangdy
 */
@RestControllerAdvice //注意加该注解
public class MyExceptionHandler {
    private Logger logger = LoggerFactory.getLogger(getClass());

    @Autowired
    private IMailService mailService;

    @Value("${alarm.email}")
    private String[] email;
 
    @ExceptionHandler(Exception.class)
    public R handleException(Exception e) {
        //产生异常,发送邮件服务
    StringWriter stringWriter = new StringWriter();
        e.printStackTrace(new PrintWriter(stringWriter));
        Email mail = new Email();
        mail.setEmail(email);
        mail.setSubject("异常告警邮件通知");
        mail.setContent(stringWriter.toString());
        // mailService.send(mail);//发送普通邮件
        mail.setTemplate("notifyEmail.ftl");
        HashMap<String, Object> mapParam = new HashMap<>(); //自定义模板参数,用于在ftl中接收展示
        mapParam.put("exceptionCause", e.getCause());
        mapParam.put("exceptionMessage", e.getMessage());
        mapParam.put("exceptionClass", e.getClass());
        mail.setKvMap(mapParam);
        mailService.sendFreemarker(mail);//发送模板邮件
        logger.error(e.getMessage(), e);
        return R.error();
    }
}

六.在resources/templates下新建邮件模板文件notifyEmail.ftl

<!doctype html>
<html lang="zh-cmn-Hans">
<head>
    <meta charset="UTF-8">
    <meta name="renderer" content="webkit"/>
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"/>
    <title>邮件通知模板</title>

    <style type="text/css">
        table {
            font-family: "Trebuchet MS", Arial, Helvetica, sans-serif;
            width: 100%;
            border-collapse: collapse;
        }

        td, th {
            font-size: 1em;
            border: 1px solid #5B4A42;
            padding: 3px 7px 2px 7px;
        }

        th {
            font-size: 1.1em;
            text-align: center;
            padding-top: 5px;
            padding-bottom: 4px;
            background-color: #24A9E1;
            color: #ffffff;
        }
    </style>
</head>
<body>
<h2>邮件消息通知</h2>
<table>
    <tr>
        <th>异常类</th>
        <th>异常消息</th>
        <th>异常原因</th>
    </tr>
    <tr>
        <td>${(exception.exceptionClass)!""}</td>
        <td>${(exception.exceptionMessage)!""}</td>
        <td>${(exception.exceptionCause)!""}</td>
    </tr>
</table>
<br>
<b>########################################################################################################################</b>
<hr>
<b>########################################################################################################################</b>
<br>
<b>##############################具体异常信息如下:##############################</b>
<br>
<pre>${mail.content}</pre>
</body>
</html>

七.随便写一个controller,然后随便报一个异常进行测试。

    @GetMapping("testExceptionSendEmail")
    public R testExceptionSendEmail() {
        int i = 1/0;
        return R.ok();
    }

然后在浏览器上访问该接口,触发报错异常。看邮件是否发送,当然如果你配置正确的话,无疑是要发送成功的:
我这边收到的邮件截图如下:
在这里插入图片描述
另一个qq邮箱收到截图如下:qq邮箱对样式的解析好像不是很好,我这边也没深究,你们看下吧。
在这里插入图片描述
以上就是全部程序了。希望帮助到你。
注: 你也可以对自定义异常进行特别的拦截,而不是拦截所有异常,可以在MyExceptionHandler类中加入如下方法进行:


    /**
     * 处理自定义异常,并发送邮件
     */
    @ExceptionHandler(MyException.class)
    public R handleMyException(MyException e) {
	    //产生异常,发送邮件服务
	    StringWriter stringWriter = new StringWriter();
        e.printStackTrace(new PrintWriter(stringWriter));
        Email mail = new Email();
        mail.setEmail(email);
        mail.setSubject("异常告警邮件通知");
        mail.setContent(stringWriter.toString());
        // mailService.send(mail);//发送普通邮件
        mail.setTemplate("notifyEmail.ftl");
        HashMap<String, Object> mapParam = new HashMap<>(); //自定义模板参数,用于在ftl中接收展示
        mapParam.put("exceptionCause", e.getCause());
        mapParam.put("exceptionMessage", e.getMessage());
        mapParam.put("exceptionClass", e.getClass());
        mail.setKvMap(mapParam);
        mailService.sendFreemarker(mail);//发送模板邮件
        R r = new R();//这个就是一个map,哈哈哈
        r.put("code", e.getCode());
        r.put("msg", e.getMessage());
        return r;
    }

其中用到的自定义异常类如下:

package com.lhyt.common.exception;

/**
 * 自定义异常
 *
 * @author wangdy
 */
public class MyException extends RuntimeException {
	private static final long serialVersionUID = 1L;
	
    private String message;
    private int code = 500;
    //getter setter 构造自己写就可以了。然后在用到的地方throw MyException 
}

END

发布了80 篇原创文章 · 获赞 190 · 访问量 19万+

猜你喜欢

转载自blog.csdn.net/wdy_2099/article/details/89414207