java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > Java项目启动成功、失败信息实时反馈提醒

Java项目启动成功、失败信息实时反馈提醒问题(邮件或者短信)

作者:程序猿杨鲍

这篇文章主要介绍了Java项目启动成功、失败信息实时反馈提醒问题(邮件或者短信),具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

在开发的流程中必须涉及的项目的部署发布,这个过程也肯定会有成功失败,在不同的公司里采用的提醒方式不同。

在说明下面的方案前,需要首先说明一下基本应用的场景。

场景说明

1、纯后台应用,现在项目基本都是前后端分离,因为一个前端服务可能会对应多个后端服务的支持,随着整个开发大环境的完善和技术的成熟,之前那种前后端耦合的应用很少,这里不在做具体的考虑。

2、项目的基本架构是Spring+Spring MVC+Mybatis,其实主要是Spring+Spring MVC,因为下面的实现方式在这种模式下模拟,其他环境可以根据这个模式仿照,但是照搬可能存在问题,因为现在很多公司都开始使用SpringBoot相关的前沿技术。

3、环境说明

4、下面的内容数据自己歪歪,如果存在问题,欢迎提建议。

简单实现的几种方式

在项目中添加一个主页,当发布完成后,访问该页面是OK就表示发布成功,反之就是失败,但是这样存在很多问题,比如在线上环境,这个页面可能就访问不到(纯后台应用可能不会提供这个访问功能)。在本地测试和开发环境可以凑合使用。

定时任务请求项目,这个不仅能监控到项目启动是否成功,也可以监控服务器宕机问题,但是也存在问题,那就是要重新开一个项目,用于发送请求,另外当项目启动的时候,刚好定时任务发起,此时是请求不通的,系统会误报启动失败或者宕机,其实不是这样。

日志扫描,通过对日志的分析查看日志中的异常,并做分析,给予开发或者维护人员一个通知,可以通过Python脚本等方式执行,设计到整体项目架构的问题,不做太多的讨论,也不是这个博客的主要讨论范畴,不做太多赘述。

项目中添加逻辑代码,用于捕获项目启动加载是否正常,从而判断项目是否启动成功。(主要讨论)

项目启动反馈提醒实现

web.xml文件中的配置

<servlet>
    <servlet-name>spring-dispatcher</servlet-name>
    <servlet-class>com.minuor.service.notice.LocalDispatcherServletDemo</servlet-class>
    <!-- 配置SpringMVC需要加载的配置文件 spring-xxx.xml -->
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath:spring-web.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
	<servlet-name>spring-dispatcher</servlet-name>
	<!--默认匹配所有的请求 -->
	<url-pattern>/</url-pattern>
</servlet-mapping>

正常应该配置spring默认的DispatcherServlet,这里需要改为加载重新后的LocalDispatcherServletDemo。

LocalDispatcherServletDemo类代码

package com.minuor.service.notice;

import com.minuor.common.utils.JavaMailSendUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationContext;
import org.springframework.context.i18n.LocaleContext;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.XmlWebApplicationContext;
import org.springframework.web.multipart.MultipartException;
import org.springframework.web.servlet.*;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.net.InetAddress;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.Map;

/**
 * @Author: Joker
 * @Date: 2018/3/19
 * @Desc: 重写DispatcherServlet,做系统启动成功失败监控并通知
 */
@Slf4j
public class LocalDispatcherServletDemo extends DispatcherServlet {

    public LocalDispatcherServletDemo() {
        super();
    }

    public LocalDispatcherServletDemo(WebApplicationContext webApplicationContext) {
        super(webApplicationContext);
    }

    @Override
    protected WebApplicationContext initWebApplicationContext() {
        WebApplicationContext webApplicationContext;
        try {
            webApplicationContext = super.initWebApplicationContext();
            sendMsg(Boolean.TRUE);
            log.info(">>>>>>>webApplicationContext初始化成功~");
        } catch (Exception e) {
            sendMsg(Boolean.FALSE);
            webApplicationContext = new XmlWebApplicationContext();//设置临时值,避免重复初始化
            log.info(">>>>>>>webApplicationContext初始化失败~");
        }
        return webApplicationContext;
    }

