feat: 添加 spring-boot-monitor starter.

This commit is contained in:
lijiahang
2023-07-11 16:00:06 +08:00
parent 0890c47871
commit ab25570a86
23 changed files with 318 additions and 49 deletions

View File

@@ -1,5 +1,6 @@
package com.orion.ops.framework.banner.core;
import com.orion.lang.utils.Threads;
import com.orion.lang.utils.ansi.AnsiColor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
@@ -28,18 +29,31 @@ public class BannerApplicationRunner implements ApplicationRunner {
@Value("${orion.api.prefix}")
private String apiPrefix;
@Value("${spring.boot.admin.context-path:''}")
private String adminSeverContextPath;
@Value("${management.endpoints.web.base-path:''}")
private String managementEndpoints;
@Override
public void run(ApplicationArguments args) {
String line = AnsiColor.GLOSS_GREEN.color(":: orion-ops-launch v" + version + " 服务已启动(" + env + ") ::\n") +
AnsiColor.GLOSS_GREEN.color(":: swagger 文档 ") +
AnsiColor.GLOSS_GREEN.color(":: swagger 文档 ") +
AnsiColor.GLOSS_BLUE.color("http://127.0.0.1:" + port + "/doc.html\n") +
AnsiColor.GLOSS_GREEN.color(":: druid console ") +
AnsiColor.GLOSS_GREEN.color(":: druid console ") +
AnsiColor.GLOSS_BLUE.color("http://127.0.0.1:" + port + "/druid/index.html\n") +
AnsiColor.GLOSS_GREEN.color(":: actuator endpoint ") +
AnsiColor.GLOSS_BLUE.color("http://127.0.0.1:" + port + managementEndpoints + "\n") +
AnsiColor.GLOSS_GREEN.color(":: admin console ") +
AnsiColor.GLOSS_BLUE.color("http://127.0.0.1:" + port + adminSeverContextPath + "\n") +
AnsiColor.GLOSS_GREEN.color(":: server 健康检测 ") +
AnsiColor.GLOSS_BLUE +
"curl -X GET --location \"http://127.0.0.1:" + port + apiPrefix + "/server/bootstrap/health\"" +
AnsiColor.SUFFIX;
System.out.println(line);
Threads.start(() -> {
Threads.sleep(1000L);
System.out.println(line);
});
}
}

View File

@@ -0,0 +1,42 @@
<?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">
<parent>
<groupId>com.orion.ops</groupId>
<artifactId>orion-ops-framework</artifactId>
<version>${revision}</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>orion-ops-spring-boot-starter-monitor</artifactId>
<name>${project.artifactId}</name>
<packaging>jar</packaging>
<description>项目监控配置包</description>
<url>https://github.com/lijiahangmax/orion-ops-pro</url>
<dependencies>
<dependency>
<groupId>com.orion.ops</groupId>
<artifactId>orion-ops-common</artifactId>
</dependency>
<!-- actuator -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- admin -->
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-server</artifactId>
</dependency>
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-client</artifactId>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,39 @@
package com.orion.ops.framework.monitor.config;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import de.codecentric.boot.admin.server.config.EnableAdminServer;
import de.codecentric.boot.admin.server.utils.jackson.AdminServerModule;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.context.annotation.Bean;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
/**
* 项目 admin console 配置
*
* @author Jiahang Li
* @version 1.0.0
* @since 2023/7/11 14:13
*/
@EnableAdminServer
@AutoConfiguration
@AutoConfigureAfter(name = "com.orion.ops.framework.web.config.OrionWebAutoConfiguration")
public class OrionAdminAutoConfiguration {
/**
* @param converter jackson converter
* @return springboot-admin 序列化配置
*/
@Bean
@ConditionalOnBean(MappingJackson2HttpMessageConverter.class)
public SimpleModule registrationModuleConverter(MappingJackson2HttpMessageConverter converter) {
ObjectMapper objectMapper = converter.getObjectMapper();
// 序列化配置
AdminServerModule module = new AdminServerModule(new String[]{".*password$"});
objectMapper.registerModule(module);
return module;
}
}

View File

@@ -0,0 +1 @@
com.orion.ops.framework.monitor.config.OrionAdminAutoConfiguration

View File

@@ -3,7 +3,7 @@ package com.orion.ops.framework.mybatis.config;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import com.orion.ops.framework.common.constant.FilterOrderConst;
import com.orion.ops.framework.common.filter.FilterCreator;
import com.orion.ops.framework.mybatis.core.cache.RowCacheClearFilter;
import com.orion.ops.framework.mybatis.core.cache.CacheClearFilter;
import com.orion.ops.framework.mybatis.core.handler.FieldFillHandler;
import org.apache.ibatis.annotations.Mapper;
import org.mybatis.spring.annotation.MapperScan;
@@ -35,8 +35,8 @@ public class OrionMybatisAutoConfiguration {
* @return mybatis 缓存清理过滤器
*/
@Bean
public FilterRegistrationBean<RowCacheClearFilter> rowCacheClearFilterBean() {
return FilterCreator.create(new RowCacheClearFilter(), FilterOrderConst.MYBATIS_CACHE_CLEAR_FILTER);
public FilterRegistrationBean<CacheClearFilter> rowCacheClearFilterBean() {
return FilterCreator.create(new CacheClearFilter(), FilterOrderConst.MYBATIS_CACHE_CLEAR_FILTER);
}
}

View File

@@ -15,7 +15,7 @@ import java.io.IOException;
* @version 1.0.0
* @since 2023/6/25 15:14
*/
public class RowCacheClearFilter extends OncePerRequestFilter {
public class CacheClearFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
@@ -25,7 +25,7 @@ public class RowCacheClearFilter extends OncePerRequestFilter {
} finally {
// 清理缓存
// TODO TEST
RowCacheHolder.remove();
CacheHolder.remove();
}
}

View File

@@ -13,9 +13,9 @@ import java.io.Serializable;
* @version 1.0.0
* @since 2023/6/25 14:21
*/
public class RowCacheHolder {
public class CacheHolder {
private RowCacheHolder() {
private CacheHolder() {
}
/**

View File

@@ -3,7 +3,7 @@ package com.orion.ops.framework.mybatis.core.query;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.orion.lang.define.wrapper.Store;
import com.orion.lang.utils.Valid;
import com.orion.ops.framework.mybatis.core.cache.RowCacheHolder;
import com.orion.ops.framework.mybatis.core.cache.CacheHolder;
import java.io.Serializable;
import java.util.Optional;
@@ -76,14 +76,14 @@ public class CacheQuery<T> {
// 不查询缓存
if (!force) {
// 从缓存中获取
Store<T> store = RowCacheHolder.get(mapperClass, id);
Store<T> store = CacheHolder.get(mapperClass, id);
return Optional.ofNullable(store)
.map(Store::get);
}
// 查询
T row = dao.selectById(id);
// 设置缓存
RowCacheHolder.set(mapperClass, id, row);
CacheHolder.set(mapperClass, id, row);
return Optional.ofNullable(row);
}

View File

@@ -163,11 +163,13 @@ public class OrionSecurityAutoConfiguration {
/**
* @param adminSeverContextPath adminSeverContextPath
* @param managementEndpoints managementEndpoints
* @return 控制台安全策略
*/
@Bean
public ConsoleAuthorizeRequestsCustomizer consoleAuthorizeRequestsCustomizer(@Value("${spring.boot.admin.context-path:''}") String adminSeverContextPath) {
return new ConsoleAuthorizeRequestsCustomizer(adminSeverContextPath);
public ConsoleAuthorizeRequestsCustomizer consoleAuthorizeRequestsCustomizer(@Value("${spring.boot.admin.context-path:''}") String adminSeverContextPath,
@Value("${management.endpoints.web.base-path:''}") String managementEndpoints) {
return new ConsoleAuthorizeRequestsCustomizer(adminSeverContextPath, managementEndpoints);
}
/**

View File

@@ -1,4 +1,4 @@
package com.orion.ops.framework.security.config;
package com.orion.ops.framework.security.core.strategy;
import org.springframework.core.Ordered;
import org.springframework.security.config.Customizer;

View File

@@ -1,6 +1,5 @@
package com.orion.ops.framework.security.core.strategy;
import com.orion.ops.framework.security.config.AuthorizeRequestsCustomizer;
import com.orion.ops.framework.security.config.SecurityConfig;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;

View File

@@ -1,6 +1,5 @@
package com.orion.ops.framework.security.core.strategy;
import com.orion.ops.framework.security.config.AuthorizeRequestsCustomizer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;
@@ -15,8 +14,11 @@ public class ConsoleAuthorizeRequestsCustomizer extends AuthorizeRequestsCustomi
private final String adminSeverContextPath;
public ConsoleAuthorizeRequestsCustomizer(String adminSeverContextPath) {
private final String managementEndpoints;
public ConsoleAuthorizeRequestsCustomizer(String adminSeverContextPath, String managementEndpoints) {
this.adminSeverContextPath = adminSeverContextPath;
this.managementEndpoints = managementEndpoints;
}
@Override
@@ -28,7 +30,7 @@ public class ConsoleAuthorizeRequestsCustomizer extends AuthorizeRequestsCustomi
// druid 监控
.antMatchers("/druid/**").anonymous()
// actuator 安全配置 TODO TEST
.antMatchers("/actuator", "/actuator/**").anonymous()
.antMatchers(managementEndpoints, managementEndpoints + "/**").anonymous()
// admin 安全配置 TODO TEST
.antMatchers(adminSeverContextPath, adminSeverContextPath + "/**").anonymous();
}

View File

@@ -1,6 +1,5 @@
package com.orion.ops.framework.security.core.strategy;
import com.orion.ops.framework.security.config.AuthorizeRequestsCustomizer;
import org.springframework.context.ApplicationContext;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;

View File

@@ -1,6 +1,5 @@
package com.orion.ops.framework.security.core.strategy;
import com.orion.ops.framework.security.config.AuthorizeRequestsCustomizer;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;

View File

@@ -1,6 +1,5 @@
package com.orion.ops.framework.security.core.strategy;
import com.orion.ops.framework.security.config.AuthorizeRequestsCustomizer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;

View File

@@ -3,9 +3,15 @@ package com.orion.ops.framework.web.config;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson.support.config.FastJsonConfig;
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import com.orion.lang.utils.collect.Lists;
import com.orion.ops.framework.common.constant.FilterOrderConst;
import com.orion.ops.framework.common.filter.FilterCreator;
import com.orion.ops.framework.web.core.convert.CustomerFastJsonHttpMessageConverter;
import com.orion.ops.framework.web.core.convert.SerializeConfig;
import com.orion.ops.framework.web.core.filter.TraceIdFilter;
import com.orion.ops.framework.web.core.handler.GlobalExceptionHandler;
import com.orion.ops.framework.web.core.handler.WrapperResultHandler;
@@ -13,11 +19,13 @@ import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.http.MediaType;
import org.springframework.http.converter.ByteArrayHttpMessageConverter;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.util.AntPathMatcher;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.cors.CorsConfiguration;
@@ -40,6 +48,7 @@ import java.util.List;
* @since 2023/6/16 16:26
*/
@AutoConfiguration
@EnableConfigurationProperties(SerializeConfig.class)
public class OrionWebAutoConfiguration implements WebMvcConfigurer {
@Value("${orion.api.prefix}")
@@ -70,12 +79,13 @@ public class OrionWebAutoConfiguration implements WebMvcConfigurer {
}
/**
* @return http message json 转换器
* @param serializeConfig 序列化配置
* @return http message fast json 转换器
*/
@Bean
public FastJsonHttpMessageConverter fastJsonHttpMessageConverter() {
public FastJsonHttpMessageConverter fastJsonHttpMessageConverter(SerializeConfig serializeConfig) {
// json 转换器
FastJsonHttpMessageConverter converter = new FastJsonHttpMessageConverter();
CustomerFastJsonHttpMessageConverter converter = new CustomerFastJsonHttpMessageConverter(serializeConfig);
// 配置
FastJsonConfig config = new FastJsonConfig();
// 支持的类型
@@ -101,21 +111,49 @@ public class OrionWebAutoConfiguration implements WebMvcConfigurer {
return converter;
}
/**
* @return http message jackson 转换器
*/
@Bean
public MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter() {
MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
// 支持的类型
List<MediaType> mediaTypes = Lists.of(
MediaType.APPLICATION_JSON,
MediaType.APPLICATION_FORM_URLENCODED,
MediaType.APPLICATION_XHTML_XML,
MediaType.TEXT_PLAIN,
MediaType.TEXT_HTML,
MediaType.TEXT_XML,
new MediaType("application", "vnd.spring-boot.actuator.v2+json")
);
converter.setSupportedMediaTypes(mediaTypes);
ObjectMapper objectMapper = converter.getObjectMapper();
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
// 序列化配置
SimpleModule module = new SimpleModule();
module.addSerializer(Long.class, ToStringSerializer.instance);
module.addSerializer(Long.TYPE, ToStringSerializer.instance);
objectMapper.registerModule(module);
return converter;
}
/**
* @return http message 转换器列表
*/
@Bean
public HttpMessageConverters httpMessageConverters(FastJsonHttpMessageConverter jsonConverter) {
// 先获取默认转换器
public HttpMessageConverters httpMessageConverters(FastJsonHttpMessageConverter fastJsonConverter,
MappingJackson2HttpMessageConverter jacksonConvert) {
List<HttpMessageConverter<?>> defaultConverters = new HttpMessageConverters().getConverters();
List<HttpMessageConverter<?>> converters = new ArrayList<>();
// 将 byte converter 添加至首位 - fix swagger api 返回base64报错
converters.add(new ByteArrayHttpMessageConverter());
// 添加自定义 converter - using WrapperResultHandler
converters.add(jsonConverter);
// 添加默认 converter
// 添加自定义 converter - using WrapperResultHandler/脱敏
converters.add(fastJsonConverter);
// 添加自定义 converter - jackson
converters.add(jacksonConvert);
// 添加默认处理器
converters.addAll(defaultConverters);
// 设置不添加默认 converter
return new HttpMessageConverters(false, converters);
}

View File

@@ -0,0 +1,40 @@
package com.orion.ops.framework.web.core.convert;
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
import org.springframework.http.MediaType;
import java.lang.reflect.Type;
import java.util.List;
/**
* 自定义 fastjson 转换器
*
* @author Jiahang Li
* @version 1.0.0
* @since 2023/7/11 11:46
*/
public class CustomerFastJsonHttpMessageConverter extends FastJsonHttpMessageConverter {
private final SerializeConfig serializeConfig;
public CustomerFastJsonHttpMessageConverter(SerializeConfig serializeConfig) {
this.serializeConfig = serializeConfig;
}
@Override
public boolean canRead(Type type, Class<?> contextClass, MediaType mediaType) {
List<String> unsupportedClasses = serializeConfig.getUnsupportedClasses();
if (unsupportedClasses != null) {
if (unsupportedClasses.contains(contextClass.getName())) {
return false;
}
}
return super.canRead(type, contextClass, mediaType);
}
@Override
public boolean canWrite(Type type, Class<?> clazz, MediaType mediaType) {
return super.canWrite(type, clazz, mediaType);
}
}

View File

@@ -0,0 +1,29 @@
package com.orion.ops.framework.web.core.convert;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import java.util.ArrayList;
import java.util.List;
/**
* 序列化配置
*
* @author Jiahang Li
* @version 1.0.0
* @since 2023/7/11 14:57
*/
@Data
@ConfigurationProperties("orion.serializer")
public class SerializeConfig {
/**
* 不支持的序列化类型
*/
private List<String> unsupportedClasses;
public SerializeConfig() {
this.unsupportedClasses = new ArrayList<>();
}
}

View File

@@ -14,6 +14,11 @@
"name": "orion.api.cors",
"type": "java.lang.Boolean",
"description": "是否开启 cors 过滤器."
},
{
"name": "orion.serializer.unsupported-classes",
"type": "java.util.List",
"description": "不支持的序列化类型."
}
]
}

View File

@@ -29,6 +29,7 @@
<module>orion-ops-spring-boot-starter-log</module>
<module>orion-ops-spring-boot-starter-storage</module>
<module>orion-ops-spring-boot-starter-security</module>
<module>orion-ops-spring-boot-starter-monitor</module>
</modules>
</project>