新增torna文档推送 新增torna配置

This commit is contained in:
Forget 2021-03-04 17:38:53 +08:00
parent d55bebe5fc
commit 97ceb1835b
10 changed files with 907 additions and 3 deletions

View File

@ -0,0 +1,245 @@
package com.power.doc.builder;
import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonParser;
import com.power.common.util.CollectionUtil;
import com.power.common.util.OkHttp3Util;
import com.power.common.util.StringUtil;
import com.power.doc.constants.TornaConstants;
import com.power.doc.model.*;
import com.power.doc.model.torna.Apis;
import com.power.doc.model.torna.DebugEnv;
import com.power.doc.model.torna.HttpParam;
import com.power.doc.model.torna.TornaApi;
import com.power.doc.template.SpringBootDocBuildTemplate;
import com.thoughtworks.qdox.JavaProjectBuilder;
import java.util.ArrayList;
import java.util.List;
import static com.power.doc.constants.TornaConstants.PUSH;
/**
* @program: smart-doc
* @description: torna对接
* @author: xingzi
* @create: 2021/2/2 18:05
**/
public class TornaBuilder {
/**
* build controller api
*
* @param config config
*/
public static void buildApiDoc(ApiConfig config) {
JavaProjectBuilder javaProjectBuilder = new JavaProjectBuilder();
buildApiDoc(config, javaProjectBuilder);
}
/**
* Only for smart-doc maven plugin and gradle plugin.
*
* @param config ApiConfig
* @param javaProjectBuilder ProjectDocConfigBuilder
*/
public static void buildApiDoc(ApiConfig config, JavaProjectBuilder javaProjectBuilder) {
config.setParamsDataToTree(true);
DocBuilderTemplate builderTemplate = new DocBuilderTemplate();
builderTemplate.checkAndInit(config);
ProjectDocConfigBuilder configBuilder = new ProjectDocConfigBuilder(config, javaProjectBuilder);
List<ApiDoc> apiDocList = new SpringBootDocBuildTemplate().getApiData(configBuilder);
buildTorna(apiDocList,config);
}
/**
* build torna Data
*
* @param apiDocs apiData
*/
public static void buildTorna(List<ApiDoc> apiDocs,ApiConfig apiConfig) {
Apis api;
for (ApiDoc a : apiDocs) {
api = new Apis();
api.setName(a.getDesc());
//推送接口分类 CATEGORY_CREATE
String responseMsg = OkHttp3Util.syncPost(apiConfig.getOpenUrl(),
TornaConstants.buildParams(TornaConstants.CATEGORY_CREATE, new Gson().toJson(api),apiConfig));
//pushApi
pushApi(responseMsg, a,apiConfig);
}
}
/**
* 推送接口
*
* @param responseMsg 标签信息
* @param a 接口列表
*/
public static void pushApi(String responseMsg, ApiDoc a,ApiConfig config) {
JsonElement element = JsonParser.parseString(responseMsg);
//如果获取分类成功
if (TornaConstants.SUCCESS_CODE.equals(element.getAsJsonObject().get(TornaConstants.CODE).getAsString())) {
//获取分类id
String labelId = element.getAsJsonObject().get(TornaConstants.DATA)
.getAsJsonObject()
.get(TornaConstants.ID).getAsString();
List<ApiMethodDoc> apiMethodDocs = a.getList();
//参数列表
List<Apis> apis = new ArrayList<>();
//环境列表
List<DebugEnv> debugEnvs = new ArrayList<>();
//推送文档数据
TornaApi tornaApi = new TornaApi();
Apis methodApi;
DebugEnv debugEnv;
//遍历分类接口
for (ApiMethodDoc apiMethodDoc : apiMethodDocs) {
/**
* "name": "获取商品信息",
* "description": "获取商品信息",
* "url": "/goods/get",
* "httpMethod": "GET",
* "contentType": "application/json",
* "isFolder": "1",
* "parentId": "",
* "isShow": "1",
*/
methodApi = new Apis();
methodApi.setIsFolder(TornaConstants.NO);
methodApi.setName(apiMethodDoc.getDesc());
methodApi.setUrl(apiMethodDoc.getUrl());
methodApi.setHttpMethod(apiMethodDoc.getType());
methodApi.setContentType(apiMethodDoc.getContentType());
methodApi.setParentId(labelId);
methodApi.setDescription(apiMethodDoc.getDetail());
methodApi.setIsShow(TornaConstants.YES);
debugEnv = new DebugEnv();
debugEnv.setName("测试环境");
debugEnv.setUrl(" ");
/**
* {
* "name": "goodsName",
* "type": "string",
* "required": "1",
* "maxLength": "128",
* "example": "iphone12",
* "description": "商品名称描述",
* "parentId": "",
* "enumInfo": {
* "name": "支付枚举",
* "description": "支付状态",
* "items": [
* {
* "name": "WAIT_PAY",
* "type": "string",
* "value": "0",
* "description": "未支付"
* }
* ]
* }
* }
*/
methodApi.setHeaderParams(buildHerder(apiMethodDoc.getRequestHeaders()));
methodApi.setResponseParams(buildParams(apiMethodDoc.getResponseParams()));
//formData
if (CollectionUtil.isNotEmpty(apiMethodDoc.getQueryParams())) {
methodApi.setRequestParams(buildParams(apiMethodDoc.getQueryParams()));
}
//Json
if (CollectionUtil.isNotEmpty(apiMethodDoc.getRequestParams())) {
methodApi.setRequestParams(buildParams(apiMethodDoc.getRequestParams()));
}
apis.add(methodApi);
debugEnvs.add(debugEnv);
}
tornaApi.setApis(apis);
tornaApi.setDebugEnvs(debugEnvs);
OkHttp3Util.syncPost(config.getOpenUrl(),
TornaConstants.buildParams(PUSH, new Gson().toJson(tornaApi),config));
} else {
System.out.println("Error" + element.getAsJsonObject()
.get(TornaConstants.MESSAGE).getAsString());
}
}
/**
* build request header
*
* @param apiReqHeaders 请求头参数列表
* @return
*/
public static List<HttpParam> buildHerder(List<ApiReqHeader> apiReqHeaders) {
/**
* name": "token",
* "required": "1",
* "example": "iphone12",
* "description": "商品名称描述"
*/
HttpParam httpParam;
List<HttpParam> headers = new ArrayList<>();
for (ApiReqHeader header : apiReqHeaders) {
httpParam = new HttpParam();
httpParam.setName(header.getName());
httpParam.setRequired(header.isRequired() ? TornaConstants.YES : TornaConstants.NO);
httpParam.setExample(StringUtil.removeQuotes(header.getValue()));
httpParam.setDescription(header.getDesc());
headers.add(httpParam);
}
return headers;
}
/**
* build request response params
*
* @param apiParams 参数列表
* @return
*/
public static List<HttpParam> buildParams(List<ApiParam> apiParams) {
HttpParam httpParam;
List<HttpParam> bodies = new ArrayList<>();
/**
* "name": "goodsName",
* "type": "string",
* "required": "1",
* "maxLength": "128",
* "example": "iphone12",
* "description": "商品名称描述",
* "parentId": "",
* "enumInfo": {
* "name": "支付枚举",
* "description": "支付状态",
* "items": [
* {
* "name": "WAIT_PAY",
* "type": "string",
* "value": "0",
* "description": "未支付"
*/
for (ApiParam apiParam : apiParams) {
httpParam = new HttpParam();
httpParam.setName(apiParam.getField());
httpParam.setType(apiParam.getType());
httpParam.setRequired(apiParam.isRequired() ? TornaConstants.YES : TornaConstants.NO);
httpParam.setExample(StringUtil.removeQuotes(apiParam.getValue()));
httpParam.setDescription(apiParam.getDesc());
if (TornaConstants.ARRAY.equals(httpParam.getType())) {
if (apiParam.getChildren() != null) {
httpParam.setChildren(buildParams(apiParam.getChildren()));
}
}
bodies.add(httpParam);
}
return bodies;
}
}

View File

@ -0,0 +1,130 @@
package com.power.doc.constants;
import com.power.doc.model.ApiConfig;
import org.apache.commons.lang3.StringUtils;
import java.io.IOException;
import java.net.URLEncoder;
import java.security.MessageDigest;
import java.text.SimpleDateFormat;
import java.util.*;
/**
* @author xingzi
* @date 2020/2/2
*/
public class TornaConstants {
public static final String ID = "id";
public static final String CODE = "code";
public static final String MESSAGE = "msg";
public static final String DATA = "data";
public static final String SUCCESS_CODE = "0";
public static final String YES = "1";
public static final String NO = "0";
public static final String ARRAY ="array";
public static final String CATEGORY_CREATE = "doc.category.create";
public static final String PUSH = "doc.push";
/**
* build torna params
* @param name interface name
* @param data json
* @return
*/
public static Map<String, String> buildParams(String name, String data, ApiConfig config) {
Map<String, String> param = new HashMap<>(8);
try {
if(StringUtils.isNotBlank(data)) {
data = URLEncoder.encode(data, "utf-8");
}
// 公共参数
param.put("name", name);
param.put("app_key", config.getAppKey());
param.put("data", data);
param.put("timestamp",getTime());
param.put("version", "1.0");
param.put("access_token", config.getAppToken());
String sign = buildSign(param, config.getSecret());
param.put("sign", sign);
return param;
} catch (IOException e) {
e.printStackTrace();
}
return param;
}
/**
* 构建签名
*
* @param paramsMap 参数
* @param secret 密钥
* @return
*/
public static String buildSign(Map<String, ?> paramsMap, String secret) {
Set<String> keySet = paramsMap.keySet();
List<String> paramNames = new ArrayList<String>(keySet);
Collections.sort(paramNames);
StringBuilder paramNameValue = new StringBuilder();
for (String paramName : paramNames) {
Object value = paramsMap.get(paramName);
if (value != null) {
paramNameValue.append(paramName).append(value);
}
}
String source = secret + paramNameValue.toString() + secret;
return md5(source);
}
/**
* 生成md5,全部大写
*
* @param message
* @return
*/
public static String md5(String message) {
try {
// 1 创建一个提供信息摘要算法的对象初始化为md5算法对象
MessageDigest md = MessageDigest.getInstance("MD5");
// 2 将消息变成byte数组
byte[] input = message.getBytes();
// 3 计算后获得字节数组,这就是那128位了
byte[] buff = md.digest(input);
// 4 把数组每一字节一个字节占八位换成16进制连成md5字符串
return byte2hex(buff);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* 二进制转十六进制字符串
*
* @param bytes
* @return
*/
private static String byte2hex(byte[] bytes) {
StringBuilder sign = new StringBuilder();
for (int i = 0; i < bytes.length; i++) {
String hex = Integer.toHexString(bytes[i] & 0xFF);
if (hex.length() == 1) {
sign.append("0");
}
sign.append(hex.toUpperCase());
}
return sign.toString();
}
public static String getTime() {
return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
}
}

View File

@ -270,6 +270,98 @@ public class ApiConfig {
*/
private boolean createDebugPage;
/**
* public static final String APP_KEY = "20201216788835306945118208";
* public static final String SECRET = "W.ZyGMOB9Q0UqujVxnfi@.I#V&tUUYZR";
* public static final String APP_TOKEN = "2f9a7d3858a147b7845ebb48785d4dc7";
* public static final String OPEN_URL = "http://torna.opensphere.cn/api/";
* @return
*/
/**
* Torna appKey
*/
private String appKey;
/**
* Torna Secret
*/
private String secret;
/**
* Torna appToken
*/
private String appToken;
/**
* Torna openUrl
*/
private String openUrl;
public void setSourceCodePaths(List<SourceCodePath> sourceCodePaths) {
this.sourceCodePaths = sourceCodePaths;
}
public void setRequestHeaders(List<ApiReqHeader> requestHeaders) {
this.requestHeaders = requestHeaders;
}
public void setCustomResponseFields(List<CustomRespField> customResponseFields) {
this.customResponseFields = customResponseFields;
}
public void setRevisionLogs(List<RevisionLog> revisionLogs) {
this.revisionLogs = revisionLogs;
}
public void setDataDictionaries(List<ApiDataDictionary> dataDictionaries) {
this.dataDictionaries = dataDictionaries;
}
public void setErrorCodeDictionaries(List<ApiErrorCodeDictionary> errorCodeDictionaries) {
this.errorCodeDictionaries = errorCodeDictionaries;
}
public void setApiObjectReplacements(List<ApiObjectReplacement> apiObjectReplacements) {
this.apiObjectReplacements = apiObjectReplacements;
}
public void setRpcApiDependencies(List<RpcApiDependency> rpcApiDependencies) {
this.rpcApiDependencies = rpcApiDependencies;
}
public void setApiConstants(List<ApiConstant> apiConstants) {
this.apiConstants = apiConstants;
}
public String getAppKey() {
return appKey;
}
public void setAppKey(String appKey) {
this.appKey = appKey;
}
public String getSecret() {
return secret;
}
public void setSecret(String secret) {
this.secret = secret;
}
public String getAppToken() {
return appToken;
}
public void setAppToken(String appToken) {
this.appToken = appToken;
}
public String getOpenUrl() {
return openUrl;
}
public void setOpenUrl(String openUrl) {
this.openUrl = openUrl;
}
public String getServerUrl() {
return serverUrl;
}

View File

@ -0,0 +1,133 @@
package com.power.doc.model.torna;
import java.util.List;
/**
* @program: smart-doc
* @description: 接口参数
* @author: xingzi
* @create: 2021/2/8 10:07
**/
public class Apis {
private String name;
private String description;
private String url;
private String httpMethod;
private String contentType;
private String isFolder;
private String parentId;
private String isShow;
private List<HttpParam> headerParams;
private List<HttpParam> requestParams;
private List<HttpParam> responseParams;
private String errorCodeParams;
private String items;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getHttpMethod() {
return httpMethod;
}
public void setHttpMethod(String httpMethod) {
this.httpMethod = httpMethod;
}
public String getContentType() {
return contentType;
}
public void setContentType(String contentType) {
this.contentType = contentType;
}
public String getIsFolder() {
return isFolder;
}
public void setIsFolder(String isFolder) {
this.isFolder = isFolder;
}
public String getParentId() {
return parentId;
}
public void setParentId(String parentId) {
this.parentId = parentId;
}
public String getIsShow() {
return isShow;
}
public void setIsShow(String isShow) {
this.isShow = isShow;
}
public List<HttpParam> getRequestParams() {
return requestParams;
}
public void setRequestParams(List<HttpParam> requestParams) {
this.requestParams = requestParams;
}
public List<HttpParam> getHeaderParams() {
return headerParams;
}
public void setHeaderParams(List<HttpParam> headerParams) {
this.headerParams = headerParams;
}
public List<HttpParam> getResponseParams() {
return responseParams;
}
public void setResponseParams(List<HttpParam> responseParams) {
this.responseParams = responseParams;
}
public String getErrorCodeParams() {
return errorCodeParams;
}
public void setErrorCodeParams(String errorCodeParams) {
this.errorCodeParams = errorCodeParams;
}
public String getItems() {
return items;
}
public void setItems(String items) {
this.items = items;
}
}

View File

@ -0,0 +1,29 @@
package com.power.doc.model.torna;
/**
* @program: smart-doc
* @description: 调试环境
* @author: Lixin
* @create: 2021/2/25 1:18
**/
public class DebugEnv {
private String name;
private String url;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
}

View File

@ -0,0 +1,53 @@
package com.power.doc.model.torna;
import java.util.List;
/**
* @program: smart-doc
* @description: 枚举参数
* @author: xingzi
* @create: 2021/2/25 12:13
**/
public class EnumInfo {
/**
* "enumInfo": {
* "name": "支付枚举",
* "description": "支付状态",
* "items": [
* {
* "name": "WAIT_PAY",
* "type": "string",
* "value": "0",
* "description": "未支付"
* }
* ]
* }
*/
private String name;
private String description;
private List<Item> items;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public List<Item> getItems() {
return items;
}
public void setItems(List<Item> items) {
this.items = items;
}
}

View File

@ -0,0 +1,121 @@
package com.power.doc.model.torna;
import java.util.List;
/**
* @program: smart-doc
* @description: Http请求参数模板
* @author: xingzi
* @create: 2021/2/8 22:40
**/
public class HttpParam {
private String name;
private String type;
private String value;
private String required;
private String maxLength;
private String example;
private String description;
private String parentId;
private String code;
private String msg;
private String solution;
private List<HttpParam> children;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public String getRequired() {
return required;
}
public void setRequired(String required) {
this.required = required;
}
public String getMaxLength() {
return maxLength;
}
public void setMaxLength(String maxLength) {
this.maxLength = maxLength;
}
public String getExample() {
return example;
}
public void setExample(String example) {
this.example = example;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getParentId() {
return parentId;
}
public void setParentId(String parentId) {
this.parentId = parentId;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public String getSolution() {
return solution;
}
public void setSolution(String solution) {
this.solution = solution;
}
public List<HttpParam> getChildren() {
return children;
}
public void setChildren(List<HttpParam> children) {
this.children = children;
}
}

View File

@ -0,0 +1,54 @@
package com.power.doc.model.torna;
/**
* @program: smart-doc
* @description: 枚举参数
* @author: xingzi
* @create: 2021/2/25 12:29
**/
public class Item {
/**
* {
* * "name": "WAIT_PAY",
* * "type": "string",
* * "value": "0",
* * "description": "未支付"
* * }
*/
private String name;
private String type;
private String value;
private String description;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}

View File

@ -0,0 +1,40 @@
package com.power.doc.model.torna;
import java.util.List;
/**
* @program: smart-doc
* @description: 推送参数
* @author: xingzi
* @create: 2021/2/25 1:09
**/
public class TornaApi {
/**
* "debugEnvs": [
* {
* "name": "测试环境",
* "url": "http://10.1.30.165:2222"
* }
* ],
* "apis": [
*/
List<DebugEnv> debugEnvs;
List<Apis> apis;
public List<DebugEnv> getDebugEnvs() {
return debugEnvs;
}
public void setDebugEnvs(List<DebugEnv> debugEnvs) {
this.debugEnvs = debugEnvs;
}
public List<Apis> getApis() {
return apis;
}
public void setApis(List<Apis> apis) {
this.apis = apis;
}
}

View File

@ -4,6 +4,7 @@ import com.power.common.util.DateTimeUtil;
import com.power.doc.builder.HtmlApiDocBuilder;
import com.power.doc.builder.OpenApiBuilder;
import com.power.doc.builder.PostmanJsonBuilder;
import com.power.doc.builder.TornaBuilder;
import com.power.doc.enums.OrderEnum;
import com.power.doc.model.*;
import org.junit.Test;
@ -30,17 +31,22 @@ public class ApiDocTest {
ApiConfig config = new ApiConfig();
config.setServerUrl("http://localhost:8080");
//config.setStrict(true);
config.setOpenUrl("http://torna.opensphere.cn/api/");
config.setAppKey("20201216788835306945118208");
config.setAppToken("2f9a7d3858a147b7845ebb48785d4dc7");
config.setSecret("W.ZyGMOB9Q0UqujVxnfi@.I#V&tUUYZR");
config.setAllInOne(true);
config.setOutPath("d:\\md3");
config.setMd5EncryptedHtmlName(true);
//不指定SourcePaths默认加载代码为项目src/main/java下的
config.setSourceCodePaths(
SourceCodePath.builder().setDesc("本项目代码").setPath("C:\\Users\\xingzi\\Desktop\\smart\\api-doc-test\\src\\main\\java\\com\\power\\doc")
SourceCodePath.builder().setDesc("本项目代码")
.setPath("C:\\Users\\xingzi\\Desktop\\api-doc-test\\src\\main\\java")
//SourcePath.path().setPath("F:\\Personal\\project\\smart\\src\\main\\java")
//SourcePath.path().setDesc("加载项目外代码").setPath("E:\\ApplicationPower\\ApplicationPower\\Common-util\\src\\main\\java")
);
config.setPackageFilters("com.power.doc.controller.ValidatorTestController");
config.setDataDictionaries(
ApiDataDictionary.builder().setTitle("订单字典").setEnumClass(OrderEnum.class).setCodeField("code").setDescField("desc")
);
@ -67,7 +73,8 @@ public class ApiDocTest {
long start = System.currentTimeMillis();
// OpenApiBuilder.buildOpenApi(config);
HtmlApiDocBuilder.buildApiDoc(config);
//HtmlApiDocBuilder.buildApiDoc(config);
TornaBuilder.buildApiDoc(config);
long end = System.currentTimeMillis();
DateTimeUtil.printRunTime(end, start);
}