From e28fd3b2ec48e0183a969bcb42341b373c3c3b97 Mon Sep 17 00:00:00 2001 From: tanghc Date: Sun, 14 Apr 2019 23:35:15 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 1 + .../zuul/param/ZuulParamBuilder.java | 11 +-- sop-common/sop-service-common/pom.xml | 18 ++++ .../servercommon/annotation/ApiMapping.java | 2 +- .../servercommon/bean/EnvironmentContext.java | 27 ++++++ .../BaseServiceConfiguration.java | 36 +++++++- .../EasyopenServiceConfiguration.java | 4 +- .../SpringMvcServiceConfiguration.java | 84 +++++++++++++++++++ .../manager/DefaultRequestMappingEvent.java | 18 ++-- .../manager/RequestMappingEvent.java | 4 +- .../mapping/ApiMappingHandlerMapping.java | 18 +--- .../sop/servercommon/mapping/MappingUtil.java | 20 +++++ .../swagger/ApiListingScannerExt.java | 16 ++++ .../DocumentationPluginsManagerExt.java | 60 +++++++++++++ .../servercommon/swagger/SwaggerSupport.java | 44 ++++++++++ .../gitee/app/config/OpenServiceConfig.java | 15 ++-- .../src/main/webapp/WEB-INF/web.xml | 2 +- sop-example/sop-story/sop-story-web/pom.xml | 24 ++++++ .../sop/bookweb/config/OpenServiceConfig.java | 24 +++++- .../bookweb/controller/AlipayController.java | 9 +- .../bookweb/controller/Story2Controller.java | 3 +- .../bookweb/controller/param/StoryParam.java | 18 ++++ .../com/gitee/sop/PermissionDemoPostTest.java | 17 +--- 23 files changed, 398 insertions(+), 77 deletions(-) create mode 100644 sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/bean/EnvironmentContext.java create mode 100644 sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/configuration/SpringMvcServiceConfiguration.java create mode 100644 sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/mapping/MappingUtil.java create mode 100644 sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/swagger/ApiListingScannerExt.java create mode 100644 sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/swagger/DocumentationPluginsManagerExt.java create mode 100644 sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/swagger/SwaggerSupport.java create mode 100644 sop-example/sop-story/sop-story-web/src/main/java/com/gitee/sop/bookweb/controller/param/StoryParam.java diff --git a/pom.xml b/pom.xml index 4d774179..5c3c18ab 100644 --- a/pom.xml +++ b/pom.xml @@ -19,5 +19,6 @@ sop-gateway sop-test sop-sdk + sop-website \ No newline at end of file diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/param/ZuulParamBuilder.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/param/ZuulParamBuilder.java index 2cff83b6..05a0f92c 100644 --- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/param/ZuulParamBuilder.java +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/param/ZuulParamBuilder.java @@ -1,7 +1,6 @@ package com.gitee.sop.gatewaycommon.zuul.param; -import com.alibaba.fastjson.JSON; -import com.gitee.sop.gatewaycommon.bean.SopConstants; +import com.gitee.sop.gatewaycommon.message.ErrorEnum; import com.gitee.sop.gatewaycommon.param.ApiParam; import com.gitee.sop.gatewaycommon.param.ApiParamFactory; import com.gitee.sop.gatewaycommon.param.ApiUploadContext; @@ -64,13 +63,7 @@ public class ZuulParamBuilder implements ParamBuilder { // json或者纯文本形式 if (contentType.contains(CONTENT_TYPE_JSON) || contentType.contains(CONTENT_TYPE_TEXT)) { - String txt = SopConstants.EMPTY_JSON; - try { - txt = RequestUtil.getText(request); - } catch (Exception e) { - log.error("获取纯文本内容失败", e); - } - params = JSON.parseObject(txt); + throw ErrorEnum.ISV_INVALID_CONTENT_TYPE.getErrorMeta().getException(); } else { params = RequestUtil.convertRequestParamsToMap(request); } diff --git a/sop-common/sop-service-common/pom.xml b/sop-common/sop-service-common/pom.xml index 78e6b080..b38cab02 100644 --- a/sop-common/sop-service-common/pom.xml +++ b/sop-common/sop-service-common/pom.xml @@ -33,6 +33,24 @@ 1.16.1 true + + io.springfox + springfox-spring-web + 2.9.2 + true + + + io.swagger + swagger-annotations + 1.5.21 + compile + true + + + org.springframework.boot + spring-boot + true + diff --git a/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/annotation/ApiMapping.java b/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/annotation/ApiMapping.java index a9ba2841..3fdb1d89 100644 --- a/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/annotation/ApiMapping.java +++ b/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/annotation/ApiMapping.java @@ -59,7 +59,7 @@ public @interface ApiMapping { @AliasFor(annotation = RequestMapping.class) - RequestMethod[] method() default {}; + RequestMethod[] method() default {RequestMethod.GET, RequestMethod.POST}; /** * Alias for {@link RequestMapping#params}. diff --git a/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/bean/EnvironmentContext.java b/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/bean/EnvironmentContext.java new file mode 100644 index 00000000..1244ea8c --- /dev/null +++ b/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/bean/EnvironmentContext.java @@ -0,0 +1,27 @@ +package com.gitee.sop.servercommon.bean; + +import org.springframework.core.env.Environment; + +/** + * @author thc + */ +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 getProfile(Environment env) { + return env.getProperty("spring.profiles.active", "default"); + } + + public static String getProfile() { + return getProfile(environment); + } +} \ No newline at end of file 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 94d54fdb..ba210c8a 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 @@ -8,7 +8,10 @@ import com.gitee.sop.servercommon.manager.RequestMappingEvent; import com.gitee.sop.servercommon.manager.ServiceZookeeperApiMetaManager; import com.gitee.sop.servercommon.mapping.ApiMappingHandlerMapping; import com.gitee.sop.servercommon.message.ServiceErrorFactory; +import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.ApplicationArguments; +import org.springframework.boot.ApplicationRunner; import org.springframework.context.annotation.Bean; import org.springframework.core.env.Environment; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; @@ -20,7 +23,9 @@ import javax.annotation.PostConstruct; /** * @author tanghc */ -public class BaseServiceConfiguration extends WebMvcConfigurationSupport { +@Slf4j +public class BaseServiceConfiguration extends WebMvcConfigurationSupport + implements ApplicationRunner { public BaseServiceConfiguration() { ServiceConfig.getInstance().getI18nModules().add("i18n/isp/bizerror"); @@ -29,6 +34,9 @@ public class BaseServiceConfiguration extends WebMvcConfigurationSupport { @Autowired private Environment environment; + private ApiMappingHandlerMapping apiMappingHandlerMapping = new ApiMappingHandlerMapping(); + + @Override protected void addInterceptors(InterceptorRegistry registry) { // 添加拦截器 @@ -42,9 +50,7 @@ public class BaseServiceConfiguration extends WebMvcConfigurationSupport { */ @Override protected RequestMappingHandlerMapping createRequestMappingHandlerMapping() { - ApiMetaManager apiMetaManager = getApiMetaManager(environment); - RequestMappingEvent requestMappingEvent = getRequestMappingEvent(apiMetaManager, environment); - return new ApiMappingHandlerMapping(requestMappingEvent); + return apiMappingHandlerMapping; } protected RequestMappingEvent getRequestMappingEvent(ApiMetaManager apiMetaManager, Environment environment) { @@ -62,14 +68,36 @@ public class BaseServiceConfiguration extends WebMvcConfigurationSupport { @PostConstruct public final void after() { + log.info("-----spring容器加载完毕-----"); initMessage(); doAfter(); } + // springboot启动完成后执行 + @Override + public void run(ApplicationArguments args) throws Exception { + log.info("-----服务器启动完毕-----"); + ApiMetaManager apiMetaManager = getApiMetaManager(environment); + RequestMappingEvent requestMappingEvent = getRequestMappingEvent(apiMetaManager, environment); + requestMappingEvent.onRegisterSuccess(apiMappingHandlerMapping); + this.onStartup(args); + } + + /** + * spring容器加载完毕后执行 + */ protected void doAfter() { } + /** + * 启动完毕后执行 + * @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/configuration/EasyopenServiceConfiguration.java b/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/configuration/EasyopenServiceConfiguration.java index 015e7ab2..f0d4b7e1 100644 --- a/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/configuration/EasyopenServiceConfiguration.java +++ b/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/configuration/EasyopenServiceConfiguration.java @@ -7,12 +7,12 @@ 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.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; @@ -49,7 +49,7 @@ public class EasyopenServiceConfiguration extends BaseServiceConfiguration { } @Override - protected List buildApiMetaList(ApiMappingHandlerMapping apiMappingHandlerMapping) { + protected List buildApiMetaList(RequestMappingHandlerMapping requestMappingHandlerMapping) { ApplicationContext ctx = getApplicationContext(); String[] apiServiceNames = ReflectionUtil.findApiServiceNames(ctx); List apiMetaList = new ArrayList<>(); diff --git a/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/configuration/SpringMvcServiceConfiguration.java b/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/configuration/SpringMvcServiceConfiguration.java new file mode 100644 index 00000000..c78307e2 --- /dev/null +++ b/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/configuration/SpringMvcServiceConfiguration.java @@ -0,0 +1,84 @@ +package com.gitee.sop.servercommon.configuration; + +import com.gitee.sop.servercommon.bean.EnvironmentContext; +import com.gitee.sop.servercommon.bean.ServiceConfig; +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.manager.ServiceZookeeperApiMetaManager; +import com.gitee.sop.servercommon.mapping.ApiMappingHandlerMapping; +import com.gitee.sop.servercommon.message.ServiceErrorFactory; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Primary; +import org.springframework.core.env.Environment; +import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; + +import javax.annotation.PostConstruct; +import java.util.concurrent.Executors; + +/** + * 提供给springmvc工程 + * @author tanghc + */ +@Slf4j +public class SpringMvcServiceConfiguration { + + public SpringMvcServiceConfiguration() { + ServiceConfig.getInstance().getI18nModules().add("i18n/isp/bizerror"); + } + + private ApiMappingHandlerMapping apiMappingHandlerMapping = new ApiMappingHandlerMapping(); + + @Autowired + private Environment environment; + + + /** + * 自定义Mapping,详见@ApiMapping + * + * @return 返回RequestMappingHandlerMapping + */ + @Bean + @Primary + public RequestMappingHandlerMapping requestMappingHandlerMapping() { + return apiMappingHandlerMapping; + } + + + @Bean + GlobalExceptionHandler globalExceptionHandler() { + return ServiceConfig.getInstance().getGlobalExceptionHandler(); + } + + @PostConstruct + public final void after() { + log.info("-----spring容器加载完毕-----"); + EnvironmentContext.setEnvironment(environment); + Executors.newSingleThreadExecutor().execute(()->{ + uploadRouteToZookeeper(); + }); + initMessage(); + doAfter(); + } + + private void uploadRouteToZookeeper() { + ApiMetaManager apiMetaManager = new ServiceZookeeperApiMetaManager(environment); + RequestMappingEvent requestMappingEvent = new DefaultRequestMappingEvent(apiMetaManager, environment); + requestMappingEvent.onRegisterSuccess(apiMappingHandlerMapping); + } + + + /** + * spring容器加载完毕后执行 + */ + protected void doAfter() { + + } + + protected void initMessage() { + ServiceErrorFactory.initMessageSource(ServiceConfig.getInstance().getI18nModules()); + } + +} diff --git a/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/manager/DefaultRequestMappingEvent.java b/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/manager/DefaultRequestMappingEvent.java index 016552f4..db470b77 100644 --- a/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/manager/DefaultRequestMappingEvent.java +++ b/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/manager/DefaultRequestMappingEvent.java @@ -1,19 +1,18 @@ package com.gitee.sop.servercommon.manager; import com.gitee.sop.servercommon.bean.ServiceApiInfo; -import com.gitee.sop.servercommon.mapping.ApiMappingHandlerMapping; import com.gitee.sop.servercommon.mapping.ApiMappingInfo; import com.gitee.sop.servercommon.mapping.ApiMappingRequestCondition; +import com.gitee.sop.servercommon.mapping.MappingUtil; import lombok.Getter; import org.apache.commons.lang3.BooleanUtils; import org.springframework.core.env.Environment; -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; +import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; import java.util.ArrayList; -import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.Map; @@ -34,12 +33,12 @@ public class DefaultRequestMappingEvent implements RequestMappingEvent { } @Override - public void onRegisterSuccess(ApiMappingHandlerMapping apiMappingHandlerMapping) { + public void onRegisterSuccess(RequestMappingHandlerMapping requestMappingHandlerMapping) { String serviceId = environment.getProperty("spring.application.name"); if (serviceId == null) { throw new IllegalArgumentException("请在application.properties中指定spring.application.name属性"); } - List apis = this.buildApiMetaList(apiMappingHandlerMapping); + List apis = this.buildApiMetaList(requestMappingHandlerMapping); // 排序 apis.sort(Comparator.comparing(ServiceApiInfo.ApiMeta::fetchNameVersion)); @@ -50,8 +49,8 @@ public class DefaultRequestMappingEvent implements RequestMappingEvent { apiMetaManager.uploadApi(serviceApiInfo); } - protected List buildApiMetaList(ApiMappingHandlerMapping apiMappingHandlerMapping) { - Map handlerMethods = apiMappingHandlerMapping.getHandlerMethods(); + protected List buildApiMetaList(RequestMappingHandlerMapping requestMappingHandlerMapping) { + Map handlerMethods = requestMappingHandlerMapping.getHandlerMethods(); Set requestMappingInfos = handlerMethods.keySet(); List store = new ArrayList<>(); List apis = new ArrayList<>(requestMappingInfos.size()); @@ -96,10 +95,7 @@ public class DefaultRequestMappingEvent implements RequestMappingEvent { } protected String buildName(String path) { - path = StringUtils.trimLeadingCharacter(path, '/'); - path = StringUtils.trimTrailingCharacter(path, '/'); - path = path.replace("/", "."); - return path; + return MappingUtil.buildApiName(path); } } diff --git a/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/manager/RequestMappingEvent.java b/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/manager/RequestMappingEvent.java index 5a798ab8..d117a793 100644 --- a/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/manager/RequestMappingEvent.java +++ b/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/manager/RequestMappingEvent.java @@ -1,6 +1,6 @@ package com.gitee.sop.servercommon.manager; -import com.gitee.sop.servercommon.mapping.ApiMappingHandlerMapping; +import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; /** * @author tanghc @@ -10,5 +10,5 @@ public interface RequestMappingEvent { * 注册成功后回调 * @param apiMappingHandlerMapping */ - void onRegisterSuccess(ApiMappingHandlerMapping apiMappingHandlerMapping); + void onRegisterSuccess(RequestMappingHandlerMapping apiMappingHandlerMapping); } diff --git a/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/mapping/ApiMappingHandlerMapping.java b/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/mapping/ApiMappingHandlerMapping.java index 0c7684d5..9ae43b00 100644 --- a/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/mapping/ApiMappingHandlerMapping.java +++ b/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/mapping/ApiMappingHandlerMapping.java @@ -1,10 +1,8 @@ package com.gitee.sop.servercommon.mapping; -import com.gitee.sop.servercommon.annotation.ApiMapping; import com.gitee.sop.servercommon.annotation.ApiAbility; +import com.gitee.sop.servercommon.annotation.ApiMapping; import com.gitee.sop.servercommon.bean.ServiceConfig; -import com.gitee.sop.servercommon.bean.ServiceContext; -import com.gitee.sop.servercommon.manager.RequestMappingEvent; import org.springframework.core.PriorityOrdered; import org.springframework.core.annotation.AnnotationUtils; import org.springframework.util.StringValueResolver; @@ -21,12 +19,6 @@ public class ApiMappingHandlerMapping extends RequestMappingHandlerMapping imple private static StringValueResolver stringValueResolver = new ApiMappingStringValueResolver(); - private RequestMappingEvent requestMappingEvent; - - public ApiMappingHandlerMapping(RequestMappingEvent requestMappingEvent) { - this.requestMappingEvent = requestMappingEvent; - } - @Override protected RequestMappingInfo getMappingForMethod(Method method, Class handlerType) { ApiMapping apiMapping = method.getAnnotation(ApiMapping.class); @@ -83,7 +75,7 @@ public class ApiMappingHandlerMapping extends RequestMappingHandlerMapping imple apiMappingInfo.setIgnoreValidate(ignoreValidate); apiMappingInfo.setMergeResult(mergeResult); apiMappingInfo.setPermission(permission); - logger.info("注册接口,method:" + method + ", version:" + version); + logger.info("注册接口,name:" + method + ", version:" + version); return new ApiMappingRequestCondition(apiMappingInfo); } @@ -95,10 +87,4 @@ public class ApiMappingHandlerMapping extends RequestMappingHandlerMapping imple } return apiAbility; } - - @Override - public void afterPropertiesSet() { - super.afterPropertiesSet(); - this.requestMappingEvent.onRegisterSuccess(this); - } } \ No newline at end of file diff --git a/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/mapping/MappingUtil.java b/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/mapping/MappingUtil.java new file mode 100644 index 00000000..4b3b1712 --- /dev/null +++ b/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/mapping/MappingUtil.java @@ -0,0 +1,20 @@ +package com.gitee.sop.servercommon.mapping; + +import org.springframework.util.StringUtils; + +/** + * @author tanghc + */ +public class MappingUtil { + /** + * 将springmvc接口路径转换成SOP方法名 + * @param path springmvc路径,如/a/b,/goods/listGoods + * @return + */ + public static String buildApiName(String path) { + path = StringUtils.trimLeadingCharacter(path, '/'); + path = StringUtils.trimTrailingCharacter(path, '/'); + path = path.replace("/", "."); + return path; + } +} diff --git a/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/swagger/ApiListingScannerExt.java b/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/swagger/ApiListingScannerExt.java new file mode 100644 index 00000000..fd322af4 --- /dev/null +++ b/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/swagger/ApiListingScannerExt.java @@ -0,0 +1,16 @@ +package com.gitee.sop.servercommon.swagger; + +import springfox.documentation.spring.web.plugins.DocumentationPluginsManager; +import springfox.documentation.spring.web.scanners.ApiDescriptionReader; +import springfox.documentation.spring.web.scanners.ApiListingScanner; +import springfox.documentation.spring.web.scanners.ApiModelReader; + +/** + * @author tanghc + */ +public class ApiListingScannerExt extends ApiListingScanner { + public ApiListingScannerExt(ApiDescriptionReader apiDescriptionReader, ApiModelReader apiModelReader, DocumentationPluginsManager pluginsManager) { + super(apiDescriptionReader, apiModelReader, pluginsManager); + } + +} diff --git a/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/swagger/DocumentationPluginsManagerExt.java b/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/swagger/DocumentationPluginsManagerExt.java new file mode 100644 index 00000000..2cdbd0a0 --- /dev/null +++ b/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/swagger/DocumentationPluginsManagerExt.java @@ -0,0 +1,60 @@ +package com.gitee.sop.servercommon.swagger; + +import com.gitee.sop.servercommon.annotation.ApiAbility; +import com.gitee.sop.servercommon.annotation.ApiMapping; +import com.gitee.sop.servercommon.bean.ServiceConfig; +import com.gitee.sop.servercommon.mapping.MappingUtil; +import com.google.common.base.Optional; +import springfox.documentation.service.Operation; +import springfox.documentation.service.StringVendorExtension; +import springfox.documentation.service.VendorExtension; +import springfox.documentation.spi.service.contexts.OperationContext; +import springfox.documentation.spring.web.plugins.DocumentationPluginsManager; + +import java.util.List; + +/** + * @author tanghc + */ +public class DocumentationPluginsManagerExt extends DocumentationPluginsManager { + + public static final String SOP_NAME = "sop_name"; + public static final String SOP_VERSION = "sop_version"; + + @Override + public Operation operation(OperationContext operationContext) { + Operation operation = super.operation(operationContext); + this.setVendorExtension(operation, operationContext); + return operation; + } + + private void setVendorExtension(Operation operation, OperationContext operationContext) { + List vendorExtensions = operation.getVendorExtensions(); + Optional mappingOptional = operationContext.findAnnotation(ApiMapping.class); + if (mappingOptional.isPresent()) { + ApiMapping apiMapping = mappingOptional.get(); + String name = apiMapping.value()[0]; + String version = buildVersion(apiMapping.version()); + vendorExtensions.add(new StringVendorExtension(SOP_NAME, name)); + vendorExtensions.add(new StringVendorExtension(SOP_VERSION, version)); + } else { + Optional abilityOptional = operationContext.findAnnotation(ApiAbility.class); + if (abilityOptional.isPresent()) { + ApiAbility apiAbility = abilityOptional.get(); + String mappingPattern = operationContext.requestMappingPattern(); + String name = MappingUtil.buildApiName(mappingPattern); + String version = buildVersion(apiAbility.version()); + vendorExtensions.add(new StringVendorExtension(SOP_NAME, name)); + vendorExtensions.add(new StringVendorExtension(SOP_VERSION, version)); + } + } + } + + private String buildVersion(String version) { + if ("".equals(version)) { + return ServiceConfig.getInstance().getDefaultVersion(); + } else { + return version; + } + } +} diff --git a/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/swagger/SwaggerSupport.java b/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/swagger/SwaggerSupport.java new file mode 100644 index 00000000..6097c459 --- /dev/null +++ b/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/swagger/SwaggerSupport.java @@ -0,0 +1,44 @@ +package com.gitee.sop.servercommon.swagger; + +import io.swagger.annotations.ApiOperation; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Primary; +import springfox.documentation.builders.ApiInfoBuilder; +import springfox.documentation.builders.PathSelectors; +import springfox.documentation.builders.RequestHandlerSelectors; +import springfox.documentation.service.ApiInfo; +import springfox.documentation.spi.DocumentationType; +import springfox.documentation.spring.web.plugins.Docket; + +public abstract class SwaggerSupport { + + protected abstract String getDocTitle(); + + @Bean + @Primary + public DocumentationPluginsManagerExt documentationPluginsManagerExt() { + return new DocumentationPluginsManagerExt(); + } + + @Bean + public Docket createRestApi() { + return new Docket(DocumentationType.SWAGGER_2) + .apiInfo(apiInfo()) + .select() + .apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class)) + .paths(PathSelectors.any()) + .build(); + } + + protected ApiInfo apiInfo() { + return new ApiInfoBuilder() + .title(getDocTitle()) + .description("文档描述") + .termsOfServiceUrl("文档") + .version("1.0") + .build(); + } + + + +} \ No newline at end of file diff --git a/sop-example/sop-springmvc/src/main/java/com/gitee/app/config/OpenServiceConfig.java b/sop-example/sop-springmvc/src/main/java/com/gitee/app/config/OpenServiceConfig.java index 8569ac3e..f558b74a 100644 --- a/sop-example/sop-springmvc/src/main/java/com/gitee/app/config/OpenServiceConfig.java +++ b/sop-example/sop-springmvc/src/main/java/com/gitee/app/config/OpenServiceConfig.java @@ -1,20 +1,15 @@ package com.gitee.app.config; -import com.gitee.sop.servercommon.configuration.AlipayServiceConfiguration; -import org.springframework.context.annotation.Bean; -import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; +import com.gitee.sop.servercommon.bean.ServiceConfig; +import com.gitee.sop.servercommon.configuration.SpringMvcServiceConfiguration; /** * 使用支付宝开放平台功能 * * @author tanghc */ -public class OpenServiceConfig extends AlipayServiceConfiguration { - - @Bean - @Override - public RequestMappingHandlerMapping requestMappingHandlerMapping() { - return super.requestMappingHandlerMapping(); +public class OpenServiceConfig extends SpringMvcServiceConfiguration { + static { + ServiceConfig.getInstance().setDefaultVersion("1.0"); } - } diff --git a/sop-example/sop-springmvc/src/main/webapp/WEB-INF/web.xml b/sop-example/sop-springmvc/src/main/webapp/WEB-INF/web.xml index 405adcf1..3e9cf399 100644 --- a/sop-example/sop-springmvc/src/main/webapp/WEB-INF/web.xml +++ b/sop-example/sop-springmvc/src/main/webapp/WEB-INF/web.xml @@ -17,7 +17,7 @@ com.gitee.app.config.EurekaInitAndRegisterListener - + appServlet diff --git a/sop-example/sop-story/sop-story-web/pom.xml b/sop-example/sop-story/sop-story-web/pom.xml index fbac8a40..5561a64a 100644 --- a/sop-example/sop-story/sop-story-web/pom.xml +++ b/sop-example/sop-story/sop-story-web/pom.xml @@ -17,6 +17,7 @@ 1.8 Greenwich.RELEASE + 2.9.2 @@ -39,6 +40,29 @@ spring-cloud-starter-openfeign + + + io.springfox + springfox-swagger2 + ${swagger.version} + + + io.swagger + swagger-models + + + + + io.swagger + swagger-models + 1.5.21 + + + io.springfox + springfox-swagger-ui + ${swagger.version} + + org.springframework.boot spring-boot-starter-test diff --git a/sop-example/sop-story/sop-story-web/src/main/java/com/gitee/sop/bookweb/config/OpenServiceConfig.java b/sop-example/sop-story/sop-story-web/src/main/java/com/gitee/sop/bookweb/config/OpenServiceConfig.java index 4aeba862..ef398533 100644 --- a/sop-example/sop-story/sop-story-web/src/main/java/com/gitee/sop/bookweb/config/OpenServiceConfig.java +++ b/sop-example/sop-story/sop-story-web/src/main/java/com/gitee/sop/bookweb/config/OpenServiceConfig.java @@ -2,10 +2,10 @@ package com.gitee.sop.bookweb.config; import com.gitee.sop.servercommon.bean.ServiceConfig; import com.gitee.sop.servercommon.configuration.AlipayServiceConfiguration; -import com.gitee.sop.servercommon.configuration.TaobaoServiceConfiguration; +import com.gitee.sop.servercommon.swagger.SwaggerSupport; import org.springframework.context.annotation.Configuration; - -import javax.annotation.PostConstruct; +import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; +import springfox.documentation.swagger2.annotations.EnableSwagger2; /** * 使用支付宝开放平台功能 @@ -19,6 +19,24 @@ public class OpenServiceConfig extends AlipayServiceConfiguration { ServiceConfig.getInstance().getI18nModules().add("i18n/isp/goods_error"); } + @Override + protected void addResourceHandlers(ResourceHandlerRegistry registry) { + super.addResourceHandlers(registry); + registry.addResourceHandler("swagger-ui.html") + .addResourceLocations("classpath:/META-INF/resources/"); + registry.addResourceHandler("/webjars/**") + .addResourceLocations("classpath:/META-INF/resources/webjars/"); + } + + // 开启文档 + @Configuration + @EnableSwagger2 + public static class Swagger2 extends SwaggerSupport { + @Override + protected String getDocTitle() { + return "故事API"; + } + } } /** diff --git a/sop-example/sop-story/sop-story-web/src/main/java/com/gitee/sop/bookweb/controller/AlipayController.java b/sop-example/sop-story/sop-story-web/src/main/java/com/gitee/sop/bookweb/controller/AlipayController.java index 6d9741ed..92b8a13e 100644 --- a/sop-example/sop-story/sop-story-web/src/main/java/com/gitee/sop/bookweb/controller/AlipayController.java +++ b/sop-example/sop-story/sop-story-web/src/main/java/com/gitee/sop/bookweb/controller/AlipayController.java @@ -1,7 +1,10 @@ package com.gitee.sop.bookweb.controller; +import com.gitee.sop.bookweb.controller.param.StoryParam; import com.gitee.sop.servercommon.annotation.ApiMapping; import com.gitee.sop.story.api.domain.Story; +import io.swagger.annotations.ApiModelProperty; +import io.swagger.annotations.ApiOperation; import lombok.Data; import org.springframework.web.bind.annotation.RestController; @@ -23,8 +26,9 @@ public class AlipayController { return story; } + @ApiOperation(value="获取故事信息", notes = "说明接口的详细信息,介绍,用途,注意事项等。") @ApiMapping(value = "alipay.story.find") - public StoryVO getStory2(Story story) { + public StoryVO getStory2(StoryParam story) { StoryVO storyVO = new StoryVO(); storyVO.id = 1L; storyVO.name = "白雪公主"; @@ -39,8 +43,11 @@ public class AlipayController { @Data public static class StoryVO { + @ApiModelProperty(value = "故事ID", example = "1") private Long id; + @ApiModelProperty(value = "故事名称", example = "海底小纵队") private String name; + @ApiModelProperty(value = "创建时间", example = "2019-04-14 19:02:12") private Date gmt_create; } } diff --git a/sop-example/sop-story/sop-story-web/src/main/java/com/gitee/sop/bookweb/controller/Story2Controller.java b/sop-example/sop-story/sop-story-web/src/main/java/com/gitee/sop/bookweb/controller/Story2Controller.java index 6f37e27a..0c058582 100644 --- a/sop-example/sop-story/sop-story-web/src/main/java/com/gitee/sop/bookweb/controller/Story2Controller.java +++ b/sop-example/sop-story/sop-story-web/src/main/java/com/gitee/sop/bookweb/controller/Story2Controller.java @@ -3,7 +3,7 @@ package com.gitee.sop.bookweb.controller; import com.gitee.sop.servercommon.annotation.ApiAbility; import com.gitee.sop.servercommon.annotation.ApiMapping; import com.gitee.sop.story.api.domain.Story; -import com.gitee.sop.story.api.service.StoryService; +import io.swagger.annotations.ApiOperation; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @@ -24,6 +24,7 @@ public class Story2Controller{ } // 优先使用方法上@ApiAbility + @ApiOperation(value="获取故事信息2", notes = "获取故事信息2的详细信息") @ApiAbility(version = "1.4") @RequestMapping("getStory4") public Story storyget() { diff --git a/sop-example/sop-story/sop-story-web/src/main/java/com/gitee/sop/bookweb/controller/param/StoryParam.java b/sop-example/sop-story/sop-story-web/src/main/java/com/gitee/sop/bookweb/controller/param/StoryParam.java new file mode 100644 index 00000000..b1d5ec89 --- /dev/null +++ b/sop-example/sop-story/sop-story-web/src/main/java/com/gitee/sop/bookweb/controller/param/StoryParam.java @@ -0,0 +1,18 @@ +package com.gitee.sop.bookweb.controller.param; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import org.hibernate.validator.constraints.Length; + +import javax.validation.constraints.NotBlank; + +@Data +public class StoryParam { + @ApiModelProperty(value = "故事ID", example = "111") + private int id; + + @NotBlank(message = "name不能为空") + @Length(max = 20, message = "name长度不能超过20") + @ApiModelProperty(value = "故事名称", required = true, example = "白雪公主") + private String name; +} \ No newline at end of file diff --git a/sop-test/src/test/java/com/gitee/sop/PermissionDemoPostTest.java b/sop-test/src/test/java/com/gitee/sop/PermissionDemoPostTest.java index 6215dd2d..8a55f6d6 100644 --- a/sop-test/src/test/java/com/gitee/sop/PermissionDemoPostTest.java +++ b/sop-test/src/test/java/com/gitee/sop/PermissionDemoPostTest.java @@ -10,7 +10,7 @@ import java.util.HashMap; import java.util.Map; /** - * 模仿支付宝客户端请求接口 + * 测试是否有权限访问,可在sop-admin中设置权限 */ public class PermissionDemoPostTest extends TestBase { @@ -19,21 +19,6 @@ public class PermissionDemoPostTest extends TestBase { // 支付宝私钥 String privateKey = "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCXJv1pQFqWNA/++OYEV7WYXwexZK/J8LY1OWlP9X0T6wHFOvxNKRvMkJ5544SbgsJpVcvRDPrcxmhPbi/sAhdO4x2PiPKIz9Yni2OtYCCeaiE056B+e1O2jXoLeXbfi9fPivJZkxH/tb4xfLkH3bA8ZAQnQsoXA0SguykMRZntF0TndUfvDrLqwhlR8r5iRdZLB6F8o8qXH6UPDfNEnf/K8wX5T4EB1b8x8QJ7Ua4GcIUqeUxGHdQpzNbJdaQvoi06lgccmL+PHzminkFYON7alj1CjDN833j7QMHdPtS9l7B67fOU/p2LAAkPMtoVBfxQt9aFj7B8rEhGCz02iJIBAgMBAAECggEARqOuIpY0v6WtJBfmR3lGIOOokLrhfJrGTLF8CiZMQha+SRJ7/wOLPlsH9SbjPlopyViTXCuYwbzn2tdABigkBHYXxpDV6CJZjzmRZ+FY3S/0POlTFElGojYUJ3CooWiVfyUMhdg5vSuOq0oCny53woFrf32zPHYGiKdvU5Djku1onbDU0Lw8w+5tguuEZ76kZ/lUcccGy5978FFmYpzY/65RHCpvLiLqYyWTtaNT1aQ/9pw4jX9HO9NfdJ9gYFK8r/2f36ZE4hxluAfeOXQfRC/WhPmiw/ReUhxPznG/WgKaa/OaRtAx3inbQ+JuCND7uuKeRe4osP2jLPHPP6AUwQKBgQDUNu3BkLoKaimjGOjCTAwtp71g1oo+k5/uEInAo7lyEwpV0EuUMwLA/HCqUgR4K9pyYV+Oyb8d6f0+Hz0BMD92I2pqlXrD7xV2WzDvyXM3s63NvorRooKcyfd9i6ccMjAyTR2qfLkxv0hlbBbsPHz4BbU63xhTJp3Ghi0/ey/1HQKBgQC2VsgqC6ykfSidZUNLmQZe3J0p/Qf9VLkfrQ+xaHapOs6AzDU2H2osuysqXTLJHsGfrwVaTs00ER2z8ljTJPBUtNtOLrwNRlvgdnzyVAKHfOgDBGwJgiwpeE9voB1oAV/mXqSaUWNnuwlOIhvQEBwekqNyWvhLqC7nCAIhj3yvNQKBgQCqYbeec56LAhWP903Zwcj9VvG7sESqXUhIkUqoOkuIBTWFFIm54QLTA1tJxDQGb98heoCIWf5x/A3xNI98RsqNBX5JON6qNWjb7/dobitti3t99v/ptDp9u8JTMC7penoryLKK0Ty3bkan95Kn9SC42YxaSghzqkt+uvfVQgiNGQKBgGxU6P2aDAt6VNwWosHSe+d2WWXt8IZBhO9d6dn0f7ORvcjmCqNKTNGgrkewMZEuVcliueJquR47IROdY8qmwqcBAN7Vg2K7r7CPlTKAWTRYMJxCT1Hi5gwJb+CZF3+IeYqsJk2NF2s0w5WJTE70k1BSvQsfIzAIDz2yE1oPHvwVAoGAA6e+xQkVH4fMEph55RJIZ5goI4Y76BSvt2N5OKZKd4HtaV+eIhM3SDsVYRLIm9ZquJHMiZQGyUGnsvrKL6AAVNK7eQZCRDk9KQz+0GKOGqku0nOZjUbAu6A2/vtXAaAuFSFx1rUQVVjFulLexkXR3KcztL1Qu2k5pB6Si0K/uwQ="; - - /** - * 参数 类型 是否必填 最大长度 描述 示例值 - * app_id String 是 32 支付宝分配给开发者的应用ID 2014072300007148 - * method String 是 128 接口名称 alipay.trade.fastpay.refund.query - * format String 否 40 仅支持JSON JSON - * charset String 是 10 请求使用的编码格式,如utf-8,gbk,gb2312等 utf-8 - * sign_type String 是 10 商户生成签名字符串所使用的签名算法类型,目前支持RSA2和RSA,推荐使用RSA2 RSA2 - * sign String 是 344 商户请求参数的签名串,详见签名 详见示例 - * timestamp String 是 19 发送请求的时间,格式"yyyy-MM-dd HH:mm:ss" 2014-07-24 03:07:50 - * version String 是 3 调用的接口版本,固定为:1.0 1.0 - * app_auth_token String 否 40 详见应用授权概述 - * biz_content String 是 请求参数的集合,最大长度不限,除公共参数外所有请求参数都必须放在这个参数中传递,具体参照各产品快速接入文档 - */ - // 这个请求会路由到story服务 @Test public void testPost() throws Exception {