    /**
     * 发送邮件
     *
     * @param flag
     */
    private void sendMsg(boolean flag) {
        try {
            JavaMailSendUtil sender = new JavaMailSendUtil();
            //成功失败信息
            String result = "FAIL";
            if (flag) result = "SUCCESS";
            //模块名
            String ip = InetAddress.getLocalHost().getHostAddress();
            String userDir = System.getProperty("user.dir");
            String tempStr = userDir.substring(0, userDir.indexOf(File.separator + "bin"));
            String userDirModel = tempStr.substring(tempStr.lastIndexOf(File.separator) + 1);
            //组装并推送信息
            String mailTest = "发布系统:" + "Minuor个人博客系统" + "<br/>" +
                    "发布环境:" + ip + "<br/>" +
                    "模块名称:" + userDirModel + "<br/>" +
                    "发布时间:" + new SimpleDateFormat("yyyyMMdd HH:mm:ss").format(new Date()) + "<br/>" +
                    "发布结果:" + result + "<br/>" +
                    "温馨提示:" + "此邮件仅为系统发布通知邮件,请勿回复!";
            sender.sendEmail("个人博客系统发布结果提醒", mailTest, "xxxx@163.com");
        } catch (Exception e) {
            log.info(">>>>>个人博客系统发布结果预警邮件推送失败!异常信息:{}", e);
        }
    }

    @Override
    public void setDetectAllHandlerMappings(boolean detectAllHandlerMappings) {
        super.setDetectAllHandlerMappings(detectAllHandlerMappings);
    }

    @Override
    protected void initFrameworkServlet() throws ServletException {
        super.initFrameworkServlet();
    }

    @Override
    public void setDetectAllHandlerAdapters(boolean detectAllHandlerAdapters) {
        super.setDetectAllHandlerAdapters(detectAllHandlerAdapters);
    }

    @Override
    public void setDetectAllHandlerExceptionResolvers(boolean detectAllHandlerExceptionResolvers) {
        super.setDetectAllHandlerExceptionResolvers(detectAllHandlerExceptionResolvers);
    }

    @Override
    public void setDetectAllViewResolvers(boolean detectAllViewResolvers) {
        super.setDetectAllViewResolvers(detectAllViewResolvers);
    }

    @Override
    public void setThrowExceptionIfNoHandlerFound(boolean throwExceptionIfNoHandlerFound) {
        super.setThrowExceptionIfNoHandlerFound(throwExceptionIfNoHandlerFound);
    }

    @Override
    public void setCleanupAfterInclude(boolean cleanupAfterInclude) {
        super.setCleanupAfterInclude(cleanupAfterInclude);
    }

    @Override
    protected void onRefresh(ApplicationContext context) {
        super.onRefresh(context);
    }

    @Override
    protected void initStrategies(ApplicationContext context) {
        super.initStrategies(context);
    }

    @Override
    protected <T> T getDefaultStrategy(ApplicationContext context, Class<T> strategyInterface) {
        return super.getDefaultStrategy(context, strategyInterface);
    }

    @Override
    protected <T> List<T> getDefaultStrategies(ApplicationContext context, Class<T> strategyInterface) {
        return super.getDefaultStrategies(context, strategyInterface);
    }

    @Override
    protected Object createDefaultStrategy(ApplicationContext context, Class<?> clazz) {
        return super.createDefaultStrategy(context, clazz);
    }

