zoukankan      html  css  js  c++  java
  • SpringBoot系列九:SpringBoot服务整合(整合邮件服务、定时调度、Actuator监控)

    声明:本文来源于MLDN培训视频的课堂笔记,写在这里只是为了方便查阅。

    1、概念:SpringBoot 服务整合

    2、背景

    在进行项目开发的时候经常会遇见以下的几个问题:需要进行邮件发送、定时的任务调度、系统的监控处理,实际上这些操 作都可以通过 SpringBoot 进行整合操作。

    2.1、SpringBoot 整合邮件服务

     如果要进行邮件的整合处理,那么你一定需要有一个邮件服务器,实际上 java 本身提供有一套 JavaMail 组件以实现邮件服务器的搭建,但是这个搭建的服务器意义不大,因为你现在搭建完成了,向一些大型的站点发送一封邮件,若干小时你就会被拉黑, 如果不想拉黑彼此之间就做一个白名单即可。

     那么如果说现在自己搭建邮件服务器不行,就可以考虑使用 QQ 邮件服务、网易邮件服务,本次可以申请一个 QQ 邮件服务器,如果要申请你一定要登录你自己的 QQ 邮箱。

    1、 如果要想实现邮件的发送服务,则首先要导入一个依赖的支持库:

            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-mail</artifactId>
            </dependency>

     2、 修改项目中的 application.yml 配置文件,实现邮件的配置:

    spring:
      messages:
        basename: i18n/Messages,i18n/Pages
      mail:
        host: smtp.qq.com
        username: 你自己的用户名,110@qq.com
        password: xxxxx
        properties:
          mail.smtp.auth: true
          mail.smtp.starttls.enable: true
          mail.smtp.starttls.required: true

     3、 编写测试类,直接调用 mail 服务:

    package cn.study.microboot;
    import javax.annotation.Resource;
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.mail.SimpleMailMessage;
    import org.springframework.mail.javamail.JavaMailSender;
    import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
    import org.springframework.test.context.web.WebAppConfiguration;
    @SpringBootTest(classes = StartSpringBootMain.class)
    @RunWith(SpringJUnit4ClassRunner.class)
    @WebAppConfiguration
    public class TestMail {
        @Resource
        private JavaMailSender javaMailSender ;
        @Test
        public void testSendMail() {
            SimpleMailMessage message = new SimpleMailMessage() ;    // 要发送的消息内容
            message.setFrom("你自己的邮箱地址,444@qq.com");
            message.setTo("接收者的邮箱地址,555@qq.com");
            message.setSubject("测试邮件)");
            message.setText("好好学习,天天向上");
            this.javaMailSender.send(message);
        }
    }

     你如果要是个人玩玩还可以,如果要进行海量发送,腾讯不会让你得逞的,你得再去申请企业的邮箱,如果现在觉得腾讯邮 箱不能够满足于你的要求,你可以考虑使用阿里云服务。

     2.2、定时调度

     所有的系统开发里面定时调度绝对是一个核心的话题,对于定时调度的实现在实际开发之中可以使用:TimerTask、Quartz、 SpringTask 配置,实际上这里面最简单的配置就是 Spring 自己所提供的 Task 处理。

     1、 如果要想实现定时调度,只需要配置一个定时调度的组件类即可:

    package cn.study.microboot.task;
    
    import java.text.SimpleDateFormat;
    import java.util.Date;
    
    import org.springframework.scheduling.annotation.Scheduled;
    import org.springframework.stereotype.Component;
    
    @Component
    public class MyScheduler {
        @Scheduled(fixedRate = 2000) // 采用间隔调度,每2秒执行一次
        public void runJobA() { // 定义一个要执行的任务
            System.out.println("【*** MyTaskA - 间隔调度 ***】"
                    + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS")
                            .format(new Date()));
        }
        @Scheduled(cron = "* * * * * ?") // 每秒调用一次
        public void runJobB() {
            System.err.println("【*** MyTaskB - 间隔调度 ***】"
                    + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS")
                            .format(new Date()));
        }
    }

     2、 如果现在要想执行此任务,那么还需要有一个基本的前提:你的程序启动类上一定要启用调度处理。

    package cn.study.microboot;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.scheduling.annotation.EnableScheduling;
    
    @SpringBootApplication // 启动SpringBoot程序,而后自带子包扫描
    @EnableScheduling    // 启用间隔调度
    public class StartSpringBootMain {
        public static void main(String[] args) throws Exception {
            SpringApplication.run(StartSpringBootMain.class, args);
        }
    }

     这个时候所实现的任务调度只是串行任务调度,也就是说所有的任务是一个一个执行的处理方式,那么如果现在有一个任务 所花费的时间特别的长,则其它的任务都会积压,实际开发之中很明显这种处理是不可能存在的。

     3、 如果要想启用并行的调度处理,则一定要准备出一个线程调度池,进行一个线程调度的配置类:

    package cn.study.microboot.config;
    
    import java.util.concurrent.Executors;
    
    import org.springframework.context.annotation.Configuration;
    import org.springframework.scheduling.annotation.SchedulingConfigurer;
    import org.springframework.scheduling.config.ScheduledTaskRegistrar;
    
    @Configuration // 定时调度的配置类一定要实现指定的父接口
    public class SchedulerConfig implements SchedulingConfigurer {
        @Override
        public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { // 开启一个线程调度池
            taskRegistrar.setScheduler(Executors.newScheduledThreadPool(100));
        }
    
    }

     2.3、Actuator 监控

    对于 SpringBoot 中的服务的监控在 SpringBoot 开发框架之中提供有一个 Actuator 监控程序,但是这个监控程序在很多的时候 使用有一些矛盾,对于此类的信息服务,一般而言会有两类信息:

    · 第一类是由系统直接提供好的信息,这个需要关闭安全控制;

    · 第二类是由用户定义的,希望可以返回固定的一些信息,例如:版本、服务名称等。

    1、 如果现在要想在代码之中启用 actuator 服务,那么首先一定要进行开发包的配置;

            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-actuator</artifactId>
            </dependency>

     2、 此时配置此依赖包的项目就具有了监控的操作能力,但是这个能力无法直接体现,如果现在要想打开默认的系统的这些监控 信息,则需要修改 application.yml 配置文件,关闭掉当前的安全配置项:

    server:
      port: 80
    management:
      security:
        enabled: false # 现在关闭系统的安全配置

     3、 但是如果现在将系统的安全配置关闭了之后,那么此时你的系统的服务信息就有可能被任何人看见,那么不希望被所有人看 见,同时也希望所有的人可以看见一些能够看见的提示信息,所以在这样的状态下,就需要去考虑自定义一些服务信息出现。例如, 现在先进行健康信息的配置;

     范例:定义一个健康配置类

    package cn.study.microboot.actuator;
    
    import org.springframework.boot.actuate.health.Health;
    import org.springframework.boot.actuate.health.HealthIndicator;
    import org.springframework.stereotype.Component;
    @Component
    public class MyHealthIndicator implements HealthIndicator {
    
        @Override
        public Health health() {
            return Health.down().withDetail("info", "老子还活着!").build();
        }
    
    }

     但是发现这种健康的信息配置是需要打开安全策略之后才能够发现一些更加详细的内容,而如果开启了安全策略之后可以看 见的信息只能够是一些基础的状态:UP(存活)、DOWN(关闭)。

    package cn.study.microboot.actuator;
    
    import org.springframework.boot.actuate.health.Health;
    import org.springframework.boot.actuate.health.HealthIndicator;
    import org.springframework.stereotype.Component;
    @Component
    public class MyHealthIndicator implements HealthIndicator {
    
        @Override
        public Health health() {
            int errorCode = 100 ;    // 这个错误的码是通过其它程序获得的
            if (errorCode != 0) {
                return Health.down().withDetail("Error Code", errorCode).build();
            }
            return Health.up().build() ;
        }
    
    }

    4、 除了健康之外,还有一项数据很重要,就是一些服务的信息(/info),而这些服务的信息可以直接通过 application.yml 文件配 置,修改 application.yml 要按照指定的格式完成:

    · 对于这样的配置信息最好的方式就是进行 pom.xml 文件的读取,所以如果要想实现这种关联操作,则必须修改 microboot 项目中的 pom.xml 文件,追加有一个访问的插件:

                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-resources-plugin</artifactId>
                    <configuration>
                        <delimiters>
                            <delimiter>$</delimiter>
                        </delimiters>
                    </configuration>
                </plugin>

    · 修改 resources 中的访问处理:

                <resource>
                    <directory>src/main/resources</directory>
                    <includes>
                        <include>**/*.properties</include>
                        <include>**/*.yml</include>
                        <include>**/*.xml</include>
                        <include>**/*.tld</include>
                        <include>**/*.p12</include>
                        <include>**/*.conf</include>
                    </includes>
                    <filtering>true</filtering>
                </resource>

    · 修改 application.yml 配置文件,追加详细信息

    info:
      app.name: mldn-microboot
      app.version: v1.0.0
      company.name: www.mldn.cn
      pom.artifactId: $project.artifactId$
      pom.version: $project.version$

    5、 由于在开发之中这种提示信息会成为微服务的重要组成部分,所以很多时候如果重复进行application.yml 配置文件的定义,那么会比较麻烦, 最简单的做法直接做一个配置程序类进行信息的配置。

    package cn.study.microboot.actuator;
    
    import org.springframework.boot.actuate.info.Info.Builder;
    import org.springframework.stereotype.Component;
    import org.springframework.boot.actuate.info.InfoContributor;
    @Component
    public class ProjectInfoContributor implements InfoContributor {
    
        @Override
        public void contribute(Builder builder) {
            builder.withDetail("company.name", "study") ;
            builder.withDetail("version", "V1.0") ;
            builder.withDetail("author", "sss") ;
        }
    
    }
  • 相关阅读:
    数据结构与算法分析-Code Blocks中出现的找不到头文件的问题
    数据结构与算法分析-用C语言实现栈(数组方式)
    数据结构与算法分析-用C语言实现栈(链表方式)
    数据结构与算法分析-用C语言实现单链表
    C语言经典算法100例-结束语
    C++ Primer 7.33 练习编写成员函数
    C语言经典算法100例-073-链表逆序插入节点
    C语言经典算法100例-072-创建一个链表
    LintCode-编辑距离
    LintCode-乘积最大子序列
  • 原文地址:https://www.cnblogs.com/leeSmall/p/8727197.html
Copyright © 2011-2022 走看看