diff --git a/fizz-core/src/main/java/we/controller/CacheCheckController.java b/fizz-core/src/main/java/we/controller/CacheCheckController.java index 874c2dd..d5e7ce9 100644 --- a/fizz-core/src/main/java/we/controller/CacheCheckController.java +++ b/fizz-core/src/main/java/we/controller/CacheCheckController.java @@ -22,7 +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.global_resource.GlobalResourceService; import we.plugin.auth.ApiConfigService; import we.plugin.auth.ApiConifg2appsService; import we.plugin.auth.AppService; @@ -56,7 +56,7 @@ public class CacheCheckController { private ApiConifg2appsService apiConifg2appsService; @Resource - private DictService dictService; + private GlobalResourceService globalResourceService; @GetMapping("/gatewayGroups") public Mono gatewayGroups(ServerWebExchange exchange) { @@ -88,8 +88,8 @@ public class CacheCheckController { return Mono.just(JacksonUtils.writeValueAsString(apiConifg2appsService.getApiConfig2appsMap())); } - @GetMapping("/dicts") + @GetMapping("/globalResources") public Mono dicts(ServerWebExchange exchange) { - return Mono.just(JacksonUtils.writeValueAsString(dictService.getDictMap())); + return Mono.just(JacksonUtils.writeValueAsString(globalResourceService.getResourceMap())); } } diff --git a/fizz-core/src/main/java/we/dict/DictService.java b/fizz-core/src/main/java/we/dict/DictService.java deleted file mode 100644 index 9e8018e..0000000 --- a/fizz-core/src/main/java/we/dict/DictService.java +++ /dev/null @@ -1,152 +0,0 @@ -/* - * 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 . - */ - -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 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> initDict() { - Flux> dicts = rt.opsForHash().entries("fizz_dict"); - dicts.collectList() - .defaultIfEmpty(Collections.emptyList()) - .flatMap( - es -> { - if (FizzAppContext.appContext != null) { - for (Map.Entry 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> 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 getDictMap() { - return dictMap; - } - - public Dict get(String key) { - return dictMap.get(key); - } -} diff --git a/fizz-core/src/main/java/we/dict/Dict.java b/fizz-core/src/main/java/we/global_resource/GlobalResource.java similarity index 75% rename from fizz-core/src/main/java/we/dict/Dict.java rename to fizz-core/src/main/java/we/global_resource/GlobalResource.java index 542d468..644b29d 100644 --- a/fizz-core/src/main/java/we/dict/Dict.java +++ b/fizz-core/src/main/java/we/global_resource/GlobalResource.java @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -package we.dict; +package we.global_resource; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; @@ -26,10 +26,11 @@ import java.util.List; import java.util.Map; /** + * just a dict. * @author hongqiaowei */ -public class Dict { +public class GlobalResource { public static final int BOOLEAN = 1; public static final int STRING = 2; @@ -46,7 +47,9 @@ public class Dict { public int type; - public String value; + public String val; + + public Object originalVal; /** for aggregate use mainly */ public boolean booleanVal; @@ -73,7 +76,7 @@ public class Dict { public long update; @JsonCreator - public Dict( + public GlobalResource( @JsonProperty("isDeleted") int isDeleted, @JsonProperty("id") int id, @JsonProperty("key") String key, @@ -87,29 +90,38 @@ public class Dict { this.id = id; this.key = key; this.type = type; - this.value = value; + this.val = value; this.create = create; this.update = update; if (type == BOOLEAN) { - booleanVal = Boolean.parseBoolean(value); + booleanVal = Boolean.parseBoolean(value); + originalVal = booleanVal; + } else if (type == STRING) { - stringVal = value; + stringVal = value; + originalVal = stringVal; + } else if (type == NUMBER) { numberVal = new BigDecimal(value); if (value.indexOf('.') == -1) { - intVal = numberVal.intValue(); - longVal = numberVal.longValue(); + intVal = numberVal.intValue(); + longVal = numberVal.longValue(); + originalVal = longVal; } else { - floatVal = numberVal.floatValue(); - doubleVal = numberVal.doubleValue(); + floatVal = numberVal.floatValue(); + doubleVal = numberVal.doubleValue(); + originalVal = doubleVal; } + } else { // JSON jsonVal = value; if (value.startsWith("{")) { - valMap = JacksonUtils.readValue(jsonVal, Map.class); + valMap = JacksonUtils.readValue(jsonVal, Map.class); + originalVal = valMap; } else { - valList = JacksonUtils.readValue(jsonVal, List.class); + valList = JacksonUtils.readValue(jsonVal, List.class); + originalVal = valList; } } } diff --git a/fizz-core/src/main/java/we/global_resource/GlobalResourceService.java b/fizz-core/src/main/java/we/global_resource/GlobalResourceService.java new file mode 100644 index 0000000..6e2991a --- /dev/null +++ b/fizz-core/src/main/java/we/global_resource/GlobalResourceService.java @@ -0,0 +1,168 @@ +/* + * 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 . + */ + +package we.global_resource; + +import org.noear.snack.ONode; +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.Fizz; +import we.config.AggregateRedisConfig; +import we.fizz.input.PathMapping; +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 GlobalResourceService { + + private static final Logger log = LoggerFactory.getLogger(GlobalResourceService.class); + + public static ONode resNode; + + private Map resourceMap = new HashMap<>(64); + + private Map objectMap = new HashMap<>(64); + + @Resource(name = AggregateRedisConfig.AGGREGATE_REACTIVE_REDIS_TEMPLATE) + private ReactiveStringRedisTemplate rt; + + @PostConstruct + public void init() throws Throwable { + initGlobalResource().subscribe( + r -> { + if (r.code == ReactiveResult.SUCC) { + lsnGlobalResourceChange().subscribe( + res -> { + if (res.code == ReactiveResult.FAIL) { + log.error(res.toString()); + if (res.t == null) { + throw Utils.runtimeExceptionWithoutStack("lsn global resource error"); + } + throw new RuntimeException(res.t); + } + updateResNode(); + } + ); + } else { + log.error(r.toString()); + if (r.t == null) { + throw Utils.runtimeExceptionWithoutStack("init global resource error"); + } + throw new RuntimeException(r.t); + } + } + ); + } + + private void updateResNode() { + resNode = PathMapping.toONode(objectMap); + log.info("new object map: {}", JacksonUtils.writeValueAsString(objectMap)); + } + + private Mono> initGlobalResource() { + Flux> dicts = rt.opsForHash().entries("fizz_global_resource"); + dicts.collectList() + .defaultIfEmpty(Collections.emptyList()) + .flatMap( + es -> { + if (Fizz.context != null) { + for (Map.Entry e : es) { + String json = (String) e.getValue(); + GlobalResource r = JacksonUtils.readValue(json, GlobalResource.class); + resourceMap.put(r.key, r); + objectMap.put(r.key, r.originalVal); + log.info("init global resource: {}", r); + } + } + return Mono.empty(); + } + ) + .doOnError( + t -> { + log.error("init global resource", t); + } + ) + .block(); + return Mono.just(Result.succ()); + } + + private Mono> lsnGlobalResourceChange() { + Result result = Result.succ(); + String channel = "fizz_global_resource_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 (Fizz.context != null) { + String message = msg.getMessage(); + try { + GlobalResource r = JacksonUtils.readValue(message, GlobalResource.class); + if (r.isDeleted == GlobalResource.DELETED) { + resourceMap.remove(r.key); + objectMap.remove(r.key); + log.info("remove global resource {}", r.key); + } else { + GlobalResource put = resourceMap.put(r.key, r); + objectMap.put(r.key, r); + log.info("update global resource {} with {}", put, r); + } + updateResNode(); + } catch (Throwable t) { + log.error("message: {}", message, t); + } + } + } + ) + .subscribe(); + return Mono.just(result); + } + + public Map getResourceMap() { + return resourceMap; + } + + public GlobalResource get(String key) { + return resourceMap.get(key); + } +} diff --git a/fizz-core/src/main/java/we/plugin/FizzPluginFilterChain.java b/fizz-core/src/main/java/we/plugin/FizzPluginFilterChain.java index f3fed7d..5716b6b 100644 --- a/fizz-core/src/main/java/we/plugin/FizzPluginFilterChain.java +++ b/fizz-core/src/main/java/we/plugin/FizzPluginFilterChain.java @@ -86,7 +86,7 @@ public final class FizzPluginFilterChain { } } - @Deprecated + // @Deprecated public static Mono next(ServerWebExchange exchange, List pcs) { Iterator it = pcs.iterator(); Map attris = exchange.getAttributes(); diff --git a/fizz-core/src/main/java/we/proxy/Route.java b/fizz-core/src/main/java/we/proxy/Route.java index 37f6816..064f918 100644 --- a/fizz-core/src/main/java/we/proxy/Route.java +++ b/fizz-core/src/main/java/we/proxy/Route.java @@ -58,8 +58,8 @@ public class Route { public long retryInterval = 0; - public Route type(byte t) { - type = t; + public Route type(int t) { + type = (byte) t; return this; } diff --git a/fizz-core/src/test/java/we/dict/DictTests.java b/fizz-core/src/test/java/we/global_resource/GlobalResourceTests.java similarity index 56% rename from fizz-core/src/test/java/we/dict/DictTests.java rename to fizz-core/src/test/java/we/global_resource/GlobalResourceTests.java index b17aece..ae3b207 100644 --- a/fizz-core/src/test/java/we/dict/DictTests.java +++ b/fizz-core/src/test/java/we/global_resource/GlobalResourceTests.java @@ -1,4 +1,4 @@ -package we.dict; +package we.global_resource; import com.fasterxml.jackson.core.JsonProcessingException; import org.junit.jupiter.api.BeforeEach; @@ -8,9 +8,8 @@ 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.Fizz; 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; @@ -27,7 +26,7 @@ import java.util.Map; @TestPropertySource("/application.properties") @SpringJUnitConfig(classes = {RedisProperties.class, RedisTemplateConfiguration.class, RedisServerConfiguration.class}) -public class DictTests { +public class GlobalResourceTests { @Resource StringRedisTemplate stringRedisTemplate; @@ -35,34 +34,34 @@ public class DictTests { @Resource ReactiveStringRedisTemplate reactiveStringRedisTemplate; - DictService dictService; + GlobalResourceService globalResourceService; @BeforeEach void beforeEach() throws NoSuchFieldException { - dictService = new DictService(); - ReflectionUtils.set(dictService, "rt", reactiveStringRedisTemplate); + globalResourceService = new GlobalResourceService(); + ReflectionUtils.set(globalResourceService, "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()); + GlobalResource globalResource = JacksonUtils.readValue(json, GlobalResource.class); +// assertEquals(96.12347, globalResource.numberVal.doubleValue()); +// assertEquals("96.12347", globalResource.numberVal.toPlainString()); +// System.err.println(globalResource.toString()); } @Test void initTest() throws Throwable { - FizzAppContext.appContext = new GenericApplicationContext(); - FizzAppContext.appContext.refresh(); + Fizz.context = new GenericApplicationContext(); + Fizz.context.refresh(); - Map 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); + Map resourceMap = new HashMap<>(); + resourceMap.put("key0", "{\"id\":1,\"key\":\"key0\",\"type\":2,\"value\":\"val0\",\"create\":1633756859538,\"update\":1633756859538,\"isDeleted\":1}"); + resourceMap.put("key1", "{\"id\":1,\"key\":\"key1\",\"type\":2,\"value\":\"val1\",\"create\":1633756859538,\"update\":1633756859538,\"isDeleted\":1}"); + stringRedisTemplate.opsForHash().putAll("fizz_global_resource", resourceMap); - dictService.init(); + globalResourceService.init(); } }