    @Override
    protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
        super.doService(request, response);
    }

    @Override
    protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
        super.doDispatch(request, response);
    }

    @Override
    protected LocaleContext buildLocaleContext(HttpServletRequest request) {
        return super.buildLocaleContext(request);
    }

    @Override
    protected HttpServletRequest checkMultipart(HttpServletRequest request) throws MultipartException {
        return super.checkMultipart(request);
    }

    @Override
    protected void cleanupMultipart(HttpServletRequest request) {
        super.cleanupMultipart(request);
    }

    @Override
    protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
        return super.getHandler(request);
    }

    @Override
    protected void noHandlerFound(HttpServletRequest request, HttpServletResponse response) throws Exception {
        super.noHandlerFound(request, response);
    }

    @Override
    protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
        return super.getHandlerAdapter(handler);
    }

    @Override
    protected ModelAndView processHandlerException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        return super.processHandlerException(request, response, handler, ex);
    }

    @Override
    protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response) throws Exception {
        super.render(mv, request, response);
    }

    @Override
    protected String getDefaultViewName(HttpServletRequest request) throws Exception {
        return super.getDefaultViewName(request);
    }

    @Override
    protected View resolveViewName(String viewName, Map<String, Object> model, Locale locale, HttpServletRequest request) throws Exception {
        return super.resolveViewName(viewName, model, locale, request);
    }
}

重新所有的方法,直接调用父类DispatcherServlet内的逻辑,实际LocalDispatcherServletDemo中没有具体的逻辑,只有构造方法、initWebApplicationContext、sendMsg短信发送逻辑的修改和创建。

JavaMailSendUtil邮件发送逻辑代码

package com.minuor.common.mail;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import javax.mail.*;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import java.util.Properties;

/**
 * @Author: Joker
 * @Date: 2018/3/19
 * @Desc: 发送邮件服务
 */
@Slf4j
public class JavaMailSendUtil {
    /**
     * 发送邮件
     */
    public void sendEmail(String subject, String mailText, String rStr) {
        try {
            // 1.创建一个程序与邮件服务器会话对象 Session
            Properties props = new Properties();
            props.setProperty("mail.smtp.host", "smtp.163.com");
            props.setProperty("mail.smtp.port", "25");
            // 指定验证为true
            props.setProperty("mail.smtp.auth", "true");
            // 验证账号及密码,密码需要是第三方授权码
            Authenticator auth = new Authenticator() {
                @Override
                protected PasswordAuthentication getPasswordAuthentication() {
                    return new PasswordAuthentication(
                            "xxxx@163.com", "123456");
                }
            };
            Session session = Session.getInstance(props, auth);

            // 2.创建一个Message,它相当于是邮件内容
            Message message = new MimeMessage(session);
            // 设置发送者
            message.setFrom(new InternetAddress("xxxxx@163.com"));
            // 设置发送方式与接收者
            if (StringUtils.isBlank(rStr)) return;
            String[] rStrs = rStr.split(",");
            InternetAddress[] address = new InternetAddress[rStrs.length];
            int index = 0;
            for (String str : rStrs) {
                address[index] = new InternetAddress(str);
                index++;
            }
            message.setRecipients(MimeMessage.RecipientType.TO, address);
            // 设置主题
            message.setSubject(subject);
            // 设置内容
            message.setContent(mailText, "text/html;charset=utf-8");
            // 3.创建 Transport用于将邮件发送
            Transport.send(message);
            log.info(">>>>>>>发送邮件成功<<<<<<<");
        } catch (Exception e) {
            log.error(">>>>>>>发送邮件异常:{}", e);
        }
    }
}

封装的最简单的发送方式,只为实现简单的邮件推送功能。

具体说明

在重新initWebApplicationContext内,对调用父类的initWebApplicationContext方法加了异常捕捉,在catch捕捉中添加了邮件处理逻辑,也将异常吃点不再打印出来;

邮件推送分为两个部分,一个是项目启动成功,一个是项目启动失败,两个部分都会给开发或者维护人员提供相应的邮件提醒;

最主要的一点,这里涉及到的邮件发送工具类,重写类LocalDispatcherServletDemo都不能交给spring管理,因为在spring加载失败的时候,这些类对应的bean是不能创建成功的,更不用说对象的注入以及具体逻辑的实现。

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

您可能感兴趣的文章:
阅读全文