From 58cd959e018889dfc4a9e227bf5a3da212727dc6 Mon Sep 17 00:00:00 2001 From: tanghc Date: Tue, 15 Oct 2019 12:41:02 +0800 Subject: [PATCH] =?UTF-8?q?restful=E8=B0=83=E7=94=A8=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- doc/docs/_sidebar.md | 64 +++++++++---------- doc/docs/files/10100_提供restful接口.md | 23 ++++--- .../BaseServiceConfiguration.java | 29 +++------ .../servercommon/manager/ApiMetaBuilder.java | 12 +++- .../manager/EnvironmentContext.java | 23 +++++++ .../servercommon/manager/EnvironmentKeys.java | 37 +++++++++++ 6 files changed, 126 insertions(+), 62 deletions(-) create mode 100644 sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/manager/EnvironmentContext.java create mode 100644 sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/manager/EnvironmentKeys.java diff --git a/doc/docs/_sidebar.md b/doc/docs/_sidebar.md index 55c08219..38a92c3e 100644 --- a/doc/docs/_sidebar.md +++ b/doc/docs/_sidebar.md @@ -1,34 +1,34 @@ -* [首页](/?t=1570680160879) +* [首页](/?t=1571107529420) * 开发文档 - * [快速体验](files/10010_快速体验.md?t=1570680160882) - * [项目接入到SOP](files/10011_项目接入到SOP.md?t=1570680160897) - * [新增接口](files/10020_新增接口.md?t=1570680160897) - * [开发流程](files/10021_开发流程.md?t=1570680160897) - * [业务参数校验](files/10030_业务参数校验.md?t=1570680160897) - * [错误处理](files/10040_错误处理.md?t=1570680160897) - * [编写文档](files/10041_编写文档.md?t=1570680160898) - * [接口交互详解](files/10050_接口交互详解.md?t=1570680160898) - * [easyopen支持](files/10070_easyopen支持.md?t=1570680160898) - * [使用签名校验工具](files/10080_使用签名校验工具.md?t=1570680160898) - * [ISV管理](files/10085_ISV管理.md?t=1570680160898) - * [自定义返回结果](files/10087_自定义返回结果.md?t=1570680160898) - * [自定义过滤器](files/10088_自定义过滤器.md?t=1570680160898) - * [路由授权](files/10090_路由授权.md?t=1570680160898) - * [接口限流](files/10092_接口限流.md?t=1570680160899) - * [监控日志](files/10093_监控日志.md?t=1570680160899) - * [SDK开发](files/10095_SDK开发.md?t=1570680160899) - * [使用SpringCloudGateway](files/10096_使用SpringCloudGateway.md?t=1570680160899) - * [应用授权](files/10097_应用授权.md?t=1570680160899) - * [提供restful接口](files/10100_提供restful接口.md?t=1570680160899) - * [文件上传](files/10104_文件上传.md?t=1570680160899) - * [配置Sleuth链路追踪](files/10109_配置Sleuth链路追踪.md?t=1570680160899) - * [预发布灰度发布](files/10110_预发布灰度发布.md?t=1570680160899) - * [动态修改请求参数](files/10111_动态修改请求参数.md?t=1570680160899) - * [使用eureka](files/10112_使用eureka.md?t=1570680160899) - * [扩展其它注册中心](files/10113_扩展其它注册中心.md?t=1570680160900) + * [快速体验](files/10010_快速体验.md?t=1571107529423) + * [项目接入到SOP](files/10011_项目接入到SOP.md?t=1571107529447) + * [新增接口](files/10020_新增接口.md?t=1571107529447) + * [开发流程](files/10021_开发流程.md?t=1571107529447) + * [业务参数校验](files/10030_业务参数校验.md?t=1571107529447) + * [错误处理](files/10040_错误处理.md?t=1571107529447) + * [编写文档](files/10041_编写文档.md?t=1571107529447) + * [接口交互详解](files/10050_接口交互详解.md?t=1571107529448) + * [easyopen支持](files/10070_easyopen支持.md?t=1571107529448) + * [使用签名校验工具](files/10080_使用签名校验工具.md?t=1571107529448) + * [ISV管理](files/10085_ISV管理.md?t=1571107529448) + * [自定义返回结果](files/10087_自定义返回结果.md?t=1571107529448) + * [自定义过滤器](files/10088_自定义过滤器.md?t=1571107529448) + * [路由授权](files/10090_路由授权.md?t=1571107529448) + * [接口限流](files/10092_接口限流.md?t=1571107529448) + * [监控日志](files/10093_监控日志.md?t=1571107529448) + * [SDK开发](files/10095_SDK开发.md?t=1571107529449) + * [使用SpringCloudGateway](files/10096_使用SpringCloudGateway.md?t=1571107529449) + * [应用授权](files/10097_应用授权.md?t=1571107529449) + * [提供restful接口](files/10100_提供restful接口.md?t=1571107529449) + * [文件上传](files/10104_文件上传.md?t=1571107529449) + * [配置Sleuth链路追踪](files/10109_配置Sleuth链路追踪.md?t=1571107529449) + * [预发布灰度发布](files/10110_预发布灰度发布.md?t=1571107529449) + * [动态修改请求参数](files/10111_动态修改请求参数.md?t=1571107529450) + * [使用eureka](files/10112_使用eureka.md?t=1571107529450) + * [扩展其它注册中心](files/10113_扩展其它注册中心.md?t=1571107529450) * 原理分析 - * [原理分析之@ApiMapping](files/90010_原理分析之@ApiMapping.md?t=1570680160900) - * [原理分析之如何存储路由](files/90011_原理分析之如何存储路由.md?t=1570680160900) - * [原理分析之如何路由](files/90012_原理分析之如何路由.md?t=1570680160900) - * [原理分析之文档归纳](files/90013_原理分析之文档归纳.md?t=1570680160900) - * [常见问题](files/90100_常见问题.md?t=1570680160900) + * [原理分析之@ApiMapping](files/90010_原理分析之@ApiMapping.md?t=1571107529450) + * [原理分析之如何存储路由](files/90011_原理分析之如何存储路由.md?t=1571107529450) + * [原理分析之如何路由](files/90012_原理分析之如何路由.md?t=1571107529450) + * [原理分析之文档归纳](files/90013_原理分析之文档归纳.md?t=1571107529450) + * [常见问题](files/90100_常见问题.md?t=1571107529450) diff --git a/doc/docs/files/10100_提供restful接口.md b/doc/docs/files/10100_提供restful接口.md index 524e7679..46561ec4 100644 --- a/doc/docs/files/10100_提供restful接口.md +++ b/doc/docs/files/10100_提供restful接口.md @@ -11,11 +11,18 @@ sop.restful.enable=true ``` -- 前端app请求网关 +- 前端app请求网关(`2.4.1+之后有变动`) -请求格式为:`http://ip:port/rest/your_path`,其中`http://ip:port/rest/`为固定部分,后面跟微服务请求路径。 +请求格式: -注意:为了确保各个微服务路径不冲突,必须保证类上方定义的`@RequestMapping`内容唯一,不与其它微服务重复。 +**2.4.1版本之前:** `http://ip:port/rest/your_path`,其中`http://ip:port/rest/`为固定部分,后面跟微服务请求路径。 + +**2.4.1之后:** `http://ip:port/rest/服务id/your_path`,其中`http://ip:port/rest/`为固定部分,后面跟微服务请求路径。 + +**注意,`2.4.1`开始多了一个服务id作为区分,这样做是为了避免各微服务之间url冲突,假如两个微服务都有一个叫`/getItems`这样的接口 +那么调用`http://ip:port/rest/getItems`接口网关无法做出正确的路由,虽然可以在代码上进行规范,为了防止万一,还是强行加上了,避免采坑** + +> 可在微服务端指定一个配置:`sop.restful.prefix=xxx`。请求路径将变成:`http://ip:port/rest/xxx/your_path` 下面是一个微服务的接口例子 @@ -34,9 +41,9 @@ public class TraditionalWebappController { } ``` -这是一个`食品服务`例子,假设网关ip为10.0.1.11,端口8081;食品服务ip为10.0.1.22,端口2222 +这是一个`食品服务`例子,serviceId为`food-service`,假设网关ip为10.0.1.11,端口8081;食品服务ip为10.0.1.22,端口2222 -1. 网关访问:`http://10.0.1.11:8081/rest/food/getFoodById?id=2` +1. 网关访问:`http://10.0.1.11:8081/rest/food-service/food/getFoodById?id=2` 2. 本地访问:`http://10.0.1.22:2222/food/getFoodById/?id=2` @@ -63,7 +70,7 @@ const client = axios.create({ const RequestUtil = { /** * 请求接口 - * @param url 请求路径,如http://localhost:8081/rest/food/getFoodById + * @param url 请求路径,如http://localhost:8081/rest/food-service/food/getFoodById * @param data 请求数据,json格式 * @param callback 成功回调 * @param errorCallback 失败回调 @@ -101,7 +108,7 @@ jQuery版本如下: var RequestUtil = { /** * 请求接口 - * @param url 请求路径,如http://localhost:8081/rest/food/getFoodById + * @param url 请求路径,如http://localhost:8081/rest/food-service/food/getFoodById * @param data 请求数据,json格式 * @param callback 成功回调 * @param errorCallback 失败回调 @@ -139,7 +146,7 @@ $(function () { id: 1 ,name: '葫芦娃' } - RequestUtil.post('http://localhost:8081/rest/food/getFoodById', data, function (result) { + RequestUtil.post('http://localhost:8081/rest/food-service/food/getFoodById', data, function (result) { console.log(result) }); }) diff --git a/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/configuration/BaseServiceConfiguration.java b/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/configuration/BaseServiceConfiguration.java index 102070cb..2520b137 100644 --- a/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/configuration/BaseServiceConfiguration.java +++ b/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/configuration/BaseServiceConfiguration.java @@ -2,14 +2,15 @@ package com.gitee.sop.servercommon.configuration; import com.gitee.sop.servercommon.bean.ServiceConfig; import com.gitee.sop.servercommon.interceptor.ServiceContextInterceptor; +import com.gitee.sop.servercommon.manager.EnvironmentContext; 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.ApplicationArguments; -import org.springframework.boot.ApplicationRunner; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.context.annotation.Bean; +import org.springframework.core.env.Environment; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.converter.StringHttpMessageConverter; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; @@ -25,8 +26,7 @@ import java.util.List; * @author tanghc */ @Slf4j -public class BaseServiceConfiguration extends WebMvcConfigurationSupport - implements ApplicationRunner { +public class BaseServiceConfiguration extends WebMvcConfigurationSupport { public BaseServiceConfiguration() { ServiceConfig.getInstance().getI18nModules().add("i18n/isp/bizerror"); @@ -34,6 +34,9 @@ public class BaseServiceConfiguration extends WebMvcConfigurationSupport private ApiMappingHandlerMapping apiMappingHandlerMapping = new ApiMappingHandlerMapping(); + @Autowired + private Environment environment; + @Override protected void addResourceHandlers(ResourceHandlerRegistry registry) { super.addResourceHandlers(registry); @@ -85,20 +88,11 @@ public class BaseServiceConfiguration extends WebMvcConfigurationSupport @PostConstruct public final void after() { log.info("-----spring容器加载完毕-----"); + EnvironmentContext.setEnvironment(environment); initMessage(); doAfter(); } - /** - * springboot启动完成后执行 - * @param args 启动参数 - * @throws Exception 出错异常 - */ - @Override - public void run(ApplicationArguments args) throws Exception { - log.info("-----服务器启动完毕-----"); - this.onStartup(args); - } /** * spring容器加载完毕后执行 @@ -107,13 +101,6 @@ public class BaseServiceConfiguration extends WebMvcConfigurationSupport } - /** - * 启动完毕后执行 - * @param args - */ - protected void onStartup(ApplicationArguments args) { - - } protected void initMessage() { ServiceErrorFactory.initMessageSource(ServiceConfig.getInstance().getI18nModules()); diff --git a/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/manager/ApiMetaBuilder.java b/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/manager/ApiMetaBuilder.java index d23d4cf0..e564f569 100644 --- a/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/manager/ApiMetaBuilder.java +++ b/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/manager/ApiMetaBuilder.java @@ -7,6 +7,7 @@ import com.gitee.sop.servercommon.mapping.ApiMappingInfo; import com.gitee.sop.servercommon.mapping.ApiMappingRequestCondition; import com.gitee.sop.servercommon.mapping.RouteUtil; import org.apache.commons.lang3.BooleanUtils; +import org.springframework.util.StringUtils; import org.springframework.web.method.HandlerMethod; import org.springframework.web.servlet.mvc.condition.RequestCondition; import org.springframework.web.servlet.mvc.method.RequestMappingInfo; @@ -91,11 +92,20 @@ public class ApiMetaBuilder { if (!ServiceContext.getCurrentContext().getBoolean(ServiceContext.RESTFUL_KEY, false)) { return null; } + // 如果是restful服务 String path = patterns.iterator().next(); if (path.contains("$") || isIgnorePattern(path)) { return null; } - ServiceApiInfo.ApiMeta apiMeta = new ServiceApiInfo.ApiMeta(path, path, ""); + String name = path; + String prefix = EnvironmentKeys.SOP_RESTFUL_PREFIX.getValue(); + if (StringUtils.isEmpty(prefix)) { + prefix = EnvironmentKeys.SPRING_APPLICATION_NAME.getValue(); + } + if (StringUtils.hasText(prefix)) { + name = "/" + prefix + "/" + StringUtils.trimLeadingCharacter(path, '/'); + } + ServiceApiInfo.ApiMeta apiMeta = new ServiceApiInfo.ApiMeta(name, path, ""); apiMeta.setIgnoreValidate(BooleanUtils.toInteger(true)); apiMeta.setMergeResult(BooleanUtils.toInteger(false)); apiMeta.setPermission(BooleanUtils.toInteger(false)); diff --git a/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/manager/EnvironmentContext.java b/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/manager/EnvironmentContext.java new file mode 100644 index 00000000..8a4f8679 --- /dev/null +++ b/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/manager/EnvironmentContext.java @@ -0,0 +1,23 @@ +package com.gitee.sop.servercommon.manager; + +import org.springframework.core.env.Environment; + +/** + * @author tanghc + */ +public class EnvironmentContext { + private static Environment environment; + + public static Environment getEnvironment() { + return environment; + } + + public static void setEnvironment(Environment environment) { + EnvironmentContext.environment = environment; + } + + public static String getValue(String key, String defaultValue) { + return environment.getProperty(key, defaultValue); + } + +} diff --git a/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/manager/EnvironmentKeys.java b/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/manager/EnvironmentKeys.java new file mode 100644 index 00000000..3ec6bea4 --- /dev/null +++ b/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/manager/EnvironmentKeys.java @@ -0,0 +1,37 @@ +package com.gitee.sop.servercommon.manager; + +import javax.annotation.Nullable; + +public enum EnvironmentKeys { + SPRING_PROFILES_ACTIVE("spring.profiles.active", "default"), + /** + * spring.application.name + */ + SPRING_APPLICATION_NAME("spring.application.name"), + + /** + * sop.restful.prefix=xxx,指定web开发模式前缀,不指定默认为service-id + */ + SOP_RESTFUL_PREFIX("sop.restful.prefix"); + + private String key; + private String defaultValue; + + public String getKey() { + return key; + } + + EnvironmentKeys(String key) { + this.key = key; + } + + EnvironmentKeys(String key, String defaultValue) { + this.key = key; + this.defaultValue = defaultValue; + } + + @Nullable + public String getValue() { + return EnvironmentContext.getValue(key, defaultValue); + } +} \ No newline at end of file