通過swagger json一鍵解析為html頁面、匯出word和excel的解析演算法分享
寫在前面:
完全通過Spring Boot工程 Java程式碼,將swagger json 一鍵解析為html頁面、匯出word和execel的解析演算法,不需要任何網上那些類似於“SwaggerMarkup2”等外掛來實現。
由於業務需要,準備開發一個openapi開放平臺,類似於阿里巴巴的CSB雲服務匯流排專案,用於企業內外服務能力的打通和統一開放管理,提供獨特的跨環境服務級聯機制和常見協議適配支援,實現了對api介面的對外發布和訂閱稽核,讓企業內外都能夠更方便的使用到api介面。
其中需要實現一個核心功能,服務的匯入功能,通過swagger json將我們其他專案中已經寫好的介面一鍵匯入到這個api開放平臺並生成api介面詳情頁,那麼這就需要實現一個swagger json解析的操作。
下面馬上進入正題,本文主要也是分享一下,自己解析swagger json為html、word等功能的程式碼、思路以及介面。
頁面效果展示:
將下圖這樣的swagger json解析出一個個api介面詳情頁。
解析前:
解析後:
通過json解析完可以顯示所有的介面資訊,如圖:
這是單個介面的api詳情資訊,如下圖:
點選按鈕匯出api詳情頁為word的效果展示,如圖:
匯出word:
Swagger Json格式詳解:
程式碼部分:
我這邊實現兩種思路,一是直接解析swagger json然後直接存入實體類生成為html,還要一種是建立好實體類以及資料庫表後,將swagger json解析入庫入表做持久化,再通過表中資料渲染到頁面上。
下面我是介紹的swagger json入庫入表再渲染為html的方案。
步驟大概是:首先定義好建好表,寫好實體類後,再開始實現swagger json解析的演算法。
實體類定義:
服務資源表:
@ApiModel(value = "服務資源表", description = "服務資源表") public class ServiceResource implements Serializable{ /** * 程式序列化ID */ private static final long serialVersionUID=1L; /** * 服務ID */ @ApiModelProperty(value = "服務ID") private String id; /** * 租戶 */ @ApiModelProperty(value = "租戶") private String gmtTenant; /** * 建立時間 */ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") @ApiModelProperty(value = "建立時間") private Date gmtCreate; public Date getGmtCreate(){ return gmtCreate==null?null:(Date) gmtCreate.clone(); } public void setGmtCreate(Date gmtCreate){ this.gmtCreate = gmtCreate==null?null:(Date) gmtCreate.clone(); } /** * 建立人 */ @ApiModelProperty(value = "建立人") private String gmtCreator; /** * 建立人名稱 */ @ApiModelProperty(value = "建立人名稱") private String gmtCrtname; /** * 最後修改時間 */ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") @ApiModelProperty(value = "最後修改時間") private Date gmtModified; public Date getGmtModified(){ return gmtModified==null?null:(Date) gmtModified.clone(); } public void setGmtModified(Date gmtModified){ this.gmtModified = gmtModified==null?null:(Date) gmtModified.clone(); } /** * 最後修改人 */ @ApiModelProperty(value = "最後修改人") private String gmtModifiedby; /** * 最後修改人名稱 */ @ApiModelProperty(value = "最後修改人名稱") private String gmtMfyname; /** * 服務名稱 */ @ApiModelProperty(value = "服務名稱") private String serviceName; /** * 請求地址 */ @ApiModelProperty(value = "請求地址") private String requestUrl; /** * 請求方法 */ @ApiModelProperty(value = "請求方法") private String requestMethod; /** * 請求格式 */ @ApiModelProperty(value = "請求型別") private String contentType; /** * 返回型別 */ @ApiModelProperty(value = "返回型別") private String callContentType; /** * 服務描述 */ @ApiModelProperty(value = "服務描述") private String serviceDesc; /** * 服務版本 */ @ApiModelProperty(value = "服務版本") private String serviceVersion; /** * 是否有效 */ @ApiModelProperty(value = "是否有效") private Integer isValid; /** * 是否釋出 */ @ApiModelProperty(value = "是否釋出") private Integer isRelease; /** * 是否釋出 */ @ApiModelProperty(value = "是否需要授權訪問") private Integer isAuthorizedAccess; /** * 操作id */ @ApiModelProperty(value = "操作id") private String operationId; private Integer isDelete; private String routeUuid; private String currentCatalogId; public static long getSerialVersionUID() { return serialVersionUID; } public String getId() { return id; } public void setId(String id) { this.id = id; } public String getGmtTenant() { return gmtTenant; } public void setGmtTenant(String gmtTenant) { this.gmtTenant = gmtTenant; } public String getGmtCreator() { return gmtCreator; } public void setGmtCreator(String gmtCreator) { this.gmtCreator = gmtCreator; } public String getGmtCrtname() { return gmtCrtname; } public void setGmtCrtname(String gmtCrtname) { this.gmtCrtname = gmtCrtname; } public String getGmtModifiedby() { return gmtModifiedby; } public void setGmtModifiedby(String gmtModifiedby) { this.gmtModifiedby = gmtModifiedby; } public String getGmtMfyname() { return gmtMfyname; } public void setGmtMfyname(String gmtMfyname) { this.gmtMfyname = gmtMfyname; } public String getServiceName() { if(!StringUtils.isEmpty(serviceName)){ return serviceName.replaceAll(" ", ""); } return serviceName; } public void setServiceName(String serviceName) { this.serviceName = serviceName; } public String getRequestUrl() { return requestUrl; } public void setRequestUrl(String requestUrl) { this.requestUrl = requestUrl; } public String getRequestMethod() { return requestMethod; } public void setRequestMethod(String requestMethod) { this.requestMethod = requestMethod; } public String getContentType() { return contentType; } public void setContentType(String contentType) { this.contentType = contentType; } public String getCallContentType() { return callContentType; } public void setCallContentType(String callContentType) { this.callContentType = callContentType; } public String getServiceDesc() { return serviceDesc; } public void setServiceDesc(String serviceDesc) { this.serviceDesc = serviceDesc; } public String getServiceVersion() { return serviceVersion; } public void setServiceVersion(String serviceVersion) { this.serviceVersion = serviceVersion; } public Integer getIsValid() { return isValid; } public void setIsValid(Integer isValid) { this.isValid = isValid; } public Integer getIsRelease() { return isRelease; } public void setIsRelease(Integer isRelease) { this.isRelease = isRelease; } public Integer getIsAuthorizedAccess() { return isAuthorizedAccess; } public void setIsAuthorizedAccess(Integer isAuthorizedAccess) { this.isAuthorizedAccess = isAuthorizedAccess; } public String getOperationId() { return operationId; } public void setOperationId(String operationId) { this.operationId = operationId; } public Integer getIsDelete() { return isDelete; } public void setIsDelete(Integer isDelete) { this.isDelete = isDelete; } public String getRouteUuid() { return routeUuid; } public void setRouteUuid(String routeUuid) { this.routeUuid = routeUuid; } public String getCurrentCatalogId() { return currentCatalogId; } public void setCurrentCatalogId(String currentCatalogId) { this.currentCatalogId = currentCatalogId; } }
服務請求資訊表:
@Data @ApiModel(value = "服務請求資訊表", description = "服務請求資訊表") public class ServiceRequest implements Serializable{ /** * 程式序列化ID */ private static final long serialVersionUID=1L; /** * 服務ID */ @ApiModelProperty(value = "服務ID") private String id; /** * 租戶 */ @ApiModelProperty(value = "租戶") private String gmtTenant; /** * 建立時間 */ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") @ApiModelProperty(value = "建立時間") private Date gmtCreate; public Date getGmtCreate(){ return gmtCreate==null?null:(Date) gmtCreate.clone(); } public void setGmtCreate(Date gmtCreate){ this.gmtCreate = gmtCreate==null?null:(Date) gmtCreate.clone(); } /** * 建立人 */ @ApiModelProperty(value = "建立人") private String gmtCreator; /** * 建立人名稱 */ @ApiModelProperty(value = "建立人名稱") private String gmtCrtname; /** * 最後修改時間 */ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") @ApiModelProperty(value = "最後修改時間") private Date gmtModified; public Date getGmtModified(){ return gmtModified==null?null:(Date) gmtModified.clone(); } public void setGmtModified(Date gmtModified){ this.gmtModified = gmtModified==null?null:(Date) gmtModified.clone(); } /** * 最後修改人 */ @ApiModelProperty(value = "最後修改人") private String gmtModifiedby; /** * 最後修改人名稱 */ @ApiModelProperty(value = "最後修改人名稱") private String gmtMfyname; /** * 服務資源ID */ @ApiModelProperty(value = "服務資源ID") private String serviceId; /** * 引數名稱 */ @ApiModelProperty(value = "引數名稱") private String reqName; /** * 引數描述 */ @ApiModelProperty(value = "引數描述") private String reqDesc; /** * 引數型別 */ @ApiModelProperty(value = "引數型別") private String reqType; /** * 引數長度 */ @ApiModelProperty(value = "引數長度") private Integer reqLength; /** * 是否必填 */ @ApiModelProperty(value = "是否必填") private Integer isRequired; /** * 引數來源 */ @ApiModelProperty(value = "引數來源") private String reqFrom; }View Code
服務響應資訊表:
@Data @ApiModel(value = "服務響應資訊表", description = "服務響應資訊表") public class ServiceResponse implements Serializable{ /** * 程式序列化ID */ private static final long serialVersionUID=1L; /** * 服務ID */ @ApiModelProperty(value = "服務ID") private String id; /** * 租戶 */ @ApiModelProperty(value = "租戶") private String gmtTenant; /** * 建立時間 */ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") @ApiModelProperty(value = "建立時間") private Date gmtCreate; public Date getGmtCreate(){ return gmtCreate==null?null:(Date) gmtCreate.clone(); } public void setGmtCreate(Date gmtCreate){ this.gmtCreate = gmtCreate==null?null:(Date) gmtCreate.clone(); } /** * 建立人 */ @ApiModelProperty(value = "建立人") private String gmtCreator; /** * 建立人名稱 */ @ApiModelProperty(value = "建立人名稱") private String gmtCrtname; /** * 最後修改時間 */ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") @ApiModelProperty(value = "最後修改時間") private Date gmtModified; public Date getGmtModified(){ return gmtModified==null?null:(Date) gmtModified.clone(); } public void setGmtModified(Date gmtModified){ this.gmtModified = gmtModified==null?null:(Date) gmtModified.clone(); } /** * 最後修改人 */ @ApiModelProperty(value = "最後修改人") private String gmtModifiedby; /** * 最後修改人名稱 */ @ApiModelProperty(value = "最後修改人名稱") private String gmtMfyname; /** * 服務資源ID */ @ApiModelProperty(value = "服務資源ID") private String serviceId; /** * 屬性名稱 */ @ApiModelProperty(value = "屬性名稱") private String propName; /** * 屬性描述 */ @ApiModelProperty(value = "屬性描述") private String propDesc; /** * 屬性型別 */ @ApiModelProperty(value = "屬性型別") private String propType; /** * 屬性長度 */ @ApiModelProperty(value = "屬性長度") private Integer propLength; }View Code
服務響應狀態表:
@Data @ApiModel(value = "服務響應狀態表", description = "服務響應狀態表") public class ResponseStatus implements Serializable{ /** * 程式序列化ID */ private static final long serialVersionUID=1L; /** * 服務ID */ @ApiModelProperty(value = "服務ID") private String id; /** * 租戶 */ @ApiModelProperty(value = "租戶") private String gmtTenant; /** * 建立時間 */ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") @ApiModelProperty(value = "建立時間") private Date gmtCreate; public Date getGmtCreate(){ return gmtCreate==null?null:(Date) gmtCreate.clone(); } public void setGmtCreate(Date gmtCreate){ this.gmtCreate = gmtCreate==null?null:(Date) gmtCreate.clone(); } /** * 建立人 */ @ApiModelProperty(value = "建立人") private String gmtCreator; /** * 建立人名稱 */ @ApiModelProperty(value = "建立人名稱") private String gmtCrtname; /** * 最後修改時間 */ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") @ApiModelProperty(value = "最後修改時間") private Date gmtModified; public Date getGmtModified(){ return gmtModified==null?null:(Date) gmtModified.clone(); } public void setGmtModified(Date gmtModified){ this.gmtModified = gmtModified==null?null:(Date) gmtModified.clone(); } /** * 最後修改人 */ @ApiModelProperty(value = "最後修改人") private String gmtModifiedby; /** * 最後修改人名稱 */ @ApiModelProperty(value = "最後修改人名稱") private String gmtMfyname; /** * 服務資源ID */ @ApiModelProperty(value = "服務資源ID") private String serviceId; /** * 狀態碼 */ @ApiModelProperty(value = "狀態碼") private String statusCode; /** * 狀態描述 */ @ApiModelProperty(value = "狀態描述") private String statusDesc; /** * 狀態說明 */ @ApiModelProperty(value = "狀態說明") private String statusRemark; }View Code
服務類別表:
@ApiModel(value = "服務類別表", description = "服務類別表") public class ServiceCatalog implements Serializable{ /** * 程式序列化ID */ private static final long serialVersionUID=1L; /** * 服務ID */ @ApiModelProperty(value = "服務ID") private String id; /** * 租戶 */ @ApiModelProperty(value = "租戶") private String gmtTenant; /** * 建立時間 */ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") @ApiModelProperty(value = "建立時間") private Date gmtCreate; public Date getGmtCreate(){ return gmtCreate==null?null:(Date) gmtCreate.clone(); } public void setGmtCreate(Date gmtCreate){ this.gmtCreate = gmtCreate==null?null:(Date) gmtCreate.clone(); } /** * 建立人 */ @ApiModelProperty(value = "建立人") private String gmtCreator; /** * 建立人名稱 */ @ApiModelProperty(value = "建立人名稱") private String gmtCrtname; /** * 最後修改時間 */ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") @ApiModelProperty(value = "最後修改時間") private Date gmtModified; public Date getGmtModified(){ return gmtModified==null?null:(Date) gmtModified.clone(); } public void setGmtModified(Date gmtModified){ this.gmtModified = gmtModified==null?null:(Date) gmtModified.clone(); } /** * 最後修改人 */ @ApiModelProperty(value = "最後修改人") private String gmtModifiedby; /** * 最後修改人名稱 */ @ApiModelProperty(value = "最後修改人名稱") private String gmtMfyname; /** * 上級目錄ID */ @ApiModelProperty(value = "上級目錄ID") private String pid; /** * 目錄名稱 */ @ApiModelProperty(value = "目錄名稱") private String catalogName; public String getId() { return id; } public void setId(String id) { this.id = id; } public String getGmtTenant() { return gmtTenant; } public void setGmtTenant(String gmtTenant) { this.gmtTenant = gmtTenant; } public String getGmtCreator() { return gmtCreator; } public void setGmtCreator(String gmtCreator) { this.gmtCreator = gmtCreator; } public String getGmtCrtname() { return gmtCrtname; } public void setGmtCrtname(String gmtCrtname) { this.gmtCrtname = gmtCrtname; } public String getGmtModifiedby() { return gmtModifiedby; } public void setGmtModifiedby(String gmtModifiedby) { this.gmtModifiedby = gmtModifiedby; } public String getGmtMfyname() { return gmtMfyname; } public void setGmtMfyname(String gmtMfyname) { this.gmtMfyname = gmtMfyname; } public String getPid() { return pid; } public void setPid(String pid) { this.pid = pid; } public String getCatalogName() { if(!StringUtils.isEmpty(catalogName)){ return catalogName.replaceAll(" ", ""); } return catalogName; } public void setCatalogName(String catalogName) { this.catalogName = catalogName; } }View Code
服務類別關係表:
@Data @ApiModel(value = "服務類別關係表", description = "服務類別關係表") public class ServiceCatalogRela implements Serializable{ /** * 程式序列化ID */ private static final long serialVersionUID=1L; /** * 服務ID */ @ApiModelProperty(value = "服務ID") private String id; /** * 租戶 */ @ApiModelProperty(value = "租戶") private String gmtTenant; /** * 建立時間 */ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") @ApiModelProperty(value = "建立時間") private Date gmtCreate; public Date getGmtCreate(){ return gmtCreate==null?null:(Date) gmtCreate.clone(); } public void setGmtCreate(Date gmtCreate){ this.gmtCreate = gmtCreate==null?null:(Date) gmtCreate.clone(); } /** * 建立人 */ @ApiModelProperty(value = "建立人") private String gmtCreator; /** * 建立人名稱 */ @ApiModelProperty(value = "建立人名稱") private String gmtCrtname; /** * 最後修改時間 */ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") @ApiModelProperty(value = "最後修改時間") private Date gmtModified; public Date getGmtModified(){ return gmtModified==null?null:(Date) gmtModified.clone(); } public void setGmtModified(Date gmtModified){ this.gmtModified = gmtModified==null?null:(Date) gmtModified.clone(); } /** * 最後修改人 */ @ApiModelProperty(value = "最後修改人") private String gmtModifiedby; /** * 最後修改人名稱 */ @ApiModelProperty(value = "最後修改人名稱") private String gmtMfyname; /** * 目錄ID */ @ApiModelProperty(value = "目錄ID") private String catalogId; /** * 服務ID */ @ApiModelProperty(value = "服務ID") private String serviceId; }View Code
服務返回屬性:
@Data public class SwaggerModelAttr implements Serializable { private static final long serialVersionUID = -4074067438450613643L; /** * 類名 */ private String className = StringUtils.EMPTY; /** * 屬性名 */ private String name = StringUtils.EMPTY; /** * 型別 */ private String type = StringUtils.EMPTY; /** * 屬性描述 */ private String description; /** * 巢狀屬性列表 */ private List<SwaggerModelAttr> properties = new ArrayList<>(); }View Code
返回給前端的dto實體:
/** * @program: share-capacity-platform * @description: javabean轉html 傳遞給前端的dto實體類 * @author: liumingyu * @date: 2020-04-14 16:35 **/ @Data public class SwaggerHtmlDto { /** * 大標題 */ private String title; /** * 小標題 */ private String tag; /** * 版本 */ private String version; /** * 封裝服務資源 */ private ServiceResource serviceResource; /** * 封裝請求引數list */ private List<ServiceRequest> requestList; /** * 封裝響應狀態碼list */ private List<ResponseStatus> responseStatusList; /** * 封裝返回屬性list */ private List<ServiceResponse> responseList; }View Code
實體類就是以上這些,將swagger json解析後存入相應的實體類欄位中。
swagger解析程式碼:
下面開始swagger json的解析程式碼:
swagger解析service層介面:
public interface SwaggerJsonImportService { /** * swaggerJson匯入業務表 * * @param jsonUrl jsonUrl * @param serviceSwagger swaggerJson * @param isAuthorized 是否需要授權訪問 * @return net.evecom.scplatform.common.entry.CommonResp<java.lang.String> * @throws IOException * @Author Torres Liu * @Description //TODO swaggerJson匯入業務表 * @Date 2020/4/24 5:07 下午 * @Param [jsonUrl, serviceSwagger, isAuthorized] **/ CommonResp<String> swaggerJsonImport(String jsonUrl, ServiceSwagger serviceSwagger, String isAuthorized) throws IOException; /** * 匯出SwaggerJson * * @param serviceId 服務id * @param catalogId 目錄id * @return net.evecom.scplatform.common.entry.CommonResp<java.lang.String> * @Author Torres Liu * @Description //TODO 匯出SwaggerJson * @Date 2020/4/22 9:41 上午 * @Param [serviceId, catalogId] **/ List<SwaggerHtmlDto> swaggerJsonExport(String serviceId, String catalogId); }View Code
swagger解析service層介面實現類(解析的核心程式碼)
下面是一大堆枯燥的json解析,大家都是程式設計師,我就不做過多的講解程式碼,有需要學習的可以參照我程式碼中的註釋,寫的都比較詳細。
package xxxxxxxx; import cn.hutool.json.JSONObject; import com.alibaba.fastjson.JSON; import lombok.extern.slf4j.Slf4j; import net.evecom.scplatform.common.entry.CommonResp; import net.evecom.scplatform.common.entry.system.CommonEntry; import net.evecom.scplatform.common.entry.system.UserUtil; import net.evecom.scplatform.common.utils.text.IDUtils; import net.evecom.scplatform.openapi.dao.*; import net.evecom.scplatform.openapi.entity.*; import net.evecom.scplatform.openapi.entity.dto.SwaggerHtmlDto; import net.evecom.scplatform.openapi.service.SwaggerJsonImportService; import net.evecom.scplatform.openapi.util.SwaggerJsonUtils; import org.apache.commons.lang3.StringUtils; import org.apache.http.HttpEntity; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClientBuilder; import org.apache.http.util.EntityUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.CollectionUtils; import org.springframework.web.client.RestTemplate; import java.io.IOException; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.URL; import java.text.SimpleDateFormat; import java.util.*; /** * @author Torres Liu * @description //TODO 服務匯入/匯出 業務層 * @date 2020-04-10 14:06 下午 **/ @SuppressWarnings({"unchecked", "rawtypes"}) @Slf4j @Service @Transactional(rollbackFor = Exception.class) public class SwaggerJsonImportServiceImpl implements SwaggerJsonImportService { @Autowired private RestTemplate restTemplate; @Autowired private ServiceCatalogDao serviceCatalogDao; @Autowired private ServiceResourceDao serviceResourceDao; @Autowired private ServiceRequestDao serviceRequestDao; @Autowired private ResponseStatusDao responseStatusDao; @Autowired private ServiceResponseDao serviceResponseDao; @Autowired private ServiceCatalogRelaDao serviceCatalogRelaDao; @Value("${kong.server-addr}") private String kongServerAddr; /** * array */ private static final String ARRAY_VAL = "array"; /** * $ref */ private static final String REF_VAL = "$ref"; /** * format */ private static final String FORMAT_VAL = "format"; /** * schema */ private static final String SCHEMA_VAL = "schema"; /** * 成功的code */ private static final int SUCCESS_CODE = 200; /** * 遞迴次數 */ private static final int RECURSION_NUMS = 199; /** * 通過JSON或URL匯入服務 * * @param jsonUrl * @param serviceSwagger * @param isAuthorized * @return net.evecom.scplatform.common.entry.CommonResp<java.lang.String> * @author Torres Liu * @description //TODO 通過JSON或URL匯入服務 * @date 2020/4/24 5:46 下午 **/ @Override @Transactional(rollbackFor = Exception.class) public CommonResp<String> swaggerJsonImport(String jsonUrl, ServiceSwagger serviceSwagger, String isAuthorized) throws IOException { String jsonStr = ""; CloseableHttpClient httpClient = HttpClientBuilder.create().build(); //提前生成 一級標題的id欄位 by liumingyu String firstTitleUuid = IDUtils.new32UUID(); //獲取前端傳入的是否授權標識 by liumingyu String isAuthorizedAccessStr = StringUtils.defaultIfBlank(isAuthorized, "0"); Integer isAuthorizedAccess = Integer.valueOf(isAuthorizedAccessStr); try { //判斷是通過url or json傳入資料 by liumingyu if (!StringUtils.isBlank(jsonUrl) && "".equals(serviceSwagger.getSwaggerJson())) { //判斷url的有效性 boolean urlValidity = ifUrlValidity(jsonUrl); //判斷url是否是swagger的url boolean swaggerUrl = ifSwaggerUrl(jsonUrl); if (urlValidity && swaggerUrl) { HttpGet httpGet = new HttpGet(jsonUrl); CloseableHttpResponse response = httpClient.execute(httpGet); if (response.getStatusLine().getStatusCode() == SUCCESS_CODE) { HttpEntity entity = response.getEntity(); String string = EntityUtils.toString(entity, "utf-8"); jsonStr = string; } response.close(); httpClient.close(); } else { return CommonResp.exception("傳入的url不正確!"); } } else if (serviceSwagger != null && !"".equals(serviceSwagger.getSwaggerJson())) { String swaggerJson = serviceSwagger.getSwaggerJson(); //判斷字串是否為json格式 boolean isJson = isJson(swaggerJson); if (isJson) { JSONObject jsonObject = new JSONObject(swaggerJson); Object o = JSON.toJSON(jsonObject); jsonStr = com.alibaba.fastjson.JSONObject.toJSONString(o); } else { return CommonResp.exception("傳入的json格式不正確!"); } } else { return CommonResp.exception("服務匯入URL或JSON出錯!"); } //獲取當前租戶 String gmtTenant = UserUtil.getLoginUser().getGmtTenant(); //獲取當前使用者id String userId = UserUtil.getLoginUser().getId(); String gmtCreator = (userId != null) ? userId : ""; //轉換 JSON string to Map by liumingyu Map<String, Object> map = SwaggerJsonUtils.readValue(jsonStr, HashMap.class); //解析info by liumingyu Map<String, Object> infoMap = (Map<String, Object>) map.get("info"); //拿到一級標題 by liumingyu String catalogName = (String) infoMap.get("title"); //拿到所有二級標題(類標題)的List by liumingyu List<Map<String, String>> tags = (List<Map<String, String>>) map.get("tags"); //如果表中沒有該一級標題名稱,需要新增一個 by liumingyu if (catalogName != null) { //查詢庫中是否有當前登入使用者且pid為-1的根目錄 ServiceCatalog catalogBeanByCreatorAndPid = serviceCatalogDao.findByCreatorAndPid(gmtCreator, "-1"); //查詢庫中是否存在該一級標題名稱 by liumingyu ServiceCatalog catalogBean = serviceCatalogDao.findByCatalogNameAndCreator(gmtCreator, catalogName); //若不存在該標題名稱,新增一級目錄和二級目錄 by liumingyu //1.插入一級二級標題資料到服務目錄表 by liumingyu if (catalogBean == null && catalogBeanByCreatorAndPid != null) { ServiceCatalog serviceCatalog = new ServiceCatalog(); serviceCatalog.setId(firstTitleUuid); //將根目錄id作為一級目錄的pid serviceCatalog.setPid(catalogBeanByCreatorAndPid.getId()); serviceCatalog.setCatalogName(catalogName); serviceCatalogDao.add(serviceCatalog); //新增二級標題(目錄)by liumingyu addTags(tags, firstTitleUuid, gmtTenant, gmtCreator); } else { //存在的話只要新增二級標題 by liumingyu //拿到該一級目錄的id by liumingyu if (catalogBean != null && catalogBean.getId() != null) { String fatherId = catalogBean.getId(); //新增二級標題(目錄)by liumingyu addTags(tags, fatherId, gmtTenant, gmtCreator); } } } //解析model by liumingyu Map<String, SwaggerModelAttr> definitinMapOld = parseDefinitions(map); Map<String, Map<String, Object>> definitinMap = newParseDefinitions(map); //獲取服務版本(取得是一級info的版本號)by liumingyu String version = (String) infoMap.get("version"); //解析paths by liumingyu Map<String, Map<String, Object>> paths = (Map<String, Map<String, Object>>) map.get("paths"); //解析bashPath by liumingyu String basePath = (String) map.get("basePath"); String[] basePathSplit = null; if (basePath != null && !"".equals(basePath)) { basePathSplit = basePath.split(","); } if (paths != null) { //通過entrySet()取出對映關係,iterator()迭代,存放到迭代器中 by liumingyu Iterator<Map.Entry<String, Map<String, Object>>> it = paths.entrySet().iterator(); //開始遍歷paths by liumingyu while (it.hasNext()) { //拿到單個path的資料資訊,用map的Entry物件存起來 by liumingyu Map.Entry<String, Map<String, Object>> path = it.next(); Iterator<Map.Entry<String, Object>> it2 = path.getValue().entrySet().iterator(); //請求url by liumingyu String requestUrl = ""; if (basePathSplit.length > 0 && !"/".equals(basePathSplit[0])) { //拼接 bashPath + url by liumingyu requestUrl = kongServerAddr + basePathSplit[0] + path.getKey(); } else { requestUrl = kongServerAddr + path.getKey(); } while (it2.hasNext()) { Map.Entry<String, Object> it2Request = it2.next(); //請求方法 GET / POST 等等 by liumingyu String requestMethod = it2Request.getKey().toUpperCase(); //拿到某個介面(服務)的具體資料 by liumingyu Map<String, Object> content = (Map<String, Object>) it2Request.getValue(); //服務名稱 by liumingyu String serviceName = String.valueOf(content.get("summary")); //該服務的操作id by liumingyu String operationId = String.valueOf(content.get("operationId")); //請求體 by liumingyu List<LinkedHashMap> parametersList = (ArrayList) content.get("parameters"); //響應Code體 by liumingyu Map<String, Object> responsesList = (Map<String, Object>) content.get("responses"); //服務描述 by liumingyu String serviceDesc = ""; String description = String.valueOf(content.get("description")); if (!"".equals(description) && description != null) { serviceDesc = description; } //請求引數格式,類似於 multipart/form-data by liumingyu String contentType = ""; List<String> consumes = (List) content.get("consumes"); if (consumes != null && consumes.size() > 0) { contentType = StringUtils.join(consumes, ","); } //返回引數格式,類似於 application/json by liumingyu String callContentType = ""; List<String> produces = (List) content.get("produces"); List<String> newProduces = new ArrayList<>(); for (String produce : produces) { String newProduce = ""; if ("*/*".equals(produce) || "".equals(produce)) { newProduce = "application/json"; } else { newProduce = produce; } newProduces.add(newProduce); } if (newProduces != null && newProduces.size() > 0) { callContentType = StringUtils.join(newProduces, ","); } //服務版本預設為1.0 by liumingyu String serviceVersion = "1.0"; serviceVersion = StringUtils.defaultIfBlank(version, serviceVersion); //查詢當前庫中是否存在operationId和服務名稱,如果存在 後續所有資料不會進行新增 by liumingyu List<ServiceResource> listByOperationId = serviceResourceDao.findByOperationId(operationId, serviceName, userId); //若operationId不存在庫中====>才進行後續的新增操作 by liumingyu if (listByOperationId.size() == 0) { //封裝serviceResource表 by liumingyu ServiceResource resourceTable = new ServiceResource(); //宣告一個uuid 作為本輪遍歷的resource表主鍵id,也是本輪遍歷其他表對應的serviceId by liumingyu String thisResourceId = IDUtils.new32UUID(); resourceTable.setId(thisResourceId); resourceTable.setServiceName(serviceName); resourceTable.setServiceDesc(serviceDesc); resourceTable.setRequestUrl(requestUrl); resourceTable.setRequestMethod(requestMethod); resourceTable.setContentType(contentType); resourceTable.setCallContentType(callContentType); resourceTable.setServiceVersion(serviceVersion); resourceTable.setIsValid(1); resourceTable.setIsRelease(0); resourceTable.setIsDelete(0); resourceTable.setRouteUuid(UUID.randomUUID().toString()); //前端傳入--->是否授權標識 by liumingyu resourceTable.setIsAuthorizedAccess(isAuthorizedAccess); //新增操作id by liumingyu resourceTable.setOperationId(operationId); //2.新增資料到serviceResource表 by liumingyu serviceResourceDao.add(resourceTable); //處理parametersList資料轉為ServiceRequest表List物件 by liumingyu List<ServiceRequest> serviceRequestList = processRequestList(parametersList, definitinMap); //3.新增資料到serviceRequest表 by liumingyu addServiceRequest(serviceRequestList, thisResourceId, gmtTenant); //處理responsesList資料轉為ResponseStatus表List物件 by liumingyu List<ResponseStatus> responseStatusList = processResponseStatusList(responsesList, definitinMap); //4.新增資料到ResponseStatus表 by liumingyu addResponseStatus(responseStatusList, thisResourceId, gmtTenant); //取出來狀態是200時的返回值 by liumingyu Map<String, Object> responsesObj = (Map<String, Object>) responsesList.get("200"); if (responsesObj != null && responsesObj.get(SCHEMA_VAL) != null) { //處理相應的返回值 by liumingyu SwaggerModelAttr swaggerModelAttr = processResponseModelAttrs(responsesObj, definitinMapOld); //拿到properties資料,這個List裡面就是需要的返回值資料 by liumingyu List<SwaggerModelAttr> propertiesList = swaggerModelAttr.getProperties(); //5.新增資料到ServiceResponse表(傳遞propertiesList和主表的id) by liumingyu addServiceResponse(propertiesList, thisResourceId, gmtTenant); } //操作服務類別關係表(目錄和服務關係表) by liumingyu String tagsName = String.valueOf(((List) content.get("tags")).get(0)); //6.新增資料到目錄關係表 by liumingyu addCatalogRela(tagsName, thisResourceId, gmtCreator); } else { log.info("迭代器當前執行到的物件operationId「" + operationId + "」已存在資料庫中,不進行插入"); } } } } } catch (Exception e) { log.error("服務匯入失敗", e); return CommonResp.exception("服務匯入失敗"); } return CommonResp.succeed("服務匯入成功!"); } /** * 服務匯出Json * * @param serviceId * @param catalogId * @return java.util.List<net.evecom.scplatform.openapi.entity.dto.SwaggerHtmlDto> * @author Torres Liu * @description //TODO 服務匯出Json * @date 2020/4/24 5:50 下午 **/ @Override public List<SwaggerHtmlDto> swaggerJsonExport(String serviceId, String catalogId) { String titleName = ""; List<SwaggerHtmlDto> result = new ArrayList<>(); try { if (serviceId != null && !"".equals(serviceId)) { SwaggerHtmlDto thisDto = new SwaggerHtmlDto(); //根據serviceId查詢所需資料 ServiceResource resourceTable = serviceResourceDao.findById(serviceId); List<ServiceRequest> requestList = serviceRequestDao.findByServiceId(serviceId); List<ResponseStatus> responseStatusList = responseStatusDao.findByServiceId(serviceId); List<ServiceResponse> serviceResponseList = serviceResponseDao.findByServiceId(serviceId); ServiceCatalog thisCatalogBean = serviceCatalogDao.findById(catalogId == null ? "" : catalogId); //將資料set到自定義封裝的dto實體中 thisDto.setServiceResource(resourceTable); thisDto.setRequestList(requestList); thisDto.setResponseStatusList(responseStatusList); thisDto.setResponseList(serviceResponseList); //宣告一個標題名 titleName = resourceTable.getServiceName(); if (thisCatalogBean != null) { thisDto.setTag(thisCatalogBean.getCatalogName()); titleName = thisCatalogBean.getCatalogName() + "-" + titleName; String thisCatalogPid = thisCatalogBean.getPid(); ServiceCatalog pidBean = serviceCatalogDao.findById(thisCatalogPid); if (pidBean != null) { thisDto.setTitle(pidBean.getCatalogName()); titleName = pidBean.getCatalogName() + "-" + titleName; } } thisDto.setVersion(resourceTable.getServiceVersion()); //將所有資料add至result result.add(thisDto); return result; } } catch (Exception e) { log.error("服務匯出異常:", e); } return result; } /** * @param tags * @param pid * @param gmtTenant * @return void * @author Torres Liu * @description //TODO 將json的二級標題,新增至目錄表作為二級目錄,pid為一級目錄id * @date 2020/4/24 5:52 下午 **/ private void addTags(List<Map<String, String>> tags, String pid, String gmtTenant, String gmtCreator) { if (tags != null) { gmtTenant = (gmtTenant != null) ? gmtTenant : ""; List<ServiceCatalog> catalogList = new ArrayList<>(); for (Map tag : tags) { String name = (String) tag.get("name"); if (name != null && !"".equals(name)) { ServiceCatalog catalogBean2 = serviceCatalogDao.findByCatalogNameAndCreator(gmtCreator, name); //如果沒有該二級目錄則開始新增二級目錄 by liumingyu if (catalogBean2 == null && pid != null) { ServiceCatalog serviceCatalogBean = new ServiceCatalog(); serviceCatalogBean.setPid(pid); serviceCatalogBean.setCatalogName(name); serviceCatalogBean.setId(IDUtils.new32UUID()); catalogList.add(serviceCatalogBean); } } } if (catalogList.size() > 0) { //傳入List批量新增 serviceCatalogDao.batchAdd(catalogList, new CommonEntry(), gmtTenant); } } } /** * @param serviceRequestList * @param thisResourceId * @param gmtTenant * @return void * @author Torres Liu * @description //TODO 新增資料到 服務請求表 * @date 2020/4/24 5:52 下午 **/ private void addServiceRequest(List<ServiceRequest> serviceRequestList, String thisResourceId, String gmtTenant) { List<ServiceRequest> requestList = new ArrayList<>(); if (serviceRequestList != null && thisResourceId != null) { gmtTenant = (gmtTenant != null) ? gmtTenant : ""; for (ServiceRequest requestParameter : serviceRequestList) { ServiceRequest requestTable = new ServiceRequest(); requestTable.setId(IDUtils.new32UUID()); requestTable.setServiceId(thisResourceId); requestTable.setReqName(requestParameter.getReqName()); requestTable.setReqDesc(requestParameter.getReqDesc()); requestTable.setIsRequired(requestParameter.getIsRequired()); requestTable.setReqType(requestParameter.getReqType()); requestTable.setReqFrom(requestParameter.getReqFrom()); requestList.add(requestTable); } if (requestList.size() > 0) { //批量新增資料 serviceRequestDao.batchAdd(requestList, new CommonEntry(), gmtTenant); } } } /** * @param responseStatusList * @param thisResourceId * @param gmtTenant * @return void * @author Torres Liu * @description //TODO 新增資料到 響應狀態表 * @date 2020/4/24 5:54 下午 **/ private void addResponseStatus(List<ResponseStatus> responseStatusList, String thisResourceId, String gmtTenant) { List<ResponseStatus> statusList = new ArrayList<>(); if (responseStatusList != null && thisResourceId != null) { gmtTenant = (gmtTenant != null) ? gmtTenant : ""; for (ResponseStatus response : responseStatusList) { ResponseStatus responseStatusTable = new ResponseStatus(); responseStatusTable.setId(IDUtils.new32UUID()); responseStatusTable.setServiceId(thisResourceId); responseStatusTable.setStatusCode(response.getStatusCode()); responseStatusTable.setStatusDesc(response.getStatusDesc()); responseStatusTable.setStatusRemark(response.getStatusRemark()); statusList.add(responseStatusTable); } if (statusList.size() > 0) { //批量新增資料 responseStatusDao.batchAdd(statusList, new CommonEntry(), gmtTenant); } } } /** * @param propertiesList * @param thisResourceId * @param gmtTenant * @return void * @author Torres Liu * @description //TODO 新增資料到 服務響應表 * @date 2020/4/24 5:55 下午 **/ private void addServiceResponse(List<SwaggerModelAttr> propertiesList, String thisResourceId, String gmtTenant) { List<ServiceResponse> responseList = new ArrayList<>(); if (propertiesList != null && thisResourceId != null) { gmtTenant = (gmtTenant != null) ? gmtTenant : ""; //新增資料到serviceResponse表 by liumingyu for (SwaggerModelAttr p : propertiesList) { ServiceResponse serviceResponseTable = new ServiceResponse(); serviceResponseTable.setId(IDUtils.new32UUID()); //該服務id 為前面生成的serviceResource表(主表)的主鍵(資源id)by liumingyu serviceResponseTable.setServiceId(thisResourceId); serviceResponseTable.setPropName(p.getName()); serviceResponseTable.setPropType(p.getType()); serviceResponseTable.setPropDesc(p.getDescription()); responseList.add(serviceResponseTable); } if (responseList.size() > 0) { //批量新增資料 serviceResponseDao.batchAdd(responseList, new CommonEntry(), gmtTenant); } } } /** * @param tagsName * @param thisResourceId * @return void * @author Torres Liu * @description //TODO 新增資料到目錄關係表 * @date 2020/4/24 5:55 下午 **/ private void addCatalogRela(String tagsName, String thisResourceId, String gmtCreator) { ServiceCatalogRela catalogRelaTable = new ServiceCatalogRela(); if (tagsName != null && !"".equals(tagsName) && thisResourceId != null) { //通過tagsName查出目錄id by liumingyu ServiceCatalog catalogBean = serviceCatalogDao.findByCatalogNameAndCreator(gmtCreator, tagsName); if (catalogBean != null && catalogBean.getId() != null) { String catalogId = catalogBean.getId(); catalogRelaTable.setId(IDUtils.new32UUID()); //將目錄id插入關係表 by liumingyu catalogRelaTable.setCatalogId(catalogId); //將當前的服務id插入關係表 by liumingyu catalogRelaTable.setServiceId(thisResourceId); serviceCatalogRelaDao.add(catalogRelaTable); } } } /** * @param map * @return java.util.Map<java.lang.String, net.evecom.scplatform.openapi.entity.SwaggerModelAttr> * @author Torres Liu * @description //TODO 解析Definitions * @date 2020/4/24 5:55 下午 **/ private Map<String, SwaggerModelAttr> parseDefinitions(Map<String, Object> map) { Map<String, Map<String, Object>> definitions = (Map<String, Map<String, Object>>) map.get("definitions"); Map<String, SwaggerModelAttr> definitinMap = new HashMap<>(256); if (definitions != null) { Iterator<String> modelNameIt = definitions.keySet().iterator(); while (modelNameIt.hasNext()) { String modeName = modelNameIt.next(); Map<String, Object> modeProperties = (Map<String, Object>) definitions.get(modeName).get("properties"); if (modeProperties == null) { continue; } Iterator<Map.Entry<String, Object>> mIt = modeProperties.entrySet().iterator(); List<SwaggerModelAttr> attrList = new ArrayList<>(); //解析屬性 by liumingyu while (mIt.hasNext()) { Map.Entry<String, Object> mEntry = mIt.next(); Map<String, Object> attrInfoMap = (Map<String, Object>) mEntry.getValue(); SwaggerModelAttr modeAttr = new SwaggerModelAttr(); modeAttr.setName(mEntry.getKey()); modeAttr.setType((String) attrInfoMap.get("type")); if (attrInfoMap.get(FORMAT_VAL) != null) { modeAttr.setType(modeAttr.getType() + "(" + attrInfoMap.get("format") + ")"); } modeAttr.setType(StringUtils.defaultIfBlank(modeAttr.getType(), "object")); modeAttr.setDescription((String) attrInfoMap.get("description")); attrList.add(modeAttr); } SwaggerModelAttr modeAttr = new SwaggerModelAttr(); Object title = definitions.get(modeName).get("title"); Object description = definitions.get(modeName).get("description"); modeAttr.setClassName(title == null ? "" : title.toString()); modeAttr.setDescription(description == null ? "" : description.toString()); modeAttr.setProperties(attrList); definitinMap.put("#/definitions/" + modeName, modeAttr); } } return definitinMap; } /** * @param map * @return java.util.Map<java.lang.String, java.util.Map < java.lang.String, java.lang.Object>> * @author Torres Liu * @description //TODO 解析Definitions---->new * @date 2020/4/24 5:55 下午 **/ private Map<String, Map<String, Object>> newParseDefinitions(Map<String, Object> map) { Map<String, Map<String, Object>> definitions = (Map<String, Map<String, Object>>) map.get("definitions"); Map<String, Map<String, Object>> definitinMap = new HashMap<>(256); if (definitions != null) { Iterator<String> modelNameIt = definitions.keySet().iterator(); while (modelNameIt.hasNext()) { String modeName = modelNameIt.next(); Map<String, Object> modeProperties = definitions.get(modeName); definitinMap.put("#/definitions/" + modeName, modeProperties); } } return definitinMap; } /** * @param parameters * @param definitionMap * @return java.util.List<net.evecom.scplatform.openapi.entity.ServiceRequest> * @author Torres Liu * @description //TODO 處理請求List * @date 2020/4/24 5:56 下午 **/ private List<ServiceRequest> processRequestList(List<LinkedHashMap> parameters, Map<String, Map<String, Object>> definitionMap) { List<ServiceRequest> requestList = new ArrayList<>(); Map<String, Object> myHashMap = new HashMap<>(2000); if (!CollectionUtils.isEmpty(parameters)) { for (Map<String, Object> param : parameters) { Object in = param.get("in"); ServiceRequest request = new ServiceRequest(); request.setReqName(String.valueOf(param.get("name"))); request.setReqType(param.get("type") == null ? "object" : param.get("type").toString()); request.setReqFrom(String.valueOf(in)); // 考慮物件引數型別 by liumingyu if (in != null && "body".equals(in)) { Map<String, Object> schema = (Map) param.get("schema"); //拿到 ----> #/definitions/檔案目錄請求物件 Object ref = schema.get("$ref"); if (ref != null) { Map<String, Object> mapByRefValue = definitionMap.get(ref); if (mapByRefValue != null) { Map<String, Object> propertiesMap = (Map<String, Object>) mapByRefValue.get("properties"); if (propertiesMap != null) { //將properties中的值進行迭代 Iterator<Map.Entry<String, Object>> itProp = propertiesMap.entrySet().iterator(); while (itProp.hasNext()) { SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String dataFormat = simpleDateFormat.format(new Date()); //取到單個值 ----> 如 endRow: {type: "integer", format: "int32"} Map.Entry<String, Object> entryIt = itProp.next(); Map<String, Object> itValue = (Map<String, Object>) entryIt.getValue(); String type = (String) itValue.get("type"); if (!StringUtils.isBlank(type)) { switch (type) { case "string": if (itValue.get(FORMAT_VAL) != null && !"".equals(itValue.get(FORMAT_VAL))) { String format = (String) itValue.get("format"); if ("date-time".equals(format) || "dateTime".equals(format)) { myHashMap.put(entryIt.getKey(), dataFormat); } } else { myHashMap.put(entryIt.getKey(), "string"); } break; case "integer": myHashMap.put(entryIt.getKey(), 0); break; case "number": myHashMap.put(entryIt.getKey(), 0.0); break; case "boolean": myHashMap.put(entryIt.getKey(), true); break; case "array": Integer initNum = 0; //開始呼叫--->遞迴演算法邏輯 ifArrayRecursion(itValue, definitionMap, dataFormat, myHashMap, entryIt, initNum); break; default: myHashMap.put(entryIt.getKey(), null); break; } } } } } } request.setReqDesc(JSON.toJSONString(myHashMap)); } else { request.setReqDesc((String.valueOf(param.get("description")))); } // 是否必填 by liumingyu request.setIsRequired(0); if (param.get("required") != null) { Boolean required = (Boolean) param.get("required"); if (required == true) { request.setIsRequired(1); } } requestList.add(request); } } return requestList; } /** * @param responsesList * @param definitionMap * @return java.util.List<net.evecom.scplatform.openapi.entity.ResponseStatus> * @author Torres Liu * @description //TODO 處理返回狀態碼CodeList(像200、404、401...) * @date 2020/4/24 5:56 下午 **/ private List<ResponseStatus> processResponseStatusList(Map<String, Object> responsesList, Map<String, Map<String, Object>> definitionMap) { List<ResponseStatus> responseStatusList = new ArrayList<>(); Iterator<Map.Entry<String, Object>> resIt = responsesList.entrySet().iterator(); while (resIt.hasNext()) { Map.Entry<String, Object> entry = resIt.next(); //宣告個響應狀態碼實體 ResponseStatus responseStatus = new ResponseStatus(); //開始迭代 狀態碼200 201 401 403 404 等等 by liumingyu responseStatus.setStatusCode(entry.getKey()); //獲取response的value 像---> {description: "OK", schema: {$ref: "#/definitions/CommonResp«string»"}} LinkedHashMap<String, Object> statusCodeInfo = (LinkedHashMap) entry.getValue(); //setDescription responseStatus.setStatusDesc(String.valueOf(statusCodeInfo.get("description"))); if ("200".equals(entry.getKey())) { Object schema = statusCodeInfo.get("schema"); if (schema != null && ((LinkedHashMap) schema).get("$ref") != null) { //定義一個儲存definition的map Map<String, Object> myHashMap = new HashMap<>(2000); Map<String, Object> myHashMap2 = new HashMap<>(2000); //如果schema不為null,開始解析$ref ---> $ref: "#/definitions/CommonResp«string»" Object ref = ((LinkedHashMap) schema).get("$ref"); //將取到的ref的值放入definitionMap