支持easyopen

pull/1/head
tanghc 6 years ago
parent 6e2a0e6c13
commit 6d240ef243
  1. 20
      sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/ServiceRoutesLoader.java
  2. 2
      sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/validate/ApiValidator.java
  3. 4
      sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/param/ZuulParamBuilder.java
  4. 92
      sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/configuration/EasyopenServiceConfiguration.java
  5. 91
      sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/easyopen/EasyopenApiMetaBuilder.java
  6. 24
      sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/easyopen/EasyopenServiceConfiguration.java
  7. 24
      sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/easyopen/EasyopenServiceRouteController.java
  8. 6
      sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/manager/ServiceRouteController.java
  9. 4
      sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/manager/ServiceRouteInfoBuilder.java

@ -20,7 +20,9 @@ import org.springframework.util.CollectionUtils;
import org.springframework.util.DigestUtils; import org.springframework.util.DigestUtils;
import org.springframework.web.client.RestTemplate; import org.springframework.web.client.RestTemplate;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Objects; import java.util.Objects;
/** /**
@ -46,15 +48,9 @@ public class ServiceRoutesLoader<T extends TargetRoute> {
private RestTemplate restTemplate = new RestTemplate(); private RestTemplate restTemplate = new RestTemplate();
private volatile long lastUpdateTime; private Map<String, Long> updateTimeMap = new HashMap<>(16);
public synchronized void load(ApplicationEvent event) { public synchronized void load(ApplicationEvent event) {
long now = System.currentTimeMillis();
// 5秒内只能执行一次,解决重启应用连续加载4次问题
if (now - lastUpdateTime < FIVE_SECONDS) {
return;
}
lastUpdateTime = now;
NamingService namingService = nacosDiscoveryProperties.namingServiceInstance(); NamingService namingService = nacosDiscoveryProperties.namingServiceInstance();
List<ServiceInfo> subscribes = null; List<ServiceInfo> subscribes = null;
try { try {
@ -74,6 +70,14 @@ public class ServiceRoutesLoader<T extends TargetRoute> {
if (Objects.equals(thisServiceId, serviceName)) { if (Objects.equals(thisServiceId, serviceName)) {
continue; continue;
} }
// nacos会不停的触发事件,这里做了一层拦截
// 同一个serviceId5秒内允许访问一次
Long lastUpdateTime = updateTimeMap.getOrDefault(serviceName, 0L);
long now = System.currentTimeMillis();
if (now - lastUpdateTime < FIVE_SECONDS) {
continue;
}
updateTimeMap.put(serviceName, now);
try { try {
String dataId = NacosConfigs.getRouteDataId(serviceName); String dataId = NacosConfigs.getRouteDataId(serviceName);
String groupId = NacosConfigs.GROUP_ROUTE; String groupId = NacosConfigs.GROUP_ROUTE;
@ -85,7 +89,7 @@ public class ServiceRoutesLoader<T extends TargetRoute> {
configService.removeConfig(dataId, groupId); configService.removeConfig(dataId, groupId);
} else { } else {
for (Instance instance : allInstances) { for (Instance instance : allInstances) {
log.info("加载服务路由,instance:{}", instance); log.info("加载服务路由,serviceId:{}, instance:{}",serviceName, instance);
String url = getRouteRequestUrl(instance); String url = getRouteRequestUrl(instance);
ResponseEntity<String> responseEntity = restTemplate.getForEntity(url, String.class); ResponseEntity<String> responseEntity = restTemplate.getForEntity(url, String.class);
if (responseEntity.getStatusCode() == HttpStatus.OK) { if (responseEntity.getStatusCode() == HttpStatus.OK) {

@ -59,7 +59,6 @@ public class ApiValidator implements Validator {
@Override @Override
public void validate(ApiParam param) { public void validate(ApiParam param) {
checkIP(param); checkIP(param);
checkEnable(param);
ApiConfig apiConfig = ApiContext.getApiConfig(); ApiConfig apiConfig = ApiContext.getApiConfig();
if (apiConfig.isIgnoreValidate() || param.fetchIgnoreValidate()) { if (apiConfig.isIgnoreValidate() || param.fetchIgnoreValidate()) {
@ -68,6 +67,7 @@ public class ApiValidator implements Validator {
} }
return; return;
} }
checkEnable(param);
// 需要验证签名,先校验appKey,后校验签名,顺序不能变 // 需要验证签名,先校验appKey,后校验签名,顺序不能变
checkAppKey(param); checkAppKey(param);
checkSign(param); checkSign(param);

@ -5,6 +5,7 @@ import com.gitee.sop.gatewaycommon.param.ApiParam;
import com.gitee.sop.gatewaycommon.param.BaseParamBuilder; import com.gitee.sop.gatewaycommon.param.BaseParamBuilder;
import com.gitee.sop.gatewaycommon.util.RequestUtil; import com.gitee.sop.gatewaycommon.util.RequestUtil;
import com.netflix.zuul.context.RequestContext; import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.http.HttpServletRequestWrapper;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.fileupload.servlet.ServletFileUpload; import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
@ -26,6 +27,9 @@ public class ZuulParamBuilder extends BaseParamBuilder<RequestContext> {
@Override @Override
public Map<String, ?> buildRequestParams(RequestContext ctx) { public Map<String, ?> buildRequestParams(RequestContext ctx) {
HttpServletRequest request = ctx.getRequest(); HttpServletRequest request = ctx.getRequest();
if (request instanceof HttpServletRequestWrapper) {
request = ((HttpServletRequestWrapper) request).getRequest();
}
Map<String, ?> params; Map<String, ?> params;
if (GET.equalsIgnoreCase(request.getMethod())) { if (GET.equalsIgnoreCase(request.getMethod())) {
params = RequestUtil.convertRequestParamsToMap(request); params = RequestUtil.convertRequestParamsToMap(request);

@ -1,92 +0,0 @@
package com.gitee.sop.servercommon.configuration;
import com.gitee.easyopen.ApiContext;
import com.gitee.easyopen.annotation.Api;
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 org.apache.commons.lang3.BooleanUtils;
import org.springframework.context.ApplicationContext;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.core.env.Environment;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
/**
* 提供给easyopen项目使用
*
* @author tanghc
*/
public class EasyopenServiceConfiguration extends BaseServiceConfiguration {
static {
ApiContext.getApiConfig().setIgnoreValidate(true);
}
class EasyopenRequestMappingEvent extends DefaultRequestMappingEvent {
String prefixPath;
public EasyopenRequestMappingEvent(ApiMetaManager apiMetaManager, Environment environment) {
super(apiMetaManager, environment);
String path = getEnvironment().getProperty("easyopen.prefix-path");
if (path == null) {
throw new IllegalArgumentException("请在application.propertis中设置easyopen.prefix-path属性,填IndexController上面的@RequestMapping()中的值");
}
this.prefixPath = path;
}
@Override
protected List<ServiceApiInfo.ApiMeta> buildApiMetaList(RequestMappingHandlerMapping requestMappingHandlerMapping) {
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(BooleanUtils.toInteger(api.ignoreValidate()));
// 对结果不合并
apiMeta.setMergeResult(BooleanUtils.toInteger(false));
// /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;
}
}
}

@ -0,0 +1,91 @@
package com.gitee.sop.servercommon.easyopen;
import com.gitee.easyopen.annotation.Api;
import com.gitee.easyopen.util.ReflectionUtil;
import com.gitee.sop.servercommon.bean.ServiceApiInfo;
import com.gitee.sop.servercommon.manager.ApiMetaBuilder;
import org.apache.commons.lang3.BooleanUtils;
import org.springframework.context.ApplicationContext;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.core.env.Environment;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
/**
* @author tanghc
*/
public class EasyopenApiMetaBuilder extends ApiMetaBuilder {
/** IndexController上面的@RequestMapping()中的值,如:/api */
private final String prefixPath;
private final String contextPath;
private ApplicationContext applicationContext;
private Environment environment;
public EasyopenApiMetaBuilder(ApplicationContext applicationContext, Environment environment) {
this.applicationContext = applicationContext;
this.environment = environment;
String path = environment.getProperty("easyopen.prefix-path");
if (path == null) {
throw new IllegalArgumentException("请在application.propertis中设置easyopen.prefix-path属性,填IndexController上面的@RequestMapping()中的值");
}
if (!path.startsWith("/")) {
path = "/" + path;
}
this.prefixPath = path;
this.contextPath = environment.getProperty("server.servlet.context-path", "/");
}
@Override
protected List<ServiceApiInfo.ApiMeta> buildApiMetaList(RequestMappingHandlerMapping requestMappingHandlerMapping) {
String[] apiServiceNames = ReflectionUtil.findApiServiceNames(applicationContext);
List<ServiceApiInfo.ApiMeta> apiMetaList = new ArrayList<>();
for (String apiServiceName : apiServiceNames) {
Object bean = applicationContext.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(BooleanUtils.toInteger(api.ignoreValidate()));
// 对结果不合并
apiMeta.setMergeResult(BooleanUtils.toInteger(false));
// /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 contextPath + prefixPath + servletPath;
}
}

@ -0,0 +1,24 @@
package com.gitee.sop.servercommon.easyopen;
import com.gitee.easyopen.ApiContext;
import com.gitee.sop.servercommon.configuration.BaseServiceConfiguration;
import com.gitee.sop.servercommon.manager.ServiceRouteController;
import org.springframework.context.annotation.Bean;
/**
* 提供给easyopen项目使用
*
* @author tanghc
*/
public class EasyopenServiceConfiguration extends BaseServiceConfiguration {
static {
ApiContext.getApiConfig().setIgnoreValidate(true);
}
@Bean
ServiceRouteController serviceRouteController() {
return new EasyopenServiceRouteController();
}
}

@ -0,0 +1,24 @@
package com.gitee.sop.servercommon.easyopen;
import com.gitee.sop.servercommon.manager.ApiMetaBuilder;
import com.gitee.sop.servercommon.manager.ServiceRouteController;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class EasyopenServiceRouteController extends ServiceRouteController implements ApplicationContextAware {
private ApplicationContext applicationContext;
@Override
protected ApiMetaBuilder getApiMetaBuilder() {
return new EasyopenApiMetaBuilder(applicationContext, getEnvironment());
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
}

@ -40,9 +40,13 @@ public class ServiceRouteController {
return getServiceRouteInfo(request, response); return getServiceRouteInfo(request, response);
} }
protected ApiMetaBuilder getApiMetaBuilder() {
return new ApiMetaBuilder();
}
protected ServiceRouteInfo getServiceRouteInfo(HttpServletRequest request, HttpServletResponse response) { protected ServiceRouteInfo getServiceRouteInfo(HttpServletRequest request, HttpServletResponse response) {
String serviceId = environment.getProperty("spring.application.name"); String serviceId = environment.getProperty("spring.application.name");
ApiMetaBuilder apiMetaBuilder = new ApiMetaBuilder(); ApiMetaBuilder apiMetaBuilder = getApiMetaBuilder();
ServiceApiInfo serviceApiInfo = apiMetaBuilder.getServiceApiInfo(serviceId, requestMappingHandlerMapping); ServiceApiInfo serviceApiInfo = apiMetaBuilder.getServiceApiInfo(serviceId, requestMappingHandlerMapping);
ServiceRouteInfoBuilder serviceRouteInfoBuilder = new ServiceRouteInfoBuilder(environment); ServiceRouteInfoBuilder serviceRouteInfoBuilder = new ServiceRouteInfoBuilder(environment);
return serviceRouteInfoBuilder.build(serviceApiInfo); return serviceRouteInfoBuilder.build(serviceApiInfo);

@ -147,4 +147,8 @@ public class ServiceRouteInfoBuilder {
throw new IllegalArgumentException(errorMsg); throw new IllegalArgumentException(errorMsg);
} }
} }
public Environment getEnvironment() {
return environment;
}
} }

Loading…
Cancel
Save