在项目常常会出现一些意料之外的错误,不能及时处理,大家都懂的哈。😁当然现在有很多监控服务,我这点能力是不够写的哈。☺
就有了这么一个小小的思路,用邮件服务来提醒出现异常啦。👩💻
(狗头保命)👩💻
很喜欢一句话:”八小时内谋生活,八小时外谋发展“我们:"待别日相见时,都已有所成”😁
一、前言
SpringBoot异步实现发送邮件服务
1)异常处理概述:
异常处理,是编程语言或计算机硬件里的一种机制,用于处理软件或信息系统中出现的异常状况(即超出程序正常执行流程的某些特殊条件)。通过异常处理,我们可以对用户在程序中的非法输入进行控制和提示,以防程序崩溃。以返回正确的信息给前台。
2)异常处理:
SpringBoot 中的异常处理分为局部处理异常和全局处理异常。方式稍稍有些差异。
2.1、局部异常处理:
例如:
@Controllerpublic class ExceptionController { private static final Logger log = LoggerFactory.getLogger(ExceptionController.class); @RequestMapping("/exceptionMethod") public String exceptionMethod(Model model) throws Exception { model.addAttribute("msg", "没有抛出异常"); int num = 1/0; log.info(String.valueOf(num)); return "home"; } /** * 描述:捕获 ExceptionController 中的 ArithmeticException 异常 * @param model 将Model对象注入到方法中 * @param e 将产生异常对象注入到方法中 * @return 指定错误页面 */ @ExceptionHandler(value = {ArithmeticException.class}) public String arithmeticExceptionHandle(Model model, Exception e) { model.addAttribute("msg", "@ExceptionHandler" + e.getMessage()); log.info(e.getMessage()); return "error"; }}
复制代码
2.2、全局异常处理:
这种稍后会在案例中讲解。
全局处理还有一种方式:配置 SimpleMappingExceptionResolver 类处理异常
因为现在使用 SpringBoot 更多的是使用前后端分离的方式,这种和视图的关联就不怎么合适,所以也归入不推荐的方式中啦。
@Configurationpublic class GlobalException { @Bean public SimpleMappingExceptionResolver getSimpleMappingExceptionResolver(){ SimpleMappingExceptionResolver resolver = new SimpleMappingExceptionResolver(); Properties mappings = new Properties(); /* * 参数一:异常的类型,注意必须是异常类型的全名 * 参数二:视图名称 */ mappings.put("java.lang.ArithmeticException", "errors"); //设置异常与视图映射信息的 resolver.setExceptionMappings(mappings); return resolver; }}
复制代码
二、环境准备
案例:
我这里只是简单模拟了一个最简单的异常来测试哈。就是请求方法出错HttpRequestMethodNotSupportedException,然后发送邮件哈。
项目结构:
下面来看具体的代码:
2.1、导入依赖
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.5.2</version> <relativePath/> <!-- lookup parent from repository --></parent><dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-mail</artifactId> </dependency></dependencies>
复制代码
2.2、yml 配置文件
server: port: 8092spring: application: name: springboot-exception-email mail: # 配置 SMTP 服务器地址 host: smtp.qq.com # 发送者邮箱 username: # 配置密码,注意不是真正的密码,而是刚刚申请到的授权码 password: # 端口号465或587 port: 587 # 默认的邮件编码为UTF-8 default-encoding: UTF-8 # 配置SSL 加密工厂 properties: mail: smtp: socketFactoryClass: javax.net.ssl.SSLSocketFactory #表示开启 DEBUG 模式,这样,邮件发送过程的日志会在控制台打印出来,方便排查错误 debug: true
复制代码
2.3、一些公共的类
ThreadPoolTaskExecutorConfig :线程池配置类
/** * 异步线程池ThreadPoolExecutor 配置类 * @author cuberxp * @since 1.0.0 * Create time 2020/4/2 23:23 */@Configuration@EnableAsyncpublic class ThreadPoolTaskExecutorConfig {
@Bean public TaskExecutor taskExecutor() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); //设置核心线程数 executor.setCorePoolSize(10); //设置最大线程数 executor.setMaxPoolSize(20); //缓冲队列200:用来缓冲执行任务的队列 executor.setQueueCapacity(200); //线程活路时间 60 秒 executor.setKeepAliveSeconds(60); //线程池名的前缀:设置好了之后可以方便我们定位处理任务所在的线程池 executor.setThreadNamePrefix("taskExecutor-"); //设置拒绝策略 executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); executor.setWaitForTasksToCompleteOnShutdown(true); return executor; }}
复制代码
ResponseDto:统一返回给前端的数据
/** * @author crush */@Data@NoArgsConstructorpublic class ResponseDto<T> { /** * 错误码*/ private Integer code; /** * 提示信息*/ private String msg; /** * 具体的内容*/ private T data;
public ResponseDto(Integer code, String msg) { this.code = code; this.msg = msg; this.data = null; } public static ResponseDto success(Object object){ ResponseDto result = new ResponseDto(); result.setCode(200); result.setMsg("操作成功"); result.setData(object); return result; }}
复制代码
一些基础环境就准备好了,剩下就是最简单的编码啦哈。
2.4、全局异常处理
/** * @author crush * @ControllerAdvice * @ResponseBody //表示返回的对象,Spring会自动把该对象进行json转化,最后写入到Response中。 */@ControllerAdvice@ResponseBody@Componentpublic class GlobalExceptionHandler {
@Autowired EmailService emailService; /** * //表示让Spring捕获到所有抛出的SignException异常,并交由这个被注解的方法处理。 * //表示设置状态码 * @return */ @ExceptionHandler(HttpRequestMethodNotSupportedException.class) @ResponseStatus(HttpStatus.METHOD_NOT_ALLOWED) ResponseDto handleException(HttpRequestMethodNotSupportedException exception){ LogEmail email = new LogEmail() .setToEmail("951930136@qq.com") .setSubject("异常报告") .setContext(exception.getMessage()); emailService.senderEmail(email); return new ResponseDto(405,exception.getMessage()); }}
复制代码
三、业务代码
3.1、entity
@Data@Accessors(chain = true)public class LogEmail { private String toEmail; private String fromEmail; private String subject; private String context;}
复制代码
3.2、Service
public interface EmailService { /*** 出现异常 发送短信*/ void senderEmail(LogEmail logEmail);}
@Slf4j@Servicepublic class EmailServiceImpl implements EmailService {
@Autowired private JavaMailSender javaMailSender;
@Value("${spring.mail.username}") private String fromEmail;
@Async("taskExecutor") @Override public void senderEmail(LogEmail logEmail) { log.info(Thread.currentThread().getName()); //一个复杂的邮件 MimeMessage message = this.javaMailSender.createMimeMessage(); try { //组装 MimeMessageHelper helper = new MimeMessageHelper(message, true); //正文 //主题 helper.setSubject(logEmail.getSubject()); //开启html模式 helper.setText("<h1>"+logEmail.getContext()+"</h1>" ,true); //附件 helper.addAttachment("1.jpg", new File("C:\\Users\\ASUS\\Desktop\\杂七杂八\\杂图\\2.gif")); helper.setTo(logEmail.getToEmail()); helper.setFrom(fromEmail); javaMailSender.send(message); } catch (MessagingException e) { e.printStackTrace(); } }}
复制代码
3.3、Controller
@RestControllerpublic class DemoController { @GetMapping("/test") public ResponseDto test(){
return ResponseDto.success("我喜欢你!!!"); }}
复制代码
业务代码就这些了,不过记得要补充一个主启动类哈,这个我就不贴啦哈。
四、测试
测试特别简单,先看正常的哈。
我们用正确的GET方式发送请求是完全没有问题的,返回也是正确的数据。
接下来我们用POST方式来请求,看能不能正确的调用邮件方法发送邮件啊😁
证明我们确实已经抓住了这个异常,并且也成功发送了邮件。
这里只是一个小小的 Demo,处理的异常也比较简单,如果真正要去用的话,肯定是不会放在这样的异常上面的,而是一些更加重要的异常上面,细节也会更加的完善。邮件可以一次性提醒很多人,方便应用程序的及时维护。
五、自言自语
我知道咱们掘金的大佬,讲话又好听,长的又帅,女朋友随便 new,给小弟一个赞👍,这肯定的吧。😁
你好,如果你正巧看到这篇文章,并且觉得对你有益的话,就给个赞吧,让我感受一下分享的喜悦吧,蟹蟹。🤗
如若有写的有误的地方,也请大家不啬赐教!!
同样如若有存在疑惑的地方,请留言或私信,定会在第一时间回复你。
持续更新中
评论