diff --git a/doc/docs/files/90100_常见问题.md b/doc/docs/files/90100_常见问题.md index 96ceafb5..fc743001 100644 --- a/doc/docs/files/90100_常见问题.md +++ b/doc/docs/files/90100_常见问题.md @@ -1,5 +1,17 @@ # 常见问题 +## 在zuul过滤器中获取请求参数 + +```java +ApiParam param = ZuulContext.getApiParam(); +``` + +## 在SpringCloudGateway中获取请求参数 + +```java +ApiParam apiParam = ServerWebExchangeUtil.getApiParam(exchange); +``` + ## 微服务端如何获取appId等参数 ```java diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/BaseRouteCache.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/BaseRouteCache.java index c542cdc5..1f9947ba 100644 --- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/BaseRouteCache.java +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/BaseRouteCache.java @@ -9,6 +9,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.function.Consumer; /** * @author tanghc @@ -37,7 +38,7 @@ public abstract class BaseRouteCache implements RouteLoad } @Override - public void load(ServiceRouteInfo serviceRouteInfo) { + public void load(ServiceRouteInfo serviceRouteInfo, Consumer callback) { try { String serviceId = serviceRouteInfo.getServiceId(); String newMd5 = serviceRouteInfo.getMd5(); @@ -51,6 +52,7 @@ public abstract class BaseRouteCache implements RouteLoad T routeDefinition = this.buildRouteDefinition(serviceRouteInfo, gatewayRouteDefinition); routeRepository.add(routeDefinition); } + callback.accept(null); } catch (Exception e) { log.error("加载路由信息失败,serviceRouteInfo:{}", serviceRouteInfo, e); } diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/RouteLoader.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/RouteLoader.java index ba4566fe..61981395 100644 --- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/RouteLoader.java +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/RouteLoader.java @@ -2,11 +2,13 @@ package com.gitee.sop.gatewaycommon.manager; import com.gitee.sop.gatewaycommon.bean.ServiceRouteInfo; +import java.util.function.Consumer; + /** * @author tanghc */ public interface RouteLoader { - void load(ServiceRouteInfo serviceRouteInfo); + void load(ServiceRouteInfo serviceRouteInfo, Consumer callback); void remove(String serviceId); } diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/ServiceRoutesLoader.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/ServiceRoutesLoader.java index 421f802d..09ffe468 100644 --- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/ServiceRoutesLoader.java +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/ServiceRoutesLoader.java @@ -18,6 +18,7 @@ import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.util.CollectionUtils; import org.springframework.util.DigestUtils; +import org.springframework.web.client.DefaultResponseErrorHandler; import org.springframework.web.client.RestTemplate; import java.util.HashMap; @@ -50,6 +51,16 @@ public class ServiceRoutesLoader { private Map updateTimeMap = new HashMap<>(16); + public ServiceRoutesLoader() { + // 解决statusCode不等于200,就抛异常问题 + restTemplate.setErrorHandler(new DefaultResponseErrorHandler() { + @Override + protected boolean hasError(HttpStatus statusCode) { + return statusCode == null; + } + }); + } + public synchronized void load(ApplicationEvent event) { NamingService namingService = nacosDiscoveryProperties.namingServiceInstance(); List subscribes = null; @@ -88,15 +99,20 @@ public class ServiceRoutesLoader { configService.removeConfig(dataId, groupId); } else { for (Instance instance : allInstances) { - log.info("加载服务路由,serviceId:{}, instance:{}",serviceName, instance); String url = getRouteRequestUrl(instance); ResponseEntity responseEntity = restTemplate.getForEntity(url, String.class); if (responseEntity.getStatusCode() == HttpStatus.OK) { String body = responseEntity.getBody(); - log.debug("加载{}路由,路由信息:{}", serviceName, body); ServiceRouteInfo serviceRouteInfo = JSON.parseObject(body, ServiceRouteInfo.class); - baseRouteCache.load(serviceRouteInfo); - configService.publishConfig(dataId, groupId, body); + baseRouteCache.load(serviceRouteInfo, callback -> { + try { + log.info("加载服务路由,serviceId:{}, instance:{}",serviceName, instance); + configService.publishConfig(dataId, groupId, body); + } catch (NacosException e) { + log.error("nacos推送失败,serviceId:{}, instance:{}",serviceName, instance); + } + }); + } } } diff --git a/sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi/service/impl/RegistryServiceNacos.java b/sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi/service/impl/RegistryServiceNacos.java index c838efad..3af74761 100644 --- a/sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi/service/impl/RegistryServiceNacos.java +++ b/sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi/service/impl/RegistryServiceNacos.java @@ -33,19 +33,13 @@ public class RegistryServiceNacos implements RegistryService { static HttpTool httpTool = new HttpTool(); - @Value("${registry.nacos-server-addr:}") + @Value("${nacos.discovery.server-addr:${registry.nacos-server-addr:}}") private String nacosAddr; - @Value("${nacos.discovery.server-addr:}") - private String nacosAddrNew; - private NamingService namingService; @PostConstruct public void after() throws NacosException { - if (StringUtils.isNotBlank(nacosAddrNew)) { - nacosAddr = nacosAddrNew; - } if (StringUtils.isNotBlank(nacosAddr)) { namingService = NamingFactory.createNamingService(nacosAddr); } diff --git a/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/bean/OpenContextImpl.java b/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/bean/OpenContextImpl.java index dcc20ae6..3dbd0f77 100644 --- a/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/bean/OpenContextImpl.java +++ b/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/bean/OpenContextImpl.java @@ -1,5 +1,6 @@ package com.gitee.sop.servercommon.bean; +import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import org.apache.commons.lang3.time.DateUtils; @@ -28,11 +29,12 @@ public class OpenContextImpl implements OpenContext { public OpenContextImpl(JSONObject rootJsonObject, Class bizClass) { this.rootJsonObject = rootJsonObject; if (bizClass != null) { - JSONObject bizJsonObj = this.rootJsonObject.getJSONObject(BIZ_CONTENT_NAME); - if (bizJsonObj == null) { - bizJsonObj = rootJsonObject; + String bizContent = this.rootJsonObject.getString(BIZ_CONTENT_NAME); + if (bizContent == null) { + bizObject = (T) rootJsonObject.toJavaObject(bizClass); + } else { + bizObject = (T) JSON.parseObject(bizContent, bizClass); } - bizObject = (T) bizJsonObj.toJavaObject(bizClass); } } diff --git a/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/configuration/SpringMvcServiceConfiguration.java b/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/configuration/SpringMvcServiceConfiguration.java index 28adc332..a1258401 100644 --- a/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/configuration/SpringMvcServiceConfiguration.java +++ b/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/configuration/SpringMvcServiceConfiguration.java @@ -1,9 +1,11 @@ package com.gitee.sop.servercommon.configuration; import com.gitee.sop.servercommon.bean.ServiceConfig; +import com.gitee.sop.servercommon.manager.ServiceRouteController; import com.gitee.sop.servercommon.mapping.ApiMappingHandlerMapping; import com.gitee.sop.servercommon.message.ServiceErrorFactory; import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Primary; import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; @@ -36,10 +38,23 @@ public class SpringMvcServiceConfiguration { @Bean + @ConditionalOnMissingBean GlobalExceptionHandler globalExceptionHandler() { return new GlobalExceptionHandler(); } + @Bean + @ConditionalOnMissingBean + ErrorController errorController() { + return new ErrorController(); + } + + @Bean + @ConditionalOnMissingBean + ServiceRouteController serviceRouteInfoHandler() { + return new ServiceRouteController(); + } + @PostConstruct public final void after() { log.info("-----spring容器加载完毕-----"); diff --git a/sop-example/sop-springmvc/pom.xml b/sop-example/sop-springmvc/pom.xml index 67488ce4..fe0ba261 100644 --- a/sop-example/sop-springmvc/pom.xml +++ b/sop-example/sop-springmvc/pom.xml @@ -12,7 +12,7 @@ 1.8 5.0.7.RELEASE 1.6.10 - 1.6.6 + 1.7.25 @@ -22,11 +22,11 @@ sop-service-common 2.0.0-SNAPSHOT - + - com.netflix.eureka - eureka-client - 1.7.0 + com.alibaba.nacos + nacos-spring-context + 0.3.3 diff --git a/sop-example/sop-springmvc/src/main/java/com/gitee/app/config/EurekaInitAndRegisterListener.java b/sop-example/sop-springmvc/src/main/java/com/gitee/app/config/EurekaInitAndRegisterListener.java deleted file mode 100644 index 0db182e8..00000000 --- a/sop-example/sop-springmvc/src/main/java/com/gitee/app/config/EurekaInitAndRegisterListener.java +++ /dev/null @@ -1,61 +0,0 @@ -package com.gitee.app.config; - -import com.netflix.appinfo.ApplicationInfoManager; -import com.netflix.appinfo.InstanceInfo; -import com.netflix.appinfo.MyDataCenterInstanceConfig; -import com.netflix.discovery.DefaultEurekaClientConfig; -import com.netflix.discovery.DiscoveryManager; -import lombok.extern.slf4j.Slf4j; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.PropertySource; - -import javax.servlet.ServletContextEvent; -import javax.servlet.ServletContextListener; -import java.net.InetAddress; -import java.net.UnknownHostException; - -/** - * 初始化Eureka Client - * @author tanghc - */ -@Slf4j -public class EurekaInitAndRegisterListener implements ServletContextListener { - - @Override - public void contextInitialized(ServletContextEvent sce) { - // 初始化Eureka Client - log.info("Eureka初始化完成,正在注册Eureka Server"); - DiscoveryManager.getInstance().initComponent(new MyInstanceConfig(), new DefaultEurekaClientConfig()); - ApplicationInfoManager.getInstance().setInstanceStatus(InstanceInfo.InstanceStatus.UP); - } - - /** - * * Notification that the servlet context is about to be shut down. - * * All servlets and filters have been destroy()ed before any - * * ServletContextListeners are notified of context - * * destruction. - * - * @param sce - */ - @Override - public void contextDestroyed(ServletContextEvent sce) { - DiscoveryManager.getInstance().shutdownComponent(); - } - - @Configuration - @PropertySource(value = "classpath:eureka-client.properties") - public static class AppConfig { - - } - - public static class MyInstanceConfig extends MyDataCenterInstanceConfig { - @Override - public String getHostName(boolean refresh) { - try { - return InetAddress.getLocalHost().getHostAddress(); - } catch (UnknownHostException e) { - return super.getHostName(refresh); - } - } - } -} \ No newline at end of file diff --git a/sop-example/sop-springmvc/src/main/java/com/gitee/app/config/OpenServiceConfig.java b/sop-example/sop-springmvc/src/main/java/com/gitee/app/config/OpenServiceConfig.java index f558b74a..1167125b 100644 --- a/sop-example/sop-springmvc/src/main/java/com/gitee/app/config/OpenServiceConfig.java +++ b/sop-example/sop-springmvc/src/main/java/com/gitee/app/config/OpenServiceConfig.java @@ -1,15 +1,44 @@ package com.gitee.app.config; +import com.alibaba.nacos.api.annotation.NacosInjected; +import com.alibaba.nacos.api.annotation.NacosProperties; +import com.alibaba.nacos.api.exception.NacosException; +import com.alibaba.nacos.api.naming.NamingService; +import com.alibaba.nacos.client.naming.utils.NetUtils; +import com.alibaba.nacos.spring.context.annotation.discovery.EnableNacosDiscovery; import com.gitee.sop.servercommon.bean.ServiceConfig; import com.gitee.sop.servercommon.configuration.SpringMvcServiceConfiguration; +import lombok.extern.slf4j.Slf4j; /** * 使用支付宝开放平台功能 * * @author tanghc */ +@Slf4j +@EnableNacosDiscovery(globalProperties = @NacosProperties(serverAddr = "127.0.0.1:8848")) public class OpenServiceConfig extends SpringMvcServiceConfiguration { static { ServiceConfig.getInstance().setDefaultVersion("1.0"); } + + // 这两个参数需要从配置文件中获取 + private String serviceId = "sop-springmvc"; + private int port = 2223; + + @NacosInjected + private NamingService namingService; + + @Override + protected void doAfter() { + super.doAfter(); + try { + String ip = NetUtils.localIP(); + namingService.registerInstance(serviceId, ip, port); + log.info("注册到nacos, serviceId:{}, ip:{}, port:{}", serviceId, ip, port); + } catch (NacosException e) { + log.error("注册nacos失败", e); + throw new RuntimeException("注册nacos失败", e); + } + } } diff --git a/sop-example/sop-springmvc/src/main/resources/eureka-client.properties b/sop-example/sop-springmvc/src/main/resources/eureka-client.properties deleted file mode 100644 index aae80c66..00000000 --- a/sop-example/sop-springmvc/src/main/resources/eureka-client.properties +++ /dev/null @@ -1,27 +0,0 @@ -# tomcat端口,根据实际情况填 -server.port=2223 -# 应用名称serviceId,根据实际情况填 -spring.application.name=sop-springmvc -# 注册中心地址,根据实际情况填 -eureka.url=http://localhost:1111/eureka/ -# zookeeper地址,根据实际情况填 -spring.cloud.zookeeper.connect-string=localhost:2181 - -# ----------- 以下内容不用改 ----------- - -# 控制是否注册自身到eureka中,本项目虽然不对外提供服务,但需要Eureka监控,在Eureka列表上显示 -eureka.registration.enabled=true -# eureka相关配置 -# 默认为true,以实现更好的基于区域的负载平衡。 -eureka.preferSameZone=true -# 是否要使用基于DNS的查找来确定其他eureka服务器 -eureka.shouldUseDns=false -# 由于shouldUseDns为false,因此我们使用以下属性来明确指定到eureka服务器的路由(eureka Server地址) -eureka.serviceUrl.default=${eureka.url} -eureka.decoderName=JacksonJson -# 客户识别此服务的虚拟主机名,这里指的是eureka服务本身 -eureka.vipAddress=${spring.application.name} -#服务指定应用名,这里指的是eureka服务本身 -eureka.name=${spring.application.name} -#服务将被识别并将提供请求的端口 -eureka.port=${server.port} diff --git a/sop-example/sop-springmvc/src/main/webapp/WEB-INF/web.xml b/sop-example/sop-springmvc/src/main/webapp/WEB-INF/web.xml index 3e9cf399..de2d58b7 100644 --- a/sop-example/sop-springmvc/src/main/webapp/WEB-INF/web.xml +++ b/sop-example/sop-springmvc/src/main/webapp/WEB-INF/web.xml @@ -14,10 +14,6 @@ org.springframework.web.context.ContextLoaderListener - - com.gitee.app.config.EurekaInitAndRegisterListener - - appServlet diff --git a/sop-website/src/main/java/com/gitee/sop/websiteserver/manager/DocDiscovery.java b/sop-website/src/main/java/com/gitee/sop/websiteserver/manager/DocDiscovery.java index 778fca4a..65591599 100644 --- a/sop-website/src/main/java/com/gitee/sop/websiteserver/manager/DocDiscovery.java +++ b/sop-website/src/main/java/com/gitee/sop/websiteserver/manager/DocDiscovery.java @@ -12,6 +12,7 @@ import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; import org.springframework.util.CollectionUtils; import org.springframework.util.DigestUtils; +import org.springframework.web.client.DefaultResponseErrorHandler; import org.springframework.web.client.RestTemplate; import java.util.HashMap; @@ -37,6 +38,16 @@ public class DocDiscovery { private Map updateTimeMap = new HashMap<>(16); + public DocDiscovery() { + // 解决statusCode不等于200,就抛异常问题 + restTemplate.setErrorHandler(new DefaultResponseErrorHandler() { + @Override + protected boolean hasError(HttpStatus statusCode) { + return statusCode == null; + } + }); + } + public synchronized void refresh(DocManager docManager) { NamingService namingService = nacosDiscoveryProperties.namingServiceInstance(); List subscribes = null; @@ -71,13 +82,15 @@ public class DocDiscovery { docManager.remove(serviceName); } else { for (Instance instance : allInstances) { - log.info("加载服务文档,instance:{}", instance); String url = getRouteRequestUrl(instance); ResponseEntity responseEntity = restTemplate.getForEntity(url, String.class); if (responseEntity.getStatusCode() == HttpStatus.OK) { String body = responseEntity.getBody(); - log.debug("加载{}文档,文档信息:{}", serviceName, body); - docManager.addDocInfo(serviceName, body); + docManager.addDocInfo( + serviceName + , body + , callback -> log.info("加载服务文档,instance:{}", instance) + ); } } } diff --git a/sop-website/src/main/java/com/gitee/sop/websiteserver/manager/DocManager.java b/sop-website/src/main/java/com/gitee/sop/websiteserver/manager/DocManager.java index f5490aa8..ddb5806d 100644 --- a/sop-website/src/main/java/com/gitee/sop/websiteserver/manager/DocManager.java +++ b/sop-website/src/main/java/com/gitee/sop/websiteserver/manager/DocManager.java @@ -3,13 +3,14 @@ package com.gitee.sop.websiteserver.manager; import com.gitee.sop.websiteserver.bean.DocInfo; import java.util.Collection; +import java.util.function.Consumer; /** * @author tanghc */ public interface DocManager { - void addDocInfo(String serviceId, String docJson); + void addDocInfo(String serviceId, String docJson, Consumer callback); DocInfo getByTitle(String title); diff --git a/sop-website/src/main/java/com/gitee/sop/websiteserver/manager/DocManagerImpl.java b/sop-website/src/main/java/com/gitee/sop/websiteserver/manager/DocManagerImpl.java index 1a553361..1c562b6f 100644 --- a/sop-website/src/main/java/com/gitee/sop/websiteserver/manager/DocManagerImpl.java +++ b/sop-website/src/main/java/com/gitee/sop/websiteserver/manager/DocManagerImpl.java @@ -16,6 +16,7 @@ import java.util.Collection; import java.util.HashMap; import java.util.Map; import java.util.Objects; +import java.util.function.Consumer; /** * @author tanghc @@ -40,7 +41,7 @@ public class DocManagerImpl implements DocManager, ApplicationListener callback) { String newMd5 = DigestUtils.md5DigestAsHex(docInfoJson.getBytes(StandardCharsets.UTF_8)); String oldMd5 = serviceIdMd5Map.get(serviceId); if (Objects.equals(newMd5, oldMd5)) { @@ -52,6 +53,7 @@ public class DocManagerImpl implements DocManager, ApplicationListener