🔨 监控逻辑.
This commit is contained in:
@@ -22,10 +22,10 @@
|
||||
*/
|
||||
package org.dromara.visor.framework.encrypt.configuration;
|
||||
|
||||
import org.dromara.visor.common.config.ConfigStore;
|
||||
import org.dromara.visor.common.constant.AutoConfigureOrderConst;
|
||||
import org.dromara.visor.common.cipher.AesEncryptor;
|
||||
import org.dromara.visor.common.cipher.RsaDecryptor;
|
||||
import org.dromara.visor.common.config.ConfigStore;
|
||||
import org.dromara.visor.common.constant.AutoConfigureOrderConst;
|
||||
import org.dromara.visor.common.utils.AesEncryptUtils;
|
||||
import org.dromara.visor.common.utils.RsaParamDecryptUtils;
|
||||
import org.dromara.visor.framework.encrypt.configuration.config.AesEncryptConfig;
|
||||
@@ -45,7 +45,7 @@ import org.springframework.context.annotation.Bean;
|
||||
*/
|
||||
@AutoConfiguration
|
||||
@EnableConfigurationProperties({AesEncryptConfig.class})
|
||||
@AutoConfigureOrder(AutoConfigureOrderConst.FRAMEWORK_ENCRYPT)
|
||||
@AutoConfigureOrder(AutoConfigureOrderConst.FRAMEWORK_CYPHER)
|
||||
public class OrionEncryptAutoConfiguration {
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
<?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>org.dromara.visor</groupId>
|
||||
<artifactId>orion-visor-framework</artifactId>
|
||||
<version>${revision}</version>
|
||||
</parent>
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>orion-visor-spring-boot-starter-influxdb</artifactId>
|
||||
<name>${project.artifactId}</name>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<description>项目 influxdb 配置包</description>
|
||||
<url>https://github.com/dromara/orion-visor</url>
|
||||
|
||||
<dependencies>
|
||||
<!-- common -->
|
||||
<dependency>
|
||||
<groupId>org.dromara.visor</groupId>
|
||||
<artifactId>orion-visor-common</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- influxdb -->
|
||||
<dependency>
|
||||
<groupId>com.influxdb</groupId>
|
||||
<artifactId>influxdb-client-java</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- web -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright (c) 2023 - present Dromara, All rights reserved.
|
||||
*
|
||||
* https://visor.dromara.org
|
||||
* https://visor.dromara.org.cn
|
||||
* https://visor.orionsec.cn
|
||||
*
|
||||
* Members:
|
||||
* Jiahang Li - ljh1553488six@139.com - author
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.dromara.visor.framework.influxdb.configuration;
|
||||
|
||||
import cn.orionsec.kit.lang.utils.Strings;
|
||||
import com.influxdb.LogLevel;
|
||||
import com.influxdb.client.InfluxDBClient;
|
||||
import com.influxdb.client.InfluxDBClientFactory;
|
||||
import com.influxdb.client.InfluxDBClientOptions;
|
||||
import org.dromara.visor.common.constant.AutoConfigureOrderConst;
|
||||
import org.dromara.visor.framework.influxdb.configuration.config.InfluxdbConfig;
|
||||
import org.dromara.visor.framework.influxdb.core.utils.InfluxdbUtils;
|
||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigureOrder;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
|
||||
import java.net.ConnectException;
|
||||
|
||||
/**
|
||||
* influxdb 配置类
|
||||
*
|
||||
* @author Jiahang Li
|
||||
* @version 1.0.0
|
||||
* @since 2025/8/10 20:35
|
||||
*/
|
||||
@Lazy(false)
|
||||
@AutoConfiguration
|
||||
@AutoConfigureOrder(AutoConfigureOrderConst.FRAMEWORK_INFLUXDB)
|
||||
@ConditionalOnProperty(value = "spring.influxdb.enabled", havingValue = "true")
|
||||
@EnableConfigurationProperties(InfluxdbConfig.class)
|
||||
public class OrionInfluxdbAutoConfiguration {
|
||||
|
||||
/**
|
||||
* TODO 重连
|
||||
*
|
||||
* @param config config
|
||||
* @return influxdb 客户端
|
||||
*/
|
||||
@Bean(name = "influxDBClient")
|
||||
public InfluxDBClient influxDBClient(InfluxdbConfig config) throws ConnectException {
|
||||
// 参数
|
||||
InfluxDBClientOptions options = InfluxDBClientOptions.builder()
|
||||
.url(config.getUrl())
|
||||
.authenticateToken(config.getToken().toCharArray())
|
||||
.org(config.getOrg())
|
||||
.bucket(config.getBucket())
|
||||
.logLevel(LogLevel.NONE)
|
||||
.build();
|
||||
// 客户端
|
||||
InfluxDBClient client = InfluxDBClientFactory.create(options);
|
||||
// 尝试连接
|
||||
Boolean ping = client.ping();
|
||||
if (!ping) {
|
||||
throw new ConnectException(Strings.format("connect to influxdb failed. url: {}, org: {}", config.getUrl(), config.getOrg()));
|
||||
}
|
||||
// 设置工具类
|
||||
InfluxdbUtils.setInfluxClient(config.getBucket(), client);
|
||||
return client;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright (c) 2023 - present Dromara, All rights reserved.
|
||||
*
|
||||
* https://visor.dromara.org
|
||||
* https://visor.dromara.org.cn
|
||||
* https://visor.orionsec.cn
|
||||
*
|
||||
* Members:
|
||||
* Jiahang Li - ljh1553488six@139.com - author
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.dromara.visor.framework.influxdb.configuration.config;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
/**
|
||||
* influxdb 配置
|
||||
*
|
||||
* @author Jiahang Li
|
||||
* @version 1.0.0
|
||||
* @since 2025/8/10 20:36
|
||||
*/
|
||||
@Data
|
||||
@ConfigurationProperties("spring.influxdb")
|
||||
public class InfluxdbConfig {
|
||||
|
||||
/**
|
||||
* url
|
||||
*/
|
||||
private String url;
|
||||
|
||||
/**
|
||||
* org
|
||||
*/
|
||||
private String org;
|
||||
|
||||
/**
|
||||
* bucket
|
||||
*/
|
||||
private String bucket;
|
||||
|
||||
/**
|
||||
* apiToken
|
||||
*/
|
||||
private String token;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,349 @@
|
||||
/*
|
||||
* Copyright (c) 2023 - present Dromara, All rights reserved.
|
||||
*
|
||||
* https://visor.dromara.org
|
||||
* https://visor.dromara.org.cn
|
||||
* https://visor.orionsec.cn
|
||||
*
|
||||
* Members:
|
||||
* Jiahang Li - ljh1553488six@139.com - author
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.dromara.visor.framework.influxdb.core.query;
|
||||
|
||||
import cn.orionsec.kit.lang.utils.collect.Collections;
|
||||
import cn.orionsec.kit.lang.utils.collect.Lists;
|
||||
import org.dromara.visor.common.constant.Const;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* flux 查询构建器
|
||||
*
|
||||
* @author Jiahang Li
|
||||
* @version 1.0.0
|
||||
* @since 2025/9/3 16:08
|
||||
*/
|
||||
public class FluxQueryBuilder {
|
||||
|
||||
private final StringBuilder query;
|
||||
|
||||
private boolean hasFilter;
|
||||
|
||||
private boolean pretty;
|
||||
|
||||
private FluxQueryBuilder(String bucket) {
|
||||
this.query = new StringBuilder();
|
||||
this.query.append(String.format("from(bucket: \"%s\")", bucket));
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建构建器
|
||||
*
|
||||
* @param bucket bucket
|
||||
* @return builder
|
||||
*/
|
||||
public static FluxQueryBuilder from(String bucket) {
|
||||
return new FluxQueryBuilder(bucket);
|
||||
}
|
||||
|
||||
/**
|
||||
* 时间范围
|
||||
*
|
||||
* @param start 开始时间
|
||||
* @param end 结束时间
|
||||
* @return this
|
||||
*/
|
||||
public FluxQueryBuilder range(long start, long end) {
|
||||
query.append(String.format(" |> range(start: %s, stop: %s)", Instant.ofEpochMilli(start), Instant.ofEpochMilli(end)));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 时间范围
|
||||
*
|
||||
* @param range range
|
||||
* @return this
|
||||
*/
|
||||
public FluxQueryBuilder range(String range) {
|
||||
query.append(String.format(" |> range(start: %s)", range));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 过滤 measurement
|
||||
*
|
||||
* @param measurement measurement
|
||||
* @return this
|
||||
*/
|
||||
public FluxQueryBuilder measurement(String measurement) {
|
||||
this.appendFilter(String.format("r[\"_measurement\"] == \"%s\"", measurement));
|
||||
this.closeFilter();
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 过滤单个 field
|
||||
*
|
||||
* @param field field
|
||||
* @return this
|
||||
*/
|
||||
public FluxQueryBuilder field(String field) {
|
||||
this.appendFilter(String.format("r[\"_field\"] == \"%s\"", field));
|
||||
this.closeFilter();
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 过滤多个 field
|
||||
*
|
||||
* @param fields fields
|
||||
* @return this
|
||||
*/
|
||||
public FluxQueryBuilder fields(Collection<String> fields) {
|
||||
if (Collections.isEmpty(fields)) {
|
||||
return this;
|
||||
}
|
||||
List<String> conditions = new ArrayList<>();
|
||||
for (String field : fields) {
|
||||
conditions.add(String.format("r[\"_field\"] == \"%s\"", field));
|
||||
}
|
||||
this.appendFilter(String.join(" or ", conditions));
|
||||
this.closeFilter();
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 过滤 tag key
|
||||
*
|
||||
* @param value value
|
||||
* @return this
|
||||
*/
|
||||
public FluxQueryBuilder key(String value) {
|
||||
return this.tag(Const.KEY, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 过滤 tag key
|
||||
*
|
||||
* @param values values
|
||||
* @return this
|
||||
*/
|
||||
public FluxQueryBuilder key(Collection<String> values) {
|
||||
return this.tag(Const.KEY, values);
|
||||
}
|
||||
|
||||
/**
|
||||
* 过滤 tag name
|
||||
*
|
||||
* @param value value
|
||||
* @return this
|
||||
*/
|
||||
public FluxQueryBuilder name(String value) {
|
||||
return this.tag(Const.NAME, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 过滤 tag name
|
||||
*
|
||||
* @param values values
|
||||
* @return this
|
||||
*/
|
||||
public FluxQueryBuilder name(Collection<String> values) {
|
||||
return this.tag(Const.NAME, values);
|
||||
}
|
||||
|
||||
/**
|
||||
* 过滤 tag
|
||||
*
|
||||
* @return this
|
||||
*/
|
||||
public FluxQueryBuilder tag(String key, String value) {
|
||||
this.appendFilter(String.format("r[\"%s\"] == \"%s\"", key, value));
|
||||
this.closeFilter();
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 过滤 tag
|
||||
*
|
||||
* @param key key
|
||||
* @param values values
|
||||
* @return this
|
||||
*/
|
||||
public FluxQueryBuilder tag(String key, Collection<String> values) {
|
||||
if (values == null || values.isEmpty()) {
|
||||
return this;
|
||||
}
|
||||
if (values.size() == 1) {
|
||||
return this.tag(key, Collections.first(values));
|
||||
}
|
||||
//
|
||||
Collection<String> conditions = values.stream()
|
||||
.map(value -> String.format("r[\"%s\"] == \"%s\"", key, value))
|
||||
.collect(Collectors.toList());
|
||||
this.appendFilter(String.join(" or ", conditions));
|
||||
this.closeFilter();
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 过滤多个 tag
|
||||
* tag 使用 and
|
||||
* value 使用 or
|
||||
*
|
||||
* @param tags tags
|
||||
* @return this
|
||||
*/
|
||||
public FluxQueryBuilder tags(Map<String, ? extends Collection<String>> tags) {
|
||||
for (Map.Entry<String, ? extends Collection<String>> entry : tags.entrySet()) {
|
||||
String key = entry.getKey();
|
||||
Collection<String> values = entry.getValue();
|
||||
if (Collections.isEmpty(values)) {
|
||||
continue;
|
||||
}
|
||||
if (values.size() == 1) {
|
||||
// 单值直接用等号
|
||||
String singleValue = values.iterator().next();
|
||||
this.appendFilter(String.format("r[\"%s\"] == \"%s\"", key, singleValue));
|
||||
} else {
|
||||
// 多值用 OR
|
||||
Collection<String> conditions = values.stream()
|
||||
.map(v -> String.format("r[\"%s\"] == \"%s\"", key, v))
|
||||
.collect(Collectors.toList());
|
||||
this.appendFilter("(" + String.join(" or ", conditions) + ")");
|
||||
}
|
||||
}
|
||||
this.closeFilter();
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 聚合窗口
|
||||
*/
|
||||
public FluxQueryBuilder aggregateWindow(String every, String fn) {
|
||||
query.append(String.format(" |> aggregateWindow(every: %s, fn: %s)", every, fn));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 聚合窗口
|
||||
*/
|
||||
public FluxQueryBuilder aggregateWindow(String every, String fn, boolean createEmpty) {
|
||||
query.append(String.format(" |> aggregateWindow(every: %s, fn: %s, createEmpty: %b)", every, fn, createEmpty));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 排序
|
||||
*
|
||||
* @param columns columns
|
||||
* @return this
|
||||
*/
|
||||
public FluxQueryBuilder sort(List<String> columns) {
|
||||
StringBuilder cols = new StringBuilder();
|
||||
for (int i = 0; i < columns.size(); i++) {
|
||||
cols.append("\"").append(columns.get(i)).append("\"");
|
||||
if (i < columns.size() - 1) cols.append(", ");
|
||||
}
|
||||
query.append(String.format(" |> sort(columns: [%s])", cols));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 降序
|
||||
*
|
||||
* @param column column
|
||||
* @return this
|
||||
*/
|
||||
public FluxQueryBuilder sortDesc(String column) {
|
||||
return this.sort(Lists.singleton("-" + column));
|
||||
}
|
||||
|
||||
/**
|
||||
* 升序
|
||||
*
|
||||
* @param column column
|
||||
* @return this
|
||||
*/
|
||||
public FluxQueryBuilder sortAsc(String column) {
|
||||
return this.sort(Lists.singleton(column));
|
||||
}
|
||||
|
||||
/**
|
||||
* 限制条数
|
||||
*
|
||||
* @param n limit
|
||||
* @return this
|
||||
*/
|
||||
public FluxQueryBuilder limit(int n) {
|
||||
query.append(String.format(" |> limit(n: %d)", n));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 基础过滤拼接
|
||||
*/
|
||||
private void appendFilter(String condition) {
|
||||
if (!hasFilter) {
|
||||
query.append(" |> filter(fn: (r) => ");
|
||||
this.hasFilter = true;
|
||||
} else {
|
||||
query.append(" and ");
|
||||
}
|
||||
query.append(condition);
|
||||
}
|
||||
|
||||
/**
|
||||
* 结束 filter 并闭合括号
|
||||
*/
|
||||
private void closeFilter() {
|
||||
if (hasFilter) {
|
||||
query.append(")");
|
||||
this.hasFilter = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置美观输出
|
||||
*
|
||||
* @return this
|
||||
*/
|
||||
public FluxQueryBuilder pretty() {
|
||||
this.pretty = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建查询
|
||||
*/
|
||||
public String build() {
|
||||
if (this.pretty) {
|
||||
return query.toString().replaceAll("\\|>", "\n |>");
|
||||
} else {
|
||||
return query.toString();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.build();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,183 @@
|
||||
/*
|
||||
* Copyright (c) 2023 - present Dromara, All rights reserved.
|
||||
*
|
||||
* https://visor.dromara.org
|
||||
* https://visor.dromara.org.cn
|
||||
* https://visor.orionsec.cn
|
||||
*
|
||||
* Members:
|
||||
* Jiahang Li - ljh1553488six@139.com - author
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.dromara.visor.framework.influxdb.core.utils;
|
||||
|
||||
import cn.orionsec.kit.lang.utils.Exceptions;
|
||||
import cn.orionsec.kit.lang.utils.collect.Lists;
|
||||
import com.influxdb.client.InfluxDBClient;
|
||||
import com.influxdb.client.WriteApi;
|
||||
import com.influxdb.client.write.Point;
|
||||
import com.influxdb.query.FluxRecord;
|
||||
import com.influxdb.query.FluxTable;
|
||||
import org.dromara.visor.common.constant.Const;
|
||||
import org.dromara.visor.common.entity.chart.TimeChartSeries;
|
||||
import org.dromara.visor.framework.influxdb.core.query.FluxQueryBuilder;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* influxdb 工具类
|
||||
*
|
||||
* @author Jiahang Li
|
||||
* @version 1.0.0
|
||||
* @since 2025/8/10 20:47
|
||||
*/
|
||||
public class InfluxdbUtils {
|
||||
|
||||
private static final String FIELD_KEY = "_field";
|
||||
|
||||
private static final List<String> SKIP_EXTRA_KEY = Lists.of("result", "table", "_measurement", "_start", "_stop", "_time", "_value");
|
||||
|
||||
private static InfluxDBClient client;
|
||||
|
||||
private static String bucket;
|
||||
|
||||
private InfluxdbUtils() {
|
||||
}
|
||||
|
||||
/**
|
||||
* 写入指标
|
||||
*
|
||||
* @param points points
|
||||
*/
|
||||
public static void writePoints(List<Point> points) {
|
||||
try (WriteApi api = client.makeWriteApi()) {
|
||||
// 写入指标
|
||||
api.writePoints(points);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询数据点
|
||||
*
|
||||
* @param query query
|
||||
* @return points
|
||||
*/
|
||||
public static List<FluxTable> queryTable(String query) {
|
||||
return client.getQueryApi().query(query);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询数据点
|
||||
*
|
||||
* @param query query
|
||||
* @return points
|
||||
*/
|
||||
public static FluxTable querySingleTable(String query) {
|
||||
return Lists.first(queryTable(query));
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询时序系列
|
||||
*
|
||||
* @param query query
|
||||
* @return points
|
||||
*/
|
||||
public static List<TimeChartSeries> querySeries(String query) {
|
||||
return toSeries(queryTable(query));
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询时序系列
|
||||
*
|
||||
* @param query query
|
||||
* @return points
|
||||
*/
|
||||
public static TimeChartSeries querySingleSeries(String query) {
|
||||
return toSeries(querySingleTable(query));
|
||||
}
|
||||
|
||||
/**
|
||||
* 转为时序系列
|
||||
*
|
||||
* @param table table
|
||||
* @return series
|
||||
*/
|
||||
public static TimeChartSeries toSeries(FluxTable table) {
|
||||
// 数据
|
||||
Map<String, Object> tags = new HashMap<>();
|
||||
List<List<Object>> dataList = new ArrayList<>();
|
||||
for (FluxRecord record : table.getRecords()) {
|
||||
Instant time = record.getTime();
|
||||
if (time == null) {
|
||||
continue;
|
||||
}
|
||||
// 设置数据
|
||||
List<Object> data = new ArrayList<>(2);
|
||||
data.add(time.toEpochMilli());
|
||||
data.add(record.getValue());
|
||||
dataList.add(data);
|
||||
// 设置额外值
|
||||
record.getValues().forEach((k, v) -> {
|
||||
if (SKIP_EXTRA_KEY.contains(k)) {
|
||||
return;
|
||||
}
|
||||
tags.put(k, v);
|
||||
});
|
||||
}
|
||||
// 设置 field
|
||||
tags.put(Const.FIELD, tags.get(FIELD_KEY));
|
||||
tags.remove(FIELD_KEY);
|
||||
// 创建 series
|
||||
return TimeChartSeries.builder()
|
||||
.data(dataList)
|
||||
.tags(tags)
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* 转为时序系列
|
||||
*
|
||||
* @param tables tables
|
||||
* @return series
|
||||
*/
|
||||
public static List<TimeChartSeries> toSeries(List<FluxTable> tables) {
|
||||
return tables.stream()
|
||||
.map(InfluxdbUtils::toSeries)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取查询构建器
|
||||
*
|
||||
* @return builder
|
||||
*/
|
||||
public static FluxQueryBuilder query() {
|
||||
return FluxQueryBuilder.from(bucket);
|
||||
}
|
||||
|
||||
public static void setInfluxClient(String bucket, InfluxDBClient client) {
|
||||
if (InfluxdbUtils.client != null) {
|
||||
// unmodified
|
||||
throw Exceptions.state();
|
||||
}
|
||||
InfluxdbUtils.client = client;
|
||||
InfluxdbUtils.bucket = bucket;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
{
|
||||
"groups": [
|
||||
{
|
||||
"name": "spring.influxdb",
|
||||
"type": "org.dromara.visor.framework.influxdb.configuration.config.InfluxdbConfig",
|
||||
"sourceType": "org.dromara.visor.framework.influxdb.configuration.config.InfluxdbConfig"
|
||||
}
|
||||
],
|
||||
"properties": [
|
||||
{
|
||||
"name": "spring.influxdb.enabled",
|
||||
"type": "java.lang.Boolean",
|
||||
"description": "是否启用 influxdb.",
|
||||
"defaultValue": "false"
|
||||
},
|
||||
{
|
||||
"name": "spring.influxdb.url",
|
||||
"type": "java.lang.String",
|
||||
"description": "influxdb 地址."
|
||||
},
|
||||
{
|
||||
"name": "spring.influxdb.org",
|
||||
"type": "java.lang.String",
|
||||
"description": "influxdb org."
|
||||
},
|
||||
{
|
||||
"name": "spring.influxdb.bucket",
|
||||
"type": "java.lang.String",
|
||||
"description": "influxdb bucket."
|
||||
},
|
||||
{
|
||||
"name": "spring.influxdb.token",
|
||||
"type": "java.lang.String",
|
||||
"description": "influxdb token."
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
org.dromara.visor.framework.influxdb.configuration.OrionInfluxdbAutoConfiguration
|
||||
@@ -23,13 +23,13 @@
|
||||
package org.dromara.visor.framework.job.configuration;
|
||||
|
||||
import org.dromara.visor.common.constant.AutoConfigureOrderConst;
|
||||
import org.dromara.visor.common.constant.Const;
|
||||
import org.dromara.visor.common.thread.ThreadPoolMdcTaskExecutor;
|
||||
import org.dromara.visor.framework.job.configuration.config.AsyncExecutorConfig;
|
||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigureOrder;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Primary;
|
||||
import org.springframework.core.task.TaskExecutor;
|
||||
import org.springframework.scheduling.annotation.EnableAsync;
|
||||
|
||||
@@ -49,13 +49,10 @@ import java.util.concurrent.ThreadPoolExecutor;
|
||||
public class OrionAsyncAutoConfiguration {
|
||||
|
||||
/**
|
||||
* 支持 MDC 的异步线程池
|
||||
* <p>
|
||||
* {@code @Async("asyncExecutor")}
|
||||
*
|
||||
* @return 异步线程池
|
||||
* @return 支持 MDC 的异步线程池
|
||||
*/
|
||||
@Primary
|
||||
@Bean(name = "asyncExecutor")
|
||||
public TaskExecutor asyncExecutor(AsyncExecutorConfig config) {
|
||||
ThreadPoolMdcTaskExecutor executor = new ThreadPoolMdcTaskExecutor();
|
||||
@@ -75,4 +72,25 @@ public class OrionAsyncAutoConfiguration {
|
||||
return executor;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@code @Async("metricsExecutor")}
|
||||
*
|
||||
* @return 指标线程池
|
||||
*/
|
||||
@Bean(name = "metricsExecutor")
|
||||
public TaskExecutor metricsExecutor() {
|
||||
ThreadPoolMdcTaskExecutor executor = new ThreadPoolMdcTaskExecutor();
|
||||
executor.setCorePoolSize(4);
|
||||
executor.setMaxPoolSize(8);
|
||||
executor.setQueueCapacity(1000);
|
||||
executor.setKeepAliveSeconds(Const.MS_S_60);
|
||||
executor.setAllowCoreThreadTimeOut(true);
|
||||
executor.setThreadNamePrefix("metrics-task-");
|
||||
executor.setWaitForTasksToCompleteOnShutdown(true);
|
||||
executor.setAwaitTerminationSeconds(60);
|
||||
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
|
||||
executor.initialize();
|
||||
return executor;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
*/
|
||||
package org.dromara.visor.framework.log.core.interceptor;
|
||||
|
||||
import cn.orionsec.kit.lang.utils.Strings;
|
||||
import cn.orionsec.kit.lang.utils.collect.Maps;
|
||||
import cn.orionsec.kit.lang.utils.reflect.Classes;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
@@ -31,8 +32,8 @@ import com.alibaba.fastjson.serializer.ValueFilter;
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
import org.dromara.visor.common.json.FieldDesensitizeFilter;
|
||||
import org.dromara.visor.common.json.FieldIgnoreFilter;
|
||||
import org.dromara.visor.common.trace.TraceIdHolder;
|
||||
import org.dromara.visor.common.security.SecurityHolder;
|
||||
import org.dromara.visor.common.trace.TraceIdHolder;
|
||||
import org.dromara.visor.framework.log.configuration.config.LogPrinterConfig;
|
||||
import org.dromara.visor.framework.log.core.annotation.IgnoreLog;
|
||||
import org.dromara.visor.framework.log.core.enums.IgnoreLogMode;
|
||||
@@ -42,12 +43,13 @@ import org.springframework.web.multipart.MultipartFile;
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Date;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
/**
|
||||
* 日志打印拦截器 基类
|
||||
@@ -60,11 +62,6 @@ public abstract class AbstractLogPrinterInterceptor implements LogPrinterInterce
|
||||
|
||||
private static final ThreadLocal<IgnoreLogMode> IGNORE_LOG_MODE = new ThreadLocal<>();
|
||||
|
||||
/**
|
||||
* 请求头过滤器
|
||||
*/
|
||||
protected Predicate<String> headerFilter;
|
||||
|
||||
/**
|
||||
* 字段过滤器
|
||||
*/
|
||||
@@ -93,8 +90,6 @@ public abstract class AbstractLogPrinterInterceptor implements LogPrinterInterce
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
// 请求头过滤器
|
||||
this.headerFilter = header -> config.getHeaders().contains(header);
|
||||
// 参数过滤器
|
||||
this.serializeFilters = new SerializeFilter[]{
|
||||
// 忽略字段过滤器
|
||||
@@ -136,6 +131,24 @@ public abstract class AbstractLogPrinterInterceptor implements LogPrinterInterce
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取请求头
|
||||
*
|
||||
* @param request request
|
||||
* @return headers
|
||||
*/
|
||||
protected Map<String, String> getHeaderMap(HttpServletRequest request) {
|
||||
Map<String, String> headers = new LinkedHashMap<>();
|
||||
for (String headerName : config.getHeaders()) {
|
||||
String headerValue = request.getHeader(headerName);
|
||||
if (Strings.isBlank(headerValue)) {
|
||||
continue;
|
||||
}
|
||||
headers.put(headerName, headerValue);
|
||||
}
|
||||
return headers;
|
||||
}
|
||||
|
||||
/**
|
||||
* 打印请求信息
|
||||
*
|
||||
|
||||
@@ -84,13 +84,11 @@ public class PrettyLogPrinterInterceptor extends AbstractLogPrinterInterceptor {
|
||||
if (request != null) {
|
||||
// remoteAddr
|
||||
requestLog.append("\tremoteAddr: ").append(IpUtils.getRemoteAddr(request)).append('\n');
|
||||
// header
|
||||
Servlets.getHeaderMap(request).forEach((hk, hv) -> {
|
||||
if (headerFilter.test(hk.toLowerCase())) {
|
||||
requestLog.append('\t')
|
||||
.append(hk).append(": ")
|
||||
.append(hv).append('\n');
|
||||
}
|
||||
// headers
|
||||
this.getHeaderMap(request).forEach((hk, hv) -> {
|
||||
requestLog.append('\t')
|
||||
.append(hk).append(": ")
|
||||
.append(hv).append('\n');
|
||||
});
|
||||
}
|
||||
Method method = invocation.getMethod();
|
||||
|
||||
@@ -85,14 +85,8 @@ public class RowLogPrinterInterceptor extends AbstractLogPrinterInterceptor impl
|
||||
if (request != null) {
|
||||
// remoteAddr
|
||||
fields.put(REMOTE_ADDR, IpUtils.getRemoteAddr(request));
|
||||
// header
|
||||
Map<String, Object> headers = new LinkedHashMap<>();
|
||||
Servlets.getHeaderMap(request).forEach((hk, hv) -> {
|
||||
if (headerFilter.test(hk.toLowerCase())) {
|
||||
headers.put(hk, hv);
|
||||
}
|
||||
});
|
||||
fields.put(HEADERS, headers);
|
||||
// headers
|
||||
fields.put(HEADERS, this.getHeaderMap(request));
|
||||
}
|
||||
Method method = invocation.getMethod();
|
||||
// 方法签名
|
||||
|
||||
@@ -66,7 +66,7 @@ public class BaseDO implements Serializable {
|
||||
private String creator;
|
||||
|
||||
@Schema(description = "修改人")
|
||||
@TableField(fill = FieldFill.INSERT_UPDATE, jdbcType = JdbcType.VARCHAR)
|
||||
@TableField(fill = FieldFill.INSERT_UPDATE, update = "IFNULL(#{et.updater}, updater)", jdbcType = JdbcType.VARCHAR)
|
||||
private String updater;
|
||||
|
||||
/**
|
||||
@@ -78,4 +78,4 @@ public class BaseDO implements Serializable {
|
||||
@TableField(fill = FieldFill.INSERT, jdbcType = JdbcType.TINYINT)
|
||||
private Boolean deleted;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,12 +54,13 @@ public class CodeGenerators {
|
||||
// 作者
|
||||
String author = Const.ORION_AUTHOR;
|
||||
// 模块
|
||||
String module = "infra";
|
||||
String module = "asset";
|
||||
// 生成的表
|
||||
Table[] tables = {
|
||||
// Template.create("dict_key", "字典配置项", "dict")
|
||||
// .enableProviderApi()
|
||||
// .disableUnitTest()
|
||||
// .enableDeleteUseBatch()
|
||||
// .cache("dict:keys", "字典配置项")
|
||||
// .expire(8, TimeUnit.HOURS)
|
||||
// .vue("system", "dict-key")
|
||||
@@ -73,23 +74,28 @@ public class CodeGenerators {
|
||||
// .color("blue", "gray", "red", "green", "white")
|
||||
// .valueUseFields()
|
||||
// .build(),
|
||||
// Template.create("exec_template_host", "执行模板主机", "exec")
|
||||
// .enableProviderApi()
|
||||
// .cache("sl", "22")
|
||||
// .vue("exec", "exec-template-host")
|
||||
// .build(),
|
||||
Template.create("system_message", "系统消息", "message")
|
||||
|
||||
Template.create("host_agent_log", "主机探针日志", "agent")
|
||||
.disableUnitTest()
|
||||
.enableProviderApi()
|
||||
.vue("system", "message")
|
||||
.dict("messageType", "type", "messageType")
|
||||
.comment("消息类型")
|
||||
.fields("EXEC_FAILED", "UPLOAD_FAILED")
|
||||
.labels("执行失败", "上传失败")
|
||||
.extra("tagLabel", "执行失败", "上传失败")
|
||||
.extra("tagVisible", true, true)
|
||||
.extra("tagColor", "red", "red")
|
||||
.vue("monitor", "monitor-host")
|
||||
.disableRowSelection()
|
||||
.enableCardView()
|
||||
.enableDrawerForm()
|
||||
|
||||
.dict("agentLogType", "type")
|
||||
.comment("探针日志类型")
|
||||
.fields("OFFLINE", "ONLINE", "INSTALL", "START", "STOP")
|
||||
.labels("下线", "上线", "安装", "启动", "停止")
|
||||
.valueUseFields()
|
||||
|
||||
.dict("agentLogStatus", "status")
|
||||
.comment("探针日志状态")
|
||||
.fields("WAIT", "RUNNING", "SUCCESS", "FAILED")
|
||||
.labels("等待中", "运行中", "成功", "失败")
|
||||
.color("green", "green", "arcoblue", "red")
|
||||
.loading(true, true, false, false)
|
||||
.valueUseFields()
|
||||
|
||||
.build(),
|
||||
};
|
||||
// jdbc 配置 - 使用配置文件
|
||||
@@ -98,7 +104,6 @@ public class CodeGenerators {
|
||||
String url = resolveConfigValue(yaml.getValue("spring.datasource.druid.url"));
|
||||
String username = resolveConfigValue(yaml.getValue("spring.datasource.druid.username"));
|
||||
String password = resolveConfigValue(yaml.getValue("spring.datasource.druid.password"));
|
||||
|
||||
// 执行
|
||||
runGenerator(outputDir, author,
|
||||
tables, module,
|
||||
|
||||
@@ -194,6 +194,8 @@ public class CodeGenerator implements Executable {
|
||||
case Types.BIT:
|
||||
case Types.TINYINT:
|
||||
return DbColumnType.INTEGER;
|
||||
case Types.DOUBLE:
|
||||
return DbColumnType.DOUBLE;
|
||||
default:
|
||||
return typeRegistry.getColumnType(metaInfo);
|
||||
}
|
||||
@@ -327,9 +329,14 @@ public class CodeGenerator implements Executable {
|
||||
*/
|
||||
private InjectionConfig getInjectionConfig() {
|
||||
String[][] customFileDefineArr = new String[][]{
|
||||
// -------------------- 后端 - module --------------------
|
||||
// -------------------- 后端 --------------------
|
||||
// http 文件
|
||||
new String[]{"/templates/orion-server-module-controller.http.vm", "${type}Controller.http", "controller"},
|
||||
// operator log define 文件
|
||||
new String[]{"/templates/orion-server-module-operator-key-define.java.vm", "${type}OperatorType.java", "define.operator"},
|
||||
// convert 文件
|
||||
new String[]{"/templates/orion-server-module-convert.java.vm", "${type}Convert.java", "convert"},
|
||||
// -------------------- 后端 - 实体 --------------------
|
||||
// vo 文件
|
||||
new String[]{"/templates/orion-server-module-entity-vo.java.vm", "${type}VO.java", "entity.vo"},
|
||||
// create request 文件
|
||||
@@ -338,19 +345,19 @@ public class CodeGenerator implements Executable {
|
||||
new String[]{"/templates/orion-server-module-entity-request-update.java.vm", "${type}UpdateRequest.java", "entity.request.${bizPackage}"},
|
||||
// query request 文件
|
||||
new String[]{"/templates/orion-server-module-entity-request-query.java.vm", "${type}QueryRequest.java", "entity.request.${bizPackage}"},
|
||||
// convert 文件
|
||||
new String[]{"/templates/orion-server-module-convert.java.vm", "${type}Convert.java", "convert"},
|
||||
// -------------------- 后端 - 缓存 --------------------
|
||||
// cache dto 文件
|
||||
new String[]{"/templates/orion-server-module-cache-dto.java.vm", "${type}CacheDTO.java", "entity.dto"},
|
||||
// cache key define 文件
|
||||
new String[]{"/templates/orion-server-module-cache-key-define.java.vm", "${type}CacheKeyDefine.java", "define.cache"},
|
||||
// operator log define 文件
|
||||
new String[]{"/templates/orion-server-module-operator-key-define.java.vm", "${type}OperatorType.java", "define.operator"},
|
||||
// -------------------- 后端 - provider --------------------
|
||||
// api 文件
|
||||
new String[]{"/templates/orion-server-provider-api.java.vm", "${type}Api.java", "api"},
|
||||
// api impl 文件
|
||||
new String[]{"/templates/orion-server-provider-api-impl.java.vm", "${type}ApiImpl.java", "api.impl"},
|
||||
// convert 文件
|
||||
new String[]{"/templates/orion-server-provider-convert.java.vm", "${type}ProviderConvert.java", "convert"},
|
||||
// -------------------- 后端 - provider 实体 --------------------
|
||||
// dto 文件
|
||||
new String[]{"/templates/orion-server-provider-entity-dto.java.vm", "${type}DTO.java", "entity.dto.${bizPackage}"},
|
||||
// create dto 文件
|
||||
@@ -359,8 +366,6 @@ public class CodeGenerator implements Executable {
|
||||
new String[]{"/templates/orion-server-provider-entity-dto-update.java.vm", "${type}UpdateDTO.java", "entity.dto.${bizPackage}"},
|
||||
// query dto 文件
|
||||
new String[]{"/templates/orion-server-provider-entity-dto-query.java.vm", "${type}QueryDTO.java", "entity.dto.${bizPackage}"},
|
||||
// convert 文件
|
||||
new String[]{"/templates/orion-server-provider-convert.java.vm", "${type}ProviderConvert.java", "convert"},
|
||||
// -------------------- 后端 - test --------------------
|
||||
// service unit test 文件
|
||||
new String[]{"/templates/orion-server-test-service-impl-tests.java.vm", "${type}ServiceImplTests.java", "service.impl"},
|
||||
@@ -375,22 +380,26 @@ public class CodeGenerator implements Executable {
|
||||
new String[]{"/templates/orion-vue-router.ts.vm", "${feature}.ts", "vue/router/routes/modules"},
|
||||
// views index.ts 文件
|
||||
new String[]{"/templates/orion-vue-views-index.vue.vm", "index.vue", "vue/views/${module}/${feature}"},
|
||||
// const.ts 文件
|
||||
new String[]{"/templates/orion-vue-views-types-const.ts.vm", "const.ts", "vue/views/${module}/${feature}/types"},
|
||||
// -------------------- 前端 - form --------------------
|
||||
// form-modal.vue 文件
|
||||
new String[]{"/templates/orion-vue-views-components-form-modal.vue.vm", "${feature}-form-modal.vue", "vue/views/${module}/${feature}/components"},
|
||||
// form-drawer.vue 文件
|
||||
new String[]{"/templates/orion-vue-views-components-form-drawer.vue.vm", "${feature}-form-drawer.vue", "vue/views/${module}/${feature}/components"},
|
||||
// table.vue 文件
|
||||
new String[]{"/templates/orion-vue-views-components-table.vue.vm", "${feature}-table.vue", "vue/views/${module}/${feature}/components"},
|
||||
// card-list.vue 文件
|
||||
new String[]{"/templates/orion-vue-views-components-card-list.vue.vm", "${feature}-card-list.vue", "vue/views/${module}/${feature}/components"},
|
||||
// const.ts 文件
|
||||
new String[]{"/templates/orion-vue-views-types-const.ts.vm", "const.ts", "vue/views/${module}/${feature}/types"},
|
||||
// form.rules.ts 文件
|
||||
new String[]{"/templates/orion-vue-views-types-form.rules.ts.vm", "form.rules.ts", "vue/views/${module}/${feature}/types"},
|
||||
// -------------------- 前端 - table --------------------
|
||||
// table.vue 文件
|
||||
new String[]{"/templates/orion-vue-views-components-table.vue.vm", "${feature}-table.vue", "vue/views/${module}/${feature}/components"},
|
||||
// table.columns.ts 文件
|
||||
new String[]{"/templates/orion-vue-views-types-table.columns.ts.vm", "table.columns.ts", "vue/views/${module}/${feature}/types"},
|
||||
// -------------------- 前端 - card --------------------
|
||||
// card-list.vue 文件
|
||||
new String[]{"/templates/orion-vue-views-components-card-list.vue.vm", "${feature}-card-list.vue", "vue/views/${module}/${feature}/components"},
|
||||
// card.fields.ts 文件
|
||||
new String[]{"/templates/orion-vue-views-types-card.fields.ts.vm", "card.fields.ts", "vue/views/${module}/${feature}/types"},
|
||||
// -------------------- sql --------------------
|
||||
// menu.sql 文件
|
||||
new String[]{"/templates/orion-sql-menu.sql.vm", "${tableName}-menu.sql", "sql"},
|
||||
// dict.sql 文件
|
||||
|
||||
@@ -81,7 +81,7 @@ public class DictParser {
|
||||
meta.setComment(Strings.def(tableField.getComment(), meta.getField()));
|
||||
}
|
||||
// 设置额外参数 schema
|
||||
if (meta.getExtraValues().size() > 0) {
|
||||
if (!meta.getExtraValues().isEmpty()) {
|
||||
List<Map<String, String>> extraSchema = meta.getExtraValues().get(0)
|
||||
.keySet()
|
||||
.stream()
|
||||
|
||||
@@ -165,6 +165,16 @@ public class DictTemplate extends Template {
|
||||
return this.extra(Const.COLOR, colors);
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加 loading
|
||||
*
|
||||
* @param loading loading
|
||||
* @return this
|
||||
*/
|
||||
public DictTemplate loading(Object... loading) {
|
||||
return this.extra(Const.LOADING, loading);
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加额外值
|
||||
*
|
||||
|
||||
@@ -133,14 +133,14 @@
|
||||
|
||||
const cardColLayout = useCardColLayout();
|
||||
const pagination = useCardPagination();
|
||||
const { loading, setLoading } = useLoading();
|
||||
const queryOrder = useQueryOrder(TableName, ASC);
|
||||
const { cardFieldConfig, fieldsHook } = useCardFieldConfig(TableName, fieldConfig);
|
||||
const { loading, setLoading } = useLoading();
|
||||
#if($dictMap.entrySet().size() > 0)
|
||||
const { toOptions, getDictValue } = useDictStore();
|
||||
#end
|
||||
|
||||
const list = ref<${vue.featureEntity}QueryResponse[]>([]);
|
||||
const list = ref<Array<${vue.featureEntity}QueryResponse>>([]);
|
||||
const formRef = ref();
|
||||
const formModel = reactive<${vue.featureEntity}QueryRequest>({
|
||||
searchValue: undefined,
|
||||
|
||||
@@ -172,9 +172,9 @@
|
||||
const rowSelection = useRowSelection();
|
||||
#end
|
||||
const pagination = useTablePagination();
|
||||
const { loading, setLoading } = useLoading();
|
||||
const queryOrder = useQueryOrder(TableName, ASC);
|
||||
const { tableColumns, columnsHook } = useTableColumns(TableName, columns);
|
||||
const { loading, setLoading } = useLoading();
|
||||
#if($dictMap.entrySet().size() > 0)
|
||||
const { toOptions, getDictValue } = useDictStore();
|
||||
#end
|
||||
|
||||
@@ -19,6 +19,8 @@ const columns = [
|
||||
minWidth: 238,
|
||||
ellipsis: true,
|
||||
tooltip: true,
|
||||
#elseif(${field.propertyType} == 'Integer' || ${field.propertyType} == 'Long')
|
||||
width: 120,
|
||||
#elseif(${field.propertyType} == 'Date')
|
||||
width: 180,
|
||||
render: ({ record }) => {
|
||||
|
||||
@@ -32,6 +32,7 @@ import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
@@ -49,6 +50,42 @@ public class RedisStrings extends RedisUtils {
|
||||
private RedisStrings() {
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取值
|
||||
*
|
||||
* @param key key
|
||||
* @return value
|
||||
*/
|
||||
public static String get(String key) {
|
||||
return redisTemplate.opsForValue().get(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取值
|
||||
*
|
||||
* @param define define
|
||||
* @return value
|
||||
*/
|
||||
public static String get(CacheKeyDefine define) {
|
||||
return get(define.getKey());
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取值
|
||||
*
|
||||
* @param key key
|
||||
* @param mapper mapper
|
||||
* @param <T> T
|
||||
* @return value
|
||||
*/
|
||||
public static <T> T get(String key, Function<String, T> mapper) {
|
||||
String value = redisTemplate.opsForValue().get(key);
|
||||
if (value == null) {
|
||||
return null;
|
||||
}
|
||||
return mapper.apply(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 json
|
||||
*
|
||||
@@ -56,11 +93,7 @@ public class RedisStrings extends RedisUtils {
|
||||
* @return JSONObject
|
||||
*/
|
||||
public static JSONObject getJson(String key) {
|
||||
String value = redisTemplate.opsForValue().get(key);
|
||||
if (value == null) {
|
||||
return null;
|
||||
}
|
||||
return JSON.parseObject(value);
|
||||
return get(key, JSON::parseObject);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -95,57 +128,7 @@ public class RedisStrings extends RedisUtils {
|
||||
* @return T
|
||||
*/
|
||||
public static <T> T getJson(String key, Class<T> type) {
|
||||
String value = redisTemplate.opsForValue().get(key);
|
||||
if (value == null) {
|
||||
return null;
|
||||
}
|
||||
return (T) JSON.parseObject(value, type);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 json 列表
|
||||
*
|
||||
* @param keys keys
|
||||
* @return cache
|
||||
*/
|
||||
public static List<JSONObject> getJsonList(Collection<String> keys) {
|
||||
List<String> values = redisTemplate.opsForValue().multiGet(keys);
|
||||
if (values == null) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
return values.stream()
|
||||
.map(JSON::parseObject)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 json 列表
|
||||
*
|
||||
* @param keys keys
|
||||
* @param define define
|
||||
* @param <T> T
|
||||
* @return cache
|
||||
*/
|
||||
public static <T> List<T> getJsonList(Collection<String> keys, CacheKeyDefine define) {
|
||||
return getJsonList(keys, (Class<T>) define.getType());
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 json 列表
|
||||
*
|
||||
* @param keys keys
|
||||
* @param type type
|
||||
* @param <T> T
|
||||
* @return cache
|
||||
*/
|
||||
public static <T> List<T> getJsonList(Collection<String> keys, Class<T> type) {
|
||||
List<String> values = redisTemplate.opsForValue().multiGet(keys);
|
||||
if (values == null) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
return values.stream()
|
||||
.map(s -> JSON.parseObject(s, type))
|
||||
.collect(Collectors.toList());
|
||||
return get(key, s -> JSON.parseObject(s, type));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -155,11 +138,7 @@ public class RedisStrings extends RedisUtils {
|
||||
* @return JSONArray
|
||||
*/
|
||||
public static JSONArray getJsonArray(String key) {
|
||||
String value = redisTemplate.opsForValue().get(key);
|
||||
if (value == null) {
|
||||
return null;
|
||||
}
|
||||
return JSON.parseArray(value);
|
||||
return get(key, JSON::parseArray);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -194,11 +173,69 @@ public class RedisStrings extends RedisUtils {
|
||||
* @return T
|
||||
*/
|
||||
public static <T> List<T> getJsonArray(String key, Class<T> type) {
|
||||
String value = redisTemplate.opsForValue().get(key);
|
||||
if (value == null) {
|
||||
return null;
|
||||
return get(key, s -> JSON.parseArray(s, type));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 json 列表
|
||||
*
|
||||
* @param keys keys
|
||||
* @return cache
|
||||
*/
|
||||
public static List<String> getList(Collection<String> keys) {
|
||||
return getList(keys, Function.identity());
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 json 列表
|
||||
*
|
||||
* @param keys keys
|
||||
* @param mapper mapper
|
||||
* @param <T> T
|
||||
* @return cache
|
||||
*/
|
||||
public static <T> List<T> getList(Collection<String> keys, Function<String, T> mapper) {
|
||||
List<String> values = redisTemplate.opsForValue().multiGet(keys);
|
||||
if (values == null) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
return JSON.parseArray(value, type);
|
||||
return values.stream()
|
||||
.map(mapper)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 json 列表
|
||||
*
|
||||
* @param keys keys
|
||||
* @return cache
|
||||
*/
|
||||
public static List<JSONObject> getJsonList(Collection<String> keys) {
|
||||
return getList(keys, JSON::parseObject);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 json 列表
|
||||
*
|
||||
* @param keys keys
|
||||
* @param define define
|
||||
* @param <T> T
|
||||
* @return cache
|
||||
*/
|
||||
public static <T> List<T> getJsonList(Collection<String> keys, CacheKeyDefine define) {
|
||||
return getList(keys, s -> JSON.parseObject(s, (Class<T>) define.getType()));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 json 列表
|
||||
*
|
||||
* @param keys keys
|
||||
* @param type type
|
||||
* @param <T> T
|
||||
* @return cache
|
||||
*/
|
||||
public static <T> List<T> getJsonList(Collection<String> keys, Class<T> type) {
|
||||
return getList(keys, s -> JSON.parseObject(s, type));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -208,13 +245,7 @@ public class RedisStrings extends RedisUtils {
|
||||
* @return cache
|
||||
*/
|
||||
public static List<JSONArray> getJsonArrayList(Collection<String> keys) {
|
||||
List<String> values = redisTemplate.opsForValue().multiGet(keys);
|
||||
if (values == null) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
return values.stream()
|
||||
.map(JSON::parseArray)
|
||||
.collect(Collectors.toList());
|
||||
return getList(keys, JSON::parseArray);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -226,7 +257,7 @@ public class RedisStrings extends RedisUtils {
|
||||
* @return cache
|
||||
*/
|
||||
public static <T> List<List<T>> getJsonArrayList(Collection<String> keys, CacheKeyDefine define) {
|
||||
return getJsonArrayList(keys, (Class<T>) define.getType());
|
||||
return getList(keys, s -> JSON.parseArray(s, (Class<T>) define.getType()));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -238,13 +269,7 @@ public class RedisStrings extends RedisUtils {
|
||||
* @return cache
|
||||
*/
|
||||
public static <T> List<List<T>> getJsonArrayList(Collection<String> keys, Class<T> type) {
|
||||
List<String> values = redisTemplate.opsForValue().multiGet(keys);
|
||||
if (values == null) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
return values.stream()
|
||||
.map(s -> JSON.parseArray(s, type))
|
||||
.collect(Collectors.toList());
|
||||
return getList(keys, s -> JSON.parseArray(s, type));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -46,6 +46,7 @@ public class AuthenticationEntryPointHandler implements AuthenticationEntryPoint
|
||||
|
||||
@Override
|
||||
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException e) throws IOException {
|
||||
log.warn("AuthenticationEntryPoint-commence-401 {}", request.getRequestURI());
|
||||
log.debug("AuthenticationEntryPoint-commence-unauthorized {}", request.getRequestURI(), e);
|
||||
Servlets.writeHttpWrapper(response, ErrorCode.UNAUTHORIZED.getWrapper());
|
||||
}
|
||||
|
||||
@@ -28,7 +28,9 @@ import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.dromara.visor.common.constant.AutoConfigureOrderConst;
|
||||
import org.dromara.visor.common.constant.FilterOrderConst;
|
||||
import org.dromara.visor.common.web.WebFilterCreator;
|
||||
import org.dromara.visor.framework.web.configuration.config.ExposeApiConfig;
|
||||
import org.dromara.visor.framework.web.core.aspect.DemoDisableApiAspect;
|
||||
import org.dromara.visor.framework.web.core.aspect.ExposeApiAspect;
|
||||
import org.dromara.visor.framework.web.core.filter.TraceIdFilter;
|
||||
import org.dromara.visor.framework.web.core.handler.GlobalExceptionHandler;
|
||||
import org.dromara.visor.framework.web.core.handler.WrapperResultHandler;
|
||||
@@ -37,6 +39,7 @@ import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigureOrder;
|
||||
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;
|
||||
@@ -50,6 +53,7 @@ import org.springframework.web.cors.CorsConfiguration;
|
||||
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
|
||||
import org.springframework.web.filter.CorsFilter;
|
||||
import org.springframework.web.servlet.config.annotation.PathMatchConfigurer;
|
||||
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
@@ -67,8 +71,12 @@ import java.util.List;
|
||||
*/
|
||||
@AutoConfiguration
|
||||
@AutoConfigureOrder(AutoConfigureOrderConst.FRAMEWORK_WEB)
|
||||
@EnableConfigurationProperties(ExposeApiConfig.class)
|
||||
public class OrionWebAutoConfiguration implements WebMvcConfigurer {
|
||||
|
||||
@Value("${orion.prefix}")
|
||||
private String orionPrefix;
|
||||
|
||||
@Value("${orion.api.prefix}")
|
||||
private String orionApiPrefix;
|
||||
|
||||
@@ -77,7 +85,14 @@ public class OrionWebAutoConfiguration implements WebMvcConfigurer {
|
||||
// 公共 api 前缀
|
||||
AntPathMatcher antPathMatcher = new AntPathMatcher(".");
|
||||
configurer.addPathPrefix(orionApiPrefix, clazz -> clazz.isAnnotationPresent(RestController.class)
|
||||
&& antPathMatcher.match("org.dromara.visor.**.controller.**", clazz.getPackage().getName()));
|
||||
&& antPathMatcher.match("org.dromara.visor.module.**.controller.**", clazz.getPackage().getName()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addResourceHandlers(ResourceHandlerRegistry registry) {
|
||||
// 公共模板前缀
|
||||
registry.addResourceHandler(orionPrefix + "/template/**")
|
||||
.addResourceLocations("classpath:/public/template/");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -171,4 +186,13 @@ public class OrionWebAutoConfiguration implements WebMvcConfigurer {
|
||||
return new DemoDisableApiAspect();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param config config
|
||||
* @return 对外服务 api 切面
|
||||
*/
|
||||
@Bean
|
||||
public ExposeApiAspect exposeApiAspect(ExposeApiConfig config) {
|
||||
return new ExposeApiAspect(config);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright (c) 2023 - present Dromara, All rights reserved.
|
||||
*
|
||||
* https://visor.dromara.org
|
||||
* https://visor.dromara.org.cn
|
||||
* https://visor.orionsec.cn
|
||||
*
|
||||
* Members:
|
||||
* Jiahang Li - ljh1553488six@139.com - author
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.dromara.visor.framework.web.configuration.config;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
/**
|
||||
* 对外服务配置属性
|
||||
*
|
||||
* @author Jiahang Li
|
||||
* @version 1.0.0
|
||||
* @since 2025/8/22 19:57
|
||||
*/
|
||||
@Data
|
||||
@ConfigurationProperties("orion.api.expose")
|
||||
public class ExposeApiConfig {
|
||||
|
||||
/**
|
||||
* 对外服务请求头
|
||||
*/
|
||||
private String header;
|
||||
|
||||
/**
|
||||
* 对外服务请求值
|
||||
*/
|
||||
private String token;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright (c) 2023 - present Dromara, All rights reserved.
|
||||
*
|
||||
* https://visor.dromara.org
|
||||
* https://visor.dromara.org.cn
|
||||
* https://visor.orionsec.cn
|
||||
*
|
||||
* Members:
|
||||
* Jiahang Li - ljh1553488six@139.com - author
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.dromara.visor.framework.web.core.annotation;
|
||||
|
||||
import javax.annotation.security.PermitAll;
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* 对外服务 api 注解
|
||||
*
|
||||
* @author Jiahang Li
|
||||
* @version 1.0.0
|
||||
* @since 2025/8/22 9:59
|
||||
*/
|
||||
@Target({ElementType.METHOD})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
@PermitAll
|
||||
public @interface ExposeApi {
|
||||
|
||||
/**
|
||||
* @return 请求来源
|
||||
*/
|
||||
String source() default "";
|
||||
|
||||
}
|
||||
@@ -22,7 +22,6 @@
|
||||
*/
|
||||
package org.dromara.visor.framework.web.core.aspect;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import org.aspectj.lang.annotation.Before;
|
||||
import org.aspectj.lang.annotation.Pointcut;
|
||||
@@ -39,7 +38,6 @@ import org.springframework.core.annotation.Order;
|
||||
* @since 2024/5/21 16:52
|
||||
*/
|
||||
@Aspect
|
||||
@Slf4j
|
||||
@Order(BeanOrderConst.DEMO_DISABLE_API_ASPECT)
|
||||
public class DemoDisableApiAspect {
|
||||
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Copyright (c) 2023 - present Dromara, All rights reserved.
|
||||
*
|
||||
* https://visor.dromara.org
|
||||
* https://visor.dromara.org.cn
|
||||
* https://visor.orionsec.cn
|
||||
*
|
||||
* Members:
|
||||
* Jiahang Li - ljh1553488six@139.com - author
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.dromara.visor.framework.web.core.aspect;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import org.aspectj.lang.annotation.Before;
|
||||
import org.aspectj.lang.annotation.Pointcut;
|
||||
import org.dromara.visor.common.constant.BeanOrderConst;
|
||||
import org.dromara.visor.common.constant.ErrorCode;
|
||||
import org.dromara.visor.framework.web.configuration.config.ExposeApiConfig;
|
||||
import org.dromara.visor.framework.web.core.annotation.ExposeApi;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.web.context.request.RequestContextHolder;
|
||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* 对外服务 api 切面
|
||||
*
|
||||
* @author Jiahang Li
|
||||
* @version 1.0.0
|
||||
* @since 2025/8/22 16:52
|
||||
*/
|
||||
@Slf4j
|
||||
@Aspect
|
||||
@Order(BeanOrderConst.EXPOSE_API_ASPECT)
|
||||
public class ExposeApiAspect {
|
||||
|
||||
private final ExposeApiConfig config;
|
||||
|
||||
public ExposeApiAspect(ExposeApiConfig config) {
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
@Pointcut("@annotation(e)")
|
||||
public void exposeApi(ExposeApi e) {
|
||||
}
|
||||
|
||||
@Before(value = "exposeApi(e)", argNames = "e")
|
||||
public void beforeExposeApi(ExposeApi e) {
|
||||
// 获取请求
|
||||
HttpServletRequest request = Optional.ofNullable(RequestContextHolder.getRequestAttributes())
|
||||
.map(s -> (ServletRequestAttributes) s)
|
||||
.map(ServletRequestAttributes::getRequest)
|
||||
.orElse(null);
|
||||
if (request == null) {
|
||||
throw ErrorCode.EXPOSE_UNAUTHORIZED.exception();
|
||||
}
|
||||
// 验证对外服务参数
|
||||
if (!config.getToken().equals(request.getHeader(config.getHeader()))) {
|
||||
log.warn("expose api unauthorized, url: {}", request.getRequestURI());
|
||||
throw ErrorCode.EXPOSE_UNAUTHORIZED.exception();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -149,6 +149,7 @@ public class GlobalExceptionHandler {
|
||||
}
|
||||
|
||||
@ExceptionHandler(value = {
|
||||
LockException.class,
|
||||
TimeoutException.class,
|
||||
java.util.concurrent.TimeoutException.class
|
||||
})
|
||||
|
||||
@@ -1,4 +1,11 @@
|
||||
{
|
||||
"groups": [
|
||||
{
|
||||
"name": "orion.api.expose",
|
||||
"type": "org.dromara.visor.framework.web.configuration.config.ExposeApiConfig",
|
||||
"sourceType": "org.dromara.visor.framework.web.configuration.config.ExposeApiConfig"
|
||||
}
|
||||
],
|
||||
"properties": [
|
||||
{
|
||||
"name": "orion.version",
|
||||
@@ -25,6 +32,16 @@
|
||||
"name": "orion.api.cors",
|
||||
"type": "java.lang.Boolean",
|
||||
"description": "是否开启 cors 过滤器."
|
||||
},
|
||||
{
|
||||
"name": "orion.api.expose.header",
|
||||
"type": "java.lang.String",
|
||||
"description": "对外服务请求头."
|
||||
},
|
||||
{
|
||||
"name": "orion.api.expose.token",
|
||||
"type": "java.lang.String",
|
||||
"description": "对外服务请求值."
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -21,17 +21,18 @@
|
||||
<module>orion-visor-spring-boot-starter-swagger</module>
|
||||
<module>orion-visor-spring-boot-starter-datasource</module>
|
||||
<module>orion-visor-spring-boot-starter-mybatis</module>
|
||||
<module>orion-visor-spring-boot-starter-cipher</module>
|
||||
<module>orion-visor-spring-boot-starter-config</module>
|
||||
<module>orion-visor-spring-boot-starter-job</module>
|
||||
<module>orion-visor-spring-boot-starter-websocket</module>
|
||||
<module>orion-visor-spring-boot-starter-redis</module>
|
||||
<module>orion-visor-spring-boot-starter-desensitize</module>
|
||||
<module>orion-visor-spring-boot-starter-cipher</module>
|
||||
<module>orion-visor-spring-boot-starter-log</module>
|
||||
<module>orion-visor-spring-boot-starter-storage</module>
|
||||
<module>orion-visor-spring-boot-starter-security</module>
|
||||
<module>orion-visor-spring-boot-starter-monitor</module>
|
||||
<module>orion-visor-spring-boot-starter-test</module>
|
||||
<module>orion-visor-spring-boot-starter-influxdb</module>
|
||||
<module>orion-visor-spring-boot-starter-biz-operator-log</module>
|
||||
</modules>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user