Add dict function #333
This commit is contained in:
@@ -65,10 +65,12 @@ public abstract class RedisReactiveConfig {
|
||||
}
|
||||
rcs.setDatabase(redisReactiveProperties.getDatabase());
|
||||
|
||||
GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();
|
||||
poolConfig.setMaxTotal(16);
|
||||
LettucePoolingClientConfiguration ccs = LettucePoolingClientConfiguration.builder()
|
||||
.clientResources(clientResources)
|
||||
.clientOptions(ClientOptions.builder().publishOnScheduler(true).build())
|
||||
.poolConfig(new GenericObjectPoolConfig())
|
||||
.poolConfig(poolConfig)
|
||||
.build();
|
||||
|
||||
return new LettuceConnectionFactory(rcs, ccs);
|
||||
|
||||
@@ -22,6 +22,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
import reactor.core.publisher.Mono;
|
||||
import we.dict.DictService;
|
||||
import we.plugin.auth.ApiConfigService;
|
||||
import we.plugin.auth.ApiConifg2appsService;
|
||||
import we.plugin.auth.AppService;
|
||||
@@ -54,6 +55,9 @@ public class CacheCheckController {
|
||||
@Resource
|
||||
private ApiConifg2appsService apiConifg2appsService;
|
||||
|
||||
@Resource
|
||||
private DictService dictService;
|
||||
|
||||
@GetMapping("/gatewayGroups")
|
||||
public Mono<String> gatewayGroups(ServerWebExchange exchange) {
|
||||
return Mono.just(JacksonUtils.writeValueAsString(gatewayGroupService.gatewayGroupMap));
|
||||
@@ -83,4 +87,9 @@ public class CacheCheckController {
|
||||
public Mono<String> apiConfig2appsConfigs(ServerWebExchange exchange) {
|
||||
return Mono.just(JacksonUtils.writeValueAsString(apiConifg2appsService.getApiConfig2appsMap()));
|
||||
}
|
||||
|
||||
@GetMapping("/dicts")
|
||||
public Mono<String> dicts(ServerWebExchange exchange) {
|
||||
return Mono.just(JacksonUtils.writeValueAsString(dictService.getDictMap()));
|
||||
}
|
||||
}
|
||||
|
||||
119
fizz-core/src/main/java/we/dict/Dict.java
Normal file
119
fizz-core/src/main/java/we/dict/Dict.java
Normal file
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
* 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.dict;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import we.util.JacksonUtils;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author hongqiaowei
|
||||
*/
|
||||
|
||||
public class Dict {
|
||||
|
||||
public static final int BOOLEAN = 1;
|
||||
public static final int STRING = 2;
|
||||
public static final int NUMBER = 3;
|
||||
public static final int JSON = 4;
|
||||
|
||||
public static final int DELETED = 1;
|
||||
|
||||
public int isDeleted = 0;
|
||||
|
||||
public int id;
|
||||
|
||||
public String key;
|
||||
|
||||
public int type;
|
||||
|
||||
public String value;
|
||||
|
||||
public boolean booleanVal;
|
||||
|
||||
public String stringVal;
|
||||
|
||||
public BigDecimal numberVal;
|
||||
|
||||
public int intVal;
|
||||
|
||||
public long longVal;
|
||||
|
||||
public float floatVal;
|
||||
|
||||
public double doubleVal;
|
||||
|
||||
public String jsonVal;
|
||||
|
||||
public Map<String, Object> valMap;
|
||||
|
||||
public List<Object> valList;
|
||||
|
||||
public long create;
|
||||
|
||||
public long update;
|
||||
|
||||
@JsonCreator
|
||||
public Dict(
|
||||
@JsonProperty("isDeleted") int isDeleted,
|
||||
@JsonProperty("id") int id,
|
||||
@JsonProperty("key") String key,
|
||||
@JsonProperty("type") int type,
|
||||
@JsonProperty("value") String value,
|
||||
@JsonProperty("create") long create,
|
||||
@JsonProperty("update") long update
|
||||
) {
|
||||
this.isDeleted = isDeleted;
|
||||
this.id = id;
|
||||
this.key = key;
|
||||
this.type = type;
|
||||
this.value = value;
|
||||
this.create = create;
|
||||
this.update = update;
|
||||
if (type == BOOLEAN) {
|
||||
booleanVal = Boolean.parseBoolean(value);
|
||||
} else if (type == STRING) {
|
||||
stringVal = value;
|
||||
} else if (type == NUMBER) {
|
||||
numberVal = new BigDecimal(value);
|
||||
if (value.indexOf('.') == -1) {
|
||||
intVal = numberVal.intValue();
|
||||
longVal = numberVal.longValue();
|
||||
} else {
|
||||
floatVal = numberVal.floatValue();
|
||||
doubleVal = numberVal.doubleValue();
|
||||
}
|
||||
} else { // JSON
|
||||
jsonVal = value;
|
||||
if (value.startsWith("{")) {
|
||||
valMap = JacksonUtils.readValue(jsonVal, Map.class);
|
||||
} else {
|
||||
valList = JacksonUtils.readValue(jsonVal, List.class);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return JacksonUtils.writeValueAsString(this);
|
||||
}
|
||||
}
|
||||
152
fizz-core/src/main/java/we/dict/DictService.java
Normal file
152
fizz-core/src/main/java/we/dict/DictService.java
Normal file
@@ -0,0 +1,152 @@
|
||||
/*
|
||||
* 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.dict;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.data.redis.core.ReactiveStringRedisTemplate;
|
||||
import org.springframework.stereotype.Service;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
import we.FizzAppContext;
|
||||
import we.config.AggregateRedisConfig;
|
||||
import we.util.JacksonUtils;
|
||||
import we.util.ReactiveResult;
|
||||
import we.util.Result;
|
||||
import we.util.Utils;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import javax.annotation.Resource;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author hongqiaowei
|
||||
*/
|
||||
|
||||
@Service
|
||||
public class DictService {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(DictService.class);
|
||||
|
||||
private Map<String, Dict> dictMap = new HashMap<>(64);
|
||||
|
||||
@Resource(name = AggregateRedisConfig.AGGREGATE_REACTIVE_REDIS_TEMPLATE)
|
||||
private ReactiveStringRedisTemplate rt;
|
||||
|
||||
@PostConstruct
|
||||
public void init() throws Throwable {
|
||||
initDict().subscribe(
|
||||
r -> {
|
||||
if (r.code == ReactiveResult.SUCC) {
|
||||
lsnInitChange().subscribe(
|
||||
res -> {
|
||||
if (res.code == ReactiveResult.FAIL) {
|
||||
log.error(res.toString());
|
||||
if (res.t == null) {
|
||||
throw Utils.runtimeExceptionWithoutStack("lsn dict error");
|
||||
}
|
||||
throw new RuntimeException(res.t);
|
||||
}
|
||||
}
|
||||
);
|
||||
} else {
|
||||
log.error(r.toString());
|
||||
if (r.t == null) {
|
||||
throw Utils.runtimeExceptionWithoutStack("init dict error");
|
||||
}
|
||||
throw new RuntimeException(r.t);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
private Mono<Result<?>> initDict() {
|
||||
Flux<Map.Entry<Object, Object>> dicts = rt.opsForHash().entries("fizz_dict");
|
||||
dicts.collectList()
|
||||
.defaultIfEmpty(Collections.emptyList())
|
||||
.flatMap(
|
||||
es -> {
|
||||
if (FizzAppContext.appContext != null) {
|
||||
for (Map.Entry<Object, Object> e : es) {
|
||||
String json = (String) e.getValue();
|
||||
Dict dict = JacksonUtils.readValue(json, Dict.class);
|
||||
dictMap.put(dict.key, dict);
|
||||
log.info("init dict: {}", dict);
|
||||
}
|
||||
}
|
||||
return Mono.empty();
|
||||
}
|
||||
)
|
||||
.doOnError(
|
||||
t -> {
|
||||
log.error("init dict", t);
|
||||
}
|
||||
)
|
||||
.block();
|
||||
return Mono.just(Result.succ());
|
||||
}
|
||||
|
||||
private Mono<Result<?>> lsnInitChange() {
|
||||
Result<?> result = Result.succ();
|
||||
String channel = "fizz_dict_channel";
|
||||
rt.listenToChannel(channel)
|
||||
.doOnError(
|
||||
t -> {
|
||||
result.code = ReactiveResult.FAIL;
|
||||
result.t = t;
|
||||
log.error("lsn {}", channel, t);
|
||||
}
|
||||
)
|
||||
.doOnSubscribe(
|
||||
s -> {
|
||||
log.info("success to lsn on {}", channel);
|
||||
}
|
||||
)
|
||||
.doOnNext(
|
||||
msg -> {
|
||||
if (FizzAppContext.appContext != null) {
|
||||
String message = msg.getMessage();
|
||||
try {
|
||||
Dict dict = JacksonUtils.readValue(message, Dict.class);
|
||||
if (dict.isDeleted == Dict.DELETED) {
|
||||
dictMap.remove(dict.key);
|
||||
log.info("remove dict {}", dict.key);
|
||||
} else {
|
||||
Dict put = dictMap.put(dict.key, dict);
|
||||
log.info("update dict {} with {}", put, dict);
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
log.error("message: {}", message, t);
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
.subscribe();
|
||||
return Mono.just(result);
|
||||
}
|
||||
|
||||
public Map<String, Dict> getDictMap() {
|
||||
return dictMap;
|
||||
}
|
||||
|
||||
public Dict get(String key) {
|
||||
return dictMap.get(key);
|
||||
}
|
||||
}
|
||||
@@ -96,7 +96,7 @@ public class ApiConfigService {
|
||||
if (res.t == null) {
|
||||
throw Utils.runtimeExceptionWithoutStack("lsn plugin config error");
|
||||
}
|
||||
throw new RuntimeException(r.t);
|
||||
throw new RuntimeException(res.t);
|
||||
}
|
||||
}
|
||||
);
|
||||
@@ -130,7 +130,7 @@ public class ApiConfigService {
|
||||
return Flux.just(e);
|
||||
}
|
||||
Object v = e.getValue();
|
||||
log.info("get api config data: {}", v.toString(), LogService.BIZ_ID, k.toString());
|
||||
log.info("init api config: {}", v.toString(), LogService.BIZ_ID, k.toString());
|
||||
String json = (String) v;
|
||||
try {
|
||||
ApiConfig ac = JacksonUtils.readValue(json, ApiConfig.class);
|
||||
|
||||
@@ -81,7 +81,7 @@ public class AppService {
|
||||
return Flux.just(e);
|
||||
}
|
||||
Object v = e.getValue();
|
||||
log.info(k.toString() + Consts.S.COLON + v.toString(), LogService.BIZ_ID, k.toString());
|
||||
log.info("init app: {}", v.toString(), LogService.BIZ_ID, k.toString());
|
||||
String json = (String) v;
|
||||
try {
|
||||
App app = JacksonUtils.readValue(json, App.class);
|
||||
|
||||
68
fizz-core/src/test/java/we/dict/DictTests.java
Normal file
68
fizz-core/src/test/java/we/dict/DictTests.java
Normal file
@@ -0,0 +1,68 @@
|
||||
package we.dict;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.context.support.GenericApplicationContext;
|
||||
import org.springframework.data.redis.core.ReactiveStringRedisTemplate;
|
||||
import org.springframework.data.redis.core.StringRedisTemplate;
|
||||
import org.springframework.test.context.TestPropertySource;
|
||||
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
|
||||
import we.FizzAppContext;
|
||||
import we.plugin.auth.ApiConfigService;
|
||||
import we.plugin.auth.ApiConfigServiceProperties;
|
||||
import we.redis.RedisProperties;
|
||||
import we.redis.RedisServerConfiguration;
|
||||
import we.redis.RedisTemplateConfiguration;
|
||||
import we.util.JacksonUtils;
|
||||
import we.util.ReflectionUtils;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author hongqiaowei
|
||||
*/
|
||||
|
||||
@TestPropertySource("/application.properties")
|
||||
@SpringJUnitConfig(classes = {RedisProperties.class, RedisTemplateConfiguration.class, RedisServerConfiguration.class})
|
||||
public class DictTests {
|
||||
|
||||
@Resource
|
||||
StringRedisTemplate stringRedisTemplate;
|
||||
|
||||
@Resource
|
||||
ReactiveStringRedisTemplate reactiveStringRedisTemplate;
|
||||
|
||||
DictService dictService;
|
||||
|
||||
@BeforeEach
|
||||
void beforeEach() throws NoSuchFieldException {
|
||||
dictService = new DictService();
|
||||
ReflectionUtils.set(dictService, "rt", reactiveStringRedisTemplate);
|
||||
}
|
||||
|
||||
@Test
|
||||
void constructTest() throws JsonProcessingException {
|
||||
String json = "{\"id\":1,\"key\":\"key\",\"type\":4,\"value\":\"{\\\"a0\\\":\\\"v0\\\",\\\"a1\\\":66}\",\"create\":1633756859538,\"update\":1633756859538,\"isDeleted\":1}";
|
||||
Dict dict = JacksonUtils.readValue(json, Dict.class);
|
||||
// assertEquals(96.12347, dict.numberVal.doubleValue());
|
||||
// assertEquals("96.12347", dict.numberVal.toPlainString());
|
||||
// System.err.println(dict.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
void initTest() throws Throwable {
|
||||
|
||||
FizzAppContext.appContext = new GenericApplicationContext();
|
||||
FizzAppContext.appContext.refresh();
|
||||
|
||||
Map<String, String> dictsMap = new HashMap<>();
|
||||
dictsMap.put("key0", "{\"id\":1,\"key\":\"key0\",\"type\":2,\"value\":\"val0\",\"create\":1633756859538,\"update\":1633756859538,\"isDeleted\":1}");
|
||||
dictsMap.put("key1", "{\"id\":1,\"key\":\"key1\",\"type\":2,\"value\":\"val1\",\"create\":1633756859538,\"update\":1633756859538,\"isDeleted\":1}");
|
||||
stringRedisTemplate.opsForHash().putAll("fizz_dict", dictsMap);
|
||||
|
||||
dictService.init();
|
||||
}
|
||||
}
|
||||
@@ -59,6 +59,5 @@ public class ApiConfigServiceTests {
|
||||
stringRedisTemplate.opsForHash().putAll("fizz_plugin_config", pluginsMap);
|
||||
|
||||
apiConfigService.init();
|
||||
Thread.sleep(2000);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user