前言
spring项目中可以使用springfox或者springdoc,通过写注解的方式生成swagger文档,下面介绍一种不写注解,动态生成swagger文档的方式,在某些场景会适用,例如接口是动态生成的,此时swagger就不能通过注解来生成了。
一、定义swagger模板
通过观察一个swagger文档的openapi结构,将其中需要动态替换的部分写成变量,生成freemaker的ftl模板。
通过点击swagger图示链接可以查看openapi的json结构。
修改一个json结构,生成一个ftl模板,将模板放在springboot项目的resources/static/data-service-swagger-templates下面
{"openapi": "3.0.3","info": {"title": "通用查询-[${interfaceName}]接口","description": "通用查询接口","version": "0.0.1"},"servers": [{"url": "${dataServicePrefix}","description": "Generated server url"}],"security": [{"secretHeader": []}],"paths": {"${url}": {"post": {"tags": ["数据服务-通用查询接口"],"summary": "通用查询接口","description": "通用查询接口,请求体采用统一数据结构","operationId": "getData2UsingPOST","requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/DmoRequest"}}}},"responses": {"200": {"description": "OK","content": {"*/*": {"schema": {"$ref": "#/components/schemas/ResponseEntity"}}}},"201": {"description": "Created"},"401": {"description": "Unauthorized"},"403": {"description": "Forbidden"},"404": {"description": "Not Found"}}}}},"components": {"schemas": {"ResponseEntity": {"title": "ResponseEntity","type": "object","properties": {"desc": {"type": "string","description": "错误详细描述"},"message": {"type": "string","description": "如果为非200的返回,可以将此message提示给用户"},"requestURL": {"type": "string"},"stackTrace": {"type": "string","description": "后端的异常栈信息,如果过长,只截取前面一部分"},"status": {"type": "integer","description": "200:正常;401:未登陆;403:没有权限;400:请求参数校验失败;500:服务器内部错误","format": "int32"},"tookInMillis": {"type": "integer","description": "请求耗时","format": "int64"},"value": {"type": "object"}}},"DmoRequest": {"title": "DmoRequest","type": "object","properties": {"fulltextNode": {"$ref": "#/components/schemas/QueryNode"},"node": {"$ref": "#/components/schemas/QueryNode"},"pageNumber": {"type": "integer","description": "页码","format": "int32"},"pageSize": {"type": "integer","description": "每页条数","format": "int32"},"showColumns": {"uniqueItems": true,"type": "array","items": {"type": "string","description": "显示的列"}},"sorts": {"type": "array","items": {"$ref": "#/components/schemas/DmoSort"}}}},"QueryNode": {"title": "QueryNode","type": "object","description": "查询条件","properties": {"children": {"type": "array","items": {"$ref": "#/components/schemas/QueryNode"}},"data": {"$ref": "#/components/schemas/NodeData"},"type": {"type": "string","description": "节点类型","enum": ["AND", "LEAF", "OR", "ROOT"]}}},"NodeData": {"title": "NodeData","type": "object","description": "节点数据","properties": {"operator": {"type": "string","description": "操作符","enum": ["BETWEEN", "EQ", "EXISTS", "GE", "GT", "IN", "IS_NOT_NULL", "IS_NULL", "LE", "LIKE", "LT", "NE", "NOT_BETWEEN", "NOT_EXISTS", "NOT_IN", "NOT_LIKE", "PREFIX", "REGEXP"]},"param": {"type": "string","description": "参数名称,一般对应表的列名"},"value": {"type": "array","description": "参数值","items": {"type": "object"}}}},"DmoSort": {"title": "DmoSort","type": "object","description": "排序","properties": {"column": {"type": "string","description": "列名"},"sortOrder": {"type": "string","description": "排序方式","enum": ["ASC", "DESC"]}}}},"securitySchemes": {"secretHeader": {"type": "apiKey","name": "Authorization","in": "header"}}}
}
二、使用freemarker生成openapi的JSON结构
1.引入库
代码如下(示例):
<dependency><groupId>org.freemarker</groupId><artifactId>freemarker</artifactId><version>2.3.32</version>
</dependency>
2.生成json
下面的serviceInterface就是一个实体,可以自行定义
@ApiOperation(value = "获取openapi的JSON", notes = "获取openapi的JSON")@GetMapping("/swagger-json/{id}")public String getSwaggerJson(@ApiParam(value = "id") @PathVariable Integer id) throws BaseException {ServiceInterface serviceInterface = getServiceInterface(id);return getOpenApiJson(ServiceInterface serviceInterface, "test.ftl") ;}private String getOpenApiJson(ServiceInterface serviceInterface, String ftl) throws BaseException {freemarker.template.Configuration configuration = new freemarker.template.Configuration(freemarker.template.Configuration.VERSION_2_3_0);// 设置默认编码configuration.setDefaultEncoding("utf-8");//设置类加载器configuration.setClassLoaderForTemplateLoading(this.getClass().getClassLoader(), "data-service-swagger-templates");try {// 生成模板对象Template template = configuration.getTemplate(fileName);TEMPLATE_CACHE.put(fileName, template);} catch (Exception e) {throw new BaseException(String.format("获取模版文件:[%s]出错", fileName), e);}Template template = getFltTemplate(ftl);String dataServicePrefix = dataServiceProtocol + dataServiceUpstream;Map<String, String> dataMap = new HashMap<>();dataMap.put("interfaceName", serviceInterface.getServiceName());dataMap.put("dataServicePrefix", dataServicePrefix);dataMap.put("url", serviceInterface.getUrl());StringWriter sw = new StringWriter();try {template.process(dataMap, sw);return sw.toString();} catch (Exception e) {throw new BaseException("模板转换出错:" + e.getMessage(), e);}}
三、前端生成swagger示例
<!DOCTYPE html>
<html><head><title>数据服务接口文档</title><link rel="stylesheet" type="text/css" href="swagger-ui.css"/></head><body><div id="swagger-ui"></div><script src="swagger-ui-bundle.js"></script><script>window.onload = function () {SwaggerUIBundle({// url: "http://localhost:14500/v3/api-docs", // 替换成您的OpenAPI规范的URL或文件路径// url: "swagger-custom-select.json", // 替换成您的OpenAPI规范的URL或文件路径url: "http://192.168.33.22:3282/dmo/service-interface/swagger-json/226", // 替换成您的OpenAPI规范的URL或文件路径dom_id: "#swagger-ui",deepLinking: true,});};</script></body>
</html>
其中url 为第二步的接口
用到的css和js下载地址:https://blog.csdn.net/weixin_41085315/article/details/124965953