系統(tǒng)異常了,發(fā)個(gè)郵件
描述
在我們的項(xiàng)目中,總是有一些我們不可控制的異常,比如數(shù)據(jù)庫(kù)連接不上,redis掛掉,以及一些代碼上未可知的異常爆發(fā),不能在項(xiàng)目上線時(shí)就可以統(tǒng)計(jì)出來(lái),并且修復(fù),所以當(dāng)我們這些bug拋出異常時(shí),或者在某些可控的嚴(yán)重異常需要推送郵件或者短信或者其他的通訊工具比如 釘釘或者飛書(shū)等,我們就需要這樣的功能,這里提供一個(gè)郵件通知方法,當(dāng)有未知異常或者被定義為嚴(yán)重異常的,就會(huì)給運(yùn)維人員發(fā)送一個(gè)郵件進(jìn)行通知,方便計(jì)時(shí)應(yīng)對(duì)和問(wèn)題定位。
解決方案
在springboot中的全局異常捕獲處,對(duì)不可控異常拿到異常棧信息,進(jìn)行異常msg的組裝和通過(guò)freemarker模板進(jìn)行渲染html文本,然后再把這個(gè)異常msg的html進(jìn)行qq模式的email的發(fā)送
,freemarker模板可以支撐字符串模板渲染,即渲染的模板字符串可以保存到數(shù)據(jù)庫(kù),也可以直接定義好xxx.ftl模板,都行,這里需要強(qiáng)調(diào)的是 渲染的模板字符串可以保存到數(shù)據(jù)庫(kù)
就更加靈活,可以設(shè)計(jì)一套freemarker模板的管理系統(tǒng),比如,對(duì)自定義的freemarker模板配置后,保存到數(shù)據(jù)庫(kù),然后根據(jù)不同的用戶或者企業(yè)或者業(yè)務(wù),就可以從庫(kù)中獲取對(duì)應(yīng)的freemarker模板,進(jìn)行數(shù)據(jù)渲染html,再通過(guò)短信或者郵件或者釘釘,這樣就實(shí)現(xiàn)了類(lèi)似阿里或者騰訊等第三方的模板配置后進(jìn)行消息推送的功能。
代碼
代碼組成包含有自定義的模板的工具jar包和郵件的springboot-starter,以及在微服務(wù)中對(duì)異常的處理,和調(diào)用郵件的消息封裝以及模板的創(chuàng)建
模板自定springboot-starter
詳細(xì)代碼
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>wlc-spring-boot-tools</artifactId>
<groupId>com.wlc</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>wlc-template</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<--freemarker依賴(lài) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
<--spring-webmvc依賴(lài),這里可以換成spring的ioc包 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.9</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>
BeanUtils,處理bean轉(zhuǎn)map
import org.springframework.cglib.beans.BeanMap;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.util.Map;
/**
* 描述 實(shí)體工具類(lèi) <br>
* 作者:IT學(xué)習(xí)道場(chǎng) <br>
* 時(shí)間:2018/10/26 13:37
*/
public class BeanUtils extends org.springframework.beans.BeanUtils {
public BeanUtils() {
}
/**
* 實(shí)例化對(duì)象:傳入類(lèi)對(duì)類(lèi)進(jìn)行實(shí)例化對(duì)象
*
* @param clazz 類(lèi)
* @return 對(duì)象
* @author Lius
* @date 2018/10/26 13:49
*/
public static <T> T newInstance(Class<?> clazz) {
return (T) instantiateClass(clazz);
}
/**
* 實(shí)例化對(duì)象,傳入類(lèi)名對(duì)該類(lèi)進(jìn)行實(shí)例化對(duì)象
*
* @param clazzStr 類(lèi)名,傳入是必須傳入全路徑,com...
* @return 對(duì)象
* @author Lius
* @date 2018/10/26 13:54
*/
public static <T> T newInstance(String clazzStr) {
try {
Class<?> clazz = Class.forName(clazzStr);
return newInstance(clazz);
} catch (ClassNotFoundException e) {
throw new RuntimeException();
}
}
/**
* 把對(duì)象封裝成Map形式
*
* @param src 需要封裝的實(shí)體對(duì)象
* @author Lius
* @date 2018/10/26 14:08
*/
public static Map toMap(Object src) {
return BeanMap.create(src);
}
/**
* 把Map轉(zhuǎn)換成bean對(duì)象
*
* @author Lius
* @date 2018/10/26 14:09
*/
public static <T> T toBean(Map<String, Object> beanMap, Class<T> valueType) {
// 對(duì)象實(shí)例化
T bean = BeanUtils.newInstance(valueType);
PropertyDescriptor[] propertyDescriptors = getPropertyDescriptors(valueType);
for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {
String properName = propertyDescriptor.getName();
// 過(guò)濾class屬性
if ("class".equals(properName)) {
continue;
}
if (beanMap.containsKey(properName)) {
Method writeMethod = propertyDescriptor.getWriteMethod();
if (null == writeMethod) {
continue;
}
Object value = beanMap.get(properName);
if (!writeMethod.isAccessible()) {
writeMethod.setAccessible(true);
}
try {
writeMethod.invoke(bean, value);
} catch (Throwable throwable) {
throw new RuntimeException("Could not set property '" + properName + " ' to bean" + throwable);
}
}
}
return bean;
}
}
FreemarkerUtil,來(lái)處理模板的封裝
import com.wlc.template.util.BeanUtils;
import freemarker.cache.StringTemplateLoader;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.ui.freemarker.FreeMarkerTemplateUtils;
import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer;
import java.io.IOException;
import java.util.Map;
/**
* 描述: FreemarkerUtil輔助類(lèi) <br>
* 時(shí)間: 2022-07-01 9:44 <br>
* 作者:IT學(xué)習(xí)道場(chǎng)
*/
@Component
public class FreemarkerUtil {
@Autowired
private FreeMarkerConfigurer freeMarkerConfigurer;
/**
* bean轉(zhuǎn)map
* @param bean 轉(zhuǎn)換bean
* @return Map<String, Object> - map對(duì)象
*/
public Map<String, Object> beanToMap(Object bean){
Map<String, Object> map = BeanUtils.toMap(bean);
return map;
}
/**
* 根據(jù)模板路徑獲取模板渲染數(shù)據(jù)
* @param templatePath 模板路徑 ,ex:templatePath = "notice.ftl",意思是 resources/templates/下的notice.ftl文件
* @param data 渲染數(shù)據(jù)對(duì)象
* @return String- 渲染后的html文本
*/
public String freeMarkerRenderHtml(String templatePath, Map<String, Object> data ){
//獲取模板信息
Template template = null;
String html= "";
try {
template = freeMarkerConfigurer.getConfiguration().getTemplate(templatePath);
html = FreeMarkerTemplateUtils.processTemplateIntoString(template, data);
} catch (IOException e) {
e.printStackTrace();
} catch (TemplateException e) {
e.printStackTrace();
}
return html;
}
/**
* 字符文本渲染成html文本
* @param templateName 模板名
* @param templateText 模板文本
* @param data 渲染數(shù)據(jù)map
* @return String - 渲染后的html文本
*/
public String textRenderFreemarkerHtml(String templateName, String templateText, Map<String, Object> data){
String html = textRenderFreemarkerHtml(templateName, templateText, "utf-8", data);
return html;
}
/**
* 字符文本渲染成html文本
* @param templateName 模板名
* @param templateText 模板文本
* @param charEncode 模板編碼
* @param data 渲染數(shù)據(jù)map
* @return String - 渲染后的html文本
*/
public String textRenderFreemarkerHtml(String templateName, String templateText, String charEncode, Map<String, Object> data){
Template template = textToFreemarkerTemplate(templateName, templateText, charEncode);
String html = freemarkerTemplateRenderHtml(template, data);
return html;
}
/**
* 根據(jù)模板對(duì)象和數(shù)據(jù)map渲染html文本
* @param template 模板對(duì)象
* @param data 渲染數(shù)據(jù)map
* @return String - html文本
*/
public String freemarkerTemplateRenderHtml(Template template, Map<String, Object> data){
String html = "";
try {
//渲染data數(shù)據(jù)到模板中
html = FreeMarkerTemplateUtils.processTemplateIntoString(template, data);
} catch (IOException e) {
e.printStackTrace();
} catch (TemplateException e) {
e.printStackTrace();
}
return html;
}
/**
* 文本轉(zhuǎn)freemarker模板
* @param templateName 模板名字
* @param templateText 模板文本
* @param charEncode 模板編碼
* @return Template- 返回freemarkerTemplate對(duì)象
*/
public Template textToFreemarkerTemplate(String templateName, String templateText, String charEncode){
//獲取配置文件
Configuration cfg = freeMarkerConfigurer.getConfiguration();
//創(chuàng)建freeMarker字符串模板加載器
StringTemplateLoader stringLoader = new StringTemplateLoader();
//加載模板名字和模板文本
stringLoader.putTemplate(templateName, templateText);
//配置文件設(shè)置模板加載器
cfg.setTemplateLoader(stringLoader);
freemarker.template.Template template = null;
try {
//從配置文件中獲取模板對(duì)象
template = cfg.getTemplate(templateName, charEncode);
} catch (IOException e) {
e.printStackTrace();
}
return template;
}
}
這樣,模板的渲染jar就封裝好了
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>wlc-spring-boot-tools</artifactId>
<groupId>com.wlc</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>wlc-email-spring-boot-starter</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<!-- 郵件發(fā)送的核心依賴(lài) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
<!-- 模板jar -->
<dependency>
<groupId>com.wlc</groupId>
<artifactId>wlc-template</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
</project>
EmailUtil-> 郵件發(fā)送工具類(lèi)
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.mail.MailProperties;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
import java.util.Date;
/**
* 描述: email輔助類(lèi) <br>
* 時(shí)間: 2022-07-01 10:20 <br>
* 作者:IT學(xué)習(xí)道場(chǎng)
*/
public class EmailUtil {
@Autowired
private JavaMailSender javaMailSender;
@Autowired
private MailProperties mailProperties;
/**
* 發(fā)送普通郵件
* @param subject 主題
* @param simpleText 內(nèi)容
* @param toEamils 郵件接受郵箱數(shù)組
*/
public void simpleEmailSend(String subject, String simpleText, String... toEamils) {
SimpleMailMessage message = new SimpleMailMessage();
message.setSentDate(new Date());
message.setFrom(mailProperties.getUsername());
message.setTo(toEamils);
message.setSubject(subject);
message.setText(simpleText);
//發(fā)送郵件
javaMailSender.send(message);
}
/**
* 發(fā)送html郵件
* @param subject 發(fā)送主題
* @param html 發(fā)送的html
* @param toEamils 郵件接收人數(shù)組
*/
public void emailSendHtml(String subject, String html, String... toEamils) {
MimeMessage mimeMessage = javaMailSender.createMimeMessage();
MimeMessageHelper message = null;
try {
message = new MimeMessageHelper(mimeMessage, true);
message.setSentDate(new Date());
message.setFrom(mailProperties.getUsername());
message.setTo(toEamils);
message.setSubject(subject);
message.setText(html, true);
//發(fā)送郵件
javaMailSender.send(mimeMessage);
} catch (MessagingException e) {
e.printStackTrace();
}
}
}
EmailService -> email服務(wù)類(lèi)的輔助類(lèi)
import com.wlc.email.util.EmailUtil;
import com.wlc.template.freemarker.FreemarkerUtil;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.Map;
/**
* 描述: email服務(wù)類(lèi) <br>
* 時(shí)間: 2022-07-01 10:33 <br>
* 作者:IT學(xué)習(xí)道場(chǎng)
*/
public class EmailService {
@Autowired
private EmailUtil emailUtil;
@Autowired
private FreemarkerUtil freemarkerUtil;
/**
* 根據(jù)模板路徑給郵件發(fā)送html模板
* @param subject 郵件主題
* @param templatePath html模板路徑
* @param data 渲染html模板里的數(shù)據(jù)map
* @param toEamils 郵件接受者數(shù)組
*/
public void emailSendHtmlByTemplatePath(String subject, String templatePath, Map<String, Object> data, String... toEamils) {
String html = freemarkerUtil.freeMarkerRenderHtml(templatePath, data);
emailUtil.emailSendHtml(subject, html, toEamils);
}
/**
* 根據(jù)字符模板文本給郵件發(fā)送html模板
* @param subject 郵件主題
* @param templateName html模板名字
* @param templateText html模板text文本(就是html的模板字符串,使用html模板易字符串的形式保存到數(shù)據(jù)庫(kù),
* 然后從數(shù)據(jù)庫(kù)中讀取模板字符串,在轉(zhuǎn)換成模板對(duì)象,把data進(jìn)行渲染成html,來(lái)發(fā)送郵件)
* @param data 渲染html模板里的數(shù)據(jù)map
* @param toEamils 郵件接受者數(shù)組
*/
public void emailSendHtmlByTemplateText(String subject, String templateName, String templateText, Map<String, Object> data, String... toEamils) {
String html = freemarkerUtil.textRenderFreemarkerHtml(templateName, templateText, data);
emailUtil.emailSendHtml(subject, html, toEamils);
}
/**
* 根據(jù)字符模板文本給郵件發(fā)送html模板
* @param subject 郵件主題
* @param templateName html模板名字
* @param templateText html模板text文本(就是html的模板字符串,使用html模板易字符串的形式保存到數(shù)據(jù)庫(kù),
* 然后從數(shù)據(jù)庫(kù)中讀取模板字符串,在轉(zhuǎn)換成模板對(duì)象,把data進(jìn)行渲染成html,來(lái)發(fā)送郵件)
* @param data 渲染html模板里的數(shù)據(jù)map
* @param charEncode 編碼格式 ex: "utf-8"
* @param toEamils 郵件接受者數(shù)組
*/
public void emailSendHtmlByTemplateText(String subject, String templateName, String templateText, String charEncode, Map<String, Object> data, String... toEamils) {
String html = freemarkerUtil.textRenderFreemarkerHtml(templateName, templateText, charEncode, data);
emailUtil.emailSendHtml(subject, html, toEamils);
}
}
EmailAutoConfiguration --> 自定義郵件自動(dòng)化配置類(lèi)
import com.wlc.email.service.EmailService;
import com.wlc.email.util.EmailUtil;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* 描述: 自定義郵件自動(dòng)化配置類(lèi) <br>
* 時(shí)間: 2022-07-01 11:00 <br>
* 作者:IT學(xué)習(xí)道場(chǎng)
*/
@Configuration
public class EmailAutoConfiguration {
@Bean
public EmailService emailService(){
EmailService emailService = new EmailService();
return emailService;
}
@Bean
EmailUtil emailUtil(){
EmailUtil emailUtil = new EmailUtil();
return emailUtil;
}
}
resources/META-INF下的spring.factories文件
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.wlc.email.config.EmailAutoConfiguration
這樣一個(gè)郵件的自定義springboot-starter就封裝好了
下面就是在各個(gè)微服務(wù)中的全局異常捕獲中進(jìn)行msg的freemarker的組裝和郵件的發(fā)送
演示的服務(wù)代碼,全局異常處理
ftl代碼,有類(lèi)似需求可以copy
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"></meta>
<title>郵件內(nèi)容</title>
</head>
<body>
<p style="text-align:center "><img width="400px" height="200px" src="https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fimgsa.baidu.com%2Fexp%2Fw%3D500%2Fsign%3Da5c70c27a1efce1bea2bc8ca9f50f3e8%2Fa9d3fd1f4134970a05665ffe93cad1c8a6865dcd.jpg&refer=http%3A%2F%2Fimgsa.baidu.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1659171243&t=17d3f0b344e9cb402e8ec4311207fa5a"></p>
<h4>系統(tǒng)管理員</h4>
<h4> 您好!</h4>
<p>系統(tǒng)異常了!日志如下:</p>
<p>服務(wù)名:<span style="color:red">${appName}</span></p>
<p>服務(wù)ip:<span style="color:red">${ipAddr}</span></p>
<p>類(lèi)路徑:<span style="color:red">${className}</span></p>
<p>方法名字:<span style="color:red">${methodName}</span></p>
<p>異常發(fā)生行號(hào):<span style="color:red">${lineNumber}</span></p>
<p style="color:red">${content}</p>
<p style="width: 100%;text-align: right">IT學(xué)習(xí)道場(chǎng)系統(tǒng)</p>
</body>
</html>
EmailExtendContent -> email的異常郵件信息組裝類(lèi),這里是給郵件哪個(gè)模板里需要的數(shù)據(jù)組裝
import com.utils.IPUtil;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.servlet.http.HttpServletRequest;
/**
* 描述: email的異常郵件信息組裝類(lèi) <br>
* 時(shí)間: 2022-06-30 17:03 <br>
* 作者:IT學(xué)習(xí)道場(chǎng)
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class EmailExtendContent {
//異常
public Exception e;
//請(qǐng)求request
public HttpServletRequest request;
//ip地址
public String ipAddr;
//類(lèi)命
public String className;
//方法名
public String methodName;
//發(fā)生異常的行號(hào)
public int lineNumber;
public EmailExtendContent(Exception e, HttpServletRequest request) {
this.e = e;
this.request = request;
handler();
}
void handler(){
StackTraceElement stackTraceElement = e.getStackTrace()[0];
// 獲取類(lèi)名
ipAddr = IPUtil.getIpAddr(request);
className = stackTraceElement.getClassName();
methodName = stackTraceElement.getMethodName();
lineNumber = stackTraceElement.getLineNumber();
}
}
EmailHandler --> 微服務(wù)中email處理類(lèi)定制化處理類(lèi)
import com.wlc.email.service.EmailService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;
/**
* 描述: email處理類(lèi) <br>
* 時(shí)間: 2022-07-01 11:11 <br>
* 作者:IT學(xué)習(xí)道場(chǎng)
*/
@Component
public class EmailHandler {
@Autowired
private EmailService emailService; // 自定義郵件starter里的 EmailService
@Value("${spring.application.name:no-service}") //服務(wù)應(yīng)用沒(méi)名字
private String appName;
@Value("#{'${spring.mail.toEamils:}'.split(',')}") //郵件接收者的郵箱數(shù)組
private String[] toEamils;
/**
* 異步發(fā)送郵件
* @param stackExceptionMsg 棧異常信息 str
* @param e 異常對(duì)象
* @param request request
*/
@Async
public void sendExceptionEmail(String stackExceptionMsg,Exception e, HttpServletRequest request){
//根據(jù)異常對(duì)象和request組裝EmailExtendContent
EmailExtendContent emailExtendContent = new EmailExtendContent(e, request);
//組裝渲染數(shù)據(jù)data
Map<String, Object> data = builderData(appName, emailExtendContent, stackExceptionMsg);
//發(fā)送郵件
emailService.emailSendHtmlByTemplatePath("美術(shù)傳媒系統(tǒng)異常報(bào)告", "notice.ftl", data, toEamils);
}
private Map builderData(String appName, EmailExtendContent extendContent, String content){
Map<String, Object> data = new HashMap<>();
data.put("appName", appName);
data.put("ipAddr", extendContent.ipAddr);
data.put("className", extendContent.className);
data.put("methodName", extendContent.methodName);
data.put("lineNumber", extendContent.lineNumber);
data.put("content", content);
return data;
}
}
然后就可以在全局異常里調(diào)用一下 EmailHandler.sendExceptionEmail即可
import cn.hutool.core.exceptions.ExceptionUtil;
import com.email.EmailHandler;
import com.http.constant.HttpCode;
import com.http.exception.BusinessException;
import com.utils.JsonUtil;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.validation.BindException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
import javax.servlet.http.HttpServletRequest;
/**
* 全局結(jié)果響應(yīng)處理,全局異常處理 <br>
* 作者:IT學(xué)習(xí)道場(chǎng) <br>
* 時(shí)間:2019-01-24 10:33
*/
@Slf4j
@RestControllerAdvice
public class ResultAdvice implements ResponseBodyAdvice<Object> {
@Autowired
private EmailHandler emailHandler;
@Override
public boolean supports(MethodParameter methodParameter, Class<? extends HttpMessageConverter<?>> aClass) {
return true;
}
/**
* 先捕獲異常 然后再把數(shù)據(jù)返回到ResponseBody中,
* 然后在Body中要返回?cái)?shù)據(jù)的時(shí)候調(diào)用上面的攔截方法beforeBodyWrite()
*/
@ExceptionHandler(value = Exception.class)
public Object handleException(Object o, Exception e, HttpServletRequest request) {
//此處返回json數(shù)據(jù)
//捕捉到的異常如果是自定義異常類(lèi),那么就返回自定義異常類(lèi)中的錯(cuò)誤碼和錯(cuò)誤信息
String stackExceptionMsg = ExceptionUtil.stacktraceToString(e);
//異常輸出到日志
log.error(stackExceptionMsg);
//自定義基礎(chǔ)異常
if (e instanceof BusinessException) {
return new ResultException(((BusinessException) e).getCode(), false, ((BusinessException) e).getMessage(), request.getRequestURL().toString());
//非法參數(shù)異常
} else if (e instanceof IllegalArgumentException) {
return new ResultException(HttpCode.BAD_REQUEST.code, false, "參數(shù)異常,請(qǐng)稍候再試", request.getRequestURL().toString());
//綁定異常
} else if (e instanceof BindException) {
return new ResultException(HttpCode.BAD_REQUEST.code, false, ((BindException) e).getBindingResult().getFieldError().getDefaultMessage(), request.getRequestURL().toString());
//方法參數(shù)異常驗(yàn)證異常
} else if (e instanceof MethodArgumentNotValidException) {
return new ResultException(HttpCode.BAD_REQUEST.code, false, ((MethodArgumentNotValidException) e).getBindingResult().getFieldError().getDefaultMessage(), request.getRequestURL().toString());
}
//這里是除了自定義異常的其他異常信息
else {
// 這里是未知不可控異常,發(fā)送異常郵件即可
emailHandler.sendExceptionEmail(stackExceptionMsg, e, request);
return new ResultException(HttpCode.SERVER_ERROR.code, false, "系統(tǒng)異常請(qǐng)聯(lián)系管理員", request.getRequestURL().toString());
}
}
}
下面是
application.yml的郵件配置
erver:
port: 8080
#啟用undertow
undertow:
# CPU有幾核,就填寫(xiě)幾。
io-threads: 4
#阻塞任務(wù)線程池, 當(dāng)執(zhí)行類(lèi)似servlet請(qǐng)求阻塞IO操作, undertow會(huì)從這個(gè)線程池中取得線程
# 它的值設(shè)置取決于系統(tǒng)線程執(zhí)行任務(wù)的阻塞系數(shù),默認(rèn)值是IO線程數(shù)*8
worker-threads: 32
# 以下的配置會(huì)影響buffer,這些buffer會(huì)用于服務(wù)器連接的IO操作,有點(diǎn)類(lèi)似netty的池化內(nèi)存管理
# 每塊buffer的空間大小,越小的空間被利用越充分,不要設(shè)置太大,以免影響其他應(yīng)用,合適即可
buffer-size: 1024
# 是否分配的直接內(nèi)存(NIO直接分配的堆外內(nèi)存)
direct-buffers: true
servlet:
context-path: /
spring:
application:
name: wlc
redis:
host: localhost
port: 6379
password:
lettuce:
pool:
# 連接池中的最大空閑連接 默認(rèn)8
max-idle: 8
# 連接池中的最小空閑連接 默認(rèn)0
min-idle: 0
# 連接池最大連接數(shù) 默認(rèn)8 ,負(fù)數(shù)表示沒(méi)有限制
max-active: 8
# 連接池最大阻塞等待時(shí)間(使用負(fù)值表示沒(méi)有限制) 默認(rèn)-1
max-wait: -1
#, 1603610130@qq.com
mail:
host: smtp.qq.com
#你開(kāi)通smtp的郵箱地址
username: xxxxx@qq.com
#你的郵箱開(kāi)通smtp時(shí)的授權(quán)碼
password: xxxxxxxxxx
port: 465
toEamils: xxxx@qq.com,yyyy@qq.com
properties:
mail:
smtp:
auth: true
ssl:
enable: true
starttls:
enable: true
required: true
驗(yàn)證,已通知找個(gè)接口,搞個(gè)異常測(cè)試,我的是 int i= 1/0,簡(jiǎn)單測(cè)試
到此結(jié)束,覺(jué)得有用就關(guān)注下,全是原創(chuàng)干貨,你可以看下我的合集,希望能對(duì)你有所幫助
作者:IT學(xué)習(xí)道場(chǎng)
歡迎關(guān)注微信公眾號(hào) : IT學(xué)習(xí)道場(chǎng)