diff --git a/src/main/java/we/FizzAppContext.java b/src/main/java/we/FizzAppContext.java
new file mode 100644
index 0000000..f9647a7
--- /dev/null
+++ b/src/main/java/we/FizzAppContext.java
@@ -0,0 +1,9 @@
+package we;
+
+import org.springframework.context.ConfigurableApplicationContext;
+
+public class FizzAppContext {
+
+ public static ConfigurableApplicationContext appContext;
+
+}
diff --git a/src/main/java/we/FizzGatewayApplication.java b/src/main/java/we/FizzGatewayApplication.java
index a45c023..591f6d3 100644
--- a/src/main/java/we/FizzGatewayApplication.java
+++ b/src/main/java/we/FizzGatewayApplication.java
@@ -1,20 +1,3 @@
-/*
- * 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;
import com.ctrip.framework.apollo.spring.annotation.EnableApolloConfig;
@@ -24,20 +7,16 @@ import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
import org.springframework.boot.autoconfigure.data.redis.RedisReactiveAutoConfiguration;
import org.springframework.boot.autoconfigure.web.reactive.error.ErrorWebFluxAutoConfiguration;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
-import org.springframework.context.ConfigurableApplicationContext;
-/**
- * @author lancer
- * @author francis
- */
-@SpringBootApplication(exclude = {ErrorWebFluxAutoConfiguration.class, RedisAutoConfiguration.class, RedisReactiveAutoConfiguration.class})
-// @EnableApolloConfig
+@SpringBootApplication(
+ exclude = {ErrorWebFluxAutoConfiguration.class, RedisAutoConfiguration.class, RedisReactiveAutoConfiguration.class},
+ scanBasePackages = {"we", "com.wh"}
+)
+@EnableApolloConfig
@EnableDiscoveryClient
public class FizzGatewayApplication {
- public static ConfigurableApplicationContext appContext;
-
public static void main(String[] args) {
- FizzGatewayApplication.appContext = SpringApplication.run(FizzGatewayApplication.class, args);
+ FizzAppContext.appContext = SpringApplication.run(FizzGatewayApplication.class, args);
}
}
diff --git a/src/main/java/we/apollo/ApolloLog4j2ConfigurationFactory.java b/src/main/java/we/apollo/ApolloLog4j2ConfigurationFactory.java
index f29889f..5c61fc9 100644
--- a/src/main/java/we/apollo/ApolloLog4j2ConfigurationFactory.java
+++ b/src/main/java/we/apollo/ApolloLog4j2ConfigurationFactory.java
@@ -27,8 +27,6 @@ import org.apache.logging.log4j.core.LoggerContext;
import org.apache.logging.log4j.core.config.Configuration;
import org.apache.logging.log4j.core.config.ConfigurationFactory;
import org.apache.logging.log4j.core.config.ConfigurationSource;
-import org.apache.logging.log4j.core.config.Order;
-import org.apache.logging.log4j.core.config.plugins.Plugin;
import org.apache.logging.log4j.core.config.properties.PropertiesConfigurationBuilder;
import java.net.URI;
diff --git a/src/main/java/we/config/AggrWebClientConfig.java b/src/main/java/we/config/AggrWebClientConfig.java
index 6f628f7..f59742a 100644
--- a/src/main/java/we/config/AggrWebClientConfig.java
+++ b/src/main/java/we/config/AggrWebClientConfig.java
@@ -23,8 +23,9 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.web.reactive.function.client.WebClient;
/**
- * @author lancer
+ * @author hongqiaowei
*/
+
@Configuration
@ConfigurationProperties(prefix = AggrWebClientConfig.prefix)
public class AggrWebClientConfig extends WebClientConfig {
diff --git a/src/main/java/we/config/AppConfigProperties.java b/src/main/java/we/config/AppConfigProperties.java
index f5346b6..5e19b1d 100644
--- a/src/main/java/we/config/AppConfigProperties.java
+++ b/src/main/java/we/config/AppConfigProperties.java
@@ -23,6 +23,7 @@ import org.springframework.context.annotation.Configuration;
/**
* @author unknown
*/
+
@Configuration
public class AppConfigProperties {
diff --git a/src/main/java/we/config/ProxyWebClientConfig.java b/src/main/java/we/config/ProxyWebClientConfig.java
index 6a4ee94..a5164c0 100644
--- a/src/main/java/we/config/ProxyWebClientConfig.java
+++ b/src/main/java/we/config/ProxyWebClientConfig.java
@@ -23,8 +23,9 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.web.reactive.function.client.WebClient;
/**
- * @author lancer
+ * @author hongqiaowei
*/
+
@Configuration
@ConfigurationProperties(prefix = ProxyWebClientConfig.prefix)
public class ProxyWebClientConfig extends WebClientConfig {
diff --git a/src/main/java/we/config/RedisReactiveConfig.java b/src/main/java/we/config/RedisReactiveConfig.java
index a6279bc..b38424c 100644
--- a/src/main/java/we/config/RedisReactiveConfig.java
+++ b/src/main/java/we/config/RedisReactiveConfig.java
@@ -30,8 +30,9 @@ import org.springframework.data.redis.connection.lettuce.LettucePoolingClientCon
import org.springframework.data.redis.core.ReactiveStringRedisTemplate;
/**
- * @author lancer
+ * @author hongqiaowei
*/
+
public abstract class RedisReactiveConfig {
protected static final Logger log = LoggerFactory.getLogger(RedisReactiveConfig.class);
diff --git a/src/main/java/we/config/RedisReactiveProperties.java b/src/main/java/we/config/RedisReactiveProperties.java
index bf40def..29cfef3 100644
--- a/src/main/java/we/config/RedisReactiveProperties.java
+++ b/src/main/java/we/config/RedisReactiveProperties.java
@@ -21,14 +21,15 @@ import we.util.Constants;
import we.util.Utils;
/**
- * @author lancer
+ * @author hongqiaowei
*/
+
public abstract class RedisReactiveProperties {
- private String host = "127.0.0.1";
- private int port = 6379;
+ private String host = "127.0.0.1";
+ private int port = 6379;
private String password;
- private int database = 0;
+ private int database = 0;
public String getHost() {
return host;
diff --git a/src/main/java/we/config/SystemConfig.java b/src/main/java/we/config/SystemConfig.java
index c2048d9..0d8bab6 100644
--- a/src/main/java/we/config/SystemConfig.java
+++ b/src/main/java/we/config/SystemConfig.java
@@ -20,11 +20,13 @@ package we.config;
import com.ctrip.framework.apollo.model.ConfigChange;
import com.ctrip.framework.apollo.model.ConfigChangeEvent;
import com.ctrip.framework.apollo.spring.annotation.ApolloConfigChangeListener;
+
import we.plugin.auth.GatewayGroup;
import we.util.Constants;
import we.util.JacksonUtils;
import we.util.NetworkUtils;
import we.util.WebUtils;
+
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -36,8 +38,9 @@ import javax.management.RuntimeErrorException;
import java.util.*;
/**
- * @author lancer
+ * @author hongqiaowei
*/
+
@Configuration
public class SystemConfig {
@@ -51,19 +54,19 @@ public class SystemConfig {
private Set logHeaderSet = new HashSet<>();
- @Value("${gateway-group:}")
- private String gatewayGroup;
-
- private Map> server2gatewayGroupSetMap = new HashMap<>();
-
- private Set currentServerGatewayGroupSet;
+ // @Value("${gateway-group:}")
+ // private String gatewayGroup;
+ //
+ // private Map> server2gatewayGroupSetMap = new HashMap<>();
+ //
+ // private Set currentServerGatewayGroupSet;
@Value("${spring.profiles.active}")
private String profile;
- public Set getCurrentServerGatewayGroupSet() {
- return currentServerGatewayGroupSet;
- }
+ // public Set getCurrentServerGatewayGroupSet() {
+ // return currentServerGatewayGroupSet;
+ // }
public Set getLogHeaderSet() {
return logHeaderSet;
@@ -73,7 +76,7 @@ public class SystemConfig {
public void afterPropertiesSet() {
afterLogResponseBodySet();
afterLogHeadersSet();
- afterGatewayGroupSet();
+ // afterGatewayGroupSet();
}
private void afterLogResponseBodySet() {
@@ -90,42 +93,42 @@ public class SystemConfig {
log.info("log header list: " + logHeaderSet.toString());
}
- private void afterGatewayGroupSet() {
- server2gatewayGroupSetMap.clear();
- if (StringUtils.isNotBlank(gatewayGroup)) {
- Arrays.stream(StringUtils.split(gatewayGroup, ';')).forEach(
- gg -> {
- Character group = Character.valueOf(gg.charAt(0));
- String servers = gg.substring(gg.indexOf(':') + 1);
- Arrays.stream(StringUtils.split(servers, ',')).forEach(
- s -> {
- Set gs = server2gatewayGroupSetMap.get(s);
- if (gs == null) {
- gs = new HashSet<>();
- server2gatewayGroupSetMap.put(s, gs);
- }
- gs.add(group);
- }
- );
- }
- );
- }
- log.info("server 2 gateway group set map: " + JacksonUtils.writeValueAsString(server2gatewayGroupSetMap));
- String serverIp = NetworkUtils.getServerIp();
- currentServerGatewayGroupSet = server2gatewayGroupSetMap.get(serverIp);
- if (currentServerGatewayGroupSet == null) {
- if (Constants.Profiles.DEV.equals(profile) || Constants.Profiles.TEST.equals(profile)) {
- currentServerGatewayGroupSet = new HashSet<>();
- currentServerGatewayGroupSet.add(GatewayGroup.C);
- currentServerGatewayGroupSet.add(GatewayGroup.B);
- currentServerGatewayGroupSet.add(GatewayGroup.T);
- server2gatewayGroupSetMap.put(serverIp, currentServerGatewayGroupSet);
- } else {
- throw new RuntimeException("no gateway group config for " + serverIp);
- }
- }
- log.info("current server: " + serverIp + ", belong to: " + currentServerGatewayGroupSet);
- }
+ // private void afterGatewayGroupSet() {
+ // server2gatewayGroupSetMap.clear();
+ // if (StringUtils.isNotBlank(gatewayGroup)) {
+ // Arrays.stream(StringUtils.split(gatewayGroup, ';')).forEach(
+ // gg -> {
+ // Character group = Character.valueOf(gg.charAt(0));
+ // String servers = gg.substring(gg.indexOf(':') + 1);
+ // Arrays.stream(StringUtils.split(servers, ',')).forEach(
+ // s -> {
+ // Set gs = server2gatewayGroupSetMap.get(s);
+ // if (gs == null) {
+ // gs = new HashSet<>();
+ // server2gatewayGroupSetMap.put(s, gs);
+ // }
+ // gs.add(group);
+ // }
+ // );
+ // }
+ // );
+ // }
+ // log.info("server 2 gateway group set map: " + JacksonUtils.writeValueAsString(server2gatewayGroupSetMap));
+ // String serverIp = NetworkUtils.getServerIp();
+ // currentServerGatewayGroupSet = server2gatewayGroupSetMap.get(serverIp);
+ // if (currentServerGatewayGroupSet == null) {
+ // if (Constants.Profiles.DEV.equals(profile) || Constants.Profiles.TEST.equals(profile)) {
+ // currentServerGatewayGroupSet = new HashSet<>();
+ // currentServerGatewayGroupSet.add(GatewayGroup.C);
+ // currentServerGatewayGroupSet.add(GatewayGroup.B);
+ // currentServerGatewayGroupSet.add(GatewayGroup.T);
+ // server2gatewayGroupSetMap.put(serverIp, currentServerGatewayGroupSet);
+ // } else {
+ // throw new RuntimeException("no gateway group config for " + serverIp);
+ // }
+ // }
+ // log.info("current server: " + serverIp + ", belong to: " + currentServerGatewayGroupSet);
+ // }
@ApolloConfigChangeListener
private void configChangeListter(ConfigChangeEvent cce) {
@@ -142,10 +145,10 @@ public class SystemConfig {
} else if (p.equals("log.headers")) {
logHeaders = nv;
afterLogHeadersSet();
- } else if (p.equals("gateway-group")) {
+ } /*else if (p.equals("gateway-group")) {
gatewayGroup = nv;
afterGatewayGroupSet();
- }
+ }*/
}
);
}
diff --git a/src/main/java/we/config/WebClientConfig.java b/src/main/java/we/config/WebClientConfig.java
index 6e3b84e..21596e0 100644
--- a/src/main/java/we/config/WebClientConfig.java
+++ b/src/main/java/we/config/WebClientConfig.java
@@ -39,31 +39,32 @@ import java.time.Duration;
import java.util.concurrent.TimeUnit;
/**
- * @author lancer
+ * @author hongqiaowei
*/
+
public abstract class WebClientConfig {
protected static final Logger log = LoggerFactory.getLogger(WebClientConfig.class);
private String name;
- private int maxConnections = 2_000;
+ private int maxConnections = 2_000;
- private Duration maxIdleTime = Duration.ofMillis(40_000);
+ private Duration maxIdleTime = Duration.ofMillis(40_000);
private Duration pendingAcquireTimeout = Duration.ofMillis(6_000);
- private long connReadTimeout = 20_000;
+ private long connReadTimeout = 20_000;
- private long connWriteTimeout = 20_000;
+ private long connWriteTimeout = 20_000;
- private int chConnTimeout = 20_000;
+ private int chConnTimeout = 20_000;
- private boolean chTcpNodelay = true;
+ private boolean chTcpNodelay = true;
- private boolean chSoKeepAlive = true;
+ private boolean chSoKeepAlive = true;
- private boolean compress = false;
+ private boolean compress = false;
public String getName() {
return name;
@@ -148,7 +149,9 @@ public abstract class WebClientConfig {
private ConnectionProvider getConnectionProvider() {
String cpName = name + "-cp";
ConnectionProvider cp = ConnectionProvider.builder(cpName).maxConnections(maxConnections)
- .pendingAcquireTimeout(pendingAcquireTimeout).maxIdleTime(maxIdleTime).build();
+ .pendingAcquireTimeout(pendingAcquireTimeout)
+ .maxIdleTime(maxIdleTime)
+ .build();
log.info(cpName + ' ' + cp);
return cp;
}
diff --git a/src/main/java/we/config/WebFluxConfig.java b/src/main/java/we/config/WebFluxConfig.java
index ba7c8af..52951af 100644
--- a/src/main/java/we/config/WebFluxConfig.java
+++ b/src/main/java/we/config/WebFluxConfig.java
@@ -40,8 +40,9 @@ import reactor.netty.resources.LoopResources;
import java.time.Duration;
/**
- * @author lancer
+ * @author hongqiaowei
*/
+
@Configuration
@ConfigurationProperties(prefix = "server")
@EnableConfigurationProperties(ServerProperties.class)
@@ -124,9 +125,9 @@ public class WebFluxConfig {
// .channel(NioServerSocketChannel.class)
.option(ChannelOption.ALLOCATOR, UnpooledByteBufAllocator.DEFAULT)
// .option(ChannelOption.SO_BACKLOG, 8192)
- .childOption(ChannelOption.ALLOCATOR, UnpooledByteBufAllocator.DEFAULT)
+ .childOption(ChannelOption.ALLOCATOR, UnpooledByteBufAllocator.DEFAULT)
.childOption(ChannelOption.SO_KEEPALIVE, true)
- .childOption(ChannelOption.TCP_NODELAY, true)
+ .childOption(ChannelOption.TCP_NODELAY, true)
)
)
);
diff --git a/src/main/java/we/controller/ConfigController.java b/src/main/java/we/controller/ConfigController.java
index b787340..fe0e39d 100644
--- a/src/main/java/we/controller/ConfigController.java
+++ b/src/main/java/we/controller/ConfigController.java
@@ -17,13 +17,13 @@
package we.controller;
-import we.fizz.ConfigLoader;
-import we.util.ScriptUtils;
import org.apache.commons.io.FileUtils;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
+import we.fizz.ConfigLoader;
+import we.util.ScriptUtils;
import javax.annotation.Resource;
import java.io.File;
@@ -32,6 +32,7 @@ import java.nio.charset.StandardCharsets;
/**
* @author unknown
*/
+
@RestController
@RequestMapping(value = "/config")
public class ConfigController {
@@ -45,7 +46,7 @@ public class ConfigController {
return Mono.just("ok");
}
- // add by lancer
+ // add by hongqiaowei
@PostMapping(value = "/fullUpdCommonJs", consumes = MediaType.TEXT_PLAIN_VALUE)
public Mono fullUpdCommonJs(ServerWebExchange exchange, @RequestBody String js) {
try {
diff --git a/src/main/java/we/controller/HealthController.java b/src/main/java/we/controller/HealthController.java
index f9e3207..8e1c3ef 100644
--- a/src/main/java/we/controller/HealthController.java
+++ b/src/main/java/we/controller/HealthController.java
@@ -18,50 +18,64 @@
package we.controller;
import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
-import we.plugin.auth.ApiConfigService;
-import we.plugin.auth.AppService;
-import we.util.JacksonUtils;
+import com.alibaba.fastjson.JSON;
import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
+import we.plugin.auth.ApiConfigService;
+import we.plugin.auth.AppService;
+import we.plugin.auth.GatewayGroupService;
+import we.util.JacksonUtils;
import javax.annotation.Resource;
/**
* @author unknown
*/
+
@RestController
public class HealthController {
+ @Resource
+ private GatewayGroupService gatewayGroupService;
+
@Resource
private AppService appService;
@Resource
private ApiConfigService apiConfigService;
- @GetMapping("/time")
- public Mono time(ServerWebExchange exchange) throws Exception{
- Date d = new Date();
- return Mono.just("Time: " + d.toString());
- }
-
- // add by lancer
+ // add by hongqiaowei
@GetMapping("/sysgc")
public Mono sysgc(ServerWebExchange exchange) throws Exception {
System.gc();
return Mono.just("sysgc done");
}
+ @GetMapping("/gatewayGroups")
+ public Mono gatewayGroups(ServerWebExchange exchange) throws Exception {
+ return Mono.just(JacksonUtils.writeValueAsString(gatewayGroupService.gatewayGroupMap));
+ }
+
+ @GetMapping("/currentGatewayGroups")
+ public Mono currentGatewayGroups(ServerWebExchange exchange) throws Exception {
+ return Mono.just(JacksonUtils.writeValueAsString(gatewayGroupService.currentGatewayGroupSet));
+ }
+
@GetMapping("/apps")
public Mono apps(ServerWebExchange exchange) throws Exception {
return Mono.just(JacksonUtils.writeValueAsString(appService.getAppMap()));
}
- @GetMapping("/apiConfigs")
+ @GetMapping("/serviceConfigs")
public Mono apiConfigs(ServerWebExchange exchange) throws Exception {
- return Mono.just(JacksonUtils.writeValueAsString(apiConfigService.getApp2gatewayGroupMap()));
+ return Mono.just(JacksonUtils.writeValueAsString(apiConfigService.serviceConfigMap));
}
}
diff --git a/src/main/java/we/controller/ManagerConfigController.java b/src/main/java/we/controller/ManagerConfigController.java
index b3d83ca..92fa2f3 100644
--- a/src/main/java/we/controller/ManagerConfigController.java
+++ b/src/main/java/we/controller/ManagerConfigController.java
@@ -17,12 +17,6 @@
package we.controller;
-import we.controller.req.BaseManagerConfigReq;
-import we.controller.req.GetConfigStrReq;
-import we.controller.req.GetConfigReq;
-import we.controller.resp.ConfigStrResp;
-import we.controller.resp.ConfigResp;
-import we.fizz.ConfigLoader;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PostMapping;
@@ -30,6 +24,12 @@ import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Mono;
+import we.controller.req.BaseManagerConfigReq;
+import we.controller.req.GetConfigReq;
+import we.controller.req.GetConfigStrReq;
+import we.controller.resp.ConfigResp;
+import we.controller.resp.ConfigStrResp;
+import we.fizz.ConfigLoader;
import javax.annotation.Resource;
import javax.validation.Valid;
diff --git a/src/main/java/we/controller/resp/ConfigResp.java b/src/main/java/we/controller/resp/ConfigResp.java
index 49d5a84..d494175 100644
--- a/src/main/java/we/controller/resp/ConfigResp.java
+++ b/src/main/java/we/controller/resp/ConfigResp.java
@@ -17,12 +17,12 @@
package we.controller.resp;
-import we.fizz.ConfigLoader;
-
import java.io.Serializable;
import java.util.List;
import java.util.Objects;
+import we.fizz.ConfigLoader;
+
/**
* 聚合配置响应实体类
* @author zhongjie
diff --git a/src/main/java/we/filter/CorsFilterConfig.java b/src/main/java/we/filter/CorsFilterConfig.java
index ebf4e2b..006839d 100644
--- a/src/main/java/we/filter/CorsFilterConfig.java
+++ b/src/main/java/we/filter/CorsFilterConfig.java
@@ -17,7 +17,6 @@
package we.filter;
-import we.config.SystemConfig;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
@@ -27,11 +26,14 @@ import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.reactive.CorsWebFilter;
import org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource;
+import we.config.SystemConfig;
+
import javax.annotation.Resource;
/**
- * @author lancer
+ * @author hongqiaowei
*/
+
@Configuration
public class CorsFilterConfig {
diff --git a/src/main/java/we/filter/FilterExceptionHandlerConfig.java b/src/main/java/we/filter/FilterExceptionHandlerConfig.java
index 1bdca11..b17bb1c 100644
--- a/src/main/java/we/filter/FilterExceptionHandlerConfig.java
+++ b/src/main/java/we/filter/FilterExceptionHandlerConfig.java
@@ -17,8 +17,6 @@
package we.filter;
-import we.exception.StopAndResponseException;
-import we.util.WebUtils;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
@@ -29,10 +27,13 @@ import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebExceptionHandler;
import reactor.core.publisher.Mono;
+import we.exception.StopAndResponseException;
+import we.util.WebUtils;
/**
- * @author lancer
+ * @author hongqiaowei
*/
+
@Configuration
public class FilterExceptionHandlerConfig {
diff --git a/src/main/java/we/filter/FilterResult.java b/src/main/java/we/filter/FilterResult.java
index 67a0a75..eb6b5a9 100644
--- a/src/main/java/we/filter/FilterResult.java
+++ b/src/main/java/we/filter/FilterResult.java
@@ -20,8 +20,9 @@ package we.filter;
import java.util.Map;
/**
- * @author lancer
+ * @author hongqiaowei
*/
+
public class FilterResult {
public String id;
diff --git a/src/main/java/we/filter/FizzGatewayFilter.java b/src/main/java/we/filter/FizzGatewayFilter.java
index cec27a2..27873f5 100644
--- a/src/main/java/we/filter/FizzGatewayFilter.java
+++ b/src/main/java/we/filter/FizzGatewayFilter.java
@@ -38,24 +38,24 @@ import org.springframework.web.server.WebFilter;
import org.springframework.web.server.WebFilterChain;
import com.alibaba.fastjson.JSON;
-import we.flume.clients.log4j2appender.LogService;
+
+import io.netty.buffer.UnpooledByteBufAllocator;
+import reactor.core.publisher.Flux;
+import reactor.core.publisher.Mono;
+import reactor.core.scheduler.Schedulers;
import we.constants.CommonConstants;
import we.fizz.AggregateResource;
import we.fizz.AggregateResult;
import we.fizz.ConfigLoader;
import we.fizz.Pipeline;
import we.fizz.input.Input;
+import we.flume.clients.log4j2appender.LogService;
import we.util.Constants;
import we.util.MapUtil;
import we.util.WebUtils;
-import io.netty.buffer.UnpooledByteBufAllocator;
-import reactor.core.publisher.Flux;
-import reactor.core.publisher.Mono;
-import reactor.core.scheduler.Schedulers;
-
/**
- * @author lancer
+ * @author francis
*/
@Component
@Order(2)
diff --git a/src/main/java/we/filter/FizzLogFilter.java b/src/main/java/we/filter/FizzLogFilter.java
index 6653ba5..3a1f054 100644
--- a/src/main/java/we/filter/FizzLogFilter.java
+++ b/src/main/java/we/filter/FizzLogFilter.java
@@ -17,8 +17,6 @@
package we.filter;
-import we.flume.clients.log4j2appender.LogService;
-import we.util.WebUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.Order;
@@ -27,10 +25,14 @@ import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilter;
import org.springframework.web.server.WebFilterChain;
import reactor.core.publisher.Mono;
+import we.flume.clients.log4j2appender.LogService;
+import we.util.ThreadContext;
+import we.util.WebUtils;
/**
- * @author lancer
+ * @author hongqiaowei
*/
+
@Component
@Order(0)
public class FizzLogFilter implements WebFilter {
@@ -46,7 +48,7 @@ public class FizzLogFilter implements WebFilter {
long startTime = System.currentTimeMillis();
return chain.filter(exchange).doAfterTerminate(
() -> {
- StringBuilder b = new StringBuilder(160);
+ StringBuilder b = ThreadContext.getStringBuilder();
WebUtils.request2stringBuilder(exchange, b);
b.append(resp).append(exchange.getResponse().getStatusCode())
.append(in) .append(System.currentTimeMillis() - startTime);
diff --git a/src/main/java/we/filter/PreFilter.java b/src/main/java/we/filter/PreFilter.java
index 01d2615..1e2241e 100644
--- a/src/main/java/we/filter/PreFilter.java
+++ b/src/main/java/we/filter/PreFilter.java
@@ -17,15 +17,6 @@
package we.filter;
-import we.config.SystemConfig;
-import we.plugin.FixedPluginFilter;
-import we.plugin.PluginConfig;
-import we.plugin.PluginFilter;
-import we.plugin.auth.*;
-import we.plugin.stat.StatPluginFilter;
-import we.util.Constants;
-import we.util.ReactorUtils;
-import we.util.WebUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -37,15 +28,24 @@ import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilterChain;
import reactor.core.publisher.Mono;
+import we.plugin.FixedPluginFilter;
+import we.plugin.PluginConfig;
+import we.plugin.PluginFilter;
+import we.plugin.auth.ApiConfig;
+import we.plugin.auth.ApiConfigService;
+import we.plugin.auth.AuthPluginFilter;
+import we.plugin.stat.StatPluginFilter;
+import we.util.ReactorUtils;
+import we.util.WebUtils;
-import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.*;
import java.util.function.Function;
/**
- * @author lancer
+ * @author hongqiaowei
*/
+
@Component(PreFilter.PRE_FILTER)
@Order(1)
public class PreFilter extends ProxyAggrFilter {
@@ -62,25 +62,12 @@ public class PreFilter extends ProxyAggrFilter {
@Value("${b-services:x}")
private Set bServices = new HashSet<>();
- @Resource
- private SystemConfig systemConfig;
-
@Resource(name = StatPluginFilter.STAT_PLUGIN_FILTER)
private StatPluginFilter statPluginFilter;
@Resource(name = AuthPluginFilter.AUTH_PLUGIN_FILTER)
private AuthPluginFilter authPluginFilter;
- private char currentGatewayGroup;
- @PostConstruct
- public void setCurrentGatewayGroup() {
- for (Character gg : systemConfig.getCurrentServerGatewayGroupSet()) {
- currentGatewayGroup = gg.charValue();
- log.info("current gateway group is " + currentGatewayGroup);
- break;
- }
- }
-
@Override
public Mono doFilter(ServerWebExchange exchange, WebFilterChain chain) {
@@ -88,24 +75,11 @@ public class PreFilter extends ProxyAggrFilter {
Map appendHdrs = new HashMap<>(6, 1.0f);
Map eas = exchange.getAttributes(); eas.put(WebUtils.FILTER_CONTEXT, fc);
eas.put(WebUtils.APPEND_HEADERS, appendHdrs);
- eas.put(WebUtils.CGG, currentGatewayGroup);
String app = WebUtils.getHeaderValue(exchange, WebUtils.APP_HEADER);
- if (StringUtils.isBlank(app)) {
- if (Constants.Profiles.DEV.equals(profile) || Constants.Profiles.TEST.equals(profile)) {
- String service = WebUtils.getServiceId(exchange);
- if (bServices.contains(service)) {
- app = App.TO_B;
- } else {
- app = App.TO_C;
- }
- } else if (currentGatewayGroup == GatewayGroup.B) {
- app = App.TO_B;
- } else {
- app = App.TO_C;
- }
+ if (StringUtils.isNotBlank(app)) {
+ eas.put(WebUtils.APP_HEADER, app);
}
- eas.put(WebUtils.APP_HEADER, app);
Mono vm = statPluginFilter.filter(exchange, null, null);
return chain(exchange, vm, authPluginFilter).defaultIfEmpty(ReactorUtils.NULL)
@@ -120,11 +94,7 @@ public class PreFilter extends ProxyAggrFilter {
if (ac.pluginConfigs == null || ac.pluginConfigs.isEmpty()) {
return m.flatMap(func(exchange, chain));
} else {
- return m.flatMap(
- e -> {
- return executeManagedPluginFilters(exchange, ac.pluginConfigs);
- }
- )
+ return m.flatMap(e -> {return executeManagedPluginFilters(exchange, ac.pluginConfigs);})
.defaultIfEmpty(ReactorUtils.NULL).flatMap(func(exchange, chain));
}
} else if (authRes == ApiConfigService.Access.YES) {
diff --git a/src/main/java/we/filter/ProxyAggrFilter.java b/src/main/java/we/filter/ProxyAggrFilter.java
index a7a90c1..99529ca 100644
--- a/src/main/java/we/filter/ProxyAggrFilter.java
+++ b/src/main/java/we/filter/ProxyAggrFilter.java
@@ -17,15 +17,16 @@
package we.filter;
-import we.util.WebUtils;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilter;
import org.springframework.web.server.WebFilterChain;
import reactor.core.publisher.Mono;
+import we.util.WebUtils;
/**
- * @author lancer
+ * @author hongqiaowei
*/
+
// TODO 类名调整
public abstract class ProxyAggrFilter implements WebFilter {
diff --git a/src/main/java/we/filter/RouteFilter.java b/src/main/java/we/filter/RouteFilter.java
index 7fe853e..1c8581f 100644
--- a/src/main/java/we/filter/RouteFilter.java
+++ b/src/main/java/we/filter/RouteFilter.java
@@ -17,11 +17,6 @@
package we.filter;
-import we.flume.clients.log4j2appender.LogService;
-import we.legacy.RespEntity;
-import we.proxy.FizzWebClient;
-import we.util.ThreadContext;
-import we.util.WebUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.Ordered;
@@ -36,14 +31,23 @@ import org.springframework.web.reactive.function.client.ClientResponse;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilterChain;
import reactor.core.publisher.Mono;
+import we.flume.clients.log4j2appender.LogService;
+import we.legacy.RespEntity;
+import we.plugin.auth.ApiConfig;
+import we.plugin.auth.AuthPluginFilter;
+import we.proxy.FizzWebClient;
+import we.util.ThreadContext;
+import we.util.WebUtils;
import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
+import java.util.function.Function;
/**
- * @author lancer
+ * @author hongqiaowei
*/
+
@Component
@Order(Ordered.LOWEST_PRECEDENCE)
public class RouteFilter extends ProxyAggrFilter {
@@ -79,7 +83,6 @@ public class RouteFilter extends ProxyAggrFilter {
private Mono doFilter0(ServerWebExchange exchange, WebFilterChain chain) {
ServerHttpRequest clientReq = exchange.getRequest();
- String rid = clientReq.getId();
HttpHeaders hdrs = new HttpHeaders();
clientReq.getHeaders().forEach(
(h, vs) -> {
@@ -101,37 +104,65 @@ public class RouteFilter extends ProxyAggrFilter {
);
}
- return fizzWebClient.proxySend2service(rid, clientReq.getMethod(), WebUtils.getServiceId(exchange), WebUtils.getRelativeUri(exchange), hdrs, exchange.getRequest().getBody()).flatMap(
- remoteResp -> {
- ServerHttpResponse clientResp = exchange.getResponse();
- clientResp.setStatusCode(remoteResp.statusCode());
- HttpHeaders clientRespHeaders = clientResp.getHeaders();
- HttpHeaders remoteRespHeaders = remoteResp.headers().asHttpHeaders();
- remoteRespHeaders.entrySet().forEach(
- h -> {
- String k = h.getKey();
- if (clientRespHeaders.containsKey(k)) {
- if (k.equals(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN) || k.equals(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS)
- || k.equals(HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS) || k.equals(HttpHeaders.ACCESS_CONTROL_MAX_AGE)) {
- } else {
- clientRespHeaders.put(k, h.getValue());
- }
- } else {
- clientRespHeaders.put(k, h.getValue());
- }
- }
- );
- if (log.isDebugEnabled()) {
- StringBuilder b = ThreadContext.getStringBuilder();
- WebUtils.response2stringBuilder(rid, remoteResp, b);
- log.debug(b.toString(), LogService.BIZ_ID, rid);
- }
- return clientResp.writeWith(remoteResp.body(BodyExtractors.toDataBuffers()))
- .doOnError(throwable -> cleanup(remoteResp)).doOnCancel(() -> cleanup(remoteResp));
- }
- );
+ ApiConfig ac = null;
+ Object authRes = WebUtils.getFilterResultDataItem(exchange, AuthPluginFilter.AUTH_PLUGIN_FILTER, AuthPluginFilter.RESULT);
+ if (authRes instanceof ApiConfig) {
+ ac = (ApiConfig) authRes;
+ }
+
+ String relativeUri = WebUtils.getRelativeUri(exchange);
+ if (ac == null || ac.proxyMode == ApiConfig.DIRECT_PROXY_MODE) {
+ return send(exchange, WebUtils.getServiceId(exchange), relativeUri, hdrs);
+ } else {
+ String realUri;
+ String backendUrl = ac.getNextBackendUrl();
+ int acpLen = ac.path.length();
+ if (acpLen == 1) {
+ realUri = backendUrl + relativeUri;
+ } else {
+ realUri = backendUrl + relativeUri.substring(acpLen);
+ }
+ relativeUri.substring(acpLen);
+ return fizzWebClient.send(clientReq.getId(), clientReq.getMethod(), realUri, hdrs, clientReq.getBody()).flatMap(genServerResponse(exchange));
+ }
}
-
+
+ private Mono send(ServerWebExchange exchange, String service, String relativeUri, HttpHeaders hdrs) {
+ ServerHttpRequest clientReq = exchange.getRequest();
+ return fizzWebClient.proxySend2service(clientReq.getId(), clientReq.getMethod(), service, relativeUri, hdrs, clientReq.getBody()).flatMap(genServerResponse(exchange));
+ }
+
+ private Function> genServerResponse(ServerWebExchange exchange) {
+ return remoteResp -> {
+ ServerHttpResponse clientResp = exchange.getResponse();
+ clientResp.setStatusCode(remoteResp.statusCode());
+ HttpHeaders clientRespHeaders = clientResp.getHeaders();
+ HttpHeaders remoteRespHeaders = remoteResp.headers().asHttpHeaders();
+ remoteRespHeaders.entrySet().forEach(
+ h -> {
+ String k = h.getKey();
+ if (clientRespHeaders.containsKey(k)) {
+ if (k.equals(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN) || k.equals(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS)
+ || k.equals(HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS) || k.equals(HttpHeaders.ACCESS_CONTROL_MAX_AGE)) {
+ } else {
+ clientRespHeaders.put(k, h.getValue());
+ }
+ } else {
+ clientRespHeaders.put(k, h.getValue());
+ }
+ }
+ );
+ if (log.isDebugEnabled()) {
+ StringBuilder b = ThreadContext.getStringBuilder();
+ String rid = exchange.getRequest().getId();
+ WebUtils.response2stringBuilder(rid, remoteResp, b);
+ log.debug(b.toString(), LogService.BIZ_ID, rid);
+ }
+ return clientResp.writeWith(remoteResp.body(BodyExtractors.toDataBuffers()))
+ .doOnError(throwable -> cleanup(remoteResp)).doOnCancel(() -> cleanup(remoteResp));
+ };
+ }
+
private void cleanup(ClientResponse clientResponse) {
if (clientResponse != null) {
clientResponse.bodyToMono(Void.class).subscribe();
diff --git a/src/main/java/we/fizz/ConfigLoader.java b/src/main/java/we/fizz/ConfigLoader.java
index df7146f..e8a661c 100644
--- a/src/main/java/we/fizz/ConfigLoader.java
+++ b/src/main/java/we/fizz/ConfigLoader.java
@@ -19,10 +19,12 @@ package we.fizz;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
+
import we.config.AppConfigProperties;
import we.fizz.input.ClientInputConfig;
import we.fizz.input.Input;
import we.fizz.input.InputType;
+
import org.apache.commons.io.FileUtils;
import org.noear.snack.ONode;
import org.springframework.beans.factory.annotation.Value;
@@ -32,6 +34,10 @@ import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import javax.annotation.Resource;
+
+import static we.listener.AggregateRedisConfig.AGGREGATE_REACTIVE_REDIS_TEMPLATE;
+import static we.util.Constants.Symbol.FORWARD_SLASH;
+
import java.io.File;
import java.io.IOException;
import java.io.Serializable;
@@ -41,9 +47,6 @@ import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
-
-import static we.listener.AggregateRedisConfig.AGGREGATE_REACTIVE_REDIS_TEMPLATE;
-import static we.util.Constants.Symbol.FORWARD_SLASH;
/**
*
* @author francis
@@ -56,7 +59,7 @@ public class ConfigLoader {
* 聚合配置存放Hash的Key
*/
private static final String AGGREGATE_HASH_KEY = "fizz_aggregate_config";
-
+
private static Map aggregateResources = null;
private static Map resourceKey2ConfigInfoMap = null;
private static Map aggregateId2ResourceKeyMap = null;
@@ -80,8 +83,13 @@ public class ConfigLoader {
clientInputConfig.setHeaders(cfgNode.select("$.headers").toObject(Map.class));
clientInputConfig.setMethod(cfgNode.select("$.method").getString());
clientInputConfig.setPath(cfgNode.select("$.path").getString());
- if(cfgNode.select("$.debug") != null) {
- clientInputConfig.setDebug(cfgNode.select("$.debug").getBoolean());
+ if(clientInputConfig.getPath().startsWith(TEST_PATH_PREFIX)) {
+ // always enable debug for testing
+ clientInputConfig.setDebug(true);
+ }else {
+ if(cfgNode.select("$.debug") != null) {
+ clientInputConfig.setDebug(cfgNode.select("$.debug").getBoolean());
+ }
}
clientInputConfig.setType(InputType.valueOf(cfgNode.select("$.type").getString()));
clientInputConfig.setLangDef(cfgNode.select("$.langDef").toObject(Map.class));
diff --git a/src/main/java/we/fizz/Pipeline.java b/src/main/java/we/fizz/Pipeline.java
index 9b5d8ba..87baf7c 100644
--- a/src/main/java/we/fizz/Pipeline.java
+++ b/src/main/java/we/fizz/Pipeline.java
@@ -25,11 +25,7 @@ import java.util.Map;
import javax.script.ScriptException;
-import we.fizz.input.ClientInputConfig;
-import we.fizz.input.InputConfig;
import we.schema.util.I18nUtils;
-import we.util.JsonSchemaUtils;
-
import org.noear.snack.ONode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -37,14 +33,17 @@ import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import com.alibaba.fastjson.JSON;
-import we.flume.clients.log4j2appender.LogService;
-import we.fizz.input.Input;
-import we.fizz.input.PathMapping;
-import we.fizz.input.ScriptHelper;
-import we.util.MapUtil;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
+import we.fizz.input.ClientInputConfig;
+import we.fizz.input.Input;
+import we.fizz.input.InputConfig;
+import we.fizz.input.PathMapping;
+import we.fizz.input.ScriptHelper;
+import we.flume.clients.log4j2appender.LogService;
+import we.util.JsonSchemaUtils;
+import we.util.MapUtil;
/**
*
diff --git a/src/main/java/we/fizz/Step.java b/src/main/java/we/fizz/Step.java
index 9a44f41..93d0bd1 100644
--- a/src/main/java/we/fizz/Step.java
+++ b/src/main/java/we/fizz/Step.java
@@ -30,14 +30,14 @@ import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.client.WebClient;
import com.alibaba.fastjson.JSON;
+
+import reactor.core.publisher.Mono;
import we.fizz.input.Input;
import we.fizz.input.InputConfig;
import we.fizz.input.InputContext;
import we.fizz.input.InputFactory;
import we.fizz.input.InputType;
-import reactor.core.publisher.Mono;
-
/**
*
* @author linwaiwai
diff --git a/src/main/java/we/fizz/input/Input.java b/src/main/java/we/fizz/input/Input.java
index 9cd571c..0904b68 100644
--- a/src/main/java/we/fizz/input/Input.java
+++ b/src/main/java/we/fizz/input/Input.java
@@ -19,11 +19,10 @@ package we.fizz.input;
import java.util.HashMap;
import java.util.Map;
+import reactor.core.publisher.Mono;
import we.fizz.StepContext;
import we.fizz.StepResponse;
-import reactor.core.publisher.Mono;
-
/**
*
* @author linwaiwai
diff --git a/src/main/java/we/fizz/input/RequestInput.java b/src/main/java/we/fizz/input/RequestInput.java
index e5ebe79..0494390 100644
--- a/src/main/java/we/fizz/input/RequestInput.java
+++ b/src/main/java/we/fizz/input/RequestInput.java
@@ -34,16 +34,16 @@ import org.springframework.web.util.UriComponents;
import org.springframework.web.util.UriComponentsBuilder;
import com.alibaba.fastjson.JSON;
-import we.flume.clients.log4j2appender.LogService;
-import we.FizzGatewayApplication;
+
+import reactor.core.publisher.Mono;
+import we.FizzAppContext;
import we.constants.CommonConstants;
import we.fizz.StepContext;
import we.fizz.StepResponse;
+import we.flume.clients.log4j2appender.LogService;
import we.proxy.FizzWebClient;
import we.util.MapUtil;
-import reactor.core.publisher.Mono;
-
/**
*
* @author linwaiwai
@@ -222,7 +222,7 @@ public class RequestInput extends Input {
String aggrPath = (String)inputContext.getStepContext().getInputReqAttr("path");
String aggrService = aggrPath.split("\\/")[2];
- FizzWebClient client = FizzGatewayApplication.appContext.getBean(FizzWebClient.class);
+ FizzWebClient client = FizzAppContext.appContext.getBean(FizzWebClient.class);
return client.aggrSend(aggrService, aggrMethod, aggrPath, null, method, url,
MapUtil.toHttpHeaders(headers), request.get("body"), (long)timeout);
}
diff --git a/src/main/java/we/fizz/input/ScriptHelper.java b/src/main/java/we/fizz/input/ScriptHelper.java
index 15e42cb..a6644d9 100644
--- a/src/main/java/we/fizz/input/ScriptHelper.java
+++ b/src/main/java/we/fizz/input/ScriptHelper.java
@@ -30,6 +30,7 @@ import org.slf4j.LoggerFactory;
import com.alibaba.fastjson.JSON;
import com.ctrip.framework.apollo.core.utils.StringUtils;
+
import we.constants.CommonConstants;
import we.exception.StopAndResponseException;
import we.fizz.StepContext;
diff --git a/src/main/java/we/flume/clients/log4j2appender/LogService.java b/src/main/java/we/flume/clients/log4j2appender/LogService.java
index 0aaf5cf..5ae538d 100644
--- a/src/main/java/we/flume/clients/log4j2appender/LogService.java
+++ b/src/main/java/we/flume/clients/log4j2appender/LogService.java
@@ -1,33 +1,31 @@
-/*
- * 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.flume.clients.log4j2appender;
-/**
- * @author lancer
- */
public enum LogService {
- BIZ_ID, HANDLE_STGY;
+ BIZ_ID, HANDLE_STGY, APP;
+
+ public static void cleanBizId() {
+ setBizId(null);
+ }
+
+ public static Object getBizId() {
+ return ThreadContext.get(Constants.BIZ_ID);
+ }
public static void setBizId(Object bizId) {
+ ThreadContext.set(Constants.BIZ_ID, bizId);
}
public static String toKF(String topic) {
return topic;
}
+
+ public static String toESaKF(String topic) {
+ return Constants.AND + topic;
+ }
+
+ public static class Constants {
+ static final String BIZ_ID = "bizId";
+ static final char AND = '&';
+ }
}
diff --git a/src/main/java/we/flume/clients/log4j2appender/ThreadContext.java b/src/main/java/we/flume/clients/log4j2appender/ThreadContext.java
new file mode 100644
index 0000000..856d58d
--- /dev/null
+++ b/src/main/java/we/flume/clients/log4j2appender/ThreadContext.java
@@ -0,0 +1,76 @@
+package we.flume.clients.log4j2appender;
+
+import java.text.SimpleDateFormat;
+import java.util.HashMap;
+import java.util.Map;
+
+/** for internal use */
+public abstract class ThreadContext {
+
+ private static ThreadLocal