SpringBoot开发案例之异常处理并邮件通知
前言
在项目开发中,对于异常处理我们通常有多种处理方式,比如:控制层手动捕获异常,拦截器统一处理异常。今天跟大家分享一种注解的方式,统一拦截异常并处理。
异常处理
在spring 3.2中,新增了@RestControllerAdvice 注解,可以用于定义@ExceptionHandler、@InitBinder、@ModelAttribute,并应用到所有@RequestMapping中。
创建 RRExceptionHandler,并添加 @RestControllerAdvice注解,来这样就可以拦截所有控制层上抛出来的异常。
/**
* 异常处理器
* 创建时间 2017年11月20日
*/
@RestControllerAdvice
public class RRExceptionHandler { @Autowired
private IMailService mailService; private Logger logger = LoggerFactory.getLogger(getClass()); @Value("${alarm.email}")
private String[] email; /**
* 自定义异常
*/
@ExceptionHandler(RRException.class)
public Result handleRRException(RRException e){
Result r = new Result();
r.put("code", e.getCode());
r.put("msg", e.getMessage());
return r;
} @ExceptionHandler(DuplicateKeyException.class)
public Result handleDuplicateKeyException(DuplicateKeyException e){
logger.error(e.getMessage(), e);
return Result.error("数据库中已存在该记录");
} @ExceptionHandler(Exception.class)
public Result 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);
mailService.sendFreemarker(mail);
logger.error(e.getMessage(), e);
return Result.error();
}
}
自定义异常 RRException:
/**
* 自定义异常
* 创建时间 2017年11月20日
*/
public class RRException extends RuntimeException { private static final long serialVersionUID = 1L; private String msg; private int code = 500; public RRException(String msg) {
super(msg);
this.msg = msg;
} public RRException(String msg, Throwable e) {
super(msg, e);
this.msg = msg;
} public RRException(String msg, int code) {
super(msg);
this.msg = msg;
this.code = code;
} public RRException(String msg, int code, Throwable e) {
super(msg, e);
this.msg = msg;
this.code = code;
} public String getMsg() {
return msg;
} public void setMsg(String msg) {
this.msg = msg;
} public int getCode() {
return code;
} public void setCode(int code) {
this.code = code;
}
}
邮件通知
邮件通知,需要引入以下配置:
<!-- 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>
配置模板邮件参数:
# freemarker
spring.freemarker.template-loader-path=classpath:/templates/
spring.freemarker.suffix=.ftl
spring.freemarker.enabled=true
spring.freemarker.cache=false
spring.freemarker.charset=UTF-8
spring.freemarker.content-type=text/html
spring.freemarker.allow-request-override=false
spring.freemarker.check-template-location=true
spring.freemarker.expose-request-attributes=false
spring.freemarker.expose-session-attributes=false
spring.freemarker.expose-spring-macro-helpers=false # 邮件配置
spring.mail.host=smtp.163.com
spring.mail.username=13105423559@163.com
spring.mail.password=123456
spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.starttls.enable=true
spring.mail.properties.mail.smtp.starttls.required=true # 告警通知 多个以逗号分隔
alarm.email = 345849402@qq.com
定义Email封装类:
/**
* Email封装类
*/
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, String> kvMap;// 自定义参数 public Email() {
super();
} public Email(String[] email, String subject, String content, String template, HashMap<String, String> kvMap) {
super();
this.email = email;
this.subject = subject;
this.content = content;
this.template = template;
this.kvMap = kvMap;
} public String[] getEmail() {
return email;
} public void setEmail(String[] email) {
this.email = email;
} public String getSubject() {
return subject;
} public void setSubject(String subject) {
this.subject = subject;
} public String getContent() {
return content;
} public void setContent(String content) {
this.content = content;
} public String getTemplate() {
return template;
} public void setTemplate(String template) {
this.template = template;
} public HashMap<String, String> getKvMap() {
return kvMap;
} public void setKvMap(HashMap<String, String> kvMap) {
this.kvMap = kvMap;
}
}
发送接口:
public interface IMailService {
/**
* 纯文本
* @param mail
* @throws Exception
*/
public void send(Email mail);
/**
* 模版发送 freemarker
* @param mail
* @throws Exception
*/
public void sendFreemarker(Email mail);
}
发送实现:
@Service
public class MailServiceImpl implements IMailService {
private static final Logger logger = LoggerFactory.getLogger(MailServiceImpl.class);
@Autowired
private JavaMailSender mailSender;//执行者
@Autowired
public Configuration configuration;//freemarker
@Value("${spring.mail.username}")
public String USER_NAME;//发送者
@Value("${server.path}")
public String PATH;//邮件服务地址,用于显示图片 //文本分割
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<String, Object>();
model.put("mail", mail);
model.put("path", PATH);
Template template = configuration.getTemplate(mail.getTemplate());
String text = FreeMarkerTemplateUtils.processTemplateIntoString(
template, model);
helper.setText(text, true);
mailSender.send(message);
} catch (Exception e) {
e.printStackTrace();
}
}
}
定义发送模板 notify.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>Document</title>
</head>
<body>
您好:${mail.content}
</body>
</html>
SpringBoot开发案例之异常处理并邮件通知的更多相关文章
- SpringBoot开发案例从0到1构建分布式秒杀系统
前言 最近,被推送了不少秒杀架构的文章,忙里偷闲自己也总结了一下互联网平台秒杀架构设计,当然也借鉴了不少同学的思路.俗话说,脱离案例讲架构都是耍流氓,最终使用SpringBoot模拟实现了部分秒杀场 ...
- SpringBoot开发案例之多任务并行+线程池处理
前言 前几篇文章着重介绍了后端服务数据库和多线程并行处理优化,并示例了改造前后的伪代码逻辑.当然了,优化是无止境的,前人栽树后人乘凉.作为我们开发者来说,既然站在了巨人的肩膀上,就要写出更加优化的程序 ...
- SpringBoot开发案例之打造私有云网盘
前言 最近在做工作流的事情,正好有个需求,要添加一个附件上传的功能,曾找过不少上传插件,都不是特别满意.无意中发现一个很好用的开源web文件管理器插件 elfinder,功能比较完善,社区也很活跃,还 ...
- SpringBoot开发案例之整合Activiti工作流引擎
前言 JBPM是目前市场上主流开源工作引擎之一,在创建者Tom Baeyens离开JBoss后,JBPM的下一个版本jBPM5完全放弃了jBPM4的基础代码,基于Drools Flow重头来过,目前官 ...
- SpringBoot开发案例之整合Dubbo分布式服务
前言 在 SpringBoot 很火热的时候,阿里巴巴的分布式框架 Dubbo 不知是处于什么考虑,在停更N年之后终于进行维护了.在之前的微服务中,使用的是当当维护的版本 Dubbox,整合方式也是使 ...
- SpringBoot开发案例之整合Kafka实现消息队列
前言 最近在做一款秒杀的案例,涉及到了同步锁.数据库锁.分布式锁.进程内队列以及分布式消息队列,这里对SpringBoot集成Kafka实现消息队列做一个简单的记录. Kafka简介 Kafka是由A ...
- SpringBoot开发案例之分布式集群共享Session
前言 在分布式系统中,为了提升系统性能,通常会对单体项目进行拆分,分解成多个基于功能的微服务,如果有条件,可能还会对单个微服务进行水平扩展,保证服务高可用. 那么问题来了,如果使用传统管理 Sessi ...
- SpringBoot开发案例Nacos配置管理中心
前言 在开发过程中,通常我们会配置一些参数来实现某些功能,比如是否开启某项服务,告警邮件配置等等.一般会通过硬编码.配置文件或者数据库的形式实现. 那么问题来了,如何更加优雅的实现?欢迎来到 Naco ...
- 转载-SpringBoot开发案例之整合日志管理
转载:https://cloud.tencent.com/developer/article/1097579 有一种力量无人能抵挡,它永不言败生来倔强.有一种理想照亮了迷茫,在那写满荣耀的地方. 00 ...
随机推荐
- Java 第十一届 蓝桥杯 省模拟赛 小明植树(DFS)
小明植树 题目 问题描述 小明和朋友们一起去郊外植树,他们带了一些在自己实验室精心研究出的小树苗. 小明和朋友们一共有 n 个人,他们经过精心挑选,在一块空地上每个人挑选了一个适合植树的位置,总共 n ...
- Java实现 LeetCode 725 分隔链表(暴力)
725. 分隔链表 给定一个头结点为 root 的链表, 编写一个函数以将链表分隔为 k 个连续的部分. 每部分的长度应该尽可能的相等: 任意两部分的长度差距不能超过 1,也就是说可能有些部分为 nu ...
- Java实现 蓝桥杯VIP 算法训练 王后传说
问题描述 地球人都知道,在国际象棋中,后如同太阳,光芒四射,威风八面,它能控制横.坚.斜线位置. 看过清宫戏的中国人都知道,后宫乃步步惊心的险恶之地.各皇后都有自己的势力范围,但也总能找到相安无事的办 ...
- 06.Django-用户认证
用户认证 Django 内置一个 auth 模块,帮助用户实现注册.登录.注销以及修改密码等功能,帮助开发者省去了很多功夫 用于认证的数据表 auth_user User是auth模块中维护用户信息的 ...
- [原创][开源]SunnyUI.Net, C# .Net WinForm开源控件库、工具类库、扩展类库、多页面开发框架
SunnyUI.Net, 基于 C# .Net WinForm 开源控件库.工具类库.扩展类库.多页面开发框架 Blog: https://www.cnblogs.com/yhuse Gitee: h ...
- PBFT共识算法
拜占庭将军问题 我们已知的共识算法,Paxos.Raft解决的都是非拜占庭问题,也就是可以容忍节点故障,消息丢失.延时.乱序等,但节点不能有恶意节点.但如何在有恶意节点存在的情况下达成共识呢?BFT共 ...
- ODEINT 求解常微分方程(3)
import numpy as np from scipy.integrate import odeint import matplotlib.pyplot as plt # function tha ...
- 曹工说JDK源码(4)--抄了一小段ConcurrentHashMap的代码,我解决了部分场景下的Redis缓存雪崩问题
曹工说JDK源码(1)--ConcurrentHashMap,扩容前大家同在一个哈希桶,为啥扩容后,你去新数组的高位,我只能去低位? 曹工说JDK源码(2)--ConcurrentHashMap的多线 ...
- Java——int、double型数组常用操作工具类
学了数组之后,感觉有好多操作需要经常去写,很不方便,因此自己做了一个工具类,方便调用,方法可能不全,希望大家可以添加,让我使用也方便一点儿. public class ArrayUtils { //求 ...
- (六)maven 聚合和继承
项目目录 my_test 聚合pom <?xml version="1.0" encoding="UTF-8"?> <project xmln ...