init
This commit is contained in:
79
fizz-common/pom.xml
Normal file
79
fizz-common/pom.xml
Normal file
@@ -0,0 +1,79 @@
|
||||
<?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>
|
||||
<artifactId>fizz-gateway-community</artifactId>
|
||||
<groupId>we</groupId>
|
||||
<version>1.5.0</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>fizz-common</artifactId>
|
||||
|
||||
<properties>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.networknt</groupId>
|
||||
<artifactId>json-schema-validator-i18n-support</artifactId>
|
||||
<version>1.0.39_4</version>
|
||||
<scope>system</scope>
|
||||
<systemPath>${project.basedir}/../lib/json-schema-validator-i18n-support-1.0.39_4.jar</systemPath>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-webflux</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-logging</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-log4j2</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-pool2</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-redis-reactive</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.session</groupId>
|
||||
<artifactId>spring-session-data-redis</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>commons-codec</groupId>
|
||||
<artifactId>commons-codec</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.bouncycastle</groupId>
|
||||
<artifactId>bcpkix-jdk15on</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>fastjson</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
76
fizz-common/src/main/java/we/config/RedisReactiveConfig.java
Normal file
76
fizz-common/src/main/java/we/config/RedisReactiveConfig.java
Normal file
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright (C) 2020 the original author or authors.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package we.config;
|
||||
|
||||
import io.lettuce.core.ClientOptions;
|
||||
import io.lettuce.core.resource.ClientResources;
|
||||
import io.lettuce.core.resource.DefaultClientResources;
|
||||
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.data.redis.connection.ReactiveRedisConnectionFactory;
|
||||
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
|
||||
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
|
||||
import org.springframework.data.redis.connection.lettuce.LettucePoolingClientConfiguration;
|
||||
import org.springframework.data.redis.core.ReactiveStringRedisTemplate;
|
||||
|
||||
/**
|
||||
* @author hongqiaowei
|
||||
*/
|
||||
|
||||
public abstract class RedisReactiveConfig {
|
||||
|
||||
protected static final Logger log = LoggerFactory.getLogger(RedisReactiveConfig.class);
|
||||
|
||||
// this should not be changed unless there is a truly good reason to do so
|
||||
private static final int ps = Runtime.getRuntime().availableProcessors();
|
||||
private static final ClientResources clientResources = DefaultClientResources.builder()
|
||||
.ioThreadPoolSize(ps)
|
||||
.computationThreadPoolSize(ps)
|
||||
.build();
|
||||
|
||||
private RedisReactiveProperties redisReactiveProperties;
|
||||
|
||||
public RedisReactiveConfig(RedisReactiveProperties properties) {
|
||||
redisReactiveProperties = properties;
|
||||
}
|
||||
|
||||
public ReactiveStringRedisTemplate reactiveStringRedisTemplate(ReactiveRedisConnectionFactory fact) {
|
||||
return new ReactiveStringRedisTemplate(fact);
|
||||
}
|
||||
|
||||
public ReactiveRedisConnectionFactory lettuceConnectionFactory() {
|
||||
|
||||
log.info("connect to " + redisReactiveProperties);
|
||||
|
||||
RedisStandaloneConfiguration rcs = new RedisStandaloneConfiguration(redisReactiveProperties.getHost(), redisReactiveProperties.getPort());
|
||||
String password = redisReactiveProperties.getPassword();
|
||||
if (password != null) {
|
||||
rcs.setPassword(password);
|
||||
}
|
||||
rcs.setDatabase(redisReactiveProperties.getDatabase());
|
||||
|
||||
LettucePoolingClientConfiguration ccs = LettucePoolingClientConfiguration.builder()
|
||||
.clientResources(clientResources)
|
||||
.clientOptions(ClientOptions.builder().publishOnScheduler(true).build())
|
||||
.poolConfig(new GenericObjectPoolConfig())
|
||||
.build();
|
||||
|
||||
return new LettuceConnectionFactory(rcs, ccs);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright (C) 2020 the original author or authors.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package we.config;
|
||||
|
||||
import we.util.Constants;
|
||||
import we.util.Utils;
|
||||
|
||||
/**
|
||||
* @author hongqiaowei
|
||||
*/
|
||||
|
||||
public abstract class RedisReactiveProperties {
|
||||
|
||||
private String host = "127.0.0.1";
|
||||
private int port = 6379;
|
||||
private String password;
|
||||
private int database = 0;
|
||||
|
||||
public String getHost() {
|
||||
return host;
|
||||
}
|
||||
|
||||
public void setHost(String host) {
|
||||
this.host = host;
|
||||
}
|
||||
|
||||
public int getPort() {
|
||||
return port;
|
||||
}
|
||||
|
||||
public void setPort(int port) {
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
public void setPassword(String password) {
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
public int getDatabase() {
|
||||
return database;
|
||||
}
|
||||
|
||||
public void setDatabase(int database) {
|
||||
this.database = database;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder b = new StringBuilder(48);
|
||||
appendTo(b);
|
||||
return b.toString();
|
||||
}
|
||||
|
||||
public void appendTo(StringBuilder b) {
|
||||
b.append(Constants.Symbol.LEFT_BRACE);
|
||||
Utils.addTo(b, "host", Constants.Symbol.EQUAL, host, Constants.Symbol.SPACE_STR);
|
||||
Utils.addTo(b, "port", Constants.Symbol.EQUAL, port, Constants.Symbol.SPACE_STR);
|
||||
Utils.addTo(b, "password", Constants.Symbol.EQUAL, password, Constants.Symbol.SPACE_STR);
|
||||
Utils.addTo(b, "database", Constants.Symbol.EQUAL, database, Constants.Symbol.EMPTY);
|
||||
b.append(Constants.Symbol.RIGHT_BRACE);
|
||||
}
|
||||
}
|
||||
62
fizz-common/src/main/java/we/config/SchedConfig.java
Normal file
62
fizz-common/src/main/java/we/config/SchedConfig.java
Normal file
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright (C) 2021 the original author or authors.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package we.config;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.scheduling.Trigger;
|
||||
import org.springframework.scheduling.TriggerContext;
|
||||
import org.springframework.scheduling.annotation.SchedulingConfigurer;
|
||||
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
|
||||
|
||||
/**
|
||||
* @author hongqiaowei
|
||||
*/
|
||||
|
||||
@ConfigurationProperties(prefix = "sched")
|
||||
public abstract class SchedConfig implements SchedulingConfigurer {
|
||||
|
||||
private int executors = 1;
|
||||
|
||||
public void setExecutors(int es) {
|
||||
executors = es;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
|
||||
taskRegistrar.setScheduler(taskScheduler());
|
||||
taskRegistrar.addTriggerTask(new Runnable() {
|
||||
public void run() {
|
||||
}
|
||||
}, new Trigger() {
|
||||
@Override
|
||||
public Date nextExecutionTime(TriggerContext triggerContext) {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Bean(destroyMethod = "shutdown")
|
||||
public Executor taskScheduler() {
|
||||
return Executors.newScheduledThreadPool(executors);
|
||||
}
|
||||
}
|
||||
235
fizz-common/src/main/java/we/config/WebClientConfig.java
Normal file
235
fizz-common/src/main/java/we/config/WebClientConfig.java
Normal file
@@ -0,0 +1,235 @@
|
||||
/*
|
||||
* Copyright (C) 2020 the original author or authors.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package we.config;
|
||||
|
||||
import io.netty.buffer.PooledByteBufAllocator;
|
||||
import io.netty.buffer.UnpooledByteBufAllocator;
|
||||
import io.netty.channel.AdaptiveRecvByteBufAllocator;
|
||||
import io.netty.channel.ChannelOption;
|
||||
import io.netty.channel.PreferHeapByteBufAllocator;
|
||||
import io.netty.channel.socket.nio.NioSocketChannel;
|
||||
import io.netty.handler.timeout.ReadTimeoutHandler;
|
||||
import io.netty.handler.timeout.WriteTimeoutHandler;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.http.client.reactive.ReactorClientHttpConnector;
|
||||
import org.springframework.http.client.reactive.ReactorResourceFactory;
|
||||
import org.springframework.web.reactive.function.client.ExchangeStrategies;
|
||||
import org.springframework.web.reactive.function.client.WebClient;
|
||||
import reactor.netty.http.client.HttpClient;
|
||||
import reactor.netty.resources.ConnectionProvider;
|
||||
import reactor.netty.resources.LoopResources;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* @author hongqiaowei
|
||||
*/
|
||||
|
||||
public abstract class WebClientConfig {
|
||||
|
||||
protected static final Logger log = LoggerFactory.getLogger(WebClientConfig.class);
|
||||
|
||||
private String name;
|
||||
|
||||
private int maxConnections = 2_000;
|
||||
|
||||
private Duration maxIdleTime = Duration.ofMillis(40_000);
|
||||
|
||||
private Duration pendingAcquireTimeout = Duration.ofMillis(6_000);
|
||||
|
||||
private long connReadTimeout = 20_000;
|
||||
|
||||
private long connWriteTimeout = 20_000;
|
||||
|
||||
private int chConnTimeout = 20_000;
|
||||
|
||||
private boolean chTcpNodelay = true;
|
||||
|
||||
private boolean chSoKeepAlive = true;
|
||||
|
||||
private boolean compress = false;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = "wc-" + name;
|
||||
}
|
||||
|
||||
public int getMaxConnections() {
|
||||
return maxConnections;
|
||||
}
|
||||
|
||||
public void setMaxConnections(int maxConnections) {
|
||||
this.maxConnections = maxConnections;
|
||||
}
|
||||
|
||||
public Duration getMaxIdleTime() {
|
||||
return maxIdleTime;
|
||||
}
|
||||
|
||||
public void setMaxIdleTime(long maxIdleTime) {
|
||||
this.maxIdleTime = Duration.ofMillis(maxIdleTime);
|
||||
}
|
||||
|
||||
public Duration getPendingAcquireTimeout() {
|
||||
return pendingAcquireTimeout;
|
||||
}
|
||||
|
||||
public void setPendingAcquireTimeout(long pendingAcquireTimeout) {
|
||||
this.pendingAcquireTimeout = Duration.ofMillis(pendingAcquireTimeout);
|
||||
}
|
||||
|
||||
public long getConnReadTimeout() {
|
||||
return connReadTimeout;
|
||||
}
|
||||
|
||||
public void setConnReadTimeout(long connReadTimeout) {
|
||||
this.connReadTimeout = connReadTimeout;
|
||||
}
|
||||
|
||||
public long getConnWriteTimeout() {
|
||||
return connWriteTimeout;
|
||||
}
|
||||
|
||||
public void setConnWriteTimeout(long connWriteTimeout) {
|
||||
this.connWriteTimeout = connWriteTimeout;
|
||||
}
|
||||
|
||||
public int getChConnTimeout() {
|
||||
return chConnTimeout;
|
||||
}
|
||||
|
||||
public void setChConnTimeout(int chConnTimeout) {
|
||||
this.chConnTimeout = chConnTimeout;
|
||||
}
|
||||
|
||||
public boolean isChTcpNodelay() {
|
||||
return chTcpNodelay;
|
||||
}
|
||||
|
||||
public void setChTcpNodelay(boolean chTcpNodelay) {
|
||||
this.chTcpNodelay = chTcpNodelay;
|
||||
}
|
||||
|
||||
public boolean isChSoKeepAlive() {
|
||||
return chSoKeepAlive;
|
||||
}
|
||||
|
||||
public void setChSoKeepAlive(boolean chSoKeepAlive) {
|
||||
this.chSoKeepAlive = chSoKeepAlive;
|
||||
}
|
||||
|
||||
public boolean isCompress() {
|
||||
return compress;
|
||||
}
|
||||
|
||||
public void setCompress(boolean compress) {
|
||||
this.compress = compress;
|
||||
}
|
||||
|
||||
private ConnectionProvider getConnectionProvider() {
|
||||
String cpName = name + "-cp";
|
||||
ConnectionProvider cp = ConnectionProvider.builder(cpName).maxConnections(maxConnections)
|
||||
.pendingAcquireTimeout(pendingAcquireTimeout)
|
||||
.maxIdleTime(maxIdleTime)
|
||||
.build();
|
||||
log.info(cpName + ' ' + cp);
|
||||
return cp;
|
||||
}
|
||||
|
||||
private LoopResources getLoopResources() {
|
||||
String elPrefix = name + "-el";
|
||||
// LoopResources lr = LoopResources.create(elPrefix, 1, Runtime.getRuntime().availableProcessors(), true);
|
||||
LoopResources lr = LoopResources.create(elPrefix, Runtime.getRuntime().availableProcessors(), true);
|
||||
lr.onServer(false);
|
||||
log.info(name + "-lr " + lr);
|
||||
return lr;
|
||||
}
|
||||
|
||||
protected ReactorResourceFactory reactorResourceFactory() {
|
||||
ReactorResourceFactory fact = new ReactorResourceFactory();
|
||||
fact.setUseGlobalResources(false);
|
||||
fact.setConnectionProvider(getConnectionProvider());
|
||||
fact.setLoopResources(getLoopResources());
|
||||
fact.afterPropertiesSet();
|
||||
return fact;
|
||||
}
|
||||
|
||||
public WebClient webClient() {
|
||||
log.info(this.toString());
|
||||
// return WebClient.builder().exchangeStrategies(ExchangeStrategies.builder().codecs(configurer -> configurer.defaultCodecs().maxInMemorySize(-1)).build())
|
||||
// .clientConnector(new ReactorClientHttpConnector(reactorResourceFactory(), httpClient -> {
|
||||
// return httpClient.compress(compress).tcpConfiguration(tcpClient -> {
|
||||
// return tcpClient.doOnConnected(connection -> {
|
||||
// connection.addHandlerLast(new ReadTimeoutHandler( connReadTimeout, TimeUnit.MILLISECONDS))
|
||||
// .addHandlerLast(new WriteTimeoutHandler( connWriteTimeout, TimeUnit.MILLISECONDS));
|
||||
// }).option(ChannelOption.CONNECT_TIMEOUT_MILLIS, chConnTimeout)
|
||||
// .option(ChannelOption.TCP_NODELAY, chTcpNodelay)
|
||||
// .option(ChannelOption.SO_KEEPALIVE, chSoKeepAlive)
|
||||
// .option(ChannelOption.ALLOCATOR, UnpooledByteBufAllocator.DEFAULT);
|
||||
// });
|
||||
// })).build();
|
||||
|
||||
ConnectionProvider cp = getConnectionProvider();
|
||||
LoopResources lr = getLoopResources();
|
||||
HttpClient httpClient = HttpClient.create(cp).compress(compress).tcpConfiguration(
|
||||
tcpClient -> {
|
||||
return tcpClient.runOn(lr, false)
|
||||
// .runOn(lr)
|
||||
// .bootstrap(
|
||||
// bootstrap -> (
|
||||
// bootstrap.channel(NioSocketChannel.class)
|
||||
// )
|
||||
// )
|
||||
.doOnConnected(
|
||||
connection -> {
|
||||
connection.addHandlerLast(new ReadTimeoutHandler( connReadTimeout, TimeUnit.MILLISECONDS))
|
||||
.addHandlerLast(new WriteTimeoutHandler(connWriteTimeout, TimeUnit.MILLISECONDS));
|
||||
}
|
||||
)
|
||||
.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, chConnTimeout)
|
||||
.option(ChannelOption.TCP_NODELAY, chTcpNodelay)
|
||||
.option(ChannelOption.SO_KEEPALIVE, chSoKeepAlive)
|
||||
// .option(ChannelOption.ALLOCATOR, PreferHeapByteBufAllocator.DEFAULT);
|
||||
// .option(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT)
|
||||
.option(ChannelOption.ALLOCATOR, UnpooledByteBufAllocator.DEFAULT);
|
||||
}
|
||||
);
|
||||
return WebClient.builder().exchangeStrategies(ExchangeStrategies.builder().codecs(configurer -> configurer.defaultCodecs().maxInMemorySize(-1)).build())
|
||||
.clientConnector(new ReactorClientHttpConnector(httpClient)).build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return " {name=" + name +
|
||||
", maxConnections=" + maxConnections +
|
||||
", maxIdleTime=" + maxIdleTime +
|
||||
", pendingAcquireTimeout=" + pendingAcquireTimeout +
|
||||
", connReadTimeout=" + connReadTimeout +
|
||||
", connWriteTimeout=" + connWriteTimeout +
|
||||
", chConnTimeout=" + chConnTimeout +
|
||||
", chTcpNodelay=" + chTcpNodelay +
|
||||
", chSoKeepAlive=" + chSoKeepAlive +
|
||||
", compress=" + compress +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
109
fizz-common/src/main/java/we/util/Constants.java
Normal file
109
fizz-common/src/main/java/we/util/Constants.java
Normal file
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* Copyright (C) 2020 the original author or authors.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package we.util;
|
||||
|
||||
import org.apache.commons.lang3.SystemUtils;
|
||||
|
||||
/**
|
||||
* @author hongqiaowei
|
||||
*/
|
||||
|
||||
public final class Constants {
|
||||
|
||||
public static final class Symbol {
|
||||
public static final String EMPTY = "";
|
||||
public static final String SPACE_STR = " ";
|
||||
public static final char BLANK = ' ';
|
||||
public static final char SPACE = BLANK;
|
||||
public static final String TWO_SPACE_STR = " ";
|
||||
|
||||
public static final char COMMA = ',';
|
||||
public static final char COLON = ':';
|
||||
public static final char FORWARD_SLASH = '/';
|
||||
public static final String FORWARD_SLASH_STR = "/";
|
||||
public static final char BACK_SLASH = '\\';
|
||||
public static final char DOT = '.';
|
||||
public static final char SEMICOLON = ';';
|
||||
public static final char QUESTION = '?';
|
||||
public static final char DOUBLE_QUOTE = '"';
|
||||
public static final char SINGLE_QUOTE = '\'';
|
||||
public static final char ASTERISK = '*';
|
||||
public static final char DASH = '-';
|
||||
public static final char UNDERLINE = '_';
|
||||
public static final char EQUAL = '=';
|
||||
public static final char AT = '@';
|
||||
public static final char HASH = '#';
|
||||
public static final char LEFT_SQUARE_BRACKET = '[';
|
||||
public static final char RIGHT_SQUARE_BRACKET = ']';
|
||||
public static final char LEFT_BRACE = '{';
|
||||
public static final char RIGHT_BRACE = '}';
|
||||
|
||||
public static final char LF = '\n';
|
||||
public static final char TAB = '\t';
|
||||
public static final char NUL = '\u0000';
|
||||
|
||||
static final char c0 = SystemUtils.IS_OS_WINDOWS ? Symbol.BACK_SLASH : Symbol.FORWARD_SLASH;
|
||||
public static final char PATH_SEPARATOR = c0;
|
||||
public static final String LINE_SEPARATOR = System.lineSeparator();
|
||||
|
||||
public static final String COMMA_SPACE = ", ";
|
||||
public static final String HTTP_PROTOCOL_PREFIX = "http://";
|
||||
}
|
||||
|
||||
public static final class Charset {
|
||||
public static final String UTF8 = "UTF-8";
|
||||
public static final String GBK = "GBK";
|
||||
public static final String ISO88591 = "ISO8859-1";
|
||||
}
|
||||
|
||||
public static final class DatetimePattern {
|
||||
public static final String DP10 = "yyyy-MM-dd";
|
||||
public static final String DP14 = "yyyyMMddHHmmss";
|
||||
public static final String DP19 = "yyyy-MM-dd HH:mm:ss";
|
||||
public static final String DP23 = "yyyy-MM-dd HH:mm:ss.SSS";
|
||||
public static final byte MILLS_LEN = 13;
|
||||
}
|
||||
|
||||
public static final class Profiles {
|
||||
public static final String LOCAL = "local";
|
||||
public static final String DEV = "dev";
|
||||
|
||||
public static final String TEST = "test";
|
||||
public static final String FAT = "fat";
|
||||
|
||||
public static final String PREPROD = "preprod";
|
||||
public static final String UAT = "uat";
|
||||
public static final String PRE = "pre";
|
||||
|
||||
public static final String PROD = "prod";
|
||||
public static final String PRO = "pro";
|
||||
}
|
||||
|
||||
public static final String HTTP_SERVER = "http_server";
|
||||
public static final String HTTP_CLIENT = "http_client";
|
||||
public static final String MYSQL = "mysql";
|
||||
public static final String REDIS = "redis";
|
||||
public static final String CODIS = "codis";
|
||||
public static final String MONGO = "mongo";
|
||||
public static final String ACTIVEMQ = "activemq";
|
||||
public static final String KAFKA = "kafka";
|
||||
public static final String ELASTICSEARCH = "elasticsearch";
|
||||
public static final String SCHED = "sched";
|
||||
|
||||
public static final String BIZ_ID = "bizId";
|
||||
}
|
||||
187
fizz-common/src/main/java/we/util/DateTimeUtils.java
Normal file
187
fizz-common/src/main/java/we/util/DateTimeUtils.java
Normal file
@@ -0,0 +1,187 @@
|
||||
/*
|
||||
* Copyright (C) 2020 the original author or authors.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package we.util;
|
||||
|
||||
import java.time.*;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import we.util.Constants.DatetimePattern;
|
||||
|
||||
/**
|
||||
* @author hongqiaowei
|
||||
*/
|
||||
|
||||
public abstract class DateTimeUtils {
|
||||
|
||||
private static Map<String, DateTimeFormatter> dateTimeFormatters = new HashMap<>();
|
||||
|
||||
private static ZoneId defaultZone = ZoneId.systemDefault();
|
||||
|
||||
private static final String zeroTimeSuffix = " 00:00:00";
|
||||
|
||||
public static DateTimeFormatter getDateTimeFormatter(String pattern) {
|
||||
DateTimeFormatter f = dateTimeFormatters.get(pattern);
|
||||
if (f == null) {
|
||||
f = DateTimeFormatter.ofPattern(pattern);
|
||||
dateTimeFormatters.put(pattern, f);
|
||||
}
|
||||
return f;
|
||||
}
|
||||
|
||||
public static Date from(Instant i) {
|
||||
return new Date(i.toEpochMilli());
|
||||
}
|
||||
|
||||
public static Date from(LocalDateTime ldt) {
|
||||
return from(ldt.atZone(defaultZone).toInstant());
|
||||
}
|
||||
|
||||
public static LocalDateTime from(Date d) {
|
||||
return LocalDateTime.ofInstant(d.toInstant(), defaultZone);
|
||||
}
|
||||
|
||||
public static LocalDateTime from(long l) {
|
||||
return LocalDateTime.ofInstant(Instant.ofEpochMilli(l), defaultZone);
|
||||
}
|
||||
|
||||
public static long toMillis(LocalDateTime ldt) {
|
||||
return ldt.atZone(defaultZone).toInstant().toEpochMilli();
|
||||
}
|
||||
|
||||
public static long toMillis(String dateTime, String... pattern) {
|
||||
if (dateTime.length() == 10) {
|
||||
dateTime += zeroTimeSuffix;
|
||||
}
|
||||
String p = DatetimePattern.DP19;
|
||||
if (pattern.length != 0) {
|
||||
p = pattern[0];
|
||||
}
|
||||
DateTimeFormatter f = getDateTimeFormatter(p);
|
||||
LocalDateTime ldt = LocalDateTime.parse(dateTime, f);
|
||||
return ldt.atZone(defaultZone).toInstant().toEpochMilli();
|
||||
}
|
||||
|
||||
public static String toDate(long mills, String... pattern) {
|
||||
String p = DatetimePattern.DP10;
|
||||
if (pattern.length != 0) {
|
||||
p = pattern[0];
|
||||
}
|
||||
LocalDateTime ldt = LocalDateTime.ofInstant(Instant.ofEpochMilli(mills), defaultZone);
|
||||
DateTimeFormatter f = getDateTimeFormatter(p);
|
||||
return ldt.format(f);
|
||||
}
|
||||
|
||||
public static long until(LocalDate thatDate) {
|
||||
return LocalDate.now().until(thatDate, ChronoUnit.DAYS);
|
||||
}
|
||||
|
||||
public static long from(LocalDate thatDate) {
|
||||
return thatDate.until(LocalDate.now(), ChronoUnit.DAYS);
|
||||
}
|
||||
|
||||
public static long until(LocalDate startDate, LocalDate endDate) {
|
||||
return startDate.until(endDate, ChronoUnit.DAYS);
|
||||
}
|
||||
|
||||
public static LocalDate date2localDate(Date date) {
|
||||
return date.toInstant().atZone(defaultZone).toLocalDate();
|
||||
}
|
||||
|
||||
public static Date localDate2date(LocalDate localDate) {
|
||||
ZonedDateTime zonedDateTime = localDate.atStartOfDay(defaultZone);
|
||||
return Date.from(zonedDateTime.toInstant());
|
||||
}
|
||||
|
||||
public static String localDate2str(LocalDate date, String... pattern) {
|
||||
String p = DatetimePattern.DP10;
|
||||
if (pattern.length != 0) {
|
||||
p = pattern[0];
|
||||
}
|
||||
DateTimeFormatter f = getDateTimeFormatter(p);
|
||||
return date.format(f);
|
||||
}
|
||||
|
||||
public static String localDateTime2str(LocalDateTime localDateTime, String... pattern) {
|
||||
String p = DatetimePattern.DP23;
|
||||
if (pattern.length != 0) {
|
||||
p = pattern[0];
|
||||
}
|
||||
DateTimeFormatter f = getDateTimeFormatter(p);
|
||||
return localDateTime.format(f);
|
||||
}
|
||||
|
||||
public static List<String> datesBetween(String start, String end) {
|
||||
LocalDate sd = LocalDate.parse(start);
|
||||
LocalDate ed = LocalDate.parse(end);
|
||||
long dist = ChronoUnit.DAYS.between(sd, ed);
|
||||
if (dist == 0) {
|
||||
return Collections.EMPTY_LIST;
|
||||
} else if (dist < 0) {
|
||||
LocalDate x = ed;
|
||||
ed = sd;
|
||||
sd = x;
|
||||
dist = Math.abs(dist);
|
||||
}
|
||||
long max = dist + 1;
|
||||
return Stream.iterate(sd, d -> {
|
||||
return d.plusDays(1);
|
||||
}).limit(max).map(LocalDate::toString).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public static class LocalDateAndStr {
|
||||
public LocalDate d;
|
||||
public String s;
|
||||
|
||||
public LocalDateAndStr(LocalDate d, String s) {
|
||||
this.d = d;
|
||||
this.s = s;
|
||||
}
|
||||
}
|
||||
|
||||
public static List<LocalDateAndStr> datesBetween0(String start, String end) {
|
||||
LocalDate sd = LocalDate.parse(start);
|
||||
LocalDate ed = LocalDate.parse(end);
|
||||
long dist = ChronoUnit.DAYS.between(sd, ed);
|
||||
if (dist == 0) {
|
||||
return Collections.EMPTY_LIST;
|
||||
} else if (dist < 0) {
|
||||
LocalDate x = ed;
|
||||
ed = sd;
|
||||
sd = x;
|
||||
dist = Math.abs(dist);
|
||||
}
|
||||
long max = dist + 1;
|
||||
return Stream.iterate(sd, d -> {
|
||||
return d.plusDays(1);
|
||||
}).limit(max).map((LocalDate e) -> {
|
||||
return new LocalDateAndStr(e, e.toString());
|
||||
}).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public static LocalDate beforeNow(long offsetDays) {
|
||||
return LocalDate.now().minusDays(offsetDays);
|
||||
}
|
||||
|
||||
public static LocalDateTime beforeNowNoTime(long offsetDays) {
|
||||
return LocalDate.now().minusDays(offsetDays).atTime(0, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
62
fizz-common/src/main/java/we/util/DigestUtils.java
Normal file
62
fizz-common/src/main/java/we/util/DigestUtils.java
Normal file
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright (C) 2020 the original author or authors.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package we.util;
|
||||
|
||||
import org.apache.commons.codec.binary.Hex;
|
||||
|
||||
import java.security.MessageDigest;
|
||||
|
||||
/**
|
||||
* @author hongqiaowei
|
||||
*/
|
||||
|
||||
public abstract class DigestUtils extends org.apache.commons.codec.digest.DigestUtils {
|
||||
|
||||
static final String md5digest = "$md5digest";
|
||||
|
||||
private DigestUtils() {
|
||||
}
|
||||
|
||||
public static String md532(String source) {
|
||||
byte[] srcBytes = source.getBytes();
|
||||
MessageDigest md = (MessageDigest) ThreadContext.get(md5digest);
|
||||
if (md == null) {
|
||||
md = getMd5Digest();
|
||||
ThreadContext.set(md5digest, md);
|
||||
} else {
|
||||
md.reset();
|
||||
}
|
||||
md.update(srcBytes);
|
||||
byte[] resultBytes = md.digest();
|
||||
return Hex.encodeHexString(resultBytes);
|
||||
}
|
||||
|
||||
public static String md516(String source) {
|
||||
return md532(source).substring(8, 24);
|
||||
}
|
||||
|
||||
// public static void main(String[] args) {
|
||||
// StringBuilder b = new StringBuilder(128);
|
||||
// long now = System.currentTimeMillis();
|
||||
// String app = "appx";
|
||||
// String timestamp = "" + now;
|
||||
// String secretKey = "fb3c057fe6134796acf33d53f240f2a9";
|
||||
// b.append(app).append(Constants.Symbol.UNDERLINE).append(timestamp).append(Constants.Symbol.UNDERLINE).append(secretKey);
|
||||
// System.err.println("timestamp: " + timestamp + ", sign: " + md532(b.toString()));
|
||||
// }
|
||||
}
|
||||
173
fizz-common/src/main/java/we/util/JacksonUtils.java
Normal file
173
fizz-common/src/main/java/we/util/JacksonUtils.java
Normal file
@@ -0,0 +1,173 @@
|
||||
/*
|
||||
* Copyright (C) 2020 the original author or authors.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package we.util;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude.Include;
|
||||
import com.fasterxml.jackson.core.JsonFactory;
|
||||
import com.fasterxml.jackson.core.JsonGenerator;
|
||||
import com.fasterxml.jackson.core.JsonParser;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.*;
|
||||
import com.fasterxml.jackson.databind.module.SimpleModule;
|
||||
|
||||
import we.util.Constants.DatetimePattern;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* @author hongqiaowei
|
||||
*/
|
||||
|
||||
public abstract class JacksonUtils {
|
||||
|
||||
private static ObjectMapper m;
|
||||
|
||||
static {
|
||||
JsonFactory f = new JsonFactory();
|
||||
f.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);
|
||||
f.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
|
||||
|
||||
m = new ObjectMapper(f);
|
||||
|
||||
m.setSerializationInclusion(Include.NON_EMPTY);
|
||||
m.configure( SerializationFeature. WRITE_ENUMS_USING_TO_STRING, true);
|
||||
m.configure( DeserializationFeature. READ_ENUMS_USING_TO_STRING, true);
|
||||
m.configure( DeserializationFeature. FAIL_ON_NUMBERS_FOR_ENUMS, true);
|
||||
m.configure( SerializationFeature. WRITE_EMPTY_JSON_ARRAYS, true); // FIXME
|
||||
m.configure( SerializationFeature. WRITE_NULL_MAP_VALUES, true);
|
||||
m.configure( DeserializationFeature. FAIL_ON_UNKNOWN_PROPERTIES, false);
|
||||
m.configure( JsonParser.Feature. ALLOW_UNQUOTED_CONTROL_CHARS, true);
|
||||
|
||||
SimpleModule m0 = new SimpleModule();
|
||||
m0.addDeserializer(Date.class, new DateDeseralizer());
|
||||
m.registerModule(m0);
|
||||
|
||||
SimpleModule m1 = new SimpleModule();
|
||||
m1.addDeserializer(LocalDate.class, new LocalDateDeseralizer());
|
||||
m.registerModule(m1);
|
||||
|
||||
SimpleModule m2 = new SimpleModule();
|
||||
m2.addDeserializer(LocalDateTime.class, new LocalDateTimeDeseralizer());
|
||||
m.registerModule(m2);
|
||||
|
||||
SimpleModule m3 = new SimpleModule();
|
||||
m3.addSerializer(LocalDateTime.class, new LocalDateTimeSeralizer());
|
||||
m.registerModule(m3);
|
||||
}
|
||||
|
||||
public static ObjectMapper getObjectMapper() {
|
||||
return m;
|
||||
}
|
||||
|
||||
public static <T> T readValue(String json, Class<T> clz) {
|
||||
try {
|
||||
return m.readValue(json, clz);
|
||||
} catch (JsonProcessingException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static String writeValueAsString(Object value) {
|
||||
try {
|
||||
return m.writeValueAsString(value);
|
||||
} catch (JsonProcessingException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class DateDeseralizer extends JsonDeserializer<Date> {
|
||||
|
||||
public Date deserialize(JsonParser jp, DeserializationContext ctx) throws IOException {
|
||||
|
||||
String s = jp.getText();
|
||||
int sl = s.length();
|
||||
if (sl == DatetimePattern.MILLS_LEN) {
|
||||
return new Date(Long.parseLong(s));
|
||||
} else {
|
||||
String dtp = DatetimePattern.DP10;
|
||||
DateTimeFormatter dtf = null;
|
||||
if (sl == DatetimePattern.DP10.length()) {
|
||||
} else if (sl == DatetimePattern.DP14.length()) {
|
||||
dtp = DatetimePattern.DP14;
|
||||
} else if (sl == DatetimePattern.DP19.length()) {
|
||||
dtp = DatetimePattern.DP19;
|
||||
} else if (sl == DatetimePattern.DP23.length()) {
|
||||
dtp = DatetimePattern.DP23;
|
||||
} else {
|
||||
throw new IOException("invalid datetime pattern: " + s);
|
||||
}
|
||||
dtf = DateTimeUtils.getDateTimeFormatter(dtp);
|
||||
LocalDateTime ldt = LocalDateTime.parse(s, dtf);
|
||||
return DateTimeUtils.from(ldt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class LocalDateDeseralizer extends JsonDeserializer<LocalDate> {
|
||||
|
||||
public LocalDate deserialize(JsonParser jp, DeserializationContext ctx) throws IOException {
|
||||
|
||||
String s = jp.getText();
|
||||
if (s.length() == DatetimePattern.DP10.length()) {
|
||||
DateTimeFormatter dtf = DateTimeUtils.getDateTimeFormatter(DatetimePattern.DP10);
|
||||
return LocalDate.parse(s, dtf);
|
||||
} else {
|
||||
throw new IOException("invalid datetime pattern: " + s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class LocalDateTimeDeseralizer extends JsonDeserializer<LocalDateTime> {
|
||||
|
||||
public LocalDateTime deserialize(JsonParser jp, DeserializationContext ctx) throws IOException {
|
||||
|
||||
String s = jp.getText();
|
||||
int sl = s.length();
|
||||
if (sl == DatetimePattern.MILLS_LEN) {
|
||||
return DateTimeUtils.from(Long.parseLong(s));
|
||||
} else {
|
||||
String dtp = DatetimePattern.DP10;
|
||||
DateTimeFormatter dtf = null;
|
||||
if (sl == DatetimePattern.DP10.length()) {
|
||||
} else if (sl == DatetimePattern.DP14.length()) {
|
||||
dtp = DatetimePattern.DP14;
|
||||
} else if (sl == DatetimePattern.DP19.length()) {
|
||||
dtp = DatetimePattern.DP19;
|
||||
} else if (sl == DatetimePattern.DP23.length()) {
|
||||
dtp = DatetimePattern.DP23;
|
||||
} else {
|
||||
throw new IOException("invalid datetime pattern: " + s);
|
||||
}
|
||||
dtf = DateTimeUtils.getDateTimeFormatter(dtp);
|
||||
return LocalDateTime.parse(s, dtf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class LocalDateTimeSeralizer extends JsonSerializer<LocalDateTime> {
|
||||
|
||||
@Override
|
||||
public void serialize(LocalDateTime ldt, JsonGenerator jg, SerializerProvider sp) throws IOException {
|
||||
jg.writeNumber(DateTimeUtils.toMillis(ldt));
|
||||
}
|
||||
}
|
||||
181
fizz-common/src/main/java/we/util/JsonSchemaUtils.java
Normal file
181
fizz-common/src/main/java/we/util/JsonSchemaUtils.java
Normal file
@@ -0,0 +1,181 @@
|
||||
/*
|
||||
* Copyright (C) 2020 the original author or authors.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package we.util;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.networknt.schema.JsonSchema;
|
||||
import com.networknt.schema.JsonSchemaFactory;
|
||||
import com.networknt.schema.SchemaValidatorsConfig;
|
||||
import com.networknt.schema.SpecVersion;
|
||||
import com.networknt.schema.ValidationMessage;
|
||||
import com.networknt.schema.ValidatorTypeCode;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* JSON Schema工具类
|
||||
* @author zhongjie
|
||||
*/
|
||||
public class JsonSchemaUtils {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(JsonSchemaUtils.class);
|
||||
static {
|
||||
try {
|
||||
// 替换验证信息提示
|
||||
Field messageFormatField = ValidatorTypeCode.class.getDeclaredField("messageFormat");
|
||||
//忽略属性的访问权限
|
||||
messageFormatField.setAccessible(true);
|
||||
messageFormatField.set(ValidatorTypeCode.ADDITIONAL_PROPERTIES, new MessageFormat(
|
||||
"{1}在schema中没有定义并且schema不允许指定外的字段"));
|
||||
messageFormatField.set(ValidatorTypeCode.ALL_OF, new MessageFormat("should be valid to all the schemas {1}"));
|
||||
messageFormatField.set(ValidatorTypeCode.ANY_OF, new MessageFormat("should be valid to any of the schemas {1}"));
|
||||
messageFormatField.set(ValidatorTypeCode.CROSS_EDITS, new MessageFormat("has an error with 'cross edits'"));
|
||||
messageFormatField.set(ValidatorTypeCode.DEPENDENCIES, new MessageFormat("has an error with dependencies {1}"));
|
||||
messageFormatField.set(ValidatorTypeCode.EDITS, new MessageFormat("has an error with 'edits'"));
|
||||
messageFormatField.set(ValidatorTypeCode.ENUM, new MessageFormat("值不在限定{1}内"));
|
||||
messageFormatField.set(ValidatorTypeCode.FORMAT, new MessageFormat("不符合{1}格式{2}"));
|
||||
messageFormatField.set(ValidatorTypeCode.ITEMS, new MessageFormat("在索引[{1}]处为找到验证器"));
|
||||
messageFormatField.set(ValidatorTypeCode.MAXIMUM, new MessageFormat("给定值应当小于等于{1}"));
|
||||
messageFormatField.set(ValidatorTypeCode.MAX_ITEMS, new MessageFormat("数组至多含有{1}个元素"));
|
||||
messageFormatField.set(ValidatorTypeCode.MAX_LENGTH, new MessageFormat("长度应当最多{1}"));
|
||||
messageFormatField.set(ValidatorTypeCode.MAX_PROPERTIES, new MessageFormat("对象最多有{1}个字段"));
|
||||
messageFormatField.set(ValidatorTypeCode.MINIMUM, new MessageFormat("给定值应当大于等于{1}"));
|
||||
messageFormatField.set(ValidatorTypeCode.MIN_ITEMS, new MessageFormat("数组至少含有{1}个元素"));
|
||||
messageFormatField.set(ValidatorTypeCode.MIN_LENGTH, new MessageFormat("长度应当最少{1}"));
|
||||
messageFormatField.set(ValidatorTypeCode.MIN_PROPERTIES, new MessageFormat("{0}:对象最少有{1}个字段"));
|
||||
messageFormatField.set(ValidatorTypeCode.MULTIPLE_OF, new MessageFormat("数值类型应当是{1}"));
|
||||
messageFormatField.set(ValidatorTypeCode.NOT_ALLOWED, new MessageFormat("{1}不允许出现在数据中"));
|
||||
messageFormatField.set(ValidatorTypeCode.NOT, new MessageFormat("should not be valid to the schema {1}"));
|
||||
messageFormatField.set(ValidatorTypeCode.ONE_OF, new MessageFormat("should be valid to one and only one of the schemas {1}"));
|
||||
messageFormatField.set(ValidatorTypeCode.PATTERN_PROPERTIES, new MessageFormat("has some error with 'pattern properties'"));
|
||||
messageFormatField.set(ValidatorTypeCode.PATTERN, new MessageFormat("应当符合格式\"{1}\""));
|
||||
messageFormatField.set(ValidatorTypeCode.PROPERTIES, new MessageFormat("对象字段存在错误"));
|
||||
messageFormatField.set(ValidatorTypeCode.READ_ONLY, new MessageFormat("is a readonly field, it cannot be changed"));
|
||||
messageFormatField.set(ValidatorTypeCode.REF, new MessageFormat("has an error with 'refs'"));
|
||||
messageFormatField.set(ValidatorTypeCode.REQUIRED, new MessageFormat("{1}字段不能为空"));
|
||||
messageFormatField.set(ValidatorTypeCode.TYPE, new MessageFormat("预期类型是{2},但实际是{1}"));
|
||||
messageFormatField.set(ValidatorTypeCode.UNION_TYPE, new MessageFormat("预期类型是{2},但实际是{1}"));
|
||||
messageFormatField.set(ValidatorTypeCode.UNIQUE_ITEMS, new MessageFormat("数组元素唯一性冲突"));
|
||||
messageFormatField.set(ValidatorTypeCode.DATETIME, new MessageFormat("{1}不是一个有效的{2}"));
|
||||
messageFormatField.set(ValidatorTypeCode.UUID, new MessageFormat("{1}不是一个有效的{2}"));
|
||||
messageFormatField.set(ValidatorTypeCode.ID, new MessageFormat("{1} is an invalid segment for URI {2}"));
|
||||
messageFormatField.set(ValidatorTypeCode.EXCLUSIVE_MAXIMUM, new MessageFormat("给定值应当小于{1}"));
|
||||
messageFormatField.set(ValidatorTypeCode.EXCLUSIVE_MINIMUM, new MessageFormat("给定值应当大于{1}"));
|
||||
messageFormatField.set(ValidatorTypeCode.FALSE, new MessageFormat("Boolean schema false is not valid"));
|
||||
messageFormatField.set(ValidatorTypeCode.CONST, new MessageFormat("值应当是一个常量{1}"));
|
||||
messageFormatField.set(ValidatorTypeCode.CONTAINS, new MessageFormat("没有包含元素能够通过验证:{1}"));
|
||||
} catch (Exception e) {
|
||||
LOGGER.warn("替换ValidatorTypeCode.messageFormat异常", e);
|
||||
}
|
||||
}
|
||||
|
||||
private JsonSchemaUtils() {}
|
||||
|
||||
/**
|
||||
* 验证JSON字符串是否符合JSON Schema要求
|
||||
* @param jsonSchema JSON Schema
|
||||
* @param inputJson JSON字符串
|
||||
* @return null:验证通过,List:报错信息列表
|
||||
*/
|
||||
public static List<String> validate(String jsonSchema, String inputJson) {
|
||||
return internalValidate(jsonSchema, inputJson, Boolean.FALSE);
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证JSON字符串是否符合JSON Schema要求,允许数字\布尔类型 是字符串格式
|
||||
* @param jsonSchema JSON Schema
|
||||
* @param inputJson JSON字符串
|
||||
* @return null:验证通过,List:报错信息列表
|
||||
*/
|
||||
public static List<String> validateAllowValueStr(String jsonSchema, String inputJson) {
|
||||
return internalValidate(jsonSchema, inputJson, Boolean.TRUE);
|
||||
}
|
||||
|
||||
private static List<String> internalValidate(String jsonSchema, String inputJson, boolean typeLoose) {
|
||||
CheckJsonResult checkJsonResult = checkJson(jsonSchema, inputJson, typeLoose);
|
||||
if (checkJsonResult.errorList != null) {
|
||||
return checkJsonResult.errorList;
|
||||
}
|
||||
|
||||
Set<ValidationMessage> validationMessageSet = checkJsonResult.schema.validate(checkJsonResult.json);
|
||||
if (CollectionUtils.isEmpty(validationMessageSet)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return validationMessageSet.stream().map(validationMessage -> {
|
||||
String message = validationMessage.getMessage();
|
||||
if (message != null) {
|
||||
return message;
|
||||
}
|
||||
return validationMessage.getCode();
|
||||
}).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private static CheckJsonResult checkJson(String jsonSchema, String inputJson, boolean typeLoose) {
|
||||
CheckJsonResult checkJsonResult = new CheckJsonResult();
|
||||
try {
|
||||
checkJsonResult.schema = getJsonSchemaFromStringContent(jsonSchema, typeLoose);
|
||||
} catch (Exception e) {
|
||||
checkJsonResult.errorList = new ArrayList<>(1);
|
||||
checkJsonResult.errorList.add(String.format("JSON Schema格式错误,提示信息[%s]", e.getMessage()));
|
||||
return checkJsonResult;
|
||||
}
|
||||
|
||||
try {
|
||||
checkJsonResult.json = getJsonNodeFromStringContent(inputJson);
|
||||
} catch (Exception e) {
|
||||
checkJsonResult.errorList = new ArrayList<>(1);
|
||||
checkJsonResult.errorList.add(String.format("待验证JSON格式错误,提示信息[%s]", e.getMessage()));
|
||||
return checkJsonResult;
|
||||
}
|
||||
|
||||
return checkJsonResult;
|
||||
}
|
||||
|
||||
private static class CheckJsonResult {
|
||||
JsonSchema schema;
|
||||
JsonNode json;
|
||||
List<String> errorList;
|
||||
}
|
||||
|
||||
private static final JsonSchemaFactory JSON_SCHEMA_FACTORY = JsonSchemaFactory.getInstance(SpecVersion.VersionFlag.V7);
|
||||
private static final SchemaValidatorsConfig CONFIG_WITH_TYPE_LOOSE;
|
||||
private static final SchemaValidatorsConfig CONFIG_WITHOUT_TYPE_LOOSE;
|
||||
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
|
||||
static {
|
||||
CONFIG_WITH_TYPE_LOOSE = new SchemaValidatorsConfig();
|
||||
CONFIG_WITH_TYPE_LOOSE.setTypeLoose(Boolean.TRUE);
|
||||
CONFIG_WITHOUT_TYPE_LOOSE = new SchemaValidatorsConfig();
|
||||
CONFIG_WITHOUT_TYPE_LOOSE.setTypeLoose(Boolean.FALSE);
|
||||
}
|
||||
private static JsonSchema getJsonSchemaFromStringContent(String schemaContent, boolean typeLoose) {
|
||||
SchemaValidatorsConfig config = typeLoose ? CONFIG_WITH_TYPE_LOOSE : CONFIG_WITHOUT_TYPE_LOOSE;
|
||||
return JSON_SCHEMA_FACTORY.getSchema(schemaContent, config);
|
||||
}
|
||||
|
||||
private static JsonNode getJsonNodeFromStringContent(String content) throws Exception {
|
||||
return OBJECT_MAPPER.readTree(content);
|
||||
}
|
||||
}
|
||||
214
fizz-common/src/main/java/we/util/MapUtil.java
Normal file
214
fizz-common/src/main/java/we/util/MapUtil.java
Normal file
@@ -0,0 +1,214 @@
|
||||
/*
|
||||
* Copyright (C) 2020 the original author or authors.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package we.util;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Francis Dong
|
||||
*
|
||||
*/
|
||||
public class MapUtil {
|
||||
|
||||
public static HttpHeaders toHttpHeaders(Map<String, Object> params) {
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
|
||||
if (params == null || params.isEmpty()) {
|
||||
return headers;
|
||||
}
|
||||
|
||||
for (Entry<String, Object> entry : params.entrySet()) {
|
||||
Object val = entry.getValue();
|
||||
List<String> list = new ArrayList<>();
|
||||
if (val instanceof List) {
|
||||
List<Object> vals = (List<Object>) val;
|
||||
for (Object value : vals) {
|
||||
if (value != null) {
|
||||
list.add(value.toString());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (val != null) {
|
||||
list.add(val.toString());
|
||||
}
|
||||
}
|
||||
if (list.size() > 0) {
|
||||
headers.put(entry.getKey(), list);
|
||||
}
|
||||
}
|
||||
|
||||
return headers;
|
||||
}
|
||||
|
||||
|
||||
public static MultiValueMap<String, String> toMultiValueMap(Map<String, Object> params) {
|
||||
MultiValueMap<String, String> mvmap = new LinkedMultiValueMap<>();
|
||||
|
||||
if (params == null || params.isEmpty()) {
|
||||
return mvmap;
|
||||
}
|
||||
|
||||
for (Entry<String, Object> entry : params.entrySet()) {
|
||||
Object val = entry.getValue();
|
||||
List<String> list = new ArrayList<>();
|
||||
if (val instanceof List) {
|
||||
List<Object> vals = (List<Object>) val;
|
||||
for (Object value : vals) {
|
||||
if (value != null) {
|
||||
list.add(value.toString());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (val != null) {
|
||||
list.add(val.toString());
|
||||
}
|
||||
}
|
||||
if (list.size() > 0) {
|
||||
mvmap.put(entry.getKey(), list);
|
||||
}
|
||||
}
|
||||
|
||||
return mvmap;
|
||||
}
|
||||
|
||||
public static Map<String, Object> toHashMap(MultiValueMap<String, String> params) {
|
||||
HashMap<String, Object> m = new HashMap<>();
|
||||
|
||||
if (params == null || params.isEmpty()) {
|
||||
return m;
|
||||
}
|
||||
|
||||
for (Entry<String, List<String>> entry : params.entrySet()) {
|
||||
List<String> val = entry.getValue();
|
||||
if (val != null && val.size() > 0) {
|
||||
if (val.size() > 1) {
|
||||
m.put(entry.getKey(), val);
|
||||
} else {
|
||||
m.put(entry.getKey(), val.get(0));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
public static Map<String, Object> headerToHashMap(HttpHeaders headers) {
|
||||
HashMap<String, Object> m = new HashMap<>();
|
||||
|
||||
if (headers == null || headers.isEmpty()) {
|
||||
return m;
|
||||
}
|
||||
|
||||
for (Entry<String, List<String>> entry : headers.entrySet()) {
|
||||
List<String> val = entry.getValue();
|
||||
if (val != null && val.size() > 0) {
|
||||
if (val.size() > 1) {
|
||||
m.put(entry.getKey().toUpperCase(), val);
|
||||
} else {
|
||||
m.put(entry.getKey().toUpperCase(), val.get(0));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
public static Map<String, Object> upperCaseKey(Map<String, Object> m) {
|
||||
HashMap<String, Object> rs = new HashMap<>();
|
||||
|
||||
if (m == null || m.isEmpty()) {
|
||||
return rs;
|
||||
}
|
||||
|
||||
for (Entry<String, Object> entry : m.entrySet()) {
|
||||
rs.put(entry.getKey().toUpperCase(), entry.getValue());
|
||||
}
|
||||
|
||||
return rs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set value by path,support multiple levels,eg:a.b.c <br>
|
||||
* Do NOT use this method if field name contains a dot <br>
|
||||
* @param data
|
||||
* @param path
|
||||
* @param value
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static void set(Map<String, Object> data, String path, Object value) {
|
||||
String[] fields = path.split("\\.");
|
||||
if(fields.length < 2) {
|
||||
data.put(path, value);
|
||||
}else {
|
||||
Map<String, Object> next = data;
|
||||
for (int i = 0; i < fields.length - 1; i++) {
|
||||
Map<String, Object> val = (Map<String, Object>) next.get(fields[i]);
|
||||
if(val == null) {
|
||||
val = new HashMap<>();
|
||||
next.put(fields[i], val);
|
||||
}
|
||||
if(i == fields.length - 2) {
|
||||
val.put(fields[i+1], value);
|
||||
break;
|
||||
}
|
||||
next = val;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get value by path, support multiple levels,eg:a.b.c <br>
|
||||
* Do NOT use this method if field name contains a dot <br>
|
||||
* @param data
|
||||
* @param path
|
||||
* @return
|
||||
*/
|
||||
public static Object get(Map<String, Object> data, String path) {
|
||||
String[] fields = path.split("\\.");
|
||||
if(fields.length < 2) {
|
||||
return data.get(path);
|
||||
}else {
|
||||
Map<String, Object> next = data;
|
||||
for (int i = 0; i < fields.length - 1; i++) {
|
||||
if(!(next.get(fields[i]) instanceof Map)) {
|
||||
return null;
|
||||
}
|
||||
Map<String, Object> val = (Map<String, Object>) next.get(fields[i]);
|
||||
if(val == null) {
|
||||
return null;
|
||||
}
|
||||
if(i == fields.length - 2) {
|
||||
return val.get(fields[i+1]);
|
||||
}
|
||||
next = val;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
107
fizz-common/src/main/java/we/util/NetworkUtils.java
Normal file
107
fizz-common/src/main/java/we/util/NetworkUtils.java
Normal file
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Copyright (C) 2020 the original author or authors.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package we.util;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.net.NetworkInterface;
|
||||
import java.net.SocketException;
|
||||
import java.net.UnknownHostException;
|
||||
import java.security.SecureRandom;
|
||||
import java.util.Enumeration;
|
||||
|
||||
/**
|
||||
* @author hongqiaowei
|
||||
*/
|
||||
|
||||
public class NetworkUtils {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(NetworkUtils.class);
|
||||
|
||||
private static final int maxServerId = 1023;
|
||||
|
||||
private static int serverId = -1;
|
||||
|
||||
private static String serverIp;
|
||||
|
||||
private static final String SERVER_IP = "SERVER_IP";
|
||||
|
||||
public static String getServerIp() {
|
||||
try {
|
||||
if (serverIp == null) {
|
||||
serverIp = System.getenv(SERVER_IP);
|
||||
log.info("SERVER_IP is " + serverIp);
|
||||
if (StringUtils.isBlank(serverIp)) {
|
||||
boolean found = false;
|
||||
Enumeration<NetworkInterface> nis = null;
|
||||
nis = NetworkInterface.getNetworkInterfaces();
|
||||
while (nis.hasMoreElements()) {
|
||||
NetworkInterface ni = (NetworkInterface) nis.nextElement();
|
||||
Enumeration<InetAddress> ias = ni.getInetAddresses();
|
||||
while (ias.hasMoreElements()) {
|
||||
InetAddress ia = ias.nextElement();
|
||||
if (ia.isSiteLocalAddress()) {
|
||||
serverIp = ia.getHostAddress();
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
InetAddress ia = InetAddress.getLocalHost();
|
||||
serverIp = ia.getHostAddress();
|
||||
}
|
||||
}
|
||||
}
|
||||
return serverIp;
|
||||
} catch (SocketException | UnknownHostException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static int getServerId() {
|
||||
if (serverId == -1) {
|
||||
try {
|
||||
StringBuilder b = ThreadContext.getStringBuilder();
|
||||
Enumeration<NetworkInterface> nis = NetworkInterface.getNetworkInterfaces();
|
||||
while (nis.hasMoreElements()) {
|
||||
NetworkInterface ni = nis.nextElement();
|
||||
byte[] mac = ni.getHardwareAddress();
|
||||
if (mac != null) {
|
||||
for (int i = 0; i < mac.length; i++) {
|
||||
b.append(String.format("%02X", mac[i]));
|
||||
}
|
||||
}
|
||||
}
|
||||
serverId = b.toString().hashCode();
|
||||
} catch (Exception e) {
|
||||
serverId = (new SecureRandom().nextInt());
|
||||
log.error(null, e);
|
||||
}
|
||||
serverId = serverId & maxServerId;
|
||||
log.info("server id is " + serverId);
|
||||
}
|
||||
return serverId;
|
||||
}
|
||||
}
|
||||
97
fizz-common/src/main/java/we/util/PemUtils.java
Normal file
97
fizz-common/src/main/java/we/util/PemUtils.java
Normal file
@@ -0,0 +1,97 @@
|
||||
//Copyright 2017 - https://github.com/lbalmaceda
|
||||
//Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
//The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
package we.util;
|
||||
|
||||
import org.bouncycastle.util.io.pem.PemObject;
|
||||
import org.bouncycastle.util.io.pem.PemReader;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.security.KeyFactory;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.PublicKey;
|
||||
import java.security.spec.EncodedKeySpec;
|
||||
import java.security.spec.InvalidKeySpecException;
|
||||
import java.security.spec.PKCS8EncodedKeySpec;
|
||||
import java.security.spec.X509EncodedKeySpec;
|
||||
|
||||
public class PemUtils {
|
||||
|
||||
private static byte[] parsePEMString(String pemStr) throws IOException {
|
||||
PemReader reader = new PemReader(new InputStreamReader(new ByteArrayInputStream(pemStr.getBytes())));
|
||||
PemObject pemObject = reader.readPemObject();
|
||||
byte[] content = pemObject.getContent();
|
||||
reader.close();
|
||||
return content;
|
||||
}
|
||||
|
||||
private static byte[] parsePEMFile(File pemFile) throws IOException {
|
||||
if (!pemFile.isFile() || !pemFile.exists()) {
|
||||
throw new FileNotFoundException(String.format("The file '%s' doesn't exist.", pemFile.getAbsolutePath()));
|
||||
}
|
||||
PemReader reader = new PemReader(new FileReader(pemFile));
|
||||
PemObject pemObject = reader.readPemObject();
|
||||
byte[] content = pemObject.getContent();
|
||||
reader.close();
|
||||
return content;
|
||||
}
|
||||
|
||||
private static PublicKey getPublicKey(byte[] keyBytes, String algorithm) {
|
||||
PublicKey publicKey = null;
|
||||
try {
|
||||
KeyFactory kf = KeyFactory.getInstance(algorithm);
|
||||
EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
|
||||
publicKey = kf.generatePublic(keySpec);
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
System.out.println("Could not reconstruct the public key, the given algorithm could not be found.");
|
||||
} catch (InvalidKeySpecException e) {
|
||||
System.out.println("Could not reconstruct the public key");
|
||||
}
|
||||
|
||||
return publicKey;
|
||||
}
|
||||
|
||||
private static PrivateKey getPrivateKey(byte[] keyBytes, String algorithm) {
|
||||
PrivateKey privateKey = null;
|
||||
try {
|
||||
KeyFactory kf = KeyFactory.getInstance(algorithm);
|
||||
EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
|
||||
privateKey = kf.generatePrivate(keySpec);
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
System.out.println("Could not reconstruct the private key, the given algorithm could not be found.");
|
||||
} catch (InvalidKeySpecException e) {
|
||||
System.out.println("Could not reconstruct the private key");
|
||||
}
|
||||
|
||||
return privateKey;
|
||||
}
|
||||
|
||||
public static PublicKey readPublicKeyFromFile(String filepath, String algorithm) throws IOException {
|
||||
byte[] bytes = PemUtils.parsePEMFile(new File(filepath));
|
||||
return PemUtils.getPublicKey(bytes, algorithm);
|
||||
}
|
||||
|
||||
public static PrivateKey readPrivateKeyFromFile(String filepath, String algorithm) throws IOException {
|
||||
byte[] bytes = PemUtils.parsePEMFile(new File(filepath));
|
||||
return PemUtils.getPrivateKey(bytes, algorithm);
|
||||
}
|
||||
|
||||
public static PublicKey readPublicKeyFromString(String pemStr, String algorithm) throws IOException {
|
||||
byte[] bytes = PemUtils.parsePEMString(pemStr);
|
||||
return PemUtils.getPublicKey(bytes, algorithm);
|
||||
}
|
||||
|
||||
public static PrivateKey readPrivateKeyFromString(String pemStr, String algorithm) throws IOException {
|
||||
byte[] bytes = PemUtils.parsePEMString(pemStr);
|
||||
return PemUtils.getPrivateKey(bytes, algorithm);
|
||||
}
|
||||
|
||||
}
|
||||
96
fizz-common/src/main/java/we/util/ReactiveResult.java
Normal file
96
fizz-common/src/main/java/we/util/ReactiveResult.java
Normal file
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Copyright (C) 2020 the original author or authors.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package we.util;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author hongqiaowei
|
||||
*/
|
||||
|
||||
public class ReactiveResult<D> extends Result<D> {
|
||||
|
||||
public Throwable t;
|
||||
|
||||
public Map<Object, Object> context;
|
||||
|
||||
public ReactiveResult() {
|
||||
super();
|
||||
}
|
||||
|
||||
public ReactiveResult(int code, String msg, D data, Throwable t) {
|
||||
super(code, msg, data);
|
||||
this.t = t;
|
||||
}
|
||||
|
||||
public static ReactiveResult succ() {
|
||||
return new ReactiveResult(SUCC, null, null, null);
|
||||
}
|
||||
|
||||
public static <D> ReactiveResult<D> succ(D data) {
|
||||
ReactiveResult rr = succ();
|
||||
rr.data = data;
|
||||
return rr;
|
||||
}
|
||||
|
||||
public static ReactiveResult fail() {
|
||||
return new ReactiveResult(FAIL, null, null, null);
|
||||
}
|
||||
|
||||
public static ReactiveResult fail(String msg) {
|
||||
ReactiveResult rr = fail();
|
||||
rr.msg = msg;
|
||||
return rr;
|
||||
}
|
||||
|
||||
public static ReactiveResult fail(Throwable t) {
|
||||
ReactiveResult rr = fail();
|
||||
rr.t = t;
|
||||
return rr;
|
||||
}
|
||||
|
||||
public static ReactiveResult with(int code) {
|
||||
return new ReactiveResult(code, null, null, null);
|
||||
}
|
||||
|
||||
public static ReactiveResult with(int code, String msg) {
|
||||
ReactiveResult rr = with(code);
|
||||
rr.msg = msg;
|
||||
return rr;
|
||||
}
|
||||
|
||||
public static <D> ReactiveResult<D> with(int code, D data) {
|
||||
ReactiveResult rr = with(code);
|
||||
rr.data = data;
|
||||
return rr;
|
||||
}
|
||||
|
||||
public static <D> ReactiveResult<D> with(int code, Throwable t) {
|
||||
ReactiveResult rr = with(code);
|
||||
rr.t = t;
|
||||
return rr;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toStringBuilder(StringBuilder b) {
|
||||
super.toStringBuilder(b);
|
||||
b.append(',');
|
||||
b.append("context:") .append(context).append(',');
|
||||
b.append("throwable:").append(t == null ? t : t.getMessage());
|
||||
}
|
||||
}
|
||||
42
fizz-common/src/main/java/we/util/ReactorUtils.java
Normal file
42
fizz-common/src/main/java/we/util/ReactorUtils.java
Normal file
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright (C) 2020 the original author or authors.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package we.util;
|
||||
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
/**
|
||||
* @author hongqiaowei
|
||||
*/
|
||||
|
||||
public interface ReactorUtils {
|
||||
|
||||
static final Object OBJ = new Object();
|
||||
|
||||
static final Object NULL = OBJ;
|
||||
|
||||
static final Throwable EMPTY_THROWABLE = Utils.throwableWithoutStack(null); // XXX
|
||||
|
||||
static Mono getInitiateMono() {
|
||||
return Mono.just(OBJ);
|
||||
}
|
||||
|
||||
static Flux getInitiateFlux() {
|
||||
return Flux.just(OBJ);
|
||||
}
|
||||
}
|
||||
33
fizz-common/src/main/java/we/util/ReflectionUtils.java
Normal file
33
fizz-common/src/main/java/we/util/ReflectionUtils.java
Normal file
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (C) 2020 the original author or authors.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package we.util;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
/**
|
||||
* @author hongqiaowei
|
||||
*/
|
||||
|
||||
public abstract class ReflectionUtils extends org.springframework.util.ReflectionUtils {
|
||||
|
||||
public static void set(Object target, String field, Object value) {
|
||||
Field f = findField(target.getClass(), field);
|
||||
makeAccessible(f);
|
||||
setField(f, target, value);
|
||||
}
|
||||
}
|
||||
97
fizz-common/src/main/java/we/util/Result.java
Normal file
97
fizz-common/src/main/java/we/util/Result.java
Normal file
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Copyright (C) 2020 the original author or authors.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package we.util;
|
||||
|
||||
/**
|
||||
* @author hongqiaowei
|
||||
*/
|
||||
|
||||
public class Result<D> {
|
||||
|
||||
public static final int SUCC = 1;
|
||||
public static final int FAIL = 0;
|
||||
|
||||
public int code = -1;
|
||||
|
||||
public String msg;
|
||||
|
||||
public D data;
|
||||
|
||||
public Result() {
|
||||
}
|
||||
|
||||
public Result(int code, String msg, D data) {
|
||||
this.code = code;
|
||||
this.msg = msg;
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public static Result succ() {
|
||||
return new Result(SUCC, null, null);
|
||||
}
|
||||
|
||||
public static <D> Result<D> succ(D data) {
|
||||
Result r = succ();
|
||||
r.data = data;
|
||||
return r;
|
||||
}
|
||||
|
||||
public static Result fail() {
|
||||
return new Result(FAIL, null, null);
|
||||
}
|
||||
|
||||
public static Result fail(String msg) {
|
||||
Result r = fail();
|
||||
r.msg = msg;
|
||||
return r;
|
||||
}
|
||||
|
||||
public static Result with(int code) {
|
||||
return new Result(code, null, null);
|
||||
}
|
||||
|
||||
public static Result with(int code, String msg) {
|
||||
Result r = with(code);
|
||||
r.msg = msg;
|
||||
return r;
|
||||
}
|
||||
|
||||
public static <D> Result<D> with(int code, D data) {
|
||||
Result r = with(code);
|
||||
r.data = data;
|
||||
return r;
|
||||
}
|
||||
|
||||
// @Override
|
||||
// public String toString() {
|
||||
// return JacksonUtils.writeValueAsString(this);
|
||||
// }
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder b = new StringBuilder();
|
||||
toStringBuilder(b);
|
||||
return b.toString();
|
||||
}
|
||||
|
||||
public void toStringBuilder(StringBuilder b) {
|
||||
b.append("code:").append(code).append(',');
|
||||
b.append("msg:") .append(msg) .append(',');
|
||||
b.append("data:").append(data);
|
||||
}
|
||||
}
|
||||
45
fizz-common/src/main/java/we/util/Script.java
Normal file
45
fizz-common/src/main/java/we/util/Script.java
Normal file
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (C) 2020 the original author or authors.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package we.util;
|
||||
|
||||
/**
|
||||
* @author hongqiaowei
|
||||
*/
|
||||
|
||||
public class Script {
|
||||
|
||||
private String type = ScriptUtils.GROOVY;
|
||||
|
||||
private String source;
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public String getSource() {
|
||||
return source;
|
||||
}
|
||||
|
||||
public void setSource(String source) {
|
||||
this.source = source;
|
||||
}
|
||||
}
|
||||
149
fizz-common/src/main/java/we/util/ScriptUtils.java
Normal file
149
fizz-common/src/main/java/we/util/ScriptUtils.java
Normal file
@@ -0,0 +1,149 @@
|
||||
/*
|
||||
* Copyright (C) 2020 the original author or authors.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package we.util;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
|
||||
import javax.script.*;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.URL;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author hongqiaowei
|
||||
*/
|
||||
|
||||
public abstract class ScriptUtils {
|
||||
|
||||
public static final String JAVA_SCRIPT = "javascript";
|
||||
|
||||
public static final String GROOVY = "groovy";
|
||||
|
||||
private static ScriptEngineManager engineManger;
|
||||
|
||||
private static final String jsFuncName = "dyFunc";
|
||||
|
||||
private static final String clazz = "clazz";
|
||||
|
||||
private static final String resJsonStr = "resJsonStr";
|
||||
|
||||
private static final String COMMON_JS_PATH = "js/common.js";
|
||||
|
||||
public static Map<Long, Long> recreateJavascriptEngineSignalMap = new HashMap<>();
|
||||
|
||||
static {
|
||||
engineManger = new ScriptEngineManager();
|
||||
}
|
||||
|
||||
private static ScriptEngine createJavascriptEngine() throws ScriptException {
|
||||
ScriptEngine eng = engineManger.getEngineByName(JAVA_SCRIPT);
|
||||
try {
|
||||
// custom common.js file
|
||||
File f = new File(COMMON_JS_PATH);
|
||||
if(f.exists()) {
|
||||
eng.eval(new FileReader(COMMON_JS_PATH));
|
||||
return eng;
|
||||
}
|
||||
// use embedded common.js while there is not custom common.js file
|
||||
ClassPathResource res = new ClassPathResource(COMMON_JS_PATH);
|
||||
eng.eval(new InputStreamReader(res.getInputStream()));
|
||||
return eng;
|
||||
} catch (FileNotFoundException e) {
|
||||
throw new ScriptException(e);
|
||||
} catch (IOException e) {
|
||||
throw new ScriptException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static ScriptEngine getScriptEngine(String type) throws ScriptException {
|
||||
if (GROOVY.equals(type)) {
|
||||
ScriptEngine groovyEngine = (ScriptEngine) ThreadContext.get(GROOVY);
|
||||
if (groovyEngine == null) {
|
||||
groovyEngine = engineManger.getEngineByName(GROOVY);
|
||||
ThreadContext.set(GROOVY, groovyEngine);
|
||||
}
|
||||
return groovyEngine;
|
||||
|
||||
} else if (JAVA_SCRIPT.equals(type)) {
|
||||
ScriptEngine javascriptEngine;
|
||||
long tid = Thread.currentThread().getId();
|
||||
Object signal = recreateJavascriptEngineSignalMap.get(tid);
|
||||
if (signal == null) {
|
||||
javascriptEngine = createJavascriptEngine();
|
||||
recreateJavascriptEngineSignalMap.put(tid, tid);
|
||||
ThreadContext.set(JAVA_SCRIPT, javascriptEngine);
|
||||
} else {
|
||||
javascriptEngine = (ScriptEngine) ThreadContext.get(JAVA_SCRIPT);
|
||||
}
|
||||
return javascriptEngine;
|
||||
|
||||
} else {
|
||||
throw new ScriptException("unknown script engine type: " + type);
|
||||
}
|
||||
}
|
||||
|
||||
public static Object execute(Script script) throws ScriptException {
|
||||
return execute(script, null);
|
||||
}
|
||||
|
||||
public static Object execute(Script script, Map<String, Object> context) throws ScriptException {
|
||||
String type = script.getType();
|
||||
ScriptEngine engine = getScriptEngine(type);
|
||||
String src = script.getSource();
|
||||
if (GROOVY.equals(type)) {
|
||||
if (context == null) {
|
||||
return engine.eval(src);
|
||||
} else {
|
||||
Bindings bis = engine.createBindings();
|
||||
bis.putAll(context);
|
||||
return engine.eval(src, bis);
|
||||
}
|
||||
} else { // js
|
||||
engine.eval(src);
|
||||
Invocable invocable = (Invocable) engine;
|
||||
String paramsJsonStr = StringUtils.EMPTY;
|
||||
// try {
|
||||
// ObjectMapper mapper = JacksonUtils.getObjectMapper();
|
||||
// if (context != null) {
|
||||
// paramsJsonStr = mapper.writeValueAsString(context);
|
||||
// }
|
||||
// ScriptObjectMirror som = (ScriptObjectMirror) invocable.invokeFunction(jsFuncName, paramsJsonStr);
|
||||
// Class<?> clz = Class.forName(som.get(clazz).toString());
|
||||
// return mapper.readValue(som.get(resJsonStr).toString(), clz);
|
||||
// } catch (JsonProcessingException | NoSuchMethodException | ClassNotFoundException e) {
|
||||
// throw new ScriptException(e);
|
||||
// }
|
||||
try {
|
||||
// ObjectMapper mapper = JacksonUtils.getObjectMapper();
|
||||
if (context != null) {
|
||||
paramsJsonStr = JacksonUtils.writeValueAsString(context);
|
||||
}
|
||||
return invocable.invokeFunction(jsFuncName, paramsJsonStr);
|
||||
} catch (NoSuchMethodException | RuntimeException e) {
|
||||
throw new ScriptException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
145
fizz-common/src/main/java/we/util/ThreadContext.java
Normal file
145
fizz-common/src/main/java/we/util/ThreadContext.java
Normal file
@@ -0,0 +1,145 @@
|
||||
/*
|
||||
* Copyright (C) 2020 the original author or authors.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package we.util;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author hongqiaowei
|
||||
*/
|
||||
|
||||
public abstract class ThreadContext {
|
||||
|
||||
private static ThreadLocal<Map<String, Object>> tl = new ThreadLocal<>();
|
||||
private static final int mapCap = 32;
|
||||
|
||||
private static final String sb = "$sb";
|
||||
private static final int sbCap = 256;
|
||||
|
||||
/** use me carefully! */
|
||||
public static StringBuilder getStringBuilder() {
|
||||
return getStringBuilder(true);
|
||||
}
|
||||
|
||||
/** use me carefully! */
|
||||
public static StringBuilder getStringBuilder(boolean clean) {
|
||||
Map<String, Object> m = getMap();
|
||||
StringBuilder b = (StringBuilder) m.get(sb);
|
||||
if (b == null) {
|
||||
b = new StringBuilder(sbCap);
|
||||
m.put(sb, b);
|
||||
} else {
|
||||
if (clean) {
|
||||
b.delete(0, b.length());
|
||||
}
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
public static StringBuilder getStringBuilder(String key) {
|
||||
StringBuilder b = (StringBuilder) get(key);
|
||||
if (b == null) {
|
||||
b = new StringBuilder(sbCap);
|
||||
Map<String, Object> m = getMap();
|
||||
m.put(key, b);
|
||||
} else {
|
||||
b.delete(0, b.length());
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
/** for legacy code. */
|
||||
public static SimpleDateFormat getSimpleDateFormat(String pattern) {
|
||||
Map<String, Object> m = getMap();
|
||||
SimpleDateFormat sdf = (SimpleDateFormat) m.get(pattern);
|
||||
if (sdf == null) {
|
||||
sdf = new SimpleDateFormat(pattern);
|
||||
m.put(pattern, sdf);
|
||||
}
|
||||
return sdf;
|
||||
}
|
||||
|
||||
private static Map<String, Object> getMap() {
|
||||
Map<String, Object> m = tl.get();
|
||||
if (m == null) {
|
||||
m = new HashMap<>(mapCap);
|
||||
tl.set(m);
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
public static Object get(String key) {
|
||||
return getMap().get(key);
|
||||
}
|
||||
|
||||
public static <T> T get(String key, Class<T> clz) {
|
||||
T t = (T) get(key);
|
||||
if (t == null) {
|
||||
try {
|
||||
t = clz.newInstance();
|
||||
set(key, t);
|
||||
} catch (InstantiationException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
public static void set(String key, Object obj) {
|
||||
getMap().put(key, obj);
|
||||
}
|
||||
|
||||
public static Object remove(String key) {
|
||||
return getMap().remove(key);
|
||||
}
|
||||
|
||||
public static <T> ArrayList<T> getArrayList(String key, Class<T> elementType) {
|
||||
return getArrayList(key, elementType, true);
|
||||
}
|
||||
|
||||
public static <T> ArrayList<T> getArrayList(String key, Class<T> elementType, boolean clear) {
|
||||
ArrayList<T> l = (ArrayList) get(key);
|
||||
if (l == null) {
|
||||
l = new ArrayList<>();
|
||||
set(key, l);
|
||||
} else if (clear) {
|
||||
l.clear();
|
||||
}
|
||||
return l;
|
||||
}
|
||||
|
||||
public static <K, V> HashMap<K, V> getHashMap(String key, Class<K> kType, Class<V> vType) {
|
||||
return getHashMap(key, kType, vType, true);
|
||||
}
|
||||
|
||||
public static <K, V> HashMap<K, V> getHashMap(String key, Class<K> kType, Class<V> vType, boolean clear) {
|
||||
HashMap<K, V> m = (HashMap<K, V>) get(key);
|
||||
if (m == null) {
|
||||
m = new HashMap<>();
|
||||
set(key ,m);
|
||||
} else if (clear) {
|
||||
m.clear();
|
||||
}
|
||||
return m;
|
||||
}
|
||||
}
|
||||
306
fizz-common/src/main/java/we/util/UrlTransformUtils.java
Normal file
306
fizz-common/src/main/java/we/util/UrlTransformUtils.java
Normal file
@@ -0,0 +1,306 @@
|
||||
package we.util;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.AntPathMatcher;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* Fizz gateway url transform util class
|
||||
*
|
||||
* @author zhongjie
|
||||
*/
|
||||
public class UrlTransformUtils {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(UrlTransformUtils.class);
|
||||
|
||||
private UrlTransformUtils() {}
|
||||
|
||||
private static final FizzGatewayUrlAntPathMatcher ANT_PATH_MATCHER = new FizzGatewayUrlAntPathMatcher();
|
||||
|
||||
/**
|
||||
* transform the backend path to the real backend request path
|
||||
* @param frontendPath frontend path
|
||||
* @param backendPath backend path
|
||||
* @param reqPath request path
|
||||
* @return the transformed backend path
|
||||
* @throws IllegalStateException when the request path does not match the frontend path pattern
|
||||
* @throws IllegalArgumentException The number of capturing groups in the pattern segment does not match the number of URI template variables it defines
|
||||
*/
|
||||
public static String transform(String frontendPath, String backendPath, String reqPath) {
|
||||
Assert.hasText(frontendPath, "frontend path cannot be null");
|
||||
Assert.hasText(backendPath, "backend path cannot be null");
|
||||
Assert.hasText(reqPath, "req path cannot be null");
|
||||
String bp = backendPath;
|
||||
Map<String, String> variables = ANT_PATH_MATCHER.extractUriTemplateVariables(frontendPath, reqPath);
|
||||
for (Map.Entry<String, String> entry : variables.entrySet()) {
|
||||
backendPath = backendPath.replaceAll("\\{" + Matcher.quoteReplacement(entry.getKey()) + "}", Matcher.quoteReplacement(entry.getValue()));
|
||||
}
|
||||
|
||||
if (backendPath.indexOf('{') != -1) {
|
||||
backendPath = backendPath.replaceAll("\\{[^/]*}", "");
|
||||
}
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("req: " + reqPath + ", frontend: " + frontendPath + ", backend: " + bp + ", target: " + backendPath);
|
||||
}
|
||||
|
||||
return backendPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* 自定义Ant风格路径匹配器
|
||||
* 设置默认路径分隔符为{@code #}
|
||||
* 使用{@link FizzGatewayAntPathStringMatcher}设置自定义的参数变量值(额外返回变量名为$1...n的键值对)
|
||||
*
|
||||
* @author zhongjie
|
||||
*/
|
||||
static class FizzGatewayUrlAntPathMatcher extends AntPathMatcher {
|
||||
private static final String DEFAULT_PATH_SEPARATOR = "#";
|
||||
|
||||
private static final int CACHE_TURNOFF_THRESHOLD = 65536;
|
||||
|
||||
private volatile Boolean cachePatterns;
|
||||
|
||||
private final Map<String, String> replaceDoubleStarPatternCache = new ConcurrentHashMap<>(256);
|
||||
|
||||
private final Map<String, String[]> tokenizedPatternCache = new ConcurrentHashMap<>(256);
|
||||
|
||||
final Map<String, AntPathStringMatcher> stringMatcherCache = new ConcurrentHashMap<>(256);
|
||||
|
||||
private boolean caseSensitive = true;
|
||||
|
||||
private static AntPathMatcher DEFAULT_ANT_PATH_MATCHER = new AntPathMatcher();
|
||||
|
||||
public FizzGatewayUrlAntPathMatcher() {
|
||||
// 设置默认路径分隔符为#
|
||||
super(DEFAULT_PATH_SEPARATOR);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPathSeparator(String pathSeparator) {
|
||||
throw new RuntimeException("operation not support");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTrimTokens(boolean trimTokens) {
|
||||
throw new RuntimeException("operation not support");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCaseSensitive(boolean caseSensitive) {
|
||||
super.setCaseSensitive(caseSensitive);
|
||||
this.caseSensitive = caseSensitive;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCachePatterns(boolean cachePatterns) {
|
||||
super.setCachePatterns(cachePatterns);
|
||||
this.cachePatterns = cachePatterns;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AntPathStringMatcher getStringMatcher(String pattern) {
|
||||
AntPathStringMatcher matcher = null;
|
||||
Boolean cachePatterns = this.cachePatterns;
|
||||
if (cachePatterns == null || cachePatterns) {
|
||||
matcher = this.stringMatcherCache.get(pattern);
|
||||
}
|
||||
if (matcher == null) {
|
||||
matcher = new FizzGatewayAntPathStringMatcher(pattern, this.caseSensitive);
|
||||
if (cachePatterns == null && this.stringMatcherCache.size() >= CACHE_TURNOFF_THRESHOLD) {
|
||||
// Try to adapt to the runtime situation that we're encountering:
|
||||
// There are obviously too many different patterns coming in here...
|
||||
// So let's turn off the cache since the patterns are unlikely to be reoccurring.
|
||||
deactivatePatternCache();
|
||||
return matcher;
|
||||
}
|
||||
if (cachePatterns == null || cachePatterns) {
|
||||
this.stringMatcherCache.put(pattern, matcher);
|
||||
}
|
||||
}
|
||||
return matcher;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String[] tokenizePattern(String pattern) {
|
||||
String[] tokenized = null;
|
||||
Boolean cachePatterns = this.cachePatterns;
|
||||
if (cachePatterns == null || cachePatterns) {
|
||||
tokenized = this.tokenizedPatternCache.get(pattern);
|
||||
}
|
||||
if (tokenized == null) {
|
||||
tokenized = tokenizePath(pattern);
|
||||
if (cachePatterns == null && this.tokenizedPatternCache.size() >= CACHE_TURNOFF_THRESHOLD) {
|
||||
// Try to adapt to the runtime situation that we're encountering:
|
||||
// There are obviously too many different patterns coming in here...
|
||||
// So let's turn off the cache since the patterns are unlikely to be reoccurring.
|
||||
deactivatePatternCache();
|
||||
return tokenized;
|
||||
}
|
||||
if (cachePatterns == null || cachePatterns) {
|
||||
this.tokenizedPatternCache.put(pattern, tokenized);
|
||||
}
|
||||
}
|
||||
return tokenized;
|
||||
}
|
||||
|
||||
private void deactivatePatternCache() {
|
||||
this.cachePatterns = false;
|
||||
this.tokenizedPatternCache.clear();
|
||||
this.stringMatcherCache.clear();
|
||||
this.replaceDoubleStarPatternCache.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String extractPathWithinPattern(String pattern, String path) {
|
||||
return DEFAULT_ANT_PATH_MATCHER.extractPathWithinPattern(pattern, path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String combine(String pattern1, String pattern2) {
|
||||
return DEFAULT_ANT_PATH_MATCHER.combine(pattern1, pattern2);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean doMatch(String pattern, String path, boolean fullMatch, Map<String, String> uriTemplateVariables) {
|
||||
String replaceDoubleStarPattern = null;
|
||||
if (pattern != null) {
|
||||
replaceDoubleStarPattern = getReplaceDoubleStarPattern(pattern);
|
||||
}
|
||||
return super.doMatch(replaceDoubleStarPattern, path, fullMatch, uriTemplateVariables);
|
||||
}
|
||||
|
||||
private String getReplaceDoubleStarPattern(String pattern) {
|
||||
String replaceDoubleStarPattern = null;
|
||||
Boolean cachePatterns = this.cachePatterns;
|
||||
if (cachePatterns == null || cachePatterns) {
|
||||
replaceDoubleStarPattern = this.replaceDoubleStarPatternCache.get(pattern);
|
||||
}
|
||||
if (replaceDoubleStarPattern == null) {
|
||||
// by-zhongjie 替换**为.*正则模式
|
||||
replaceDoubleStarPattern = pattern.replaceAll("/\\*\\*$", "/{\\$:.*}")
|
||||
.replaceAll("/\\*\\*/", "/{\\$:.*}/")
|
||||
.replaceAll("^\\*\\*/", "{\\$:.*}/");
|
||||
if (cachePatterns == null && this.replaceDoubleStarPatternCache.size() >= CACHE_TURNOFF_THRESHOLD) {
|
||||
// Try to adapt to the runtime situation that we're encountering:
|
||||
// There are obviously too many different patterns coming in here...
|
||||
// So let's turn off the cache since the patterns are unlikely to be reoccurring.
|
||||
deactivatePatternCache();
|
||||
return replaceDoubleStarPattern;
|
||||
}
|
||||
if (cachePatterns == null || cachePatterns) {
|
||||
this.replaceDoubleStarPatternCache.put(pattern, replaceDoubleStarPattern);
|
||||
}
|
||||
}
|
||||
return replaceDoubleStarPattern;
|
||||
}
|
||||
|
||||
protected static class FizzGatewayAntPathStringMatcher extends AntPathStringMatcher {
|
||||
// by-zhongjie 将 \?|\*|\{((?:\{[^/]+?\}|[^/{}]|\\[{}])+?)\} 改为 \?|\*|\{((?:\{[^/]+?\}|[^{}]|\\[{}])+?)\},排除/的限制
|
||||
private static final Pattern GLOB_PATTERN = Pattern.compile("\\?|\\*|\\{((?:\\{[^/]+?\\}|[^{}]|\\\\[{}])+?)\\}");
|
||||
|
||||
// by-zhongjie 将 (.*) 改为 ([^/]*),限制变量只能匹配在非/的字符内
|
||||
private static final String DEFAULT_VARIABLE_PATTERN = "([^/]*)";
|
||||
|
||||
private final Pattern pattern;
|
||||
|
||||
private final List<String> variableNames = new LinkedList<>();
|
||||
|
||||
// by-zhongjie 匿名占位符
|
||||
private final String ANONYMOUS_PLACEHOLDER = "$";
|
||||
|
||||
public FizzGatewayAntPathStringMatcher(String pattern) {
|
||||
this(pattern, true);
|
||||
}
|
||||
|
||||
public FizzGatewayAntPathStringMatcher(String pattern, boolean caseSensitive) {
|
||||
super(pattern, caseSensitive);
|
||||
StringBuilder patternBuilder = new StringBuilder();
|
||||
Matcher matcher = GLOB_PATTERN.matcher(pattern);
|
||||
int end = 0;
|
||||
while (matcher.find()) {
|
||||
patternBuilder.append(quote(pattern, end, matcher.start()));
|
||||
String match = matcher.group();
|
||||
if ("?".equals(match)) {
|
||||
// by-zhongjie 对 ? 也使用模式匹配
|
||||
patternBuilder.append('(');
|
||||
patternBuilder.append('.');
|
||||
patternBuilder.append(')');
|
||||
this.variableNames.add(ANONYMOUS_PLACEHOLDER);
|
||||
}
|
||||
else if ("*".equals(match)) {
|
||||
// by-zhongjie 对 * 也使用模式匹配
|
||||
patternBuilder.append(DEFAULT_VARIABLE_PATTERN);
|
||||
this.variableNames.add(ANONYMOUS_PLACEHOLDER);
|
||||
}
|
||||
else if (match.startsWith("{") && match.endsWith("}")) {
|
||||
int colonIdx = match.indexOf(':');
|
||||
if (colonIdx == -1) {
|
||||
patternBuilder.append(DEFAULT_VARIABLE_PATTERN);
|
||||
this.variableNames.add(matcher.group(1));
|
||||
}
|
||||
else {
|
||||
String variablePattern = match.substring(colonIdx + 1, match.length() - 1);
|
||||
patternBuilder.append('(');
|
||||
patternBuilder.append(variablePattern);
|
||||
patternBuilder.append(')');
|
||||
String variableName = match.substring(1, colonIdx);
|
||||
this.variableNames.add(variableName);
|
||||
}
|
||||
}
|
||||
end = matcher.end();
|
||||
}
|
||||
patternBuilder.append(quote(pattern, end, pattern.length()));
|
||||
this.pattern = (caseSensitive ? Pattern.compile(patternBuilder.toString()) :
|
||||
Pattern.compile(patternBuilder.toString(), Pattern.CASE_INSENSITIVE));
|
||||
}
|
||||
|
||||
private String quote(String s, int start, int end) {
|
||||
if (start == end) {
|
||||
return "";
|
||||
}
|
||||
return Pattern.quote(s.substring(start, end));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean matchStrings(String str, @Nullable Map<String, String> uriTemplateVariables) {
|
||||
Matcher matcher = this.pattern.matcher(str);
|
||||
if (matcher.matches()) {
|
||||
if (uriTemplateVariables != null) {
|
||||
// SPR-8455
|
||||
if (this.variableNames.size() != matcher.groupCount()) {
|
||||
throw new IllegalArgumentException("The number of capturing groups in the pattern segment " +
|
||||
this.pattern + " does not match the number of URI template variables it defines, " +
|
||||
"which can occur if capturing groups are used in a URI template regex. " +
|
||||
"Use non-capturing groups instead.");
|
||||
}
|
||||
for (int i = 1; i <= matcher.groupCount(); i++) {
|
||||
String name = this.variableNames.get(i - 1);
|
||||
String value = matcher.group(i);
|
||||
|
||||
if (!ANONYMOUS_PLACEHOLDER.equals(name)) {
|
||||
uriTemplateVariables.put(name, value);
|
||||
}
|
||||
// by-zhongjie 对提取到的变量按序号输出
|
||||
uriTemplateVariables.put(ANONYMOUS_PLACEHOLDER + i, value);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
110
fizz-common/src/main/java/we/util/Utils.java
Normal file
110
fizz-common/src/main/java/we/util/Utils.java
Normal file
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
* Copyright (C) 2020 the original author or authors.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package we.util;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalTime;
|
||||
|
||||
/**
|
||||
* @author hongqiaowei
|
||||
*/
|
||||
|
||||
public abstract class Utils {
|
||||
|
||||
public static void addTo(StringBuilder b, String k, char c, boolean v, String separator) {
|
||||
b.append(k).append(c).append(v).append(separator);
|
||||
}
|
||||
|
||||
public static void addTo(StringBuilder b, String k, char c, char v, String separator) {
|
||||
b.append(k).append(c).append(v).append(separator);
|
||||
}
|
||||
|
||||
public static void addTo(StringBuilder b, String k, char c, int v, String separator) {
|
||||
b.append(k).append(c).append(v).append(separator);
|
||||
}
|
||||
|
||||
public static void addTo(StringBuilder b, String k, char c, long v, String separator) {
|
||||
b.append(k).append(c).append(v).append(separator);
|
||||
}
|
||||
|
||||
public static void addTo(StringBuilder b, String k, char c, float v, String separator) {
|
||||
b.append(k).append(c).append(v).append(separator);
|
||||
}
|
||||
|
||||
public static void addTo(StringBuilder b, String k, char c, double v, String separator) {
|
||||
b.append(k).append(c).append(v).append(separator);
|
||||
}
|
||||
|
||||
public static void addTo(StringBuilder b, String k, char c, String v, String separator) {
|
||||
b.append(k).append(c).append(v).append(separator);
|
||||
}
|
||||
|
||||
public static void addTo(StringBuilder b, String k, char c, LocalTime v, String separator) {
|
||||
b.append(k).append(c).append(v).append(separator);
|
||||
}
|
||||
|
||||
public static void addTo(StringBuilder b, String k, char c, LocalDate v, String separator) {
|
||||
b.append(k).append(c).append(v).append(separator);
|
||||
}
|
||||
|
||||
public static void addTo(StringBuilder b, String k, char c, LocalDateTime v, String separator) { b.append(k).append(c).append(v).append(separator); }
|
||||
|
||||
public static void addTo(StringBuilder b, String k, char c, Object v, String separator) {
|
||||
b.append(k).append(c).append(v).append(separator);
|
||||
}
|
||||
|
||||
public static String initials2lowerCase(String s) {
|
||||
if (StringUtils.isBlank(s)) {
|
||||
return s;
|
||||
}
|
||||
int cp = s.codePointAt(0);
|
||||
if (cp < 65 || cp > 90) {
|
||||
return s;
|
||||
}
|
||||
char[] ca = s.toCharArray();
|
||||
ca[0] += 32;
|
||||
return String.valueOf(ca);
|
||||
}
|
||||
|
||||
public static void threadCurrentStack2stringBuilder(StringBuilder b) {
|
||||
StackTraceElement[] stackTraces = Thread.currentThread().getStackTrace();
|
||||
if (stackTraces != null) {
|
||||
for (int i = 0; i < stackTraces.length; i++) {
|
||||
b.append(stackTraces[i]).append(Constants.Symbol.LF);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static RuntimeException runtimeExceptionWithoutStack(String msg) {
|
||||
return new RuntimeException(msg, null, false, false) {
|
||||
};
|
||||
}
|
||||
|
||||
public static Exception exceptionWithoutStack(String msg) {
|
||||
return new Exception(msg, null, false, false) {
|
||||
};
|
||||
}
|
||||
|
||||
public static Throwable throwableWithoutStack(String msg) {
|
||||
return new Throwable(null, null, false, false) {
|
||||
};
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user