Spring Boot Admin 是一个开源的社区项目,用于管理和监控 Spring Boot 应用程序。应用程序可以通过 http 的方式,或 Spring Cloud 服务发现机制注册到 SBA 中,然后就可以实现对 Spring Boot 项目的可视化管理
Spring Boot Admin 可以监控 Spring Boot 单机或集群项目,它提供详细的健康 (Health)信息、内存信息、JVM 系统和环境属性、垃圾回收信息、日志设置和查看、定时任务查看、Spring Boot 缓存查看和管理等功能
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-test
de.codecentric
spring-boot-admin-starter-server
2.7.0
org.springframework.boot
spring-boot-starter-actuator
org.springframework.boot
spring-boot-starter-security
org.springframework.boot
spring-boot-starter-mail
org.springframework.boot
spring-boot-maven-plugin
2.7.0
spring:
profiles:
active: dev
server:
address: 127.0.0.1
port: 9999
servlet:
context-path: /springBootAdmin
spring:
application:
name: springBootAdmin
security:
user:
name: admin
password: admin
mail:
protocol: smtp
host: smtp.163.com
username: [email protected]
password: JFURNCZSERNXYCVE
default-encoding: UTF-8
properties:
mail:
smtp:
auth: true
starttls:
enable: true
required: true
@SpringBootApplication
@EnableAdminServer // 开启SpringBootAdmin服务
@EnableWebSecurity // 开启SpringSecurity安全认证
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
package com.example.demo.config;
import de.codecentric.boot.admin.server.config.AdminServerProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer;
import org.springframework.security.web.DefaultSecurityFilterChain;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import javax.servlet.Filter;
import java.util.ArrayList;
import java.util.List;
@Configuration
public class SecurityConfig {
// @Bean
// UserDetailsService userDetailsService() {
// InMemoryUserDetailsManager users = new InMemoryUserDetailsManager();
// // TODO 创建默认用户
// users.createUser(User.withUsername("admin").password("admin").roles("admin").build());
// users.createUser(User.withUsername("lixing").password("lixing").roles("admin").build());
// return users;
// }
// @Bean
// WebSecurityCustomizer webSecurityCustomizer() {
// return new WebSecurityCustomizer() {
// @Override
// public void customize(WebSecurity web) {
// // TODO 设置 /demo/noAuth 匿名登录,不经过 Spring Security 过滤器链
// web.ignoring().antMatchers("/demo/noAuth");
// }
// };
// }
/**
* Spring Security 的底层实际上就是一堆过滤器,所以我们之前在 configure(HttpSecurity) 方法中的配置,实际上就是配置过滤器链。
* 现在过滤器链的配置,我们通过提供一个 SecurityFilterChain Bean 来配置过滤器链,SecurityFilterChain 是一个接口,这个接口只有一个实现类 DefaultSecurityFilterChain,
* 构建 DefaultSecurityFilterChain 的第一个参数是拦截规则,也就是哪些路径需要拦截,
* 第二个参数则是过滤器链,这里我给了一个空集合,也就是我们的 Spring Security 会拦截下所有的请求,然后在一个空集合中走一圈就结束了,相当于不拦截任何请求
*/
// @Bean
// SecurityFilterChain securityFilterChain() {
// List filters = new ArrayList<>();
// return new DefaultSecurityFilterChain(new AntPathRequestMatcher("/**"), filters);
// }
private final String adminContextPath;
public SecurityConfig(AdminServerProperties adminServerProperties) {
this.adminContextPath = adminServerProperties.getContextPath();
}
@Bean
SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
// 静态资源和登录页面可以不用认证
http.authorizeRequests().antMatchers(adminContextPath + "/assets/**").permitAll()
.antMatchers(adminContextPath + "/login").permitAll()
// 其他请求必须认证
.anyRequest().authenticated()
// 自定义登录和退出
.and().formLogin().loginPage(adminContextPath + "/login")
.and().logout().logoutUrl(adminContextPath + "/logout")
// 启用HTTP-Basic, 用于Spring Boot Admin Client注册
.and().httpBasic().and().csrf().disable();
return http.build();
}
}
package com.example.demo.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
@Configuration
public class SecurityPermitAllConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().anyRequest().permitAll()
.and().csrf().disable();
}
}
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
dependency>
<dependency>
<groupId>de.codecentricgroupId>
<artifactId>spring-boot-admin-starter-clientartifactId>
<version>2.7.0version>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-actuatorartifactId>
dependency>
dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-maven-pluginartifactId>
<version>2.7.0version>
plugin>
plugins>
build>
spring:
profiles:
active: dev
server:
address: 127.0.0.1
port: 9998
servlet:
context-path: /springBootClient
# spring Boot Admin 服务端地址
spring:
application:
name: springBootClient
boot:
admin:
client:
url: http://127.0.0.1:9999/springBootAdmin
username: admin
password: admin
instance:
service-url: http://127.0.0.1:9998/springBootClient
metadata:
user.name: admin
user.password: admin
# TODO SpringBootAdmin资源监控配置
management:
endpoints:
web:
exposure:
include: "*"
endpoint:
health:
show-details: ALWAYS
logfile:
enabled: on
custom:
log:
level: debug
path: D:\logs
debug: on
logging:
config: classpath:logback-spring.xml
level:
root: debug
#com.example.demo.demo1: warn
#com.example.demo.demo2: error
file:
name: D:\logs\info.log
custom:
log:
level: info
path: D:\logs
debug: off
logging:
config: classpath:logback-spring.xml
level:
root: info
#com.example.demo.demo1: warn
#com.example.demo.demo2: error
file:
name: D:\logs\info.log
<configuration scan="true">
<property name="CONTEXT_NAME" value="springBootClient"/>
<contextName>${CONTEXT_NAME}contextName>
<property name="MAX_FILE_SIZE" value="100MB"/>
<property name="MAX_HISTORY" value="30"/>
<springProperty scope="context" name="logLevel" source="custom.log.level"/>
<springProperty scope="context" name="logPath" source="custom.log.path"/>
<conversionRule conversionWord="clr"
converterClass="org.springframework.boot.logging.logback.ColorConverter"/>
<conversionRule conversionWord="wex"
converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter"/>
<conversionRule conversionWord="wEx"
converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter"/>
<statusListener class="ch.qos.logback.core.status.NopStatusListener"/>
<logger name="org.apache.catalina.connector.CoyoteAdapter" level="OFF"/>
<property name="CONSOLE_LOG_PATTERN"
value="${CONSOLE_LOG_PATTERN:-%clr(%d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd HH:mm:ss.SSS}}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} [%L] %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/>
<property name="FILE_LOG_PATTERN"
value="${FILE_LOG_PATTERN:-%d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd HH:mm:ss.SSS}} ${LOG_LEVEL_PATTERN:-%5p} ${PID:- } [%t] %-40.40logger{39} %L : %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/>
<springProfile name="dev">
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${CONSOLE_LOG_PATTERN}pattern>
<charset>UTF-8charset>
encoder>
appender>
<root level="${logLevel}">
<appender-ref ref="CONSOLE"/>
root>
springProfile>
<springProfile name="fat">
<appender name="INFO_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${logPath}/info.logfile>
<encoder>
<pattern>${FILE_LOG_PATTERN}pattern>
<charset>UTF-8charset>
encoder>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${logPath}/info-%d{yyyy-MM-dd}.%i.logfileNamePattern>
<maxFileSize>${MAX_FILE_SIZE}maxFileSize>
<maxHistory>${MAX_HISTORY}maxHistory>
rollingPolicy>
appender>
<appender name="WARN_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${logPath}/warn.logfile>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>WARNlevel>
<onMatch>ACCEPTonMatch>
<onMismatch>DENYonMismatch>
filter>
<encoder>
<pattern>${FILE_LOG_PATTERN}pattern>
<charset>UTF-8charset>
encoder>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${logPath}/warn-%d{yyyy-MM-dd}.%i.logfileNamePattern>
<maxFileSize>${MAX_FILE_SIZE}maxFileSize>
<maxHistory>${MAX_HISTORY}maxHistory>
rollingPolicy>
appender>
<appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${logPath}/error.logfile>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>ERRORlevel>
<onMatch>ACCEPTonMatch>
<onMismatch>DENYonMismatch>
filter>
<encoder>
<pattern>${FILE_LOG_PATTERN}pattern>
<charset>UTF-8charset>
encoder>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${logPath}/error-%d{yyyy-MM-dd}.%i.logfileNamePattern>
<maxFileSize>${MAX_FILE_SIZE}maxFileSize>
<maxHistory>${MAX_HISTORY}maxHistory>
rollingPolicy>
appender>
<appender name="ASYNC_INFO_FILE" class="ch.qos.logback.classic.AsyncAppender">
<discardingThreshold>0discardingThreshold>
<queueSize>1024queueSize>
<appender-ref ref="INFO_FILE"/>
appender>
<appender name="ASYNC_WARN_FILE" class="ch.qos.logback.classic.AsyncAppender">
<discardingThreshold>0discardingThreshold>
<queueSize>1024queueSize>
<appender-ref ref="WARN_FILE"/>
appender>
<appender name="ASYNC_ERROR_FILE" class="ch.qos.logback.classic.AsyncAppender">
<discardingThreshold>0discardingThreshold>
<queueSize>1024queueSize>
<appender-ref ref="ERROR_FILE"/>
appender>
<root level="${logLevel}">
<appender-ref ref="ASYNC_INFO_FILE"/>
<appender-ref ref="ASYNC_WARN_FILE"/>
<appender-ref ref="ASYNC_ERROR_FILE"/>
root>
springProfile>
configuration>