前言
在项目开发中,对于异常处理我们通常有多种处理方式,比如:控制层手动捕获异常,拦截器统一处理异常。今天跟大家分享一种注解的方式,统一拦截异常并处理。
异常处理
在spring 3.2中,新增了@RestControllerAdvice 注解,可以用于定义@ExceptionHandler、@InitBinder、@ModelAttribute,并应用到所有@RequestMapping中。
创建 RRExceptionHandler,并添加 @RestControllerAdvice注解,来这样就可以拦截所有控制层上抛出来的异常。
/**
* 异常处理器
* 创建时间 2017年11月20日
*/
@RestControllerAdvice
publicclassRRExceptionHandler{
@Autowired
privateIMailServicemailService;
privateLoggerlogger =LoggerFactory.getLogger(getClass());
@Value("${alarm.email}")
privateString[] email;
/**
* 自定义异常
*/
@ExceptionHandler(RRException.class)
publicResulthandleRRException(RRExceptione){
Resultr =newResult();
r.put("code", e.getCode());
r.put("msg", e.getMessage());
returnr;
}
@ExceptionHandler(DuplicateKeyException.class)
publicResulthandleDuplicateKeyException(DuplicateKeyExceptione){
logger.error(e.getMessage(), e);
returnResult.error("数据库中已存在该记录");
}
@ExceptionHandler(Exception.class)
publicResulthandleException(Exceptione){
StringWriterstringWriter =newStringWriter();
e.printStackTrace(newPrintWriter(stringWriter));
Emailmail =newEmail();
mail.setEmail(email);
mail.setSubject("工作流系统告警");
mail.setContent(stringWriter.toString());
//mailService.send(mail);
mailService.sendFreemarker(mail);
logger.error(e.getMessage(), e);
returnResult.error();
}
}
自定义异常 RRException:
/**
* 自定义异常
* 创建时间 2017年11月20日
*/
publicclassRRExceptionextendsRuntimeException{
privatestaticfinallongserialVersionUID =1L;
privateStringmsg;
privateintcode =500;
publicRRException(Stringmsg) {
super(msg);
this.msg = msg;
}
publicRRException(Stringmsg,Throwablee) {
super(msg, e);
this.msg = msg;
}
publicRRException(Stringmsg,intcode) {
super(msg);
this.msg = msg;
this.code = code;
}
publicRRException(Stringmsg,intcode,Throwablee) {
super(msg, e);
this.msg = msg;
this.code = code;
}
publicStringgetMsg() {
returnmsg;
}
publicvoidsetMsg(Stringmsg) {
this.msg = msg;
}
publicintgetCode() {
returncode;
}
publicvoidsetCode(intcode) {
this.code = code;
}
}
邮件通知
邮件通知,需要引入以下配置:
org.springframework.boot
spring-boot-starter-mail
org.springframework.boot
spring-boot-starter-freemarker
配置模板邮件参数:
# 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封装类
*/
publicclassEmailimplementsSerializable{
privatestaticfinallongserialVersionUID =1L;
// 必填参数
privateString[] email;// 接收方邮件
privateStringsubject;// 主题
privateStringcontent;// 邮件内容
// 选填
privateStringtemplate;// 模板
privateHashMap kvMap;// 自定义参数
publicEmail() {
super();
}
publicEmail(String[] email,Stringsubject,Stringcontent,Stringtemplate,HashMap kvMap) {
super();
this.email = email;
this.subject = subject;
this.content = content;
this.template = template;
this.kvMap = kvMap;
}
publicString[] getEmail() {
returnemail;
}
publicvoidsetEmail(String[] email) {
this.email = email;
}
publicStringgetSubject() {
returnsubject;
}
publicvoidsetSubject(Stringsubject) {
this.subject = subject;
}
publicStringgetContent() {
returncontent;
}
publicvoidsetContent(Stringcontent) {
this.content = content;
}
publicStringgetTemplate() {
returntemplate;
}
publicvoidsetTemplate(Stringtemplate) {
this.template = template;
}
publicHashMap getKvMap() {
returnkvMap;
}
publicvoidsetKvMap(HashMap kvMap) {
this.kvMap = kvMap;
}
}
发送接口:
publicinterfaceIMailService{
/**
* 纯文本
* @param mail
* @throws Exception
*/
publicvoidsend(Emailmail);
/**
* 模版发送 freemarker
* @param mail
* @throws Exception
*/
publicvoidsendFreemarker(Emailmail);
}
发送实现:
@Service
publicclassMailServiceImplimplementsIMailService{
privatestaticfinalLoggerlogger =LoggerFactory.getLogger(MailServiceImpl.class);
@Autowired
privateJavaMailSendermailSender;//执行者
@Autowired
publicConfigurationconfiguration;//freemarker
@Value("${spring.mail.username}")
publicStringUSER_NAME;//发送者
@Value("${server.path}")
publicStringPATH;//邮件服务地址,用于显示图片
//文本分割
static{
System.setProperty("mail.mime.splitlongparameters","false");
}
@Override
publicvoidsend(Emailmail) {
try{
logger.info("发送邮件:{}",mail.getContent());
SimpleMailMessagemessage =newSimpleMailMessage();
message.setFrom(USER_NAME);
message.setTo(mail.getEmail());
message.setSubject(mail.getSubject());
message.setText(mail.getContent());
mailSender.send(message);
}catch(Exceptione) {
e.printStackTrace();
}
}
@Override
publicvoidsendFreemarker(Emailmail) {
try{
MimeMessagemessage = mailSender.createMimeMessage();
MimeMessageHelperhelper =newMimeMessageHelper(message,true);
//这里可以自定义发信名称比如:工作流
helper.setFrom(USER_NAME,"工作流");
helper.setTo(mail.getEmail());
helper.setSubject(mail.getSubject());
Map model =newHashMap();
model.put("mail", mail);
model.put("path", PATH);
Templatetemplate = configuration.getTemplate(mail.getTemplate());
Stringtext =FreeMarkerTemplateUtils.processTemplateIntoString(
template, model);
helper.setText(text,true);
mailSender.send(message);
}catch(Exceptione) {
e.printStackTrace();
}
}
}
定义发送模板 notify.ftl :
Document您好:${mail.content}