SpringBoot admin 2.0 详解

作者: 程序员果果 | 来源:发表于2019-01-25 09:31 被阅读180次

    一、什么是Spring Boot Admin ?

    Spring Boot Admin是一个开源社区项目,用于管理和监控SpringBoot应用程序。 应用程序作为Spring Boot Admin Client向为Spring Boot Admin Server注册(通过HTTP)或使用SpringCloud注册中心(例如Eureka,Consul)发现。 UI是的Vue.js应用程序,展示Spring Boot Admin Client的Actuator端点上的一些监控。服务端采用Spring WebFlux + Netty的方式。Spring Boot Admin为注册的应用程序提供以下功能:

    • 显示健康状况
    • 显示详细信息,例如
    • JVM和内存指标
    • micrometer.io指标
    • 数据源指标
    • 缓存指标
    • 显示构建信息编号
    • 关注并下载日志文件
    • 查看jvm system-和environment-properties
    • 查看Spring Boot配置属性
    • 支持Spring Cloud的postable / env-和/ refresh-endpoint
    • 轻松的日志级管理
    • 与JMX-beans交互
    • 查看线程转储
    • 查看http-traces
    • 查看auditevents
    • 查看http-endpoints
    • 查看计划任务
    • 查看和删除活动会话(使用spring-session)
    • 查看Flyway / Liquibase数据库迁移
    • 下载heapdump
    • 状态变更通知(通过电子邮件,Slack,Hipchat,......)
    • 状态更改的事件日志(非持久性)

    二、入门

    1. 创建 Spring Boot Admin Server

    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">
        <modelVersion>4.0.0</modelVersion>
        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>2.1.0.RELEASE</version>
            <relativePath/> <!-- lookup parent from repository -->
        </parent>
        <groupId>com.gf</groupId>
        <artifactId>admin-server</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <name>admin-server</name>
        <description>Demo project for Spring Boot</description>
    
        <properties>
            <java.version>1.8</java.version>
            <spring-boot-admin.version>2.1.0</spring-boot-admin.version>
        </properties>
    
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
            <dependency>
                <groupId>de.codecentric</groupId>
                <artifactId>spring-boot-admin-starter-server</artifactId>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
            </dependency>
        </dependencies>
    
        <dependencyManagement>
            <dependencies>
                <dependency>
                    <groupId>de.codecentric</groupId>
                    <artifactId>spring-boot-admin-dependencies</artifactId>
                    <version>${spring-boot-admin.version}</version>
                    <type>pom</type>
                    <scope>import</scope>
                </dependency>
            </dependencies>
        </dependencyManagement>
    
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
            </plugins>
        </build>
    
    </project>
    

    application.yml

    spring:
      application:
        name: admin-server
    server:
      port: 8769
    

    启动类 AdminServerApplication

    启动类加上@EnableAdminServer注解,开启AdminServer的功能:

    @SpringBootApplication
    @EnableAdminServer
    public class AdminServerApplication {
    
        public static void main(String[] args) {
            SpringApplication.run( AdminServerApplication.class, args );
        }
    
    }
    

    2. 创建 Spring Boot Admin Client

    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">
        <modelVersion>4.0.0</modelVersion>
        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>2.1.0.RELEASE</version>
            <relativePath/> <!-- lookup parent from repository -->
        </parent>
        <groupId>com.gf</groupId>
        <artifactId>admin-client</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <name>admin-client</name>
        <description>Demo project for Spring Boot</description>
    
        <properties>
            <java.version>1.8</java.version>
            <spring-boot-admin.version>2.1.0</spring-boot-admin.version>
        </properties>
    
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
            <dependency>
                <groupId>de.codecentric</groupId>
                <artifactId>spring-boot-admin-starter-client</artifactId>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
            </dependency>
        </dependencies>
    
        <dependencyManagement>
            <dependencies>
                <dependency>
                    <groupId>de.codecentric</groupId>
                    <artifactId>spring-boot-admin-dependencies</artifactId>
                    <version>${spring-boot-admin.version}</version>
                    <type>pom</type>
                    <scope>import</scope>
                </dependency>
            </dependencies>
        </dependencyManagement>
    
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
            </plugins>
        </build>
    
    </project>
    
    

    application.yml

    • spring.boot.admin.client.url:要注册的Spring Boot Admin Server的URL。
    • management.endpoints.web.exposure.include:与Spring Boot 2一样,默认情况下,大多数actuator的端口都不会通过http公开,* 代表公开所有这些端点。对于生产环境,应该仔细选择要公开的端点。
    spring:
      application:
        name: admin-client
      boot:
        admin:
          client:
            url: http://localhost:8769
    server:
      port: 8768
    
    management:
      endpoints:
        web:
          exposure:
            include: '*'
      endpoint:
        health:
          show-details: ALWAYS
    

    启动类 AdminClientApplication

    @SpringBootApplication
    public class AdminClientApplication {
    
        public static void main(String[] args) {
            SpringApplication.run( AdminClientApplication.class, args );
        }
    
    }
    

    启动两个工程,在浏览器上输入localhost:8769 ,浏览器显示的界面如下:

    查看wallboard:

    点击wallboard,可以查看admin-client具体的信息,比如内存状态信息:

    查看spring bean的情况:

    查看应用程序运行状况,信息和详细:

    还有很多监控信息,多点一点就知道。

    三、集成 Eureka

    1. 创建 sc-eureka-server

    这是一个 eureka-server 注册中心。

    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">
        <modelVersion>4.0.0</modelVersion>
        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>2.1.0.RELEASE</version>
            <relativePath/> <!-- lookup parent from repository -->
        </parent>
        <groupId>com.gf</groupId>
        <artifactId>sc-admin-server</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <name>sc-admin-server</name>
        <description>Demo project for Spring Boot</description>
    
        <properties>
            <java.version>1.8</java.version>
            <spring-boot-admin.version>2.1.0</spring-boot-admin.version>
            <spring-cloud.version>Finchley.RELEASE</spring-cloud.version>
        </properties>
    
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
            <dependency>
                <groupId>de.codecentric</groupId>
                <artifactId>spring-boot-admin-starter-server</artifactId>
                <version>2.1.0</version>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-security</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-mail</artifactId>
            </dependency>
            <dependency>
                <groupId>org.jolokia</groupId>
                <artifactId>jolokia-core</artifactId>
            </dependency>
        </dependencies>
    
        <dependencyManagement>
            <dependencies>
                <dependency>
                    <groupId>org.springframework.cloud</groupId>
                    <artifactId>spring-cloud-dependencies</artifactId>
                    <version>${spring-cloud.version}</version>
                    <type>pom</type>
                    <scope>import</scope>
                </dependency>
                <dependency>
                    <groupId>de.codecentric</groupId>
                    <artifactId>spring-boot-admin-dependencies</artifactId>
                    <version>${spring-boot-admin.version}</version>
                    <type>pom</type>
                    <scope>import</scope>
                </dependency>
            </dependencies>
        </dependencyManagement>
    
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
            </plugins>
        </build>
    
    </project>
    
    

    application.yml

    spring:
      application:
        name: sc-eureka-server
    server:
      port: 8761
    eureka:
      client:
        service-url:
          defaultZone: http://localhost:8761/eureka
        register-with-eureka: false
        fetch-registry: false
    management:
      endpoints:
        web:
          exposure:
            include: "*"
      endpoint:
        health:
          show-details: ALWAYS
    

    启动类 ScEurekaServerApplication

    @SpringBootApplication
    @EnableEurekaServer
    public class ScEurekaServerApplication {
    
        public static void main(String[] args) {
            SpringApplication.run( ScEurekaServerApplication.class, args );
        }
    
    }
    

    2. 创建 sc-admin-server

    这是一个 Spring Boot Admin Server端。

    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">
        <modelVersion>4.0.0</modelVersion>
        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>2.1.0.RELEASE</version>
            <relativePath/> <!-- lookup parent from repository -->
        </parent>
        <groupId>com.gf</groupId>
        <artifactId>sc-admin-server</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <name>sc-admin-server</name>
        <description>Demo project for Spring Boot</description>
    
        <properties>
            <java.version>1.8</java.version>
            <spring-boot-admin.version>2.1.0</spring-boot-admin.version>
            <spring-cloud.version>Finchley.RELEASE</spring-cloud.version>
        </properties>
    
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
            <dependency>
                <groupId>de.codecentric</groupId>
                <artifactId>spring-boot-admin-starter-server</artifactId>
                <version>2.1.0</version>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-security</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-mail</artifactId>
            </dependency>
            <dependency>
                <groupId>org.jolokia</groupId>
                <artifactId>jolokia-core</artifactId>
            </dependency>
        </dependencies>
    
        <dependencyManagement>
            <dependencies>
                <dependency>
                    <groupId>org.springframework.cloud</groupId>
                    <artifactId>spring-cloud-dependencies</artifactId>
                    <version>${spring-cloud.version}</version>
                    <type>pom</type>
                    <scope>import</scope>
                </dependency>
                <dependency>
                    <groupId>de.codecentric</groupId>
                    <artifactId>spring-boot-admin-dependencies</artifactId>
                    <version>${spring-boot-admin.version}</version>
                    <type>pom</type>
                    <scope>import</scope>
                </dependency>
            </dependencies>
        </dependencyManagement>
    
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
            </plugins>
        </build>
    
    </project>
    
    

    application.yml

    spring:
      application:
        name: admin-server
    server:
      port: 8769
    eureka:
      client:
        registryFetchIntervalSeconds: 5
        service-url:
          defaultZone: ${EUREKA_SERVICE_URL:http://localhost:8761}/eureka/
      instance:
        leaseRenewalIntervalInSeconds: 10
        health-check-url-path: /actuator/health
    
    management:
      endpoints:
        web:
          exposure:
            include: "*"
      endpoint:
        health:
          show-details: ALWAYS
    

    启动类 ScAdminServerApplication

    @SpringBootApplication
    @EnableAdminServer
    @EnableDiscoveryClient
    public class ScAdminServerApplication {
    
        public static void main(String[] args) {
            SpringApplication.run( ScAdminServerApplication.class, args );
        }
    
    }
    

    3. 创建 sc-admin-client

    这是一个 Spring Boot Admin client 端。

    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">
        <modelVersion>4.0.0</modelVersion>
        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>2.1.0.RELEASE</version>
            <relativePath/> <!-- lookup parent from repository -->
        </parent>
        <groupId>com.gf</groupId>
        <artifactId>sc-admin-client</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <name>sc-admin-client</name>
        <description>Demo project for Spring Boot</description>
    
        <properties>
            <java.version>1.8</java.version>
            <spring-boot-admin.version>2.1.0</spring-boot-admin.version>
            <spring-cloud.version>Finchley.SR2</spring-cloud.version>
        </properties>
    
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-actuator</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-webflux</artifactId>
            </dependency>
            <dependency>
                <groupId>de.codecentric</groupId>
                <artifactId>spring-boot-admin-starter-client</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
            </dependency>
        </dependencies>
    
        <dependencyManagement>
            <dependencies>
                <dependency>
                    <groupId>org.springframework.cloud</groupId>
                    <artifactId>spring-cloud-dependencies</artifactId>
                    <version>${spring-cloud.version}</version>
                    <type>pom</type>
                    <scope>import</scope>
                </dependency>
                <dependency>
                    <groupId>de.codecentric</groupId>
                    <artifactId>spring-boot-admin-dependencies</artifactId>
                    <version>${spring-boot-admin.version}</version>
                    <type>pom</type>
                    <scope>import</scope>
                </dependency>
            </dependencies>
        </dependencyManagement>
    
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
            </plugins>
        </build>
    
    </project>
    
    

    application.yml

    spring:
      application:
        name: sc-admin-client
    eureka:
      instance:
        leaseRenewalIntervalInSeconds: 10
        health-check-url-path: /actuator/health
    
      client:
        registryFetchIntervalSeconds: 5
        service-url:
          defaultZone: ${EUREKA_SERVICE_URL:http://localhost:8761}/eureka/
    management:
      endpoints:
        web:
          exposure:
            include: "*"
      endpoint:
        health:
          show-details: ALWAYS
    server:
      port: 8762
    

    启动类 ScAdminClientApplication

    @SpringBootApplication
    @EnableDiscoveryClient
    public class ScAdminClientApplication {
    
        public static void main(String[] args) {
            SpringApplication.run( ScAdminClientApplication.class, args );
        }
    
    }
    

    启动三个工程,访问localhost:8769,出现如下界面:

    admin 会自己拉取 Eureka 上注册的 app 信息,主动去注册。这也是唯一区别之前入门中手动注册的地方,就是 client 端不需要 admin-client 的依赖,也不需要配置 admin 地址了,一切全部由 admin-server 自己实现。这样的设计对环境变化很友好,不用改了admin-server后去改所有app 的配置了。

    四、集成 Spring Security

    Web应用程序中的身份验证和授权有多种方法,因此Spring Boot Admin不提供默认方法。默认情况下,spring-boot-admin-server-ui提供登录页面和注销按钮。我们结合 Spring Security 实现需要用户名和密码登录的安全认证。

    sc-admin-server工程的pom文件需要增加以下的依赖:

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

    在 sc-admin-server工的配置文件 application.yml 中配置 spring security 的用户名和密码,这时需要在服务注册时带上 metadata-map 的信息,如下:

    spring:
      security:
        user:
          name: "admin"
          password: "admin"
          
    eureka:
      instance:
        metadata-map:
          user.name: ${spring.security.user.name}
          user.password: ${spring.security.user.password}
    

    @EnableWebSecurity注解以及WebSecurityConfigurerAdapter一起配合提供基于web的security。继承了WebSecurityConfigurerAdapter之后,再加上几行代码,我们就能实现要求用户在进入应用的任何URL之前都进行验证的功能,写一个配置类SecuritySecureConfig继承WebSecurityConfigurerAdapter,配置如下:

    @Configuration
    public class SecuritySecureConfig extends WebSecurityConfigurerAdapter {
    
        private final String adminContextPath;
    
        public SecuritySecureConfig(AdminServerProperties adminServerProperties) {
            this.adminContextPath = adminServerProperties.getContextPath();
        }
    
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            // @formatter:off
            SavedRequestAwareAuthenticationSuccessHandler successHandler = new SavedRequestAwareAuthenticationSuccessHandler();
            successHandler.setTargetUrlParameter("redirectTo");
            successHandler.setDefaultTargetUrl(adminContextPath + "/");
    
            http.authorizeRequests()
                    //授予对所有静态资产和登录页面的公共访问权限。
                    .antMatchers(adminContextPath + "/assets/**").permitAll()
                    .antMatchers(adminContextPath + "/login").permitAll()
                    //必须对每个其他请求进行身份验证
                    .anyRequest().authenticated()
                    .and()
                    //配置登录和注销
                    .formLogin().loginPage(adminContextPath + "/login").successHandler(successHandler).and()
                    .logout().logoutUrl(adminContextPath + "/logout").and()
                    //启用HTTP-Basic支持。这是Spring Boot Admin Client注册所必需的
                    .httpBasic().and();
            // @formatter:on
        }
    }
    

    重新访问 http://localhost:8769/ 会出现登录界面,密码是 配置文件中配置好的,账号 admin 密码 admin,界面如下:

    五、通知

    1. 邮件通知

    在 Spring Boot Admin 中 当注册的应用程序状态更改为DOWN、UNKNOWN、OFFLINE 都可以指定触发通知,下面讲解配置邮件通知。

    在sc-admin-server工程pom文件,加上mail的依赖,如下:

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

    在配置文件application.yml文件中,配置收发邮件的配置:

    spring:
      mail:
        host: smtp.163.com
        username: xxxx@163.com
        password: xxxx
        properties:
          mail:
            smtp:
              auth: true
              starttls:
                enable: true
                required: true
      boot:
        admin:
          notify:
            mail:
              from: xxxx@163.com
              to: xxxx@qq.com
    

    配置后,重启sc-admin-server工程,之后若出现注册的客户端的状态从 UP 变为 OFFLINE 或其他状态,服务端就会自动将电子邮件发送到上面配置的收件地址。

    注意 : 配置了邮件通知后,会出现 反复通知 service offline / up。这个问题的原因在于 查询应用程序的状态和信息超时,下面给出两种解决方案:

    #方法一:增加超时时间(单位:ms)
    
    spring.boot.admin.monitor.read-timeout=20000
    
    #方法二:关闭闭未使用或不重要的检查点
    
    management.health.db.enabled=false
    management.health.mail.enabled=false
    management.health.redis.enabled=false
    management.health.mongo.enabled=false
    

    2. 自定义通知

    可以通过添加实现Notifier接口的Spring Beans来添加您自己的通知程序,最好通过扩展 AbstractEventNotifier或AbstractStatusChangeNotifier。在sc-admin-server工程中编写一个自定义的通知器:

    @Component
    public class CustomNotifier  extends AbstractStatusChangeNotifier {
        private static final Logger LOGGER = LoggerFactory.getLogger( LoggingNotifier.class);
    
        public CustomNotifier(InstanceRepository repository) {
            super(repository);
        }
    
        @Override
        protected Mono<Void> doNotify(InstanceEvent event, Instance instance) {
            return Mono.fromRunnable(() -> {
                if (event instanceof InstanceStatusChangedEvent) {
                    LOGGER.info("Instance {} ({}) is {}", instance.getRegistration().getName(), event.getInstance(),
                            ((InstanceStatusChangedEvent) event).getStatusInfo().getStatus());
    
                    String status = ((InstanceStatusChangedEvent) event).getStatusInfo().getStatus();
    
                    switch (status) {
                        // 健康检查没通过
                        case "DOWN":
                            System.out.println("发送 健康检查没通过 的通知!");
                            break;
                        // 服务离线
                        case "OFFLINE":
                            System.out.println("发送 服务离线 的通知!");
                            break;
                        //服务上线
                        case "UP":
                            System.out.println("发送 服务上线 的通知!");
                            break;
                        // 服务未知异常
                        case "UNKNOWN":
                            System.out.println("发送 服务未知异常 的通知!");
                            break;
                        default:
                            break;
                    }
    
                } else {
                    LOGGER.info("Instance {} ({}) {}", instance.getRegistration().getName(), event.getInstance(),
                            event.getType());
                }
            });
        }
    }
    

    源码下载:https://github.com/gf-huanchupk/SpringBootLearning/tree/master/springboot-admin

    相关文章

      网友评论

        本文标题:SpringBoot admin 2.0 详解

        本文链接:https://www.haomeiwen.com/subject/hwapjqtx.html