From 3060bf443539f175274cfa07e1205da5bf858684 Mon Sep 17 00:00:00 2001 From: WenG <450292408@qq.com> Date: Sat, 14 Aug 2021 14:59:43 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9ESwagger=E6=8E=A5=E5=8F=A3?= =?UTF-8?q?=E6=96=87=E6=A1=A3=E5=AF=BC=E5=87=BA=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cloud-common/pom.xml | 6 + .../common/controller/ApiDocController.java | 47 + .../com/cm/common/service/IApiDocService.java | 37 + .../service/impl/ApiDocServiceImpl.java | 187 + .../resources/templates/ftl/api-template.ftl | 3745 +++++++++++++++++ 5 files changed, 4022 insertions(+) create mode 100644 cloud-common/src/main/java/com/cm/common/controller/ApiDocController.java create mode 100644 cloud-common/src/main/java/com/cm/common/service/IApiDocService.java create mode 100644 cloud-common/src/main/java/com/cm/common/service/impl/ApiDocServiceImpl.java create mode 100644 cloud-common/src/main/resources/templates/ftl/api-template.ftl diff --git a/cloud-common/pom.xml b/cloud-common/pom.xml index 0f843c3..1b1410b 100644 --- a/cloud-common/pom.xml +++ b/cloud-common/pom.xml @@ -264,6 +264,12 @@ pdfbox + + + org.springframework.boot + spring-boot-starter-freemarker + ${spring-boot.version} + \ No newline at end of file diff --git a/cloud-common/src/main/java/com/cm/common/controller/ApiDocController.java b/cloud-common/src/main/java/com/cm/common/controller/ApiDocController.java new file mode 100644 index 0000000..3ea9b95 --- /dev/null +++ b/cloud-common/src/main/java/com/cm/common/controller/ApiDocController.java @@ -0,0 +1,47 @@ +package com.cm.common.controller; + +import com.cm.common.base.AbstractController; +import com.cm.common.constants.ISystemConstant; +import com.cm.common.service.IApiDocService; +import freemarker.template.TemplateException; +import io.swagger.annotations.Api; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.util.Map; + +/** + * When you feel like quitting. Think about why you started + * 当你想要放弃的时候,想想当初你为何开始 + * + * @ClassName: ApiDocController + * @Description: api文档 + * @Author: WangGeng + * @Date: 2021/8/14 10:58 + * @Version: 1.0 + **/ +@Api(tags = ISystemConstant.API_TAGS_SYSTEM_PREFIX + "api文档") +@RestController +@RequestMapping(ISystemConstant.API_PREFIX + "/api-doc") +public class ApiDocController extends AbstractController { + + @Autowired + private IApiDocService apiDocService; + + @GetMapping("get-api") + public Map getApi() { + return apiDocService.getApi(); + } + + @GetMapping("get") + public void get(HttpServletRequest request, HttpServletResponse response) throws IOException, TemplateException { + apiDocService.get(request, response); + } + +} diff --git a/cloud-common/src/main/java/com/cm/common/service/IApiDocService.java b/cloud-common/src/main/java/com/cm/common/service/IApiDocService.java new file mode 100644 index 0000000..7d33951 --- /dev/null +++ b/cloud-common/src/main/java/com/cm/common/service/IApiDocService.java @@ -0,0 +1,37 @@ +package com.cm.common.service; + +import freemarker.template.TemplateException; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.util.Map; + +/** + * When you feel like quitting. Think about why you started + * 当你想要放弃的时候,想想当初你为何开始 + * + * @ClassName: IApiDocService + * @Description: api文档 + * @Author: WangGeng + * @Date: 2021/8/14 10:57 + * @Version: 1.0 + **/ +public interface IApiDocService { + + /** + * 获取接口 + * + * @return + */ + Map getApi(); + + /** + * 获取文档 + * + * @param request + * @param response + */ + void get(HttpServletRequest request, HttpServletResponse response) throws IOException, TemplateException; + +} diff --git a/cloud-common/src/main/java/com/cm/common/service/impl/ApiDocServiceImpl.java b/cloud-common/src/main/java/com/cm/common/service/impl/ApiDocServiceImpl.java new file mode 100644 index 0000000..95e05c9 --- /dev/null +++ b/cloud-common/src/main/java/com/cm/common/service/impl/ApiDocServiceImpl.java @@ -0,0 +1,187 @@ +package com.cm.common.service.impl; + +import com.cm.common.base.AbstractService; +import com.cm.common.constants.ISystemConstant; +import com.cm.common.service.IApiDocService; +import com.cm.common.utils.DateUtil; +import freemarker.template.Configuration; +import freemarker.template.Template; +import freemarker.template.TemplateException; +import io.swagger.models.*; +import io.swagger.models.parameters.Parameter; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer; +import springfox.documentation.service.Documentation; +import springfox.documentation.spring.web.DocumentationCache; +import springfox.documentation.swagger2.mappers.ServiceModelToSwagger2Mapper; + +import javax.annotation.PostConstruct; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.*; +import java.net.URLEncoder; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * When you feel like quitting. Think about why you started + * 当你想要放弃的时候,想想当初你为何开始 + * + * @ClassName: ApiDocServiceImpl + * @Description: api文档 + * @Author: WangGeng + * @Date: 2021/8/14 10:57 + * @Version: 1.0 + **/ +@Service +public class ApiDocServiceImpl extends AbstractService implements IApiDocService { + + private static String API_TYPE_GET = "get"; + private static String API_TYPE_POST = "post"; + private static String API_TYPE_PUT = "put"; + private static String API_TYPE_DELETE = "delete"; + @Autowired + private DocumentationCache documentationCache; + @Autowired + private ServiceModelToSwagger2Mapper serviceModelToSwagger2Mapper; + @Autowired + private FreeMarkerConfigurer freeMarkerConfigurer; + + @PostConstruct + public void init() { + freeMarkerConfigurer.getConfiguration().setClassForTemplateLoading(ApiDocServiceImpl.class, "/templates"); + } + + @Override + public Map getApi() { + Map apiDocMap = new HashMap<>(); + + List> apiGroups = new ArrayList<>(); + Map systemDocMap = new HashMap<>(); + systemDocMap.put("name", "系统接口"); + systemDocMap.put("api", getApi("SYSTEM")); + apiGroups.add(systemDocMap); + + Map appDocMap = new HashMap<>(); + appDocMap.put("name", "APP接口"); + appDocMap.put("api", getApi("APP")); + apiGroups.add(appDocMap); + + Map resourceDocMap = new HashMap<>(); + resourceDocMap.put("name", "资源接口"); + resourceDocMap.put("api", getApi("RESOURCE")); + apiGroups.add(resourceDocMap); + + Map wechatDocMap = new HashMap<>(); + wechatDocMap.put("name", "微信接口"); + wechatDocMap.put("api", getApi("WECHAT")); + apiGroups.add(wechatDocMap); + + apiDocMap.put("apiGroups", apiGroups); + apiDocMap.put("author", "System"); + apiDocMap.put("date", DateUtil.getDay()); + apiDocMap.put("version", "v1.0"); + return apiDocMap; + } + + @Override + public void get(HttpServletRequest request, HttpServletResponse response) throws IOException, TemplateException { + Template template = freeMarkerConfigurer.getConfiguration().getTemplate("ftl/api-template.ftl"); + response.setHeader("Content-Disposition", "attachment;fileName=" + URLEncoder.encode("接口文档.doc", "UTF-8")); + Map apiDocMap = getApi(); + Writer writer = new BufferedWriter(new OutputStreamWriter(response.getOutputStream(), ISystemConstant.CHARSET_UTF8)); + template.process(apiDocMap, writer); + } + + private Map getApi(String groupName) { + Documentation documentation = documentationCache.documentationByGroup(groupName); + if (documentation == null) { + return null; + } + Swagger swagger = serviceModelToSwagger2Mapper.mapDocumentation(documentation); + Info info = swagger.getInfo(); + String host = swagger.getHost(); + String basePath = swagger.getBasePath(); + List tags = swagger.getTags(); + Map paths = swagger.getPaths(); + Map definitions = swagger.getDefinitions(); + + List> apiControllers = new ArrayList<>(); + Map apiMap = new HashMap<>(); + apiMap.put("info", info); + apiMap.put("host", host); + apiMap.put("basePath", basePath); + apiMap.put("apiControllers", apiControllers); + for (Tag tag : tags) { + Map apiController = new HashMap<>(); + apiController.put("name", tag.getName()); + apiController.put("description", tag.getDescription()); + apiController.put("apis", listApiMap(tag.getName(), paths)); + apiControllers.add(apiController); + } + return apiMap; + } + + private List> listApiMap(String apiController, Map paths) { + List> pathMaps = new ArrayList<>(); + for (Map.Entry kv : paths.entrySet()) { + String apiUrl = kv.getKey(); + Path path = kv.getValue(); + + Map operationMap = path.getOperationMap(); + for (Map.Entry operationEntry : operationMap.entrySet()) { + HttpMethod httpMethod = operationEntry.getKey(); + Operation operation = operationEntry.getValue(); + if (StringUtils.equalsIgnoreCase(apiController, operation.getTags().get(0))) { + Map methodOperationMap = new HashMap<>(); + methodOperationMap.put("apiUrl", apiUrl); + methodOperationMap.put("method", httpMethod.name()); + methodOperationMap.put("summary", operation.getSummary()); + methodOperationMap.put("description", operation.getDescription() == null ? "无" : operation.getDescription()); + methodOperationMap.put("consumes", operation.getConsumes()); + methodOperationMap.put("produces", operation.getProduces()); + methodOperationMap.put("parameters", listRequestParameter(operation)); + methodOperationMap.put("responses", listResponseMap(operation)); + pathMaps.add(methodOperationMap); + } + } + } + return pathMaps; + } + + private List> listRequestParameter(Operation operation) { + List> requestParameterList = new ArrayList<>(); + List parameters = operation.getParameters(); + for (Parameter parameter : parameters) { + Map requestParameter = new HashMap<>(); + requestParameter.put("name", parameter.getName()); + requestParameter.put("description", parameter.getDescription()); + requestParameter.put("in", parameter.getIn()); + requestParameter.put("type", parameter.getPattern() == null ? "string" : parameter.getPattern()); + requestParameter.put("source", parameter); + requestParameterList.add(requestParameter); + } + return requestParameterList; + } + + private List> listResponseMap(Operation operation) { + Map responses = operation.getResponses(); + List> responseMaps = new ArrayList<>(); + for (Map.Entry responseEntry : responses.entrySet()) { + String code = responseEntry.getKey(); + Response response = responseEntry.getValue(); + Map responseMap = new HashMap<>(); + responseMap.put("code", code); + responseMap.put("description", response.getDescription()); + responseMap.put("schema", response.getSchema()); + responseMaps.add(responseMap); + } + return responseMaps; + } + +} diff --git a/cloud-common/src/main/resources/templates/ftl/api-template.ftl b/cloud-common/src/main/resources/templates/ftl/api-template.ftl new file mode 100644 index 0000000..e68489b --- /dev/null +++ b/cloud-common/src/main/resources/templates/ftl/api-template.ftl @@ -0,0 +1,3745 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + X + + + + + + + + + + XXX + + + + + + + + + + + + + + + + + + + + + + 接口设计文档 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 作者:${author} + + + + + + + + + + + + + + + + + + 时间:${date} + + + + + + + + + + + + + + + + + + 版本:${version} + + + + + + + + + + + + + + + + + + + + + +<#list apiGroups as apiGroup> + + + + + + + + + + + + + + + + + + + + + + + ${apiGroup.name} + + + <#list apiGroup.api.apiControllers as apiController> + + + + + + + + + + + + + + + + + + + + + + ${apiController.name} + + + <#list apiController.apis as api> + + + + + + + + + + + + + + + + + + + + + + 功能说明 + + + + + + + + + + + + + + + + + + + + + + + + ${api.summary} + + + + + + + + + + + + + + + + ${api.description} + + + + + + + + + + + + + + + + + + + + + + + + 接口说明 + + + + + + + + + + + + + + + + + + + + + + 请求方式:${api.method} + + + + + + + + + + + + + + + + + + + + + + 请求地址:${api.apiUrl} + + + + + + + + + + + + + + + + + + + + + + 请求参数 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 名称 + + + + + + + + + + + + + + + + + + + + + + + + + + + + 描述 + + + + + + + + + + + + + + + + + + + + + + + + + + + + 参数类型 + + + + + + + + + + + + + + + + + + + + + + + + + + + + 数据类型 + + + + + <#list api.parameters as parameter> + + + + + + + + + + + + + + + + + + + + + + ${parameter.name} + + + + + + + + + + + + + + + + + + + + + + + + ${parameter.description} + + + + + + + + + + + + + + + + + + + + + + + + ${parameter.in} + + + + + + + + + + + + + + + + + + + + + + + + ${parameter.type} + + + + + + + + + + + + + + + + + + + + X + + + + + + + XX + + + + + + + 对象属性 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 名称 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 描述 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 类型 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 示例 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 请求 + + + + + + + 示例 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 响应 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 响应状态 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 原因 + + + + + + + + + + + + + + + + + + + + + + + + + + + + 名称 + + + + + + + + + + + + + + + + + + + + + + + + + + + + 响应类型 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 4 + + + + + + + + 00 + + + + + + + + + + + + + + + + + + + + + + + + 请求失败 + + + + + + + + + + + + + + + + + + + + + + + + xxx + + + + + + + + + + + + + + + + + + + + + + + + object + + + + + + + + + + + + + + + + + + + + + + + + + + 4 + + + + + + + + 04 + + + + + + + + + + + + + + + + + + + + + + + + 请求不存在 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 4 + + + + + + + + 03 + + + + + + + + + + + + + + + + + + + + + + + + 权限不足 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + + + + + + + + 03 + + + + + + + + + + + + + + + + + + + + + + + + 服务 + + + + + + + + + + + + + + + + + + 可用 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 500 + + + + + + + + + + + + + + + + + + + + + + + + 系统异常 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 2 + + + + + + + + 00 + + + + + + + + + + + + + + + + + + + + + + + + 请求成功 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + object + + + + + + + + + + + + + + + + + + + X + + + + + + + XXX + + + + + + + 属性 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 名称 + + + + + + + + + + + + + + + + + + + + + + + + + + + + 描述 + + + + + + + + + + + + + + + + + + + + + + + + + + + + 类型 + + + + + + + + + + + + + + + + + + + + + + + + + + + + 示例 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 请求失败示例、 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 请求成功示例 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 王 耿 + + + 王 耿 + 2 + 2021-08-13T23:46:00Z + 2021-08-13T23:46:00Z + + + + + + + + 1 + 2 + 60 + 342 + Microsoft Office Word + 0 + 2 + 1 + false + + false + 401 + false + false + 16.0000 + + + + + + + + + + + \ No newline at end of file