mirror of
https://gitee.com/durcframework/SOP.git
synced 2025-08-11 21:57:56 +08:00
对接easyopen
This commit is contained in:
@@ -35,11 +35,11 @@ SOP封装了开放平台大部分功能包括:签名验证、统一异常处
|
|||||||
- 秘钥管理
|
- 秘钥管理
|
||||||
- 微服务端自动验证(JSR-303)
|
- 微服务端自动验证(JSR-303)
|
||||||
- 支持Spring Cloud Gateway
|
- 支持Spring Cloud Gateway
|
||||||
|
- 关闭签名校验功能
|
||||||
|
- 整合[easyopen](https://gitee.com/durcframework/easyopen)
|
||||||
|
|
||||||
## 后期规划
|
## 后期规划
|
||||||
|
|
||||||
- 关闭签名校验功能
|
|
||||||
- 整合[easyopen](https://gitee.com/durcframework/easyopen)
|
|
||||||
- 配置中心,Spring Cloud Config(Zookeeper)
|
- 配置中心,Spring Cloud Config(Zookeeper)
|
||||||
- Admin管理平台,统一管理微服务配置,管理路由信息,微服务上下线,API文档管理等功能
|
- Admin管理平台,统一管理微服务配置,管理路由信息,微服务上下线,API文档管理等功能
|
||||||
|
|
||||||
|
@@ -2,21 +2,19 @@
|
|||||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<parent>
|
|
||||||
<groupId>org.springframework.boot</groupId>
|
|
||||||
<artifactId>spring-boot-starter-parent</artifactId>
|
|
||||||
<version>2.1.2.RELEASE</version>
|
|
||||||
<relativePath/> <!-- lookup parent from repository -->
|
|
||||||
</parent>
|
|
||||||
<groupId>com.gitee.sop</groupId>
|
<groupId>com.gitee.sop</groupId>
|
||||||
<artifactId>sop-gateway-common</artifactId>
|
<artifactId>sop-gateway-common</artifactId>
|
||||||
<version>1.0.0-SNAPSHOT</version>
|
<version>1.0.0-SNAPSHOT</version>
|
||||||
|
<packaging>jar</packaging>
|
||||||
<name>sop-gateway-common</name>
|
<name>sop-gateway-common</name>
|
||||||
<description>sop-gateway-common</description>
|
<description>sop-gateway-common</description>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<java.version>1.8</java.version>
|
<java.version>1.8</java.version>
|
||||||
<spring-cloud.version>Greenwich.RELEASE</spring-cloud.version>
|
<spring-cloud.version>Greenwich.RELEASE</spring-cloud.version>
|
||||||
|
<spring-boot.version>2.1.2.RELEASE</spring-boot.version>
|
||||||
|
<maven.compiler.source>1.8</maven.compiler.source>
|
||||||
|
<maven.compiler.target>1.8</maven.compiler.target>
|
||||||
<!-- Logging -->
|
<!-- Logging -->
|
||||||
<logback.version>1.0.13</logback.version>
|
<logback.version>1.0.13</logback.version>
|
||||||
<slf4j.version>1.7.5</slf4j.version>
|
<slf4j.version>1.7.5</slf4j.version>
|
||||||
@@ -28,28 +26,44 @@
|
|||||||
<commons-io.version>2.5</commons-io.version>
|
<commons-io.version>2.5</commons-io.version>
|
||||||
<commons-fileupload.version>1.3.3</commons-fileupload.version>
|
<commons-fileupload.version>1.3.3</commons-fileupload.version>
|
||||||
<commons-collection.version>3.2.2</commons-collection.version>
|
<commons-collection.version>3.2.2</commons-collection.version>
|
||||||
<xstream.version>1.4.7</xstream.version>
|
<commons-lang3.version>3.8.1</commons-lang3.version>
|
||||||
<velocity.version>1.7</velocity.version>
|
|
||||||
<hibernate-validator.version>6.0.10.Final</hibernate-validator.version>
|
|
||||||
<oltu.version>0.31</oltu.version>
|
|
||||||
<jwt.version>3.2.0</jwt.version>
|
|
||||||
<guava.version>18.0</guava.version>
|
|
||||||
<spring-data-redis.version>1.8.8.RELEASE</spring-data-redis.version>
|
|
||||||
<netty.version>4.1.25.Final</netty.version>
|
|
||||||
<jboss-marshalling-serial.version>2.0.5.Final</jboss-marshalling-serial.version>
|
|
||||||
<itextpdf.version>5.5.12</itextpdf.version>
|
|
||||||
<xmlworker.version>5.5.8</xmlworker.version>
|
|
||||||
<itext-asian.version>5.2.0</itext-asian.version>
|
|
||||||
<asm.version>6.2</asm.version>
|
|
||||||
<commons-codec.version>1.11</commons-codec.version>
|
<commons-codec.version>1.11</commons-codec.version>
|
||||||
|
<xstream.version>1.4.7</xstream.version>
|
||||||
|
<zookeeper.version>3.4.12</zookeeper.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
|
<dependencyManagement>
|
||||||
|
<dependencies>
|
||||||
|
<!-- 加了这个就不需要加版本号了 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-dependencies</artifactId>
|
||||||
|
<version>${spring-boot.version}</version>
|
||||||
|
<type>pom</type>
|
||||||
|
<scope>import</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.cloud</groupId>
|
||||||
|
<artifactId>spring-cloud-dependencies</artifactId>
|
||||||
|
<version>${spring-cloud.version}</version>
|
||||||
|
<type>pom</type>
|
||||||
|
<scope>import</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</dependencyManagement>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.cloud</groupId>
|
<groupId>org.springframework.cloud</groupId>
|
||||||
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
|
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
|
||||||
<optional>true</optional>
|
<optional>true</optional>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.cloud</groupId>
|
||||||
|
<artifactId>spring-cloud-netflix-ribbon</artifactId>
|
||||||
|
<scope>compile</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.cloud</groupId>
|
<groupId>org.springframework.cloud</groupId>
|
||||||
<artifactId>spring-cloud-starter-gateway</artifactId>
|
<artifactId>spring-cloud-starter-gateway</artifactId>
|
||||||
@@ -60,10 +74,6 @@
|
|||||||
<artifactId>spring-boot-starter-webflux</artifactId>
|
<artifactId>spring-boot-starter-webflux</artifactId>
|
||||||
<optional>true</optional>
|
<optional>true</optional>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework.boot</groupId>
|
|
||||||
<artifactId>spring-boot-starter-actuator</artifactId>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<!-- zookeeper -->
|
<!-- zookeeper -->
|
||||||
<dependency>
|
<dependency>
|
||||||
@@ -84,7 +94,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.zookeeper</groupId>
|
<groupId>org.apache.zookeeper</groupId>
|
||||||
<artifactId>zookeeper</artifactId>
|
<artifactId>zookeeper</artifactId>
|
||||||
<version>3.4.12</version>
|
<version>${zookeeper.version}</version>
|
||||||
<exclusions>
|
<exclusions>
|
||||||
<exclusion>
|
<exclusion>
|
||||||
<groupId>org.slf4j</groupId>
|
<groupId>org.slf4j</groupId>
|
||||||
@@ -93,11 +103,17 @@
|
|||||||
</exclusions>
|
</exclusions>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-data-redis</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-starter-test</artifactId>
|
<artifactId>spring-boot-starter-test</artifactId>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.thoughtworks.xstream</groupId>
|
<groupId>com.thoughtworks.xstream</groupId>
|
||||||
<artifactId>xstream</artifactId>
|
<artifactId>xstream</artifactId>
|
||||||
@@ -109,15 +125,11 @@
|
|||||||
<artifactId>fastjson</artifactId>
|
<artifactId>fastjson</artifactId>
|
||||||
<version>${fastjson.version}</version>
|
<version>${fastjson.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework.boot</groupId>
|
|
||||||
<artifactId>spring-boot-starter-data-redis</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<!-- commons -->
|
<!-- commons -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.commons</groupId>
|
<groupId>org.apache.commons</groupId>
|
||||||
<artifactId>commons-lang3</artifactId>
|
<artifactId>commons-lang3</artifactId>
|
||||||
<version>3.8.1</version>
|
<version>${commons-lang3.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>commons-collections</groupId>
|
<groupId>commons-collections</groupId>
|
||||||
@@ -151,42 +163,60 @@
|
|||||||
<version>3.1.0</version>
|
<version>3.1.0</version>
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework.cloud</groupId>
|
|
||||||
<artifactId>spring-cloud-netflix-ribbon</artifactId>
|
|
||||||
<version>2.1.0.RELEASE</version>
|
|
||||||
<scope>compile</scope>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<dependencyManagement>
|
|
||||||
<dependencies>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework.cloud</groupId>
|
|
||||||
<artifactId>spring-cloud-dependencies</artifactId>
|
|
||||||
<version>${spring-cloud.version}</version>
|
|
||||||
<type>pom</type>
|
|
||||||
<scope>import</scope>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
|
||||||
</dependencyManagement>
|
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
<plugins>
|
<plugins>
|
||||||
|
<!-- 打包时跳过测试 -->
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
<artifactId>maven-surefire-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<skipTests>true</skipTests>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<source>${java.version}</source>
|
||||||
|
<target>${java.version}</target>
|
||||||
|
<encoding>UTF-8</encoding>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-source-plugin</artifactId>
|
||||||
|
<version>2.2.1</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>attach-sources</id>
|
||||||
|
<goals>
|
||||||
|
<goal>jar-no-fork</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-javadoc-plugin</artifactId>
|
||||||
|
<version>2.9</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>attach-javadocs</id>
|
||||||
|
<goals>
|
||||||
|
<goal>jar</goal>
|
||||||
|
</goals>
|
||||||
|
<!-- JDK8必须使用下面的配置 -->
|
||||||
|
<configuration>
|
||||||
|
<additionalparam>-Xdoclint:none</additionalparam>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
</plugin>
|
</plugin>
|
||||||
</plugins>
|
</plugins>
|
||||||
</build>
|
</build>
|
||||||
|
|
||||||
<repositories>
|
|
||||||
<repository>
|
|
||||||
<id>spring-milestones</id>
|
|
||||||
<name>Spring Milestones</name>
|
|
||||||
<url>https://repo.spring.io/milestone</url>
|
|
||||||
</repository>
|
|
||||||
</repositories>
|
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
@@ -95,6 +95,11 @@ public class ApiConfig {
|
|||||||
*/
|
*/
|
||||||
private boolean ignoreValidate;
|
private boolean ignoreValidate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否对结果进行合并
|
||||||
|
*/
|
||||||
|
private boolean mergeResult = true;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 超时时间
|
* 超时时间
|
||||||
*/
|
*/
|
||||||
|
@@ -21,4 +21,9 @@ public class BaseRouteDefinition {
|
|||||||
* 路由执行的顺序
|
* 路由执行的顺序
|
||||||
*/
|
*/
|
||||||
private int order = 0;
|
private int order = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否忽略验证,业务参数验证除外
|
||||||
|
*/
|
||||||
|
private boolean ignoreValidate;
|
||||||
}
|
}
|
||||||
|
@@ -32,7 +32,7 @@ public class SopConstants {
|
|||||||
public static final int BIZ_ERROR_STATUS = 4000;
|
public static final int BIZ_ERROR_STATUS = 4000;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* zookeeper存放接口信息的根目录
|
* zookeeper存放接口路由信息的根目录
|
||||||
*/
|
*/
|
||||||
public static final String SOP_SERVICE_API_PATH = "/sop-service-api";
|
public static final String SOP_SERVICE_ROUTE_PATH = "/sop-service-route";
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,27 @@
|
|||||||
|
package com.gitee.sop.gatewaycommon.easyopen;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSON;
|
||||||
|
import com.gitee.sop.gatewaycommon.message.Error;
|
||||||
|
import com.gitee.sop.gatewaycommon.result.ApiResult;
|
||||||
|
import com.gitee.sop.gatewaycommon.result.ResultExecutor;
|
||||||
|
import com.gitee.sop.gatewaycommon.zuul.result.ZuulResultExecutor;
|
||||||
|
import com.netflix.zuul.context.RequestContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author tanghc
|
||||||
|
*/
|
||||||
|
public class EasyopenResultExecutor implements ResultExecutor<RequestContext, String> {
|
||||||
|
@Override
|
||||||
|
public String mergeResult(RequestContext request, String serviceResult) {
|
||||||
|
return serviceResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String buildErrorResult(RequestContext request, Throwable ex) {
|
||||||
|
ApiResult apiResult = new ApiResult();
|
||||||
|
Error error = ZuulResultExecutor.getError(ex);
|
||||||
|
apiResult.setCode(error.getSub_code());
|
||||||
|
apiResult.setMsg(error.getSub_msg());
|
||||||
|
return JSON.toJSONString(apiResult);
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,34 @@
|
|||||||
|
package com.gitee.sop.gatewaycommon.easyopen;
|
||||||
|
|
||||||
|
import com.gitee.sop.gatewaycommon.param.ApiParam;
|
||||||
|
import com.gitee.sop.gatewaycommon.validate.AbstractSigner;
|
||||||
|
import com.gitee.sop.gatewaycommon.validate.taobao.TaobaoSigner;
|
||||||
|
import org.apache.commons.codec.digest.DigestUtils;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author tanghc
|
||||||
|
*/
|
||||||
|
public class EasyopenSigner extends AbstractSigner {
|
||||||
|
@Override
|
||||||
|
protected String buildServerSign(ApiParam params, String secret) {
|
||||||
|
Set<String> keySet = params.keySet();
|
||||||
|
List<String> paramNames = new ArrayList<String>(keySet);
|
||||||
|
|
||||||
|
Collections.sort(paramNames);
|
||||||
|
|
||||||
|
StringBuilder paramNameValue = new StringBuilder();
|
||||||
|
|
||||||
|
for (String paramName : paramNames) {
|
||||||
|
paramNameValue.append(paramName).append(params.get(paramName));
|
||||||
|
}
|
||||||
|
|
||||||
|
String source = secret + paramNameValue.toString() + secret;
|
||||||
|
|
||||||
|
return DigestUtils.md5Hex(source).toUpperCase();
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,26 @@
|
|||||||
|
package com.gitee.sop.gatewaycommon.easyopen;
|
||||||
|
|
||||||
|
import com.gitee.sop.gatewaycommon.bean.ApiConfig;
|
||||||
|
import com.gitee.sop.gatewaycommon.bean.ApiContext;
|
||||||
|
import com.gitee.sop.gatewaycommon.gateway.configuration.BaseGatewayConfiguration;
|
||||||
|
import com.gitee.sop.gatewaycommon.param.ParamNames;
|
||||||
|
import com.gitee.sop.gatewaycommon.validate.taobao.TaobaoSigner;
|
||||||
|
import com.gitee.sop.gatewaycommon.zuul.configuration.BaseZuulConfiguration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author tanghc
|
||||||
|
*/
|
||||||
|
public class EasyopenZuulConfiguration extends BaseZuulConfiguration {
|
||||||
|
|
||||||
|
static {
|
||||||
|
ParamNames.APP_KEY_NAME = "app_key";
|
||||||
|
ParamNames.API_NAME = "name";
|
||||||
|
ParamNames.SIGN_TYPE_NAME = "sign_type";
|
||||||
|
ParamNames.APP_AUTH_TOKEN_NAME = "access_token";
|
||||||
|
ApiConfig apiConfig = ApiContext.getApiConfig();
|
||||||
|
apiConfig.setSigner(new EasyopenSigner());
|
||||||
|
apiConfig.setZuulResultExecutor(new EasyopenResultExecutor());
|
||||||
|
apiConfig.setMergeResult(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -2,6 +2,7 @@ package com.gitee.sop.gatewaycommon.gateway.param;
|
|||||||
|
|
||||||
import com.gitee.sop.gatewaycommon.bean.SopConstants;
|
import com.gitee.sop.gatewaycommon.bean.SopConstants;
|
||||||
import com.gitee.sop.gatewaycommon.param.ApiParam;
|
import com.gitee.sop.gatewaycommon.param.ApiParam;
|
||||||
|
import com.gitee.sop.gatewaycommon.param.ApiParamFactory;
|
||||||
import com.gitee.sop.gatewaycommon.param.ParamBuilder;
|
import com.gitee.sop.gatewaycommon.param.ParamBuilder;
|
||||||
import org.springframework.web.server.ServerWebExchange;
|
import org.springframework.web.server.ServerWebExchange;
|
||||||
|
|
||||||
@@ -14,11 +15,7 @@ public class GatewayParamBuilder implements ParamBuilder<ServerWebExchange> {
|
|||||||
@Override
|
@Override
|
||||||
public ApiParam build(ServerWebExchange exchange) {
|
public ApiParam build(ServerWebExchange exchange) {
|
||||||
Map<String, String> params = exchange.getAttribute(SopConstants.CACHE_REQUEST_BODY_FOR_MAP);
|
Map<String, String> params = exchange.getAttribute(SopConstants.CACHE_REQUEST_BODY_FOR_MAP);
|
||||||
ApiParam apiParam = new ApiParam();
|
return ApiParamFactory.build(params);
|
||||||
for (Map.Entry<String, String> entry : params.entrySet()) {
|
|
||||||
apiParam.put(entry.getKey(), entry.getValue());
|
|
||||||
}
|
|
||||||
return apiParam;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -16,7 +16,7 @@ import org.springframework.util.StringUtils;
|
|||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static com.gitee.sop.gatewaycommon.bean.SopConstants.SOP_SERVICE_API_PATH;
|
import static com.gitee.sop.gatewaycommon.bean.SopConstants.SOP_SERVICE_ROUTE_PATH;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -30,7 +30,7 @@ import static com.gitee.sop.gatewaycommon.bean.SopConstants.SOP_SERVICE_API_PATH
|
|||||||
@Slf4j
|
@Slf4j
|
||||||
public abstract class BaseRouteManager<R extends BaseServiceRouteInfo<E>, E extends BaseRouteDefinition, T> implements RouteManager {
|
public abstract class BaseRouteManager<R extends BaseServiceRouteInfo<E>, E extends BaseRouteDefinition, T> implements RouteManager {
|
||||||
|
|
||||||
protected String sopServiceApiPath = SOP_SERVICE_API_PATH;
|
protected String sopServiceApiPath = SOP_SERVICE_ROUTE_PATH;
|
||||||
|
|
||||||
protected Environment environment;
|
protected Environment environment;
|
||||||
|
|
||||||
@@ -93,10 +93,7 @@ public abstract class BaseRouteManager<R extends BaseServiceRouteInfo<E>, E exte
|
|||||||
String nodeData = new String(childData.getData());
|
String nodeData = new String(childData.getData());
|
||||||
log.info("\t* 子节点路径:" + childData.getPath() + ",该节点的数据为:" + nodeData);
|
log.info("\t* 子节点路径:" + childData.getPath() + ",该节点的数据为:" + nodeData);
|
||||||
R serviceRouteInfo = JSON.parseObject(nodeData, getServiceRouteInfoClass());
|
R serviceRouteInfo = JSON.parseObject(nodeData, getServiceRouteInfoClass());
|
||||||
for (E routeDefinitionItem : serviceRouteInfo.getRouteDefinitionList()) {
|
saveRouteDefinitionList(serviceRouteInfo);
|
||||||
T routeDefinition = buildRouteDefinition(serviceRouteInfo, routeDefinitionItem);
|
|
||||||
routeRepository.add(serviceRouteInfo, routeDefinition);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// 添加事件监听器
|
// 添加事件监听器
|
||||||
childrenCache.getListenable().addListener(new PathChildrenCacheListener() {
|
childrenCache.getListenable().addListener(new PathChildrenCacheListener() {
|
||||||
@@ -110,10 +107,7 @@ public abstract class BaseRouteManager<R extends BaseServiceRouteInfo<E>, E exte
|
|||||||
R serviceRouteInfo = JSON.parseObject(nodeData, getServiceRouteInfoClass());
|
R serviceRouteInfo = JSON.parseObject(nodeData, getServiceRouteInfoClass());
|
||||||
// 添加子节点时触发
|
// 添加子节点时触发
|
||||||
log.info("子节点:{}添加,数据为:{}", event.getData().getPath(), nodeData);
|
log.info("子节点:{}添加,数据为:{}", event.getData().getPath(), nodeData);
|
||||||
for (E routeDefinitionItem : serviceRouteInfo.getRouteDefinitionList()) {
|
saveRouteDefinitionList(serviceRouteInfo);
|
||||||
T routeDefinition = buildRouteDefinition(serviceRouteInfo, routeDefinitionItem);
|
|
||||||
routeRepository.add(serviceRouteInfo, routeDefinition);
|
|
||||||
}
|
|
||||||
} else if (PathChildrenCacheEvent.Type.CHILD_UPDATED.equals(type)) {
|
} else if (PathChildrenCacheEvent.Type.CHILD_UPDATED.equals(type)) {
|
||||||
String nodeData = new String(event.getData().getData());
|
String nodeData = new String(event.getData().getData());
|
||||||
R serviceRouteInfo = JSON.parseObject(nodeData, getServiceRouteInfoClass());
|
R serviceRouteInfo = JSON.parseObject(nodeData, getServiceRouteInfoClass());
|
||||||
@@ -122,20 +116,31 @@ public abstract class BaseRouteManager<R extends BaseServiceRouteInfo<E>, E exte
|
|||||||
// 删除下面所有节点
|
// 删除下面所有节点
|
||||||
routeRepository.deleteAll(serviceRouteInfo);
|
routeRepository.deleteAll(serviceRouteInfo);
|
||||||
// 添加新节点
|
// 添加新节点
|
||||||
for (E routeDefinitionItem : serviceRouteInfo.getRouteDefinitionList()) {
|
saveRouteDefinitionList(serviceRouteInfo);
|
||||||
T routeDefinition = buildRouteDefinition(serviceRouteInfo, routeDefinitionItem);
|
|
||||||
routeRepository.add(serviceRouteInfo, routeDefinition);
|
|
||||||
}
|
|
||||||
} else if (PathChildrenCacheEvent.Type.CHILD_REMOVED.equals(type)) {
|
} else if (PathChildrenCacheEvent.Type.CHILD_REMOVED.equals(type)) {
|
||||||
String nodeData = new String(event.getData().getData());
|
String nodeData = new String(event.getData().getData());
|
||||||
log.info("子节点:{}删除,数据为:{}", event.getData().getPath(), nodeData);
|
log.info("子节点:{}删除,数据为:{}", event.getData().getPath(), nodeData);
|
||||||
R serviceRouteInfo = JSON.parseObject(nodeData, getServiceRouteInfoClass());
|
R serviceRouteInfo = JSON.parseObject(nodeData, getServiceRouteInfoClass());
|
||||||
routeRepository.deleteAll(serviceRouteInfo);
|
deleteRouteDefinitionList(serviceRouteInfo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void saveRouteDefinitionList(R serviceRouteInfo) {
|
||||||
|
for (E routeDefinitionItem : serviceRouteInfo.getRouteDefinitionList()) {
|
||||||
|
RouteDefinitionItemContext.add(routeDefinitionItem);
|
||||||
|
T routeDefinition = buildRouteDefinition(serviceRouteInfo, routeDefinitionItem);
|
||||||
|
routeRepository.add(serviceRouteInfo, routeDefinition);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void deleteRouteDefinitionList(R serviceRouteInfo) {
|
||||||
|
for (E routeDefinitionItem : serviceRouteInfo.getRouteDefinitionList()) {
|
||||||
|
RouteDefinitionItemContext.delete(routeDefinitionItem);
|
||||||
|
}
|
||||||
|
routeRepository.deleteAll(serviceRouteInfo);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,27 @@
|
|||||||
|
package com.gitee.sop.gatewaycommon.manager;
|
||||||
|
|
||||||
|
import com.gitee.sop.gatewaycommon.bean.BaseRouteDefinition;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author tanghc
|
||||||
|
*/
|
||||||
|
public class RouteDefinitionItemContext {
|
||||||
|
// key:id
|
||||||
|
private static Map<String, BaseRouteDefinition> routeDefinitionMap = new HashMap<>(64);
|
||||||
|
|
||||||
|
public static void add(BaseRouteDefinition routeDefinition) {
|
||||||
|
routeDefinitionMap.put(routeDefinition.getId(), routeDefinition);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static BaseRouteDefinition getRouteDefinition(String id) {
|
||||||
|
return routeDefinitionMap.get(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void delete(BaseRouteDefinition routeDefinition) {
|
||||||
|
routeDefinitionMap.remove(routeDefinition.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,25 @@
|
|||||||
|
package com.gitee.sop.gatewaycommon.param;
|
||||||
|
|
||||||
|
import com.gitee.sop.gatewaycommon.bean.BaseRouteDefinition;
|
||||||
|
import com.gitee.sop.gatewaycommon.manager.RouteDefinitionItemContext;
|
||||||
|
import com.gitee.sop.gatewaycommon.message.ErrorEnum;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author tanghc
|
||||||
|
*/
|
||||||
|
public class ApiParamFactory {
|
||||||
|
public static ApiParam build(Map<String, ?> params) {
|
||||||
|
ApiParam apiParam = new ApiParam();
|
||||||
|
for (Map.Entry<String, ?> entry : params.entrySet()) {
|
||||||
|
apiParam.put(entry.getKey(), entry.getValue());
|
||||||
|
}
|
||||||
|
BaseRouteDefinition routeDefinition = RouteDefinitionItemContext.getRouteDefinition(apiParam.fetchNameVersion());
|
||||||
|
if (routeDefinition == null) {
|
||||||
|
throw ErrorEnum.ISV_INVALID_METHOD.getErrorMeta().getException();
|
||||||
|
}
|
||||||
|
apiParam.setIgnoreValidate(routeDefinition.isIgnoreValidate());
|
||||||
|
return apiParam;
|
||||||
|
}
|
||||||
|
}
|
@@ -2,10 +2,14 @@ package com.gitee.sop.gatewaycommon.result;
|
|||||||
|
|
||||||
import com.alibaba.fastjson.JSON;
|
import com.alibaba.fastjson.JSON;
|
||||||
import com.alibaba.fastjson.JSONObject;
|
import com.alibaba.fastjson.JSONObject;
|
||||||
|
import com.gitee.sop.gatewaycommon.bean.ApiContext;
|
||||||
import com.gitee.sop.gatewaycommon.bean.SopConstants;
|
import com.gitee.sop.gatewaycommon.bean.SopConstants;
|
||||||
|
import com.gitee.sop.gatewaycommon.exception.ApiException;
|
||||||
|
import com.gitee.sop.gatewaycommon.message.Error;
|
||||||
import com.gitee.sop.gatewaycommon.message.ErrorEnum;
|
import com.gitee.sop.gatewaycommon.message.ErrorEnum;
|
||||||
import com.gitee.sop.gatewaycommon.message.ErrorMeta;
|
import com.gitee.sop.gatewaycommon.message.ErrorMeta;
|
||||||
import com.gitee.sop.gatewaycommon.param.ParamNames;
|
import com.gitee.sop.gatewaycommon.param.ParamNames;
|
||||||
|
import com.netflix.zuul.exception.ZuulException;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
@@ -45,6 +49,10 @@ public abstract class BaseExecutorAdapter<T, R> implements ResultExecutor<T, R>
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String mergeResult(T request, String serviceResult) {
|
public String mergeResult(T request, String serviceResult) {
|
||||||
|
boolean isMergeResult = ApiContext.getApiConfig().isMergeResult();
|
||||||
|
if (!isMergeResult) {
|
||||||
|
return serviceResult;
|
||||||
|
}
|
||||||
serviceResult = wrapResult(serviceResult);
|
serviceResult = wrapResult(serviceResult);
|
||||||
int responseStatus = this.getBizHeaderCode(request);
|
int responseStatus = this.getBizHeaderCode(request);
|
||||||
JSONObject jsonObjectService;
|
JSONObject jsonObjectService;
|
||||||
@@ -99,4 +107,5 @@ public abstract class BaseExecutorAdapter<T, R> implements ResultExecutor<T, R>
|
|||||||
ret.put(ParamNames.SIGN_NAME, sign);
|
ret.put(ParamNames.SIGN_NAME, sign);
|
||||||
return ret.toJSONString();
|
return ret.toJSONString();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -37,7 +37,7 @@ public interface ResultExecutor<T, R> {
|
|||||||
* 合并结果
|
* 合并结果
|
||||||
* @param request
|
* @param request
|
||||||
* @param serviceResult
|
* @param serviceResult
|
||||||
* @return
|
* @return 返回最终输出结果
|
||||||
*/
|
*/
|
||||||
String mergeResult(T request, String serviceResult);
|
String mergeResult(T request, String serviceResult);
|
||||||
|
|
||||||
@@ -45,7 +45,7 @@ public interface ResultExecutor<T, R> {
|
|||||||
* 合并错误结果
|
* 合并错误结果
|
||||||
* @param request
|
* @param request
|
||||||
* @param ex
|
* @param ex
|
||||||
* @return
|
* @return 返回最终输出结果
|
||||||
*/
|
*/
|
||||||
R buildErrorResult(T request, Throwable ex);
|
R buildErrorResult(T request, Throwable ex);
|
||||||
}
|
}
|
||||||
|
@@ -30,6 +30,9 @@ public class PostResultFilter extends BaseZuulFilter {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Object doRun(RequestContext requestContext) throws ZuulException {
|
protected Object doRun(RequestContext requestContext) throws ZuulException {
|
||||||
|
if (requestContext.getResponse().isCommitted()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
InputStream responseDataStream = requestContext.getResponseDataStream();
|
InputStream responseDataStream = requestContext.getResponseDataStream();
|
||||||
ApiConfig apiConfig = ApiContext.getApiConfig();
|
ApiConfig apiConfig = ApiContext.getApiConfig();
|
||||||
ResultExecutor<RequestContext, String> resultExecutor = apiConfig.getZuulResultExecutor();
|
ResultExecutor<RequestContext, String> resultExecutor = apiConfig.getZuulResultExecutor();
|
||||||
|
@@ -2,10 +2,13 @@ package com.gitee.sop.gatewaycommon.zuul.filter;
|
|||||||
|
|
||||||
import com.gitee.sop.gatewaycommon.bean.ApiContext;
|
import com.gitee.sop.gatewaycommon.bean.ApiContext;
|
||||||
import com.gitee.sop.gatewaycommon.bean.ApiConfig;
|
import com.gitee.sop.gatewaycommon.bean.ApiConfig;
|
||||||
|
import com.gitee.sop.gatewaycommon.bean.BaseRouteDefinition;
|
||||||
import com.gitee.sop.gatewaycommon.exception.ApiException;
|
import com.gitee.sop.gatewaycommon.exception.ApiException;
|
||||||
|
import com.gitee.sop.gatewaycommon.manager.RouteDefinitionItemContext;
|
||||||
import com.gitee.sop.gatewaycommon.param.ApiParam;
|
import com.gitee.sop.gatewaycommon.param.ApiParam;
|
||||||
import com.gitee.sop.gatewaycommon.validate.Validator;
|
import com.gitee.sop.gatewaycommon.validate.Validator;
|
||||||
import com.gitee.sop.gatewaycommon.zuul.ZuulContext;
|
import com.gitee.sop.gatewaycommon.zuul.ZuulContext;
|
||||||
|
import com.gitee.sop.gatewaycommon.zuul.route.ZuulRouteDefinition;
|
||||||
import com.netflix.zuul.context.RequestContext;
|
import com.netflix.zuul.context.RequestContext;
|
||||||
import com.netflix.zuul.exception.ZuulException;
|
import com.netflix.zuul.exception.ZuulException;
|
||||||
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
|
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
|
||||||
|
@@ -1,14 +1,17 @@
|
|||||||
package com.gitee.sop.gatewaycommon.zuul.param;
|
package com.gitee.sop.gatewaycommon.zuul.param;
|
||||||
|
|
||||||
import com.alibaba.fastjson.JSON;
|
import com.alibaba.fastjson.JSON;
|
||||||
|
import com.gitee.sop.gatewaycommon.bean.SopConstants;
|
||||||
import com.gitee.sop.gatewaycommon.message.ErrorEnum;
|
import com.gitee.sop.gatewaycommon.message.ErrorEnum;
|
||||||
import com.gitee.sop.gatewaycommon.param.ApiParam;
|
import com.gitee.sop.gatewaycommon.param.ApiParam;
|
||||||
|
import com.gitee.sop.gatewaycommon.param.ApiParamFactory;
|
||||||
import com.gitee.sop.gatewaycommon.param.ApiUploadContext;
|
import com.gitee.sop.gatewaycommon.param.ApiUploadContext;
|
||||||
import com.gitee.sop.gatewaycommon.param.ParamBuilder;
|
import com.gitee.sop.gatewaycommon.param.ParamBuilder;
|
||||||
import com.gitee.sop.gatewaycommon.util.RequestUtil;
|
import com.gitee.sop.gatewaycommon.util.RequestUtil;
|
||||||
import com.gitee.sop.gatewaycommon.zuul.ZuulContext;
|
import com.gitee.sop.gatewaycommon.zuul.ZuulContext;
|
||||||
import com.netflix.zuul.context.RequestContext;
|
import com.netflix.zuul.context.RequestContext;
|
||||||
import com.netflix.zuul.http.HttpServletRequestWrapper;
|
import com.netflix.zuul.http.HttpServletRequestWrapper;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
import org.springframework.web.multipart.MultipartHttpServletRequest;
|
import org.springframework.web.multipart.MultipartHttpServletRequest;
|
||||||
@@ -24,6 +27,7 @@ import java.util.Set;
|
|||||||
*
|
*
|
||||||
* @author tanghc
|
* @author tanghc
|
||||||
*/
|
*/
|
||||||
|
@Slf4j
|
||||||
public class ZuulParamBuilder implements ParamBuilder<RequestContext> {
|
public class ZuulParamBuilder implements ParamBuilder<RequestContext> {
|
||||||
|
|
||||||
private static final String CONTENT_TYPE_MULTIPART = MediaType.MULTIPART_FORM_DATA_VALUE;
|
private static final String CONTENT_TYPE_MULTIPART = MediaType.MULTIPART_FORM_DATA_VALUE;
|
||||||
@@ -33,16 +37,12 @@ public class ZuulParamBuilder implements ParamBuilder<RequestContext> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ApiParam build(RequestContext ctx) {
|
public ApiParam build(RequestContext ctx) {
|
||||||
try {
|
HttpServletRequest request = ctx.getRequest();
|
||||||
HttpServletRequest request = ctx.getRequest();
|
Map<String, Object> params = this.getParams(request);
|
||||||
Map<String, Object> params = this.getJson(request);
|
return ApiParamFactory.build(params);
|
||||||
return new ApiParam(params);
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw ErrorEnum.ISV_INVALID_PARAMETER.getErrorMeta().getException();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<String, Object> getJson(HttpServletRequest request) throws Exception {
|
public Map<String, Object> getParams(HttpServletRequest request) {
|
||||||
// zuul会做一层包装
|
// zuul会做一层包装
|
||||||
if (request instanceof HttpServletRequestWrapper) {
|
if (request instanceof HttpServletRequestWrapper) {
|
||||||
HttpServletRequestWrapper req = (HttpServletRequestWrapper) request;
|
HttpServletRequestWrapper req = (HttpServletRequestWrapper) request;
|
||||||
@@ -63,7 +63,12 @@ public class ZuulParamBuilder implements ParamBuilder<RequestContext> {
|
|||||||
|
|
||||||
// json或者纯文本形式
|
// json或者纯文本形式
|
||||||
if (contectType.contains(CONTENT_TYPE_JSON) || contectType.contains(CONTENT_TYPE_TEXT)) {
|
if (contectType.contains(CONTENT_TYPE_JSON) || contectType.contains(CONTENT_TYPE_TEXT)) {
|
||||||
String txt = RequestUtil.getText(request);
|
String txt = SopConstants.EMPTY_JSON;
|
||||||
|
try {
|
||||||
|
txt = RequestUtil.getText(request);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("获取纯文本内容失败", e);
|
||||||
|
}
|
||||||
params = JSON.parseObject(txt);
|
params = JSON.parseObject(txt);
|
||||||
} else if (contectType.contains(CONTENT_TYPE_MULTIPART)) {
|
} else if (contectType.contains(CONTENT_TYPE_MULTIPART)) {
|
||||||
// 上传文件形式
|
// 上传文件形式
|
||||||
|
@@ -40,6 +40,12 @@ public class ZuulResultExecutor extends BaseExecutorAdapter<RequestContext, Stri
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String buildErrorResult(RequestContext request, Throwable throwable) {
|
public String buildErrorResult(RequestContext request, Throwable throwable) {
|
||||||
|
Error error = getError(throwable);
|
||||||
|
JSONObject jsonObject = (JSONObject) JSON.toJSON(error);
|
||||||
|
return this.merge(request, jsonObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Error getError(Throwable throwable) {
|
||||||
Error error = null;
|
Error error = null;
|
||||||
if (throwable instanceof ZuulException) {
|
if (throwable instanceof ZuulException) {
|
||||||
ZuulException ex = (ZuulException) throwable;
|
ZuulException ex = (ZuulException) throwable;
|
||||||
@@ -52,8 +58,6 @@ public class ZuulResultExecutor extends BaseExecutorAdapter<RequestContext, Stri
|
|||||||
if (error == null) {
|
if (error == null) {
|
||||||
error = ErrorEnum.AOP_UNKNOW_ERROR.getErrorMeta().getError();
|
error = ErrorEnum.AOP_UNKNOW_ERROR.getErrorMeta().getError();
|
||||||
}
|
}
|
||||||
JSONObject jsonObject = (JSONObject) JSON.toJSON(error);
|
return error;
|
||||||
return this.merge(request, jsonObject);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -43,6 +43,10 @@
|
|||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-starter-webflux</artifactId>
|
<artifactId>spring-boot-starter-webflux</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-actuator</artifactId>
|
||||||
|
</dependency>
|
||||||
-->
|
-->
|
||||||
<!-- ↑↑↑ 使用spring cloud gateway ↑↑↑ -->
|
<!-- ↑↑↑ 使用spring cloud gateway ↑↑↑ -->
|
||||||
|
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
package com.gitee.sop.gateway.config;
|
package com.gitee.sop.gateway.config;
|
||||||
|
|
||||||
import com.gitee.sop.gatewaycommon.bean.ApiContext;
|
import com.gitee.sop.gatewaycommon.bean.ApiContext;
|
||||||
|
import com.gitee.sop.gatewaycommon.easyopen.EasyopenZuulConfiguration;
|
||||||
import com.gitee.sop.gatewaycommon.zuul.configuration.AlipayZuulConfiguration;
|
import com.gitee.sop.gatewaycommon.zuul.configuration.AlipayZuulConfiguration;
|
||||||
import com.gitee.sop.gatewaycommon.zuul.configuration.TaobaoZuulConfiguration;
|
import com.gitee.sop.gatewaycommon.zuul.configuration.TaobaoZuulConfiguration;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
@@ -42,4 +43,14 @@ public class ZuulConfig extends AlipayZuulConfiguration {
|
|||||||
// }
|
// }
|
||||||
//}
|
//}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 对接easyopen
|
||||||
|
*/
|
||||||
|
//@Configuration
|
||||||
|
//public class ZuulConfig extends EasyopenZuulConfiguration {
|
||||||
|
// {
|
||||||
|
// Map<String, String> appSecretStore = new HashMap();
|
||||||
|
// appSecretStore.put("easyopen_test", "G9w0BAQEFAAOCAQ8AMIIBCgKCA");
|
||||||
|
// ApiContext.getApiConfig().addAppSecret(appSecretStore);
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
@@ -3,27 +3,53 @@
|
|||||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<parent>
|
|
||||||
<groupId>org.springframework.boot</groupId>
|
|
||||||
<artifactId>spring-boot-starter-parent</artifactId>
|
|
||||||
<version>2.1.2.RELEASE</version>
|
|
||||||
<relativePath/> <!-- lookup parent from repository -->
|
|
||||||
</parent>
|
|
||||||
<groupId>com.gitee.sop</groupId>
|
<groupId>com.gitee.sop</groupId>
|
||||||
<artifactId>sop-service-common</artifactId>
|
<artifactId>sop-service-common</artifactId>
|
||||||
<name>sop-service-common</name>
|
<name>sop-service-common</name>
|
||||||
<version>1.0.0-SNAPSHOT</version>
|
<version>1.0.0-SNAPSHOT</version>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
|
<java.version>1.8</java.version>
|
||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
<spring-cloud.version>Greenwich.RELEASE</spring-cloud.version>
|
<spring-cloud.version>Greenwich.RELEASE</spring-cloud.version>
|
||||||
|
<spring-boot.version>2.1.2.RELEASE</spring-boot.version>
|
||||||
<maven.compiler.source>1.8</maven.compiler.source>
|
<maven.compiler.source>1.8</maven.compiler.source>
|
||||||
<maven.compiler.target>1.8</maven.compiler.target>
|
<maven.compiler.target>1.8</maven.compiler.target>
|
||||||
<spring-data-redis.version>1.8.8.RELEASE</spring-data-redis.version>
|
|
||||||
<fastjson.version>1.2.15</fastjson.version>
|
<fastjson.version>1.2.15</fastjson.version>
|
||||||
|
<zookeeper.version>3.4.12</zookeeper.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
|
<dependencyManagement>
|
||||||
|
<dependencies>
|
||||||
|
<!-- 加了这个就不需要加版本号了 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-dependencies</artifactId>
|
||||||
|
<version>${spring-boot.version}</version>
|
||||||
|
<type>pom</type>
|
||||||
|
<scope>import</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.cloud</groupId>
|
||||||
|
<artifactId>spring-cloud-dependencies</artifactId>
|
||||||
|
<version>${spring-cloud.version}</version>
|
||||||
|
<type>pom</type>
|
||||||
|
<scope>import</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</dependencyManagement>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-web</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-data-redis</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.alibaba</groupId>
|
<groupId>com.alibaba</groupId>
|
||||||
<artifactId>fastjson</artifactId>
|
<artifactId>fastjson</artifactId>
|
||||||
@@ -49,7 +75,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.zookeeper</groupId>
|
<groupId>org.apache.zookeeper</groupId>
|
||||||
<artifactId>zookeeper</artifactId>
|
<artifactId>zookeeper</artifactId>
|
||||||
<version>3.4.12</version>
|
<version>${zookeeper.version}</version>
|
||||||
<exclusions>
|
<exclusions>
|
||||||
<exclusion>
|
<exclusion>
|
||||||
<groupId>org.slf4j</groupId>
|
<groupId>org.slf4j</groupId>
|
||||||
@@ -59,26 +85,25 @@
|
|||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>net.oschina.durcframework</groupId>
|
||||||
<artifactId>spring-boot-starter-web</artifactId>
|
<artifactId>easyopen</artifactId>
|
||||||
</dependency>
|
<version>1.16.0</version>
|
||||||
<dependency>
|
<optional>true</optional>
|
||||||
<groupId>org.springframework.boot</groupId>
|
|
||||||
<artifactId>spring-boot-starter-data-redis</artifactId>
|
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.apache.tomcat.embed</groupId>
|
|
||||||
<artifactId>tomcat-embed-core</artifactId>
|
|
||||||
<version>9.0.14</version>
|
|
||||||
<scope>provided</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.projectlombok</groupId>
|
<groupId>org.projectlombok</groupId>
|
||||||
<artifactId>lombok</artifactId>
|
<artifactId>lombok</artifactId>
|
||||||
<version>1.18.4</version>
|
<version>1.18.4</version>
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>javax.servlet</groupId>
|
||||||
|
<artifactId>javax.servlet-api</artifactId>
|
||||||
|
<version>3.1.0</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>junit</groupId>
|
<groupId>junit</groupId>
|
||||||
@@ -89,23 +114,55 @@
|
|||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<dependencyManagement>
|
|
||||||
<dependencies>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework.cloud</groupId>
|
|
||||||
<artifactId>spring-cloud-dependencies</artifactId>
|
|
||||||
<version>${spring-cloud.version}</version>
|
|
||||||
<type>pom</type>
|
|
||||||
<scope>import</scope>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
|
||||||
</dependencyManagement>
|
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
<plugins>
|
<plugins>
|
||||||
|
<!-- 打包时跳过测试 -->
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
<artifactId>maven-surefire-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<skipTests>true</skipTests>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<source>${java.version}</source>
|
||||||
|
<target>${java.version}</target>
|
||||||
|
<encoding>UTF-8</encoding>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-source-plugin</artifactId>
|
||||||
|
<version>2.2.1</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>attach-sources</id>
|
||||||
|
<goals>
|
||||||
|
<goal>jar-no-fork</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-javadoc-plugin</artifactId>
|
||||||
|
<version>2.9</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>attach-javadocs</id>
|
||||||
|
<goals>
|
||||||
|
<goal>jar</goal>
|
||||||
|
</goals>
|
||||||
|
<!-- JDK8必须使用下面的配置 -->
|
||||||
|
<configuration>
|
||||||
|
<additionalparam>-Xdoclint:none</additionalparam>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
</plugin>
|
</plugin>
|
||||||
</plugins>
|
</plugins>
|
||||||
</build>
|
</build>
|
||||||
|
@@ -20,4 +20,9 @@ public @interface ApiAbility {
|
|||||||
* 版本号,如:1.0
|
* 版本号,如:1.0
|
||||||
*/
|
*/
|
||||||
String version() default "";
|
String version() default "";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 忽略验证,业务参数除外
|
||||||
|
*/
|
||||||
|
boolean ignoreValidate() default false;
|
||||||
}
|
}
|
||||||
|
@@ -27,6 +27,11 @@ public @interface ApiMapping {
|
|||||||
*/
|
*/
|
||||||
String version() default "";
|
String version() default "";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 忽略验证,业务参数除外
|
||||||
|
*/
|
||||||
|
boolean ignoreValidate() default false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 接口名
|
* 接口名
|
||||||
* Alias for {@link RequestMapping#value}.
|
* Alias for {@link RequestMapping#value}.
|
||||||
|
@@ -24,6 +24,8 @@ public class ServiceApiInfo {
|
|||||||
private String path;
|
private String path;
|
||||||
/** 版本号 */
|
/** 版本号 */
|
||||||
private String version;
|
private String version;
|
||||||
|
/** 是否忽略验证 */
|
||||||
|
private boolean ignoreValidate;
|
||||||
|
|
||||||
public ApiMeta() {
|
public ApiMeta() {
|
||||||
}
|
}
|
||||||
|
@@ -47,6 +47,11 @@ public class ServiceConfig {
|
|||||||
*/
|
*/
|
||||||
private GlobalExceptionHandler globalExceptionHandler = new DefaultGlobalExceptionHandler();
|
private GlobalExceptionHandler globalExceptionHandler = new DefaultGlobalExceptionHandler();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置为true,所有接口不进行校验
|
||||||
|
*/
|
||||||
|
private boolean ignoreValidate;
|
||||||
|
|
||||||
public static ServiceConfig getInstance() {
|
public static ServiceConfig getInstance() {
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
@@ -4,6 +4,7 @@ import com.gitee.sop.servercommon.bean.ServiceConfig;
|
|||||||
import com.gitee.sop.servercommon.interceptor.ServiceContextInterceptor;
|
import com.gitee.sop.servercommon.interceptor.ServiceContextInterceptor;
|
||||||
import com.gitee.sop.servercommon.manager.ApiMetaManager;
|
import com.gitee.sop.servercommon.manager.ApiMetaManager;
|
||||||
import com.gitee.sop.servercommon.manager.DefaultRequestMappingEvent;
|
import com.gitee.sop.servercommon.manager.DefaultRequestMappingEvent;
|
||||||
|
import com.gitee.sop.servercommon.manager.RequestMappingEvent;
|
||||||
import com.gitee.sop.servercommon.manager.ServiceZookeeperApiMetaManager;
|
import com.gitee.sop.servercommon.manager.ServiceZookeeperApiMetaManager;
|
||||||
import com.gitee.sop.servercommon.mapping.ApiMappingHandlerMapping;
|
import com.gitee.sop.servercommon.mapping.ApiMappingHandlerMapping;
|
||||||
import com.gitee.sop.servercommon.message.ServiceErrorFactory;
|
import com.gitee.sop.servercommon.message.ServiceErrorFactory;
|
||||||
@@ -41,11 +42,19 @@ public class BaseServiceConfiguration extends WebMvcConfigurationSupport {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected RequestMappingHandlerMapping createRequestMappingHandlerMapping() {
|
protected RequestMappingHandlerMapping createRequestMappingHandlerMapping() {
|
||||||
ApiMetaManager apiMetaManager = new ServiceZookeeperApiMetaManager(environment);
|
ApiMetaManager apiMetaManager = getApiMetaManager(environment);
|
||||||
DefaultRequestMappingEvent requestMappingEvent = new DefaultRequestMappingEvent(apiMetaManager, environment);
|
RequestMappingEvent requestMappingEvent = getRequestMappingEvent(apiMetaManager, environment);
|
||||||
return new ApiMappingHandlerMapping(requestMappingEvent);
|
return new ApiMappingHandlerMapping(requestMappingEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected RequestMappingEvent getRequestMappingEvent(ApiMetaManager apiMetaManager, Environment environment) {
|
||||||
|
return new DefaultRequestMappingEvent(apiMetaManager, environment);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected ApiMetaManager getApiMetaManager(Environment environment) {
|
||||||
|
return new ServiceZookeeperApiMetaManager(environment);
|
||||||
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
GlobalExceptionHandler globalExceptionHandler() {
|
GlobalExceptionHandler globalExceptionHandler() {
|
||||||
return ServiceConfig.getInstance().getGlobalExceptionHandler();
|
return ServiceConfig.getInstance().getGlobalExceptionHandler();
|
||||||
|
@@ -0,0 +1,102 @@
|
|||||||
|
package com.gitee.sop.servercommon.configuration;
|
||||||
|
|
||||||
|
import com.gitee.easyopen.ApiContext;
|
||||||
|
import com.gitee.easyopen.annotation.Api;
|
||||||
|
import com.gitee.easyopen.annotation.ApiService;
|
||||||
|
import com.gitee.easyopen.util.ReflectionUtil;
|
||||||
|
import com.gitee.sop.servercommon.bean.ServiceApiInfo;
|
||||||
|
import com.gitee.sop.servercommon.manager.ApiMetaManager;
|
||||||
|
import com.gitee.sop.servercommon.manager.DefaultRequestMappingEvent;
|
||||||
|
import com.gitee.sop.servercommon.manager.RequestMappingEvent;
|
||||||
|
import com.gitee.sop.servercommon.mapping.ApiMappingHandlerMapping;
|
||||||
|
import org.springframework.context.ApplicationContext;
|
||||||
|
import org.springframework.core.annotation.AnnotationUtils;
|
||||||
|
import org.springframework.core.env.Environment;
|
||||||
|
import org.springframework.util.ReflectionUtils;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
import org.springframework.web.method.HandlerMethod;
|
||||||
|
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
|
||||||
|
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 提供给easyopen项目使用
|
||||||
|
* @author tanghc
|
||||||
|
*/
|
||||||
|
public class EasyopenServiceConfiguration extends BaseServiceConfiguration {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected RequestMappingEvent getRequestMappingEvent(ApiMetaManager apiMetaManager, Environment environment) {
|
||||||
|
return new EasyopenRequestMappingEvent(apiMetaManager, environment);
|
||||||
|
}
|
||||||
|
|
||||||
|
class EasyopenRequestMappingEvent extends DefaultRequestMappingEvent {
|
||||||
|
String prefixPath;
|
||||||
|
|
||||||
|
public EasyopenRequestMappingEvent(ApiMetaManager apiMetaManager, Environment environment) {
|
||||||
|
super(apiMetaManager, environment);
|
||||||
|
|
||||||
|
String prefixPath = getEnvironment().getProperty("easyopen.prefix-path");
|
||||||
|
if (prefixPath == null) {
|
||||||
|
throw new IllegalArgumentException("请在application.propertis中设置easyopen.prefix-path属性,填IndexController上面的@RequestMapping()中的值");
|
||||||
|
}
|
||||||
|
this.prefixPath = prefixPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected List<ServiceApiInfo.ApiMeta> buildApiMetaList(ApiMappingHandlerMapping apiMappingHandlerMapping) {
|
||||||
|
ApplicationContext ctx = getApplicationContext();
|
||||||
|
String[] apiServiceNames = ReflectionUtil.findApiServiceNames(ctx);
|
||||||
|
List<ServiceApiInfo.ApiMeta> apiMetaList = new ArrayList<>();
|
||||||
|
for (String apiServiceName : apiServiceNames) {
|
||||||
|
Object bean = ctx.getBean(apiServiceName);
|
||||||
|
doWithMethods(bean.getClass(), method -> {
|
||||||
|
Api api = AnnotationUtils.findAnnotation(method, Api.class);
|
||||||
|
ServiceApiInfo.ApiMeta apiMeta = new ServiceApiInfo.ApiMeta();
|
||||||
|
apiMeta.setName(api.name());
|
||||||
|
apiMeta.setVersion(api.version());
|
||||||
|
apiMeta.setIgnoreValidate(api.ignoreValidate());
|
||||||
|
// /api/goods.get/
|
||||||
|
String servletPath = this.buildPath(api);
|
||||||
|
apiMeta.setPath(servletPath);
|
||||||
|
apiMetaList.add(apiMeta);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return apiMetaList;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void doWithMethods(Class<?> clazz, Consumer<Method> consumer) {
|
||||||
|
// Keep backing up the inheritance hierarchy.
|
||||||
|
Method[] methods = clazz.getDeclaredMethods();
|
||||||
|
for (Method method : methods) {
|
||||||
|
boolean match = !method.isSynthetic() && AnnotationUtils.findAnnotation(method, Api.class) != null;
|
||||||
|
if (match) {
|
||||||
|
consumer.accept(method);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String buildPath(Api api) {
|
||||||
|
// /api/goods.get/
|
||||||
|
String servletPath = prefixPath + "/" + api.name() + "/";
|
||||||
|
String version = api.version();
|
||||||
|
if (StringUtils.hasLength(version)) {
|
||||||
|
// /api/goods.get/1.0/
|
||||||
|
servletPath = servletPath + version + "/";
|
||||||
|
}
|
||||||
|
return servletPath;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void after() {
|
||||||
|
super.after();
|
||||||
|
// 取消验证
|
||||||
|
// todo:需要在easyopen端修改
|
||||||
|
//ApiContext.getApiConfig().setIgnoreValidate(true);
|
||||||
|
}
|
||||||
|
}
|
@@ -35,38 +35,11 @@ public class DefaultRequestMappingEvent implements RequestMappingEvent {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onRegisterSuccess(ApiMappingHandlerMapping apiMappingHandlerMapping) {
|
public void onRegisterSuccess(ApiMappingHandlerMapping apiMappingHandlerMapping) {
|
||||||
Map<RequestMappingInfo, HandlerMethod> handlerMethods = apiMappingHandlerMapping.getHandlerMethods();
|
|
||||||
Set<RequestMappingInfo> requestMappingInfos = handlerMethods.keySet();
|
|
||||||
List<String> store = new ArrayList<>(requestMappingInfos.size());
|
|
||||||
List<ServiceApiInfo.ApiMeta> apis = new ArrayList<>(requestMappingInfos.size());
|
|
||||||
|
|
||||||
for (RequestMappingInfo requestMappingInfo : requestMappingInfos) {
|
|
||||||
Set<String> patterns = requestMappingInfo.getPatternsCondition().getPatterns();
|
|
||||||
RequestCondition<?> customCondition = requestMappingInfo.getCustomCondition();
|
|
||||||
if (customCondition instanceof ApiMappingRequestCondition) {
|
|
||||||
ApiMappingRequestCondition condition = (ApiMappingRequestCondition) customCondition;
|
|
||||||
ApiMappingInfo apiMappingInfo = condition.getApiMappingInfo();
|
|
||||||
String name = apiMappingInfo.getName();
|
|
||||||
String version = apiMappingInfo.getVersion();
|
|
||||||
String path = patterns.iterator().next();
|
|
||||||
// 不是ApiMapping注解的接口,name属性是null
|
|
||||||
if (name == null) {
|
|
||||||
name = buildName(path);
|
|
||||||
}
|
|
||||||
String key = path + version;
|
|
||||||
if (store.contains(key)) {
|
|
||||||
throw new RuntimeException("重复申明接口,请检查path和version,path:" + path + ", version:" + version);
|
|
||||||
} else {
|
|
||||||
store.add(key);
|
|
||||||
}
|
|
||||||
apis.add(new ServiceApiInfo.ApiMeta(name, path, version));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
String appName = environment.getProperty("spring.application.name");
|
String appName = environment.getProperty("spring.application.name");
|
||||||
if (appName == null) {
|
if (appName == null) {
|
||||||
throw new RuntimeException("请在application.properties中指定spring.application.name属性");
|
throw new RuntimeException("请在application.properties中指定spring.application.name属性");
|
||||||
}
|
}
|
||||||
|
List<ServiceApiInfo.ApiMeta> apis = this.buildApiMetaList(apiMappingHandlerMapping);
|
||||||
// 排序
|
// 排序
|
||||||
Collections.sort(apis, new Comparator<ServiceApiInfo.ApiMeta>() {
|
Collections.sort(apis, new Comparator<ServiceApiInfo.ApiMeta>() {
|
||||||
@Override
|
@Override
|
||||||
@@ -83,6 +56,49 @@ public class DefaultRequestMappingEvent implements RequestMappingEvent {
|
|||||||
apiMetaManager.uploadApi(serviceApiInfo);
|
apiMetaManager.uploadApi(serviceApiInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected List<ServiceApiInfo.ApiMeta> buildApiMetaList(ApiMappingHandlerMapping apiMappingHandlerMapping) {
|
||||||
|
Map<RequestMappingInfo, HandlerMethod> handlerMethods = apiMappingHandlerMapping.getHandlerMethods();
|
||||||
|
Set<RequestMappingInfo> requestMappingInfos = handlerMethods.keySet();
|
||||||
|
List<String> store = new ArrayList<>();
|
||||||
|
List<ServiceApiInfo.ApiMeta> apis = new ArrayList<>(requestMappingInfos.size());
|
||||||
|
|
||||||
|
for (Map.Entry<RequestMappingInfo, HandlerMethod> handlerMethodEntry : handlerMethods.entrySet()) {
|
||||||
|
ServiceApiInfo.ApiMeta apiMeta = this.buildApiMeta(handlerMethodEntry);
|
||||||
|
if (apiMeta == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
String key = apiMeta.fetchNameVersion();
|
||||||
|
if (store.contains(key)) {
|
||||||
|
throw new RuntimeException("重复申明接口,请检查path和version,path:" + apiMeta.getPath() + ", version:" + apiMeta.getVersion());
|
||||||
|
} else {
|
||||||
|
store.add(key);
|
||||||
|
}
|
||||||
|
apis.add(apiMeta);
|
||||||
|
}
|
||||||
|
return apis;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected ServiceApiInfo.ApiMeta buildApiMeta(Map.Entry<RequestMappingInfo, HandlerMethod> handlerMethodEntry) {
|
||||||
|
RequestMappingInfo requestMappingInfo = handlerMethodEntry.getKey();
|
||||||
|
Set<String> patterns = requestMappingInfo.getPatternsCondition().getPatterns();
|
||||||
|
RequestCondition<?> customCondition = requestMappingInfo.getCustomCondition();
|
||||||
|
if (customCondition instanceof ApiMappingRequestCondition) {
|
||||||
|
ApiMappingRequestCondition condition = (ApiMappingRequestCondition) customCondition;
|
||||||
|
ApiMappingInfo apiMappingInfo = condition.getApiMappingInfo();
|
||||||
|
String name = apiMappingInfo.getName();
|
||||||
|
String version = apiMappingInfo.getVersion();
|
||||||
|
String path = patterns.iterator().next();
|
||||||
|
// 不是ApiMapping注解的接口,name属性是null
|
||||||
|
if (name == null) {
|
||||||
|
name = buildName(path);
|
||||||
|
}
|
||||||
|
ServiceApiInfo.ApiMeta apiMeta = new ServiceApiInfo.ApiMeta(name, path, version);
|
||||||
|
apiMeta.setIgnoreValidate(apiMappingInfo.isIgnoreValidate());
|
||||||
|
return apiMeta;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
protected String buildName(String path) {
|
protected String buildName(String path) {
|
||||||
path = StringUtils.trimLeadingCharacter(path, '/');
|
path = StringUtils.trimLeadingCharacter(path, '/');
|
||||||
path = StringUtils.trimTrailingCharacter(path, '/');
|
path = StringUtils.trimTrailingCharacter(path, '/');
|
||||||
|
@@ -27,6 +27,11 @@ import java.util.List;
|
|||||||
@Setter
|
@Setter
|
||||||
public class ServiceZookeeperApiMetaManager implements ApiMetaManager {
|
public class ServiceZookeeperApiMetaManager implements ApiMetaManager {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* zookeeper存放接口路由信息的根目录
|
||||||
|
*/
|
||||||
|
public static final String SOP_SERVICE_ROUTE_PATH = "/sop-service-route";
|
||||||
|
public static final String PATH_START_CHAR = "/";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* NameVersion=alipay.story.get1.0
|
* NameVersion=alipay.story.get1.0
|
||||||
@@ -36,8 +41,6 @@ public class ServiceZookeeperApiMetaManager implements ApiMetaManager {
|
|||||||
|
|
||||||
private static ServiceApiInfo.ApiMeta FIRST_API_META = new ServiceApiInfo.ApiMeta("_" + System.currentTimeMillis() + "_", "/", "0.0");
|
private static ServiceApiInfo.ApiMeta FIRST_API_META = new ServiceApiInfo.ApiMeta("_" + System.currentTimeMillis() + "_", "/", "0.0");
|
||||||
|
|
||||||
private String sopServiceApiPath = "/sop-service-api";
|
|
||||||
|
|
||||||
private Environment environment;
|
private Environment environment;
|
||||||
|
|
||||||
public ServiceZookeeperApiMetaManager(Environment environment) {
|
public ServiceZookeeperApiMetaManager(Environment environment) {
|
||||||
@@ -97,11 +100,27 @@ public class ServiceZookeeperApiMetaManager implements ApiMetaManager {
|
|||||||
List<GatewayPredicateDefinition> predicates = Arrays.asList(this.buildNameVersionPredicateDefinition(apiMeta));
|
List<GatewayPredicateDefinition> predicates = Arrays.asList(this.buildNameVersionPredicateDefinition(apiMeta));
|
||||||
gatewayRouteDefinition.setPredicates(predicates);
|
gatewayRouteDefinition.setPredicates(predicates);
|
||||||
// lb://story-service#/alipay.story.get/
|
// lb://story-service#/alipay.story.get/
|
||||||
String servletPath = "#" + apiMeta.getPath();
|
String uri = this.buildUri(serviceApiInfo, apiMeta);
|
||||||
gatewayRouteDefinition.setUri("lb://" + serviceApiInfo.getAppName() + servletPath);
|
gatewayRouteDefinition.setUri(uri);
|
||||||
|
gatewayRouteDefinition.setIgnoreValidate(apiMeta.isIgnoreValidate());
|
||||||
return gatewayRouteDefinition;
|
return gatewayRouteDefinition;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected String buildUri(ServiceApiInfo serviceApiInfo, ServiceApiInfo.ApiMeta apiMeta) {
|
||||||
|
String servletPath = getServletPath(serviceApiInfo, apiMeta);
|
||||||
|
if (servletPath == null) {
|
||||||
|
servletPath = PATH_START_CHAR;
|
||||||
|
}
|
||||||
|
if (!servletPath.startsWith(PATH_START_CHAR)) {
|
||||||
|
servletPath = PATH_START_CHAR + servletPath;
|
||||||
|
}
|
||||||
|
return "lb://" + serviceApiInfo.getAppName() + "#" + servletPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String getServletPath(ServiceApiInfo serviceApiInfo, ServiceApiInfo.ApiMeta apiMeta) {
|
||||||
|
return apiMeta.getPath();
|
||||||
|
}
|
||||||
|
|
||||||
protected GatewayPredicateDefinition buildNameVersionPredicateDefinition(ServiceApiInfo.ApiMeta apiMeta) {
|
protected GatewayPredicateDefinition buildNameVersionPredicateDefinition(ServiceApiInfo.ApiMeta apiMeta) {
|
||||||
return new GatewayPredicateDefinition(String.format(QUERY_PREDICATE_DEFINITION_TPL, apiMeta.fetchNameVersion()));
|
return new GatewayPredicateDefinition(String.format(QUERY_PREDICATE_DEFINITION_TPL, apiMeta.fetchNameVersion()));
|
||||||
}
|
}
|
||||||
@@ -120,7 +139,7 @@ public class ServiceZookeeperApiMetaManager implements ApiMetaManager {
|
|||||||
CuratorFramework client = null;
|
CuratorFramework client = null;
|
||||||
try {
|
try {
|
||||||
// 保存路径
|
// 保存路径
|
||||||
String savePath = sopServiceApiPath + "/" + serviceRouteInfo.getAppName();
|
String savePath = SOP_SERVICE_ROUTE_PATH + "/" + serviceRouteInfo.getAppName();
|
||||||
|
|
||||||
client = CuratorFrameworkFactory.builder()
|
client = CuratorFrameworkFactory.builder()
|
||||||
.connectString(zookeeperServerAddr)
|
.connectString(zookeeperServerAddr)
|
||||||
|
@@ -3,6 +3,7 @@ package com.gitee.sop.servercommon.mapping;
|
|||||||
import com.gitee.sop.servercommon.annotation.ApiMapping;
|
import com.gitee.sop.servercommon.annotation.ApiMapping;
|
||||||
import com.gitee.sop.servercommon.annotation.ApiAbility;
|
import com.gitee.sop.servercommon.annotation.ApiAbility;
|
||||||
import com.gitee.sop.servercommon.bean.ServiceConfig;
|
import com.gitee.sop.servercommon.bean.ServiceConfig;
|
||||||
|
import com.gitee.sop.servercommon.bean.ServiceContext;
|
||||||
import com.gitee.sop.servercommon.manager.RequestMappingEvent;
|
import com.gitee.sop.servercommon.manager.RequestMappingEvent;
|
||||||
import org.springframework.core.PriorityOrdered;
|
import org.springframework.core.PriorityOrdered;
|
||||||
import org.springframework.core.annotation.AnnotationUtils;
|
import org.springframework.core.annotation.AnnotationUtils;
|
||||||
@@ -42,14 +43,17 @@ public class ApiMappingHandlerMapping extends RequestMappingHandlerMapping imple
|
|||||||
method.setAccessible(true);
|
method.setAccessible(true);
|
||||||
String name = null;
|
String name = null;
|
||||||
String version;
|
String version;
|
||||||
|
boolean ignoreValidate = false;
|
||||||
ApiMapping apiMapping = method.getAnnotation(ApiMapping.class);
|
ApiMapping apiMapping = method.getAnnotation(ApiMapping.class);
|
||||||
if (apiMapping != null) {
|
if (apiMapping != null) {
|
||||||
name = apiMapping.value()[0];
|
name = apiMapping.value()[0];
|
||||||
version = apiMapping.version();
|
version = apiMapping.version();
|
||||||
|
ignoreValidate = apiMapping.ignoreValidate();
|
||||||
} else {
|
} else {
|
||||||
ApiAbility apiAbility = this.findApiAbilityAnnotation(method);
|
ApiAbility apiAbility = this.findApiAbilityAnnotation(method);
|
||||||
if (apiAbility != null) {
|
if (apiAbility != null) {
|
||||||
version = apiAbility.version();
|
version = apiAbility.version();
|
||||||
|
ignoreValidate = apiAbility.ignoreValidate();
|
||||||
} else {
|
} else {
|
||||||
return super.getCustomMethodCondition(method);
|
return super.getCustomMethodCondition(method);
|
||||||
}
|
}
|
||||||
@@ -58,6 +62,11 @@ public class ApiMappingHandlerMapping extends RequestMappingHandlerMapping imple
|
|||||||
version = ServiceConfig.getInstance().getDefaultVersion();
|
version = ServiceConfig.getInstance().getDefaultVersion();
|
||||||
}
|
}
|
||||||
ApiMappingInfo apiMappingInfo = new ApiMappingInfo(name, version);
|
ApiMappingInfo apiMappingInfo = new ApiMappingInfo(name, version);
|
||||||
|
// 如果是默认配置,则采用全局配置
|
||||||
|
if (!ignoreValidate) {
|
||||||
|
ignoreValidate = ServiceConfig.getInstance().isIgnoreValidate();
|
||||||
|
}
|
||||||
|
apiMappingInfo.setIgnoreValidate(ignoreValidate);
|
||||||
logger.info("注册接口,method:" + method + ", version:" + version);
|
logger.info("注册接口,method:" + method + ", version:" + version);
|
||||||
return new ApiMappingRequestCondition(apiMappingInfo);
|
return new ApiMappingRequestCondition(apiMappingInfo);
|
||||||
}
|
}
|
||||||
|
@@ -9,6 +9,7 @@ import lombok.Data;
|
|||||||
public class ApiMappingInfo {
|
public class ApiMappingInfo {
|
||||||
private String name;
|
private String name;
|
||||||
private String version;
|
private String version;
|
||||||
|
private boolean ignoreValidate;
|
||||||
|
|
||||||
public ApiMappingInfo(String name, String version) {
|
public ApiMappingInfo(String name, String version) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
|
@@ -20,4 +20,6 @@ public class GatewayRouteDefinition {
|
|||||||
private String uri;
|
private String uri;
|
||||||
/** 路由执行的顺序 */
|
/** 路由执行的顺序 */
|
||||||
private int order = 0;
|
private int order = 0;
|
||||||
|
/** 是否忽略验证,业务参数验证除外 */
|
||||||
|
private boolean ignoreValidate;
|
||||||
}
|
}
|
@@ -0,0 +1,93 @@
|
|||||||
|
package com.gitee.sop;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSON;
|
||||||
|
import junit.framework.TestCase;
|
||||||
|
import org.apache.commons.codec.digest.DigestUtils;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.URLEncoder;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author tanghc
|
||||||
|
*/
|
||||||
|
public class EasyopenClientPostTest extends TestBase {
|
||||||
|
|
||||||
|
String url = "http://localhost:8081/api";
|
||||||
|
String appKey = "easyopen_test";
|
||||||
|
String secret = "G9w0BAQEFAAOCAQ8AMIIBCgKCA";
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPost() throws IOException {
|
||||||
|
// 业务参数
|
||||||
|
Map<String, String> bizParams = new HashMap<String, String>();
|
||||||
|
bizParams.put("goods_name", "iphoneX");
|
||||||
|
|
||||||
|
String json = JSON.toJSONString(bizParams);
|
||||||
|
json = URLEncoder.encode(json, "utf-8");
|
||||||
|
|
||||||
|
// 系统参数
|
||||||
|
Map<String, String> params = new HashMap<>();
|
||||||
|
params.put("name", "goods.get");
|
||||||
|
params.put("app_key", appKey);
|
||||||
|
params.put("data", json);
|
||||||
|
params.put("timestamp", getTime());
|
||||||
|
params.put("version", "");
|
||||||
|
|
||||||
|
String sign = buildSign(params, secret);
|
||||||
|
|
||||||
|
params.put("sign", sign);
|
||||||
|
|
||||||
|
System.out.println("=====请求数据=====");
|
||||||
|
System.out.println(JSON.toJSONString(params));
|
||||||
|
System.out.println("=====返回结果=====");
|
||||||
|
String resp = post(url, params);
|
||||||
|
System.out.println(resp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构建签名串
|
||||||
|
* @param paramsMap 请求参数
|
||||||
|
* @param secret 秘钥
|
||||||
|
* @return
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
public String buildSign(Map<String, ?> paramsMap, String secret) throws IOException {
|
||||||
|
Set<String> keySet = paramsMap.keySet();
|
||||||
|
List<String> paramNames = new ArrayList<String>(keySet);
|
||||||
|
|
||||||
|
Collections.sort(paramNames);
|
||||||
|
|
||||||
|
StringBuilder paramNameValue = new StringBuilder();
|
||||||
|
|
||||||
|
for (String paramName : paramNames) {
|
||||||
|
paramNameValue.append(paramName).append(paramsMap.get(paramName));
|
||||||
|
}
|
||||||
|
|
||||||
|
String source = secret + paramNameValue.toString() + secret;
|
||||||
|
|
||||||
|
return md5(source);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成md5,全部大写。
|
||||||
|
*
|
||||||
|
* @param source
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static String md5(String source) {
|
||||||
|
return DigestUtils.md5Hex(source).toUpperCase();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTime() {
|
||||||
|
return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user