From c32fc3f05d94c3b069b4e31d0a354dbd6f1b15ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9A=AE=E5=85=89=EF=BC=9A=E5=9F=8E=E4=B8=AD=E5=9F=8E?= <806783409@qq.com> Date: Sun, 27 Jan 2019 22:28:35 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E6=96=87=E6=A1=A3=E5=AD=98?= =?UTF-8?q?=E5=82=A8=EF=BC=8C=E5=B1=95=E7=A4=BA=E6=96=87=E6=A1=A3=E9=80=89?= =?UTF-8?q?=E6=8B=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../config/SwaggerConfiguration.java | 11 +- .../controller/MgDocumentController.java | 503 ++++++++++++------ .../controller/MgOpenDocController.java | 38 ++ .../swagger/controller/vo/LocationListVo.java | 87 +++ .../configuration/EnableSwaggerMgUi.java | 13 +- .../framework/constant/StorageKeys.java | 4 +- .../src/main/resources/document.html | 12 +- .../resources/webjars/mg-ui/css/mg-ui.css | 5 + .../webjars/mg-ui/js/mg-ui-cache-keys.js | 1 + .../main/resources/webjars/mg-ui/js/mg-ui.js | 136 +++-- .../webjars/zpages/docUrlDetailConfig.html | 202 +++++++ 11 files changed, 797 insertions(+), 215 deletions(-) create mode 100644 zyplayer-doc-swagger/src/main/java/com/zyplayer/doc/swagger/controller/MgOpenDocController.java create mode 100644 zyplayer-doc-swagger/src/main/java/com/zyplayer/doc/swagger/controller/vo/LocationListVo.java create mode 100644 zyplayer-doc-swagger/src/main/resources/webjars/zpages/docUrlDetailConfig.html diff --git a/zyplayer-doc-manage/src/main/java/com/zyplayer/doc/manage/framework/config/SwaggerConfiguration.java b/zyplayer-doc-manage/src/main/java/com/zyplayer/doc/manage/framework/config/SwaggerConfiguration.java index 4a345b7c..dde4510c 100644 --- a/zyplayer-doc-manage/src/main/java/com/zyplayer/doc/manage/framework/config/SwaggerConfiguration.java +++ b/zyplayer-doc-manage/src/main/java/com/zyplayer/doc/manage/framework/config/SwaggerConfiguration.java @@ -1,13 +1,11 @@ package com.zyplayer.doc.manage.framework.config; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - import com.google.common.base.Predicates; import com.zyplayer.doc.swagger.framework.configuration.EnableSwaggerMgUi; - import io.swagger.annotations.Api; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; import springfox.documentation.builders.ApiInfoBuilder; import springfox.documentation.builders.PathSelectors; import springfox.documentation.builders.RequestHandlerSelectors; @@ -15,7 +13,6 @@ import springfox.documentation.service.ApiInfo; import springfox.documentation.service.Contact; import springfox.documentation.spi.DocumentationType; import springfox.documentation.spring.web.plugins.Docket; -import springfox.documentation.swagger2.annotations.EnableSwagger2; /** * 不需要管理本项目的文档,只需要开启@EnableSwaggerMgUi即可 @@ -26,8 +23,8 @@ import springfox.documentation.swagger2.annotations.EnableSwagger2; //@EnableSwagger2 @EnableSwaggerMgUi( selfDoc = false,// 是否开启自身的文档 - defaultResources = {// 启动后第一次访问没有数据情况下需要加载进来的swagger-resources地址 - //"http://localhost:8080/swagger-resources" + defaultLocation = {// 启动后第一次访问没有数据情况下需要加载进来的/v2/doc地址 + //"http://localhost:8080/v2/doc" } ) public class SwaggerConfiguration { diff --git a/zyplayer-doc-swagger/src/main/java/com/zyplayer/doc/swagger/controller/MgDocumentController.java b/zyplayer-doc-swagger/src/main/java/com/zyplayer/doc/swagger/controller/MgDocumentController.java index 155ae51f..4049942f 100644 --- a/zyplayer-doc-swagger/src/main/java/com/zyplayer/doc/swagger/controller/MgDocumentController.java +++ b/zyplayer-doc-swagger/src/main/java/com/zyplayer/doc/swagger/controller/MgDocumentController.java @@ -5,6 +5,8 @@ import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.TypeReference; import com.zyplayer.doc.core.json.DocResponseJson; import com.zyplayer.doc.core.json.ResponseJson; +import com.zyplayer.doc.swagger.controller.vo.LocationListVo; +import com.zyplayer.doc.swagger.controller.vo.SwaggerLocationVo; import com.zyplayer.doc.swagger.controller.vo.SwaggerResourcesInfoVo; import com.zyplayer.doc.swagger.framework.configuration.EnableSwaggerMgUi; import com.zyplayer.doc.swagger.framework.configuration.SpringContextUtil; @@ -14,13 +16,13 @@ import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.aop.support.AopUtils; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.RestController; import springfox.documentation.swagger.web.SwaggerResource; +import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.net.URLEncoder; @@ -37,10 +39,9 @@ import java.util.stream.Collectors; @RestController @RequestMapping("/swagger-mg-ui/document") public class MgDocumentController { - private static Logger logger = LoggerFactory.getLogger(MgDocumentController.class); - @Autowired + @Resource private MgStorageService storageService; /** @@ -71,48 +72,33 @@ public class MgDocumentController { @ResponseBody @PostMapping(value = "/docs") public void docs(HttpServletRequest request, HttpServletResponse response) { - boolean needRestorage = true; - String choiceDocList = request.getParameter("choiseDocList"); - // 转成set,防止重复 + String choiceLocationList = request.getParameter("choiceLocationList"); List resourcesSet = new LinkedList<>(); - Set swaggerDocsDeleteSet = new HashSet<>(); + List locationList = this.getLocationSet(); - List resourcesList = new LinkedList<>(); - String swaggerResourcesStr = storageService.get(StorageKeys.SWAGGER_RESOURCES_LIST); - String swaggerDocsDeleteStr = storageService.get(StorageKeys.SWAGGER_DOCS_DELETE_LIST); - if (StringUtils.isNotBlank(swaggerResourcesStr)) { - resourcesList = JSON.parseArray(swaggerResourcesStr, SwaggerResourcesInfoVo.class); + if (StringUtils.isNotBlank(choiceLocationList)) { + // 当前choiceLocationList只有一个,可以这样搞 + locationList = locationList.stream().filter(val -> Objects.equals(val.getLocation(), choiceLocationList)).collect(Collectors.toList()); } - if (StringUtils.isNotBlank(choiceDocList)) { - needRestorage = false;// 选择的则不再存入 - Map infoVoMap = resourcesList.stream().collect(Collectors.toMap(SwaggerResourcesInfoVo::getUrl, val -> val)); - for (String url : choiceDocList.split(",")) { - SwaggerResourcesInfoVo resourcesInfoVo = infoVoMap.get(url); - if (resourcesInfoVo != null) { - resourcesSet.add(resourcesInfoVo); - } - } - } else { - if (resourcesList.size() > 0) { - resourcesSet.addAll(resourcesList); - } else { - // 默认加上自身的文档 - String serverPath = "http://" + request.getServerName() // 服务器地址 - + ":" + request.getServerPort() // 端口号 - + request.getContextPath(); - // 是否加入自身的文档 - Object object = SpringContextUtil.getBeanWithAnnotation(EnableSwaggerMgUi.class); - EnableSwaggerMgUi swaggerMgUi = object.getClass().getAnnotation(EnableSwaggerMgUi.class); + if (locationList.size() <= 0) { + // 默认加上自身的文档 + String serverPath = "http://" + request.getServerName() // 服务器地址 + + ":" + request.getServerPort() // 端口号 + + request.getContextPath(); + // 是否加入自身的文档 + Object enableSwaggerMgUi = SpringContextUtil.getBeanWithAnnotation(EnableSwaggerMgUi.class); + if (enableSwaggerMgUi != null) { + EnableSwaggerMgUi swaggerMgUi = enableSwaggerMgUi.getClass().getAnnotation(EnableSwaggerMgUi.class); if (swaggerMgUi == null) { // 直接通过superclass去找 - Class superclass = object.getClass().getSuperclass(); + Class superclass = enableSwaggerMgUi.getClass().getSuperclass(); if (superclass != null) { swaggerMgUi = superclass.getAnnotation(EnableSwaggerMgUi.class); } } if (swaggerMgUi == null) { // 再通过AopUtils去找 - Class targetClass = AopUtils.getTargetClass(object); + Class targetClass = AopUtils.getTargetClass(enableSwaggerMgUi); if (targetClass != null) { swaggerMgUi = targetClass.getAnnotation(EnableSwaggerMgUi.class); } @@ -125,82 +111,194 @@ public class MgDocumentController { } // 启动后第一次访问没有数据情况下需要加载进来的swagger-resources地址 String[] defaultResources = swaggerMgUi.defaultResources(); - if (defaultResources != null && defaultResources.length > 0) { - for (String url : defaultResources) { - resourcesSet.add(new SwaggerResourcesInfoVo(url)); - } + for (String url : defaultResources) { + resourcesSet.add(new SwaggerResourcesInfoVo(url)); + } + String[] defaultLocation = swaggerMgUi.defaultLocation(); + for (String url : defaultLocation) { + locationList.add(new LocationListVo(url, "")); } } } - if (StringUtils.isNotBlank(swaggerDocsDeleteStr)) { - List swaggerDocsDeleteList = JSON.parseArray(swaggerDocsDeleteStr, String.class); - swaggerDocsDeleteSet.addAll(swaggerDocsDeleteList); - } } - List> swaggerResourceList = new LinkedList<>(); - List swaggerResourceStrList = new LinkedList<>(); - for (SwaggerResourcesInfoVo resourcesInfoVo : resourcesSet) { - List resourceList = null; - String resourcesUrl = resourcesInfoVo.getUrl(); - try { - String resourcesStr = HttpRequest.get(resourcesUrl).timeout(3000).execute().body(); - resourceList = JSON.parseArray(resourcesStr, SwaggerResource.class); - } catch (Exception e) { - logger.error("获取文档失败:{},{}", resourcesUrl, e.getMessage()); - } - if (resourceList == null || resourceList.isEmpty()) { - continue; - } - resourcesInfoVo.setResourceList(resourceList); - resourcesUrl = resourcesUrl.substring(0, resourcesUrl.lastIndexOf("/") + 1); - for (SwaggerResource resource : resourceList) { - String location = resource.getLocation(); - // 最后一个斜杠在resourcesUrl中已经加上,替换掉后面的防止两根斜杠 - location = location.startsWith("/") ? location.replaceFirst("/", "") : location; - if (location.indexOf("?") >= 0) { - try { - String encode = URLEncoder.encode(resource.getName(), "utf-8"); - location = location.substring(0, location.lastIndexOf("?")) + "?group=" + encode; - } catch (Exception e) { - e.printStackTrace(); - } + if (resourcesSet.size() > 0) { + List locationListStorage = this.getLocationSet(); + for (SwaggerResourcesInfoVo resourcesInfoVo : resourcesSet) { + List resourceList = null; + String resourcesUrl = resourcesInfoVo.getUrl(); + try { + String resourcesStr = HttpRequest.get(resourcesUrl).timeout(3000).execute().body(); + resourceList = JSON.parseArray(resourcesStr, SwaggerResource.class); + } catch (Exception e) { + logger.error("获取文档失败:{},{}", resourcesUrl, e.getMessage()); } - location = resourcesUrl + location; - // 已删除的则不处理 - if (swaggerDocsDeleteSet.contains(location)) { + if (resourceList == null || resourceList.isEmpty()) { continue; } - try { - String resourceStr = HttpRequest.get(location).timeout(3000).execute().body(); - Map jsonObject = JSON.parseObject(resourceStr, new TypeReference>(){}); - if (jsonObject == null || jsonObject.isEmpty()) { - continue; - } - jsonObject.put("fullUrl", location); - swaggerResourceList.add(jsonObject); - // 本来想转对象之后赋值,但是在此转成JSON字符串之后格式就不是之前的了,所有不能转。。。 - // 直接字符串拼接,坑真多~ - String rewriteDomainUrl = Optional.ofNullable(resourcesInfoVo.getRewriteDomainUrl()).orElse(""); - resourceStr = resourceStr.substring(1); - resourceStr = "{\"fullUrl\":\"" + location + "\"," - + "\"domainUrl\":\"" + resourcesUrl + "\"," - + "\"rewriteDomainUrl\":\"" + rewriteDomainUrl + "\"," - + resourceStr; - swaggerResourceStrList.add(resourceStr); - } catch (Exception e) { - logger.error("获取文档失败:{},{}", location, e.getMessage()); + resourcesInfoVo.setResourceList(resourceList); + String resourcesDomain = resourcesUrl.substring(0, resourcesUrl.lastIndexOf("/") + 1); + for (SwaggerResource swaggerResource : resourceList) { + String location = this.getLocationUrl(resourcesDomain, swaggerResource.getLocation(), swaggerResource.getName()); + locationListStorage.add(new LocationListVo(location, resourcesUrl)); } } - } - if (needRestorage) { + locationList.addAll(locationListStorage); + this.storageSwaggerLocationList(locationListStorage); + AtomicInteger idIndex = new AtomicInteger(1); resourcesSet.forEach(val -> val.setId(idIndex.getAndIncrement())); storageService.put(StorageKeys.SWAGGER_RESOURCES_LIST, JSON.toJSONString(resourcesSet)); } + List swaggerResourceStrList = new LinkedList<>(); + for (LocationListVo location : locationList) { + try { + String resourceStr = HttpRequest.get(location.getLocation()).timeout(3000).execute().body(); + Map jsonObject = JSON.parseObject(resourceStr, new TypeReference>(){}); + if (jsonObject == null || jsonObject.isEmpty()) { + continue; + } + jsonObject.put("fullUrl", location); + + String resourcesUrl = location.getLocation(); + int indexV2 = location.getLocation().indexOf("/v2"); + if (indexV2 >= 0) { + resourcesUrl = location.getLocation().substring(0, indexV2); + } + // 本来想转对象之后赋值,但是在此转成JSON字符串之后格式就不是之前的了,所有不能转。。。 + // 直接字符串拼接,坑真多~ + String rewriteDomainUrl = Optional.ofNullable(location.getRewriteDomainUrl()).orElse(""); + resourceStr = resourceStr.substring(1); + resourceStr = "{\"fullUrl\":\"" + location.getLocation() + "\"," + + "\"domainUrl\":\"" + resourcesUrl + "\"," + + "\"rewriteDomainUrl\":\"" + rewriteDomainUrl + "\"," + + resourceStr; + swaggerResourceStrList.add(resourceStr); + } catch (Exception e) { + logger.error("获取文档失败:{},{}", location, e.getMessage()); + } + } // 用默认的json解析要内存溢出,解析不了JSONObject、、就只有这样写了~ DocResponseJson.ok(swaggerResourceStrList).send(response); } + /** + * 获取所有的文档 + * @author 暮光:城中城 + * @since 2018年8月21日 + * @param request request + * @param response response + */ + @ResponseBody + @PostMapping(value = "/docsOld") + public void docsOld(HttpServletRequest request, HttpServletResponse response) { +// boolean needStorage = false; +// String choiceDocList = request.getParameter("choiceDocList"); +// // 转成set,防止重复 +// List resourcesSet = new LinkedList<>(); +// +// List resourcesList = new LinkedList<>(); +// String swaggerResourcesStr = storageService.get(StorageKeys.SWAGGER_RESOURCES_LIST); +// if (StringUtils.isNotBlank(swaggerResourcesStr)) { +// resourcesList = JSON.parseArray(swaggerResourcesStr, SwaggerResourcesInfoVo.class); +// } +// if (StringUtils.isNotBlank(choiceDocList)) { +// Map infoVoMap = resourcesList.stream().collect(Collectors.toMap(SwaggerResourcesInfoVo::getUrl, val -> val)); +// for (String url : choiceDocList.split(",")) { +// SwaggerResourcesInfoVo resourcesInfoVo = infoVoMap.get(url); +// if (resourcesInfoVo != null) { +// resourcesSet.add(resourcesInfoVo); +// } +// } +// } else if (resourcesList.size() > 0) { +// resourcesSet.addAll(resourcesList); +// } else { +// needStorage = true; +// // 默认加上自身的文档 +// String serverPath = "http://" + request.getServerName() // 服务器地址 +// + ":" + request.getServerPort() // 端口号 +// + request.getContextPath(); +// // 是否加入自身的文档 +// Object enableSwaggerMgUi = SpringContextUtil.getBeanWithAnnotation(EnableSwaggerMgUi.class); +// if (enableSwaggerMgUi != null) { +// EnableSwaggerMgUi swaggerMgUi = enableSwaggerMgUi.getClass().getAnnotation(EnableSwaggerMgUi.class); +// if (swaggerMgUi == null) { +// // 直接通过superclass去找 +// Class superclass = enableSwaggerMgUi.getClass().getSuperclass(); +// if (superclass != null) { +// swaggerMgUi = superclass.getAnnotation(EnableSwaggerMgUi.class); +// } +// } +// if (swaggerMgUi == null) { +// // 再通过AopUtils去找 +// Class targetClass = AopUtils.getTargetClass(enableSwaggerMgUi); +// if (targetClass != null) { +// swaggerMgUi = targetClass.getAnnotation(EnableSwaggerMgUi.class); +// } +// } +// if (swaggerMgUi == null) { +// resourcesSet.add(new SwaggerResourcesInfoVo(serverPath + "/swagger-resources")); +// } else { +// if (swaggerMgUi.selfDoc()) { +// resourcesSet.add(new SwaggerResourcesInfoVo(serverPath + "/swagger-resources")); +// } +// // 启动后第一次访问没有数据情况下需要加载进来的swagger-resources地址 +// String[] defaultResources = swaggerMgUi.defaultResources(); +// for (String url : defaultResources) { +// resourcesSet.add(new SwaggerResourcesInfoVo(url)); +// } +// } +// } +// } +// List swaggerResourceStrList = new LinkedList<>(); +// for (SwaggerResourcesInfoVo resourcesInfoVo : resourcesSet) { +// List resourceList = null; +// String resourcesUrl = resourcesInfoVo.getUrl(); +// try { +// String resourcesStr = HttpRequest.get(resourcesUrl).timeout(3000).execute().body(); +// resourceList = JSON.parseArray(resourcesStr, SwaggerResource.class); +// } catch (Exception e) { +// logger.error("获取文档失败:{},{}", resourcesUrl, e.getMessage()); +// } +// if (resourceList == null || resourceList.isEmpty()) { +// continue; +// } +// resourcesInfoVo.setResourceList(resourceList); +// resourcesUrl = resourcesUrl.substring(0, resourcesUrl.lastIndexOf("/") + 1); +// for (SwaggerResource resource : resourceList) { +// String location = this.getLocationUrl(resourcesUrl, resource.getLocation(), resource.getName()); +// try { +// String resourceStr = HttpRequest.get(location).timeout(3000).execute().body(); +// Map jsonObject = JSON.parseObject(resourceStr, new TypeReference>(){}); +// if (jsonObject == null || jsonObject.isEmpty()) { +// continue; +// } +// jsonObject.put("fullUrl", location); +// // 本来想转对象之后赋值,但是在此转成JSON字符串之后格式就不是之前的了,所有不能转。。。 +// // 直接字符串拼接,坑真多~ +// String rewriteDomainUrl = Optional.ofNullable(resourcesInfoVo.getRewriteDomainUrl()).orElse(""); +// resourceStr = resourceStr.substring(1); +// resourceStr = "{\"fullUrl\":\"" + location + "\"," +// + "\"domainUrl\":\"" + resourcesUrl + "\"," +// + "\"rewriteDomainUrl\":\"" + rewriteDomainUrl + "\"," +// + resourceStr; +// swaggerResourceStrList.add(resourceStr); +// } catch (Exception e) { +// logger.error("获取文档失败:{},{}", location, e.getMessage()); +// } +// } +// if (needStorage) { +// this.addSwaggerLocationList(resourceList, resourcesUrl); +// } +// } +// if (needStorage && resourcesSet.size() > 0) { +// AtomicInteger idIndex = new AtomicInteger(1); +// resourcesSet.forEach(val -> val.setId(idIndex.getAndIncrement())); +// storageService.put(StorageKeys.SWAGGER_RESOURCES_LIST, JSON.toJSONString(resourcesSet)); +// } +// // 用默认的json解析要内存溢出,解析不了JSONObject、、就只有这样写了~ +// DocResponseJson.ok(swaggerResourceStrList).send(response); + } + /** * 增加/swagger-resources地址 * @@ -212,71 +310,38 @@ public class MgDocumentController { @PostMapping(value = "/addSwaggerResources") public ResponseJson addSwaggerResources(String resourcesUrl, String rewriteDomainUrl, String oldUrl) { String swaggerResourcesStr = storageService.get(StorageKeys.SWAGGER_RESOURCES_LIST); - String swaggerDocsDeleteStr = storageService.get(StorageKeys.SWAGGER_DOCS_DELETE_LIST); - Set swaggerDocsDeleteSet = new HashSet<>(); - if (StringUtils.isNotBlank(swaggerDocsDeleteStr)) { - List swaggerDocsDeleteList = JSON.parseArray(swaggerDocsDeleteStr, String.class); - swaggerDocsDeleteSet.addAll(swaggerDocsDeleteList); - } // 转成set,防止重复 List resourcesList = new LinkedList<>(); if (StringUtils.isNotBlank(swaggerResourcesStr)) { resourcesList = JSON.parseArray(swaggerResourcesStr, SwaggerResourcesInfoVo.class); // 如果是编辑,把之前的删除掉,再在后面添加 if (StringUtils.isNotBlank(oldUrl)) { - resourcesList = resourcesList.stream().filter(val -> !Objects.equals(val.getUrl(), oldUrl)).collect(Collectors.toList()); + final String tempStr = oldUrl; + resourcesList = resourcesList.stream().filter(val -> !Objects.equals(val.getUrl(), tempStr)).collect(Collectors.toList()); } } try { + oldUrl = this.encodeUrlParam(oldUrl); + resourcesUrl = this.encodeUrlParam(resourcesUrl); String resourcesStr = HttpRequest.get(resourcesUrl).timeout(3000).execute().body(); - List resourceList = JSON.parseArray(resourcesStr, SwaggerResource.class); - if (resourceList == null || resourceList.isEmpty()) { - return DocResponseJson.warn("该地址未找到文档"); - } - // 重新加入的时候把之前的已删除的回恢复 - String resourcesDomain = resourcesUrl.substring(0, resourcesUrl.lastIndexOf("/") + 1); - for (SwaggerResource swaggerResource : resourceList) { - String location = swaggerResource.getLocation(); - // 最后一个斜杠在resourcesUrl中已经加上,替换掉后面的防止两根斜杠 - location = location.startsWith("/") ? location.replaceFirst("/", "") : location; - if (location.indexOf("?") >= 0) { - try { - String encode = URLEncoder.encode(swaggerResource.getName(), "utf-8"); - location = location.substring(0, location.lastIndexOf("?")) + "?group=" + encode; - } catch (Exception e) { - e.printStackTrace(); - } + boolean isLocation = this.addSwaggerLocationList(resourcesStr, rewriteDomainUrl, resourcesUrl, oldUrl); + if (!isLocation) { + List resourceList = JSON.parseArray(resourcesStr, SwaggerResource.class); + if (resourceList == null || resourceList.isEmpty()) { + return DocResponseJson.warn("该地址未找到文档"); } - location = resourcesDomain + location; - swaggerDocsDeleteSet.remove(location); + this.addSwaggerLocationList(resourceList, resourcesUrl); + SwaggerResourcesInfoVo resourcesInfoVo = new SwaggerResourcesInfoVo(resourcesUrl, resourceList); + resourcesInfoVo.setRewriteDomainUrl(rewriteDomainUrl); + resourcesList.add(resourcesInfoVo); + AtomicInteger idIndex = new AtomicInteger(1); + resourcesList.forEach(val -> val.setId(idIndex.getAndIncrement())); } - SwaggerResourcesInfoVo resourcesInfoVo = new SwaggerResourcesInfoVo(resourcesUrl, resourceList); - resourcesInfoVo.setRewriteDomainUrl(rewriteDomainUrl); - resourcesList.add(resourcesInfoVo); - AtomicInteger idIndex = new AtomicInteger(1); - resourcesList.forEach(val -> val.setId(idIndex.getAndIncrement())); } catch (Exception e) { -// 暂不想支持直接添加地址 -// try { -// SwaggerLocationVo swaggerLocationVo = JSON.parseObject(resourcesStr, SwaggerLocationVo.class); -// if (StringUtils.isNotBlank(swaggerLocationVo.getSwagger())) { -// Set locationSet = new HashSet<>(); -// if (StringUtils.isNotBlank(swaggerLocationListStr)) { -// String swaggerLocationListStr = storageService.get(StorageKeys.SWAGGER_LOCATION_LIST); -// List locationList = JSON.parseArray(swaggerLocationListStr, String.class); -// locationSet.addAll(locationList); -// storageService.put(StorageKeys.SWAGGER_LOCATION_LIST, JSON.toJSONString(locationSet)); -// } -// } else { -// return DocResponseJson.warn("该地址查找文档失败"); -// } -// } catch (Exception e2) { - logger.error("获取文档失败:{},{}", resourcesUrl, e.getMessage()); - return DocResponseJson.warn("该地址查找文档失败"); -// } + logger.error("获取文档失败:{},{}", resourcesUrl, e.getMessage()); + return DocResponseJson.warn("该地址查找文档失败"); } storageService.put(StorageKeys.SWAGGER_RESOURCES_LIST, JSON.toJSONString(resourcesList)); - storageService.put(StorageKeys.SWAGGER_DOCS_DELETE_LIST, JSON.toJSONString(swaggerDocsDeleteSet)); return DocResponseJson.ok(); } @@ -303,22 +368,6 @@ public class MgDocumentController { if (resourceList == null || resourceList.isEmpty()) { return DocResponseJson.warn("该地址未找到文档"); } - // 重新加入的时候把之前的已删除的回恢复 - String resourcesDomain = resourcesUrl.substring(0, resourcesUrl.lastIndexOf("/") + 1); - for (SwaggerResource swaggerResource : resourceList) { - String location = swaggerResource.getLocation(); - // 最后一个斜杠在resourcesUrl中已经加上,替换掉后面的防止两根斜杠 - location = location.startsWith("/") ? location.replaceFirst("/", "") : location; - if (location.indexOf("?") >= 0) { - try { - String encode = URLEncoder.encode(swaggerResource.getName(), "utf-8"); - location = location.substring(0, location.lastIndexOf("?")) + "?group=" + encode; - } catch (Exception e) { - e.printStackTrace(); - } - } - location = resourcesDomain + location; - } resourcesSet.add(new SwaggerResourcesInfoVo(resourcesUrl)); } catch (Exception e) { logger.error("获取文档失败:{},{}", resourcesUrl, e.getMessage()); @@ -336,16 +385,136 @@ public class MgDocumentController { * @param docUrl 文档地址 * @return 删除结果 */ + @Deprecated @PostMapping(value = "/deleteSwaggerDoc") public ResponseJson deleteSwaggerDoc(String docUrl) { - String swaggerDocsDeleteStr = storageService.get(StorageKeys.SWAGGER_DOCS_DELETE_LIST); - Set swaggerDocsDeleteSet = new HashSet<>(); - if (StringUtils.isNotBlank(swaggerDocsDeleteStr)) { - List swaggerDocsDeleteList = JSON.parseArray(swaggerDocsDeleteStr, String.class); - swaggerDocsDeleteSet.addAll(swaggerDocsDeleteList); - } - swaggerDocsDeleteSet.add(docUrl); - storageService.put(StorageKeys.SWAGGER_DOCS_DELETE_LIST, JSON.toJSONString(swaggerDocsDeleteSet)); +// String swaggerDocsDeleteStr = storageService.get(StorageKeys.SWAGGER_DOCS_DELETE_LIST); +// Set swaggerDocsDeleteSet = new HashSet<>(); +// if (StringUtils.isNotBlank(swaggerDocsDeleteStr)) { +// List swaggerDocsDeleteList = JSON.parseArray(swaggerDocsDeleteStr, String.class); +// swaggerDocsDeleteSet.addAll(swaggerDocsDeleteList); +// } +// swaggerDocsDeleteSet.add(docUrl); +// storageService.put(StorageKeys.SWAGGER_DOCS_DELETE_LIST, JSON.toJSONString(swaggerDocsDeleteSet)); return DocResponseJson.ok(); } + + /** + * 获取swaggerLocation列表 + * + * @author 暮光:城中城 + * @since 2018年8月21日 + */ + @PostMapping(value = "/getLocationList") + public ResponseJson> getLocationList() { + List locationSet = this.getLocationSet(); + return DocResponseJson.ok(locationSet); + } + + /** + * 直接添加地址 + */ + private boolean addSwaggerLocationList(String resourcesStr, String rewriteDomainUrl, String locationUrl, String oldUrl) { + try { + SwaggerLocationVo swaggerLocationVo = JSON.parseObject(resourcesStr, SwaggerLocationVo.class); + if (swaggerLocationVo != null && StringUtils.isNotBlank(swaggerLocationVo.getSwagger())) { + List locationList = this.getLocationSet(); + locationList = locationList.stream().filter(val -> !Objects.equals(val.getLocation(), oldUrl)).collect(Collectors.toList()); + LocationListVo locationListVo = new LocationListVo(locationUrl, ""); + locationListVo.setRewriteDomainUrl(rewriteDomainUrl); + locationList.add(locationListVo); + this.storageSwaggerLocationList(locationList); + return true; + } + } catch (Exception e) { + e.printStackTrace(); + } + return false; + } + + /** + * 直接添加地址 + */ + private void addSwaggerLocationList(List resourceList, String resourcesUrl) { + List locationList = this.getLocationSet(); + // 加入到location列表 + String resourcesDomain = resourcesUrl.substring(0, resourcesUrl.lastIndexOf("/") + 1); + for (SwaggerResource swaggerResource : resourceList) { + String location = this.getLocationUrl(resourcesDomain, swaggerResource.getLocation(), swaggerResource.getName()); + locationList.add(new LocationListVo(location, resourcesUrl)); + } + this.storageSwaggerLocationList(locationList); + } + + /** + * 保存location列表 + */ + private void storageSwaggerLocationList(List locationSet) { + AtomicInteger idIndex = new AtomicInteger(1); + locationSet = locationSet.stream().distinct().collect(Collectors.toList()); + locationSet.forEach(val -> val.setId(idIndex.getAndIncrement())); + storageService.put(StorageKeys.SWAGGER_LOCATION_LIST, JSON.toJSONString(locationSet)); + } + + /** + * 获取swaggerLocation列表 + */ + private List getLocationSet() { + List locationList = new LinkedList<>(); + String swaggerLocationListStr = storageService.get(StorageKeys.SWAGGER_LOCATION_LIST); + if (StringUtils.isNotBlank(swaggerLocationListStr)) { + locationList = JSON.parseArray(swaggerLocationListStr, LocationListVo.class); + } + return locationList; + } + + /** + * 获取拼接好的location + */ + private String getLocationUrl(String resourcesDomain, String location, String resourceName) { + // 最后一个斜杠在resourcesUrl中已经加上,替换掉后面的防止两根斜杠 + location = location.startsWith("/") ? location.replaceFirst("/", "") : location; + if (location.contains("?")) { + try { + String encode = URLEncoder.encode(resourceName, "utf-8"); + location = location.substring(0, location.lastIndexOf("?")) + "?group=" + encode; + } catch (Exception e) { + e.printStackTrace(); + } + } + return resourcesDomain + location; + } + + /** + * url编码参数 + */ + private String encodeUrlParam(String resourcesUrl) { + int indexOf = resourcesUrl.indexOf("?"); + if (indexOf < 0) { + return resourcesUrl; + } + StringBuilder baseUrl = new StringBuilder(resourcesUrl.substring(0, indexOf + 1)); + String[] paramArr = resourcesUrl.substring(indexOf + 1).split("&"); + for (int i = 0; i < paramArr.length; i++) { + String param = paramArr[i]; + String[] split = param.split("="); + if (i > 0) { + baseUrl.append("&"); + } + if (split.length == 2) { + String value = split[1]; + try { + value = URLEncoder.encode(split[1], "utf-8"); + } catch (Exception e) { + e.printStackTrace(); + } + baseUrl.append(split[0]).append("=").append(value); + } else { + baseUrl.append(param); + } + } + return baseUrl.toString(); + } + + } diff --git a/zyplayer-doc-swagger/src/main/java/com/zyplayer/doc/swagger/controller/MgOpenDocController.java b/zyplayer-doc-swagger/src/main/java/com/zyplayer/doc/swagger/controller/MgOpenDocController.java new file mode 100644 index 00000000..76ebab01 --- /dev/null +++ b/zyplayer-doc-swagger/src/main/java/com/zyplayer/doc/swagger/controller/MgOpenDocController.java @@ -0,0 +1,38 @@ +package com.zyplayer.doc.swagger.controller; + +import com.zyplayer.doc.core.json.DocResponseJson; +import com.zyplayer.doc.core.json.ResponseJson; +import com.zyplayer.doc.swagger.controller.vo.SwaggerResourcesInfoVo; +import com.zyplayer.doc.swagger.framework.service.MgStorageService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; +import java.util.List; + +/** + * 开放接口文档控制器 + * + * @author 暮光:城中城 + * @since 2019年1月27日 + */ +@RestController +@RequestMapping("/swagger-mg-ui/open-doc") +public class MgOpenDocController { + private static Logger logger = LoggerFactory.getLogger(MgOpenDocController.class); + + @Resource + private MgStorageService storageService; + + /** + * @author 暮光:城中城 + * @since 2019年1月27日 + */ + @ResponseBody + @PostMapping(value = "/{source}") + public ResponseJson> resourcesList(@PathVariable String source) { + + return DocResponseJson.ok(); + } +} diff --git a/zyplayer-doc-swagger/src/main/java/com/zyplayer/doc/swagger/controller/vo/LocationListVo.java b/zyplayer-doc-swagger/src/main/java/com/zyplayer/doc/swagger/controller/vo/LocationListVo.java new file mode 100644 index 00000000..a7c72bf7 --- /dev/null +++ b/zyplayer-doc-swagger/src/main/java/com/zyplayer/doc/swagger/controller/vo/LocationListVo.java @@ -0,0 +1,87 @@ +package com.zyplayer.doc.swagger.controller.vo; + +import java.net.URLDecoder; +import java.util.Objects; + +public class LocationListVo { + private Integer id; + private String name; + private String location; + private String resources; + private String rewriteDomainUrl; + + public LocationListVo(){ + + } + + public LocationListVo(String location, String resources) { + this.location = location; + this.resources = resources; + this.name = location; + // 修正名字 + int indexGroup = location.indexOf("group="); + int indexV2 = location.indexOf("/v2"); + if (indexGroup >= 0 && location.length() > indexGroup) { + try { + this.name = URLDecoder.decode(location.substring(indexGroup + 6), "utf-8"); + } catch (Exception e) { + e.printStackTrace(); + } + } else if (indexV2 >= 0) { + this.name = location.substring(indexV2 + 3); + } + } + + public String getLocation() { + return location; + } + + public void setLocation(String location) { + this.location = location; + } + + public String getResources() { + return resources; + } + + public void setResources(String resources) { + this.resources = resources; + } + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + @Override + public boolean equals(Object obj) { + if (obj == null) { + return false; + } + return Objects.equals(this.location, ((LocationListVo) obj).getLocation()); + } + + @Override + public int hashCode() { + return location.hashCode(); + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getRewriteDomainUrl() { + return rewriteDomainUrl; + } + + public void setRewriteDomainUrl(String rewriteDomainUrl) { + this.rewriteDomainUrl = rewriteDomainUrl; + } +} diff --git a/zyplayer-doc-swagger/src/main/java/com/zyplayer/doc/swagger/framework/configuration/EnableSwaggerMgUi.java b/zyplayer-doc-swagger/src/main/java/com/zyplayer/doc/swagger/framework/configuration/EnableSwaggerMgUi.java index 21adfe14..e149b928 100644 --- a/zyplayer-doc-swagger/src/main/java/com/zyplayer/doc/swagger/framework/configuration/EnableSwaggerMgUi.java +++ b/zyplayer-doc-swagger/src/main/java/com/zyplayer/doc/swagger/framework/configuration/EnableSwaggerMgUi.java @@ -1,12 +1,12 @@ package com.zyplayer.doc.swagger.framework.configuration; +import com.zyplayer.doc.swagger.framework.filter.ZyplayerProxyFilter; +import org.springframework.context.annotation.Import; + import java.lang.annotation.Documented; import java.lang.annotation.Retention; import java.lang.annotation.Target; -import com.zyplayer.doc.swagger.framework.filter.ZyplayerProxyFilter; -import org.springframework.context.annotation.Import; - @Retention(value = java.lang.annotation.RetentionPolicy.RUNTIME) @Target(value = {java.lang.annotation.ElementType.TYPE}) @Documented @@ -26,4 +26,11 @@ public @interface EnableSwaggerMgUi { * @return swagger-resources地址 */ String[] defaultResources() default {}; + + /** + * 启动后第一次访问没有数据情况下需要加载进来的/v2/doc地址 + * + * @return /v2/doc地址 + */ + String[] defaultLocation() default {}; } diff --git a/zyplayer-doc-swagger/src/main/java/com/zyplayer/doc/swagger/framework/constant/StorageKeys.java b/zyplayer-doc-swagger/src/main/java/com/zyplayer/doc/swagger/framework/constant/StorageKeys.java index 88bbe4d7..e9779775 100644 --- a/zyplayer-doc-swagger/src/main/java/com/zyplayer/doc/swagger/framework/constant/StorageKeys.java +++ b/zyplayer-doc-swagger/src/main/java/com/zyplayer/doc/swagger/framework/constant/StorageKeys.java @@ -9,8 +9,8 @@ package com.zyplayer.doc.swagger.framework.constant; public class StorageKeys { // 所有文档地址 public static final String SWAGGER_RESOURCES_LIST = "swagger-resources-list"; - // 已删除的文档 - public static final String SWAGGER_DOCS_DELETE_LIST = "swagger-docs-delete-list"; + // 已删除的文档(废弃,不在支持删除) +// public static final String SWAGGER_DOCS_DELETE_LIST = "swagger-docs-delete-list"; // 所有详细文档地址 public static final String SWAGGER_LOCATION_LIST = "swagger-location-list"; // 文档的离线数据key diff --git a/zyplayer-doc-swagger/src/main/resources/document.html b/zyplayer-doc-swagger/src/main/resources/document.html index b2c8302f..51433c86 100644 --- a/zyplayer-doc-swagger/src/main/resources/document.html +++ b/zyplayer-doc-swagger/src/main/resources/document.html @@ -17,6 +17,12 @@
+
+ + +
@@ -48,7 +55,10 @@
-
+
+
+
+