# Conflicts: # sop-website/website-server/src/main/java/com/gitee/sop/websiteserver/manager/DocManagerImpl.java1.x
commit
12df3e403f
@ -1,27 +0,0 @@ |
||||
package com.gitee.sop.servercommon.bean; |
||||
|
||||
import org.springframework.core.env.Environment; |
||||
|
||||
/** |
||||
* @author thc |
||||
*/ |
||||
public class EnvironmentContext { |
||||
|
||||
private static Environment environment; |
||||
|
||||
public static Environment getEnvironment() { |
||||
return environment; |
||||
} |
||||
|
||||
public static void setEnvironment(Environment environment) { |
||||
EnvironmentContext.environment = environment; |
||||
} |
||||
|
||||
public static String getProfile(Environment env) { |
||||
return env.getProperty("spring.profiles.active", "default"); |
||||
} |
||||
|
||||
public static String getProfile() { |
||||
return getProfile(environment); |
||||
} |
||||
} |
@ -0,0 +1,11 @@ |
||||
package com.gitee.sop.servercommon.bean; |
||||
|
||||
/** |
||||
* @author tanghc |
||||
*/ |
||||
public class ServiceConstants { |
||||
/** |
||||
* zookeeper存放接口路由信息的根目录 |
||||
*/ |
||||
public static final String SOP_SERVICE_ROUTE_PATH = "/com.gitee.sop.route"; |
||||
} |
@ -0,0 +1,99 @@ |
||||
package com.gitee.sop.servercommon.bean; |
||||
|
||||
import lombok.Getter; |
||||
import lombok.extern.slf4j.Slf4j; |
||||
import org.apache.commons.lang.StringUtils; |
||||
import org.apache.commons.lang.math.NumberUtils; |
||||
import org.apache.curator.framework.CuratorFramework; |
||||
import org.apache.curator.framework.CuratorFrameworkFactory; |
||||
import org.apache.curator.retry.ExponentialBackoffRetry; |
||||
import org.springframework.core.env.Environment; |
||||
|
||||
import java.io.Closeable; |
||||
import java.io.IOException; |
||||
|
||||
|
||||
/** |
||||
* @author tanghc |
||||
*/ |
||||
@Slf4j |
||||
@Getter |
||||
public class ZookeeperTool implements Closeable { |
||||
|
||||
private CuratorFramework client; |
||||
private Environment environment; |
||||
|
||||
public ZookeeperTool(Environment environment) { |
||||
this.environment = environment; |
||||
initZookeeperClient(environment); |
||||
} |
||||
|
||||
public void initZookeeperClient(Environment environment) { |
||||
String zookeeperServerAddr = environment.getProperty("spring.cloud.zookeeper.connect-string"); |
||||
if (StringUtils.isBlank(zookeeperServerAddr)) { |
||||
throw new RuntimeException("未指定spring.cloud.zookeeper.connect-string参数"); |
||||
} |
||||
String baseSleepTimeMs = environment.getProperty("spring.cloud.zookeeper.baseSleepTimeMs"); |
||||
String maxRetries = environment.getProperty("spring.cloud.zookeeper.maxRetries"); |
||||
log.info("初始化zookeeper客户端,zookeeperServerAddr:{}, baseSleepTimeMs:{}, maxRetries:{}", |
||||
zookeeperServerAddr, baseSleepTimeMs, maxRetries); |
||||
CuratorFramework client = CuratorFrameworkFactory.builder() |
||||
.connectString(zookeeperServerAddr) |
||||
.retryPolicy(new ExponentialBackoffRetry(NumberUtils.toInt(baseSleepTimeMs, 3000), NumberUtils.toInt(maxRetries, 3))) |
||||
.build(); |
||||
|
||||
client.start(); |
||||
|
||||
this.client = client; |
||||
} |
||||
|
||||
public boolean isPathExist(String path) { |
||||
try { |
||||
return client.checkExists().forPath(path) != null; |
||||
} catch (Exception e) { |
||||
return false; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 创建path,如果path存在不报错,静默返回path名称 |
||||
* |
||||
* @param path |
||||
* @param data |
||||
* @return |
||||
* @throws Exception |
||||
*/ |
||||
public String createPath(String path, String data) throws Exception { |
||||
if (isPathExist(path)) { |
||||
return path; |
||||
} |
||||
return getClient().create() |
||||
// 如果指定节点的父节点不存在,则Curator将会自动级联创建父节点
|
||||
.creatingParentContainersIfNeeded() |
||||
.forPath(path, data.getBytes()); |
||||
} |
||||
|
||||
/** |
||||
* 新建或保存节点 |
||||
* |
||||
* @param path |
||||
* @param data |
||||
* @return 返回path |
||||
* @throws Exception |
||||
*/ |
||||
public String createOrUpdateData(String path, String data) throws Exception { |
||||
return getClient().create() |
||||
// 如果节点存在则Curator将会使用给出的数据设置这个节点的值
|
||||
.orSetData() |
||||
// 如果指定节点的父节点不存在,则Curator将会自动级联创建父节点
|
||||
.creatingParentContainersIfNeeded() |
||||
.forPath(path, data.getBytes()); |
||||
} |
||||
|
||||
@Override |
||||
public void close() throws IOException { |
||||
if (this.client != null) { |
||||
this.client.close(); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,54 @@ |
||||
package com.gitee.sop.servercommon.configuration; |
||||
|
||||
import com.gitee.easyopen.doc.ApiDocHolder; |
||||
import com.gitee.sop.servercommon.swagger.SwaggerValidator; |
||||
import org.springframework.web.bind.annotation.RequestMapping; |
||||
import org.springframework.web.bind.annotation.ResponseBody; |
||||
|
||||
import javax.servlet.http.HttpServletRequest; |
||||
import javax.servlet.http.HttpServletResponse; |
||||
import java.io.IOException; |
||||
import java.util.HashMap; |
||||
import java.util.Map; |
||||
|
||||
/** |
||||
* 文档支持 |
||||
* @author thc |
||||
*/ |
||||
public abstract class EasyopenDocSupportController { |
||||
|
||||
private SwaggerValidator swaggerValidator; |
||||
|
||||
public abstract String getDocTitle(); |
||||
|
||||
public EasyopenDocSupportController() { |
||||
swaggerValidator = new SwaggerValidator(this.swaggerAccessProtected()); |
||||
} |
||||
|
||||
@RequestMapping("/v2/api-docs") |
||||
@ResponseBody |
||||
public Map<String, Object> getDocInfo(HttpServletRequest request, HttpServletResponse response) throws IOException { |
||||
if (swaggerValidator.swaggerAccessProtected() && !swaggerValidator.validate(request)) { |
||||
swaggerValidator.writeForbidden(response); |
||||
return null; |
||||
} |
||||
Map<String, Object> context = this.getContext(); |
||||
context.put("easyopen", "1.16.3"); |
||||
context.put("apiModules", ApiDocHolder.getApiDocBuilder().getApiModules()); |
||||
context.put("title", getDocTitle()); |
||||
return context; |
||||
} |
||||
|
||||
public Map<String, Object> getContext() { |
||||
return new HashMap<>(8); |
||||
} |
||||
|
||||
/** |
||||
* swagger访问是否加密保护 |
||||
* @return |
||||
*/ |
||||
protected boolean swaggerAccessProtected() { |
||||
return true; |
||||
} |
||||
|
||||
} |
@ -1,16 +0,0 @@ |
||||
package com.gitee.sop.servercommon.swagger; |
||||
|
||||
import springfox.documentation.spring.web.plugins.DocumentationPluginsManager; |
||||
import springfox.documentation.spring.web.scanners.ApiDescriptionReader; |
||||
import springfox.documentation.spring.web.scanners.ApiListingScanner; |
||||
import springfox.documentation.spring.web.scanners.ApiModelReader; |
||||
|
||||
/** |
||||
* @author tanghc |
||||
*/ |
||||
public class ApiListingScannerExt extends ApiListingScanner { |
||||
public ApiListingScannerExt(ApiDescriptionReader apiDescriptionReader, ApiModelReader apiModelReader, DocumentationPluginsManager pluginsManager) { |
||||
super(apiDescriptionReader, apiModelReader, pluginsManager); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,87 @@ |
||||
package com.gitee.sop.servercommon.swagger; |
||||
|
||||
import lombok.extern.slf4j.Slf4j; |
||||
|
||||
import javax.servlet.Filter; |
||||
import javax.servlet.FilterChain; |
||||
import javax.servlet.FilterConfig; |
||||
import javax.servlet.ServletException; |
||||
import javax.servlet.ServletRequest; |
||||
import javax.servlet.ServletResponse; |
||||
import javax.servlet.http.HttpServletRequest; |
||||
import javax.servlet.http.HttpServletResponse; |
||||
import java.io.IOException; |
||||
import java.util.ArrayList; |
||||
import java.util.List; |
||||
|
||||
/** |
||||
* @author tanghc |
||||
*/ |
||||
@Slf4j |
||||
public class SwaggerSecurityFilter implements Filter { |
||||
|
||||
protected List<String> urlFilters = new ArrayList<>(); |
||||
|
||||
{ |
||||
urlFilters.add(".*?/doc\\.html.*"); |
||||
urlFilters.add(".*?/v2/api-docs.*"); |
||||
urlFilters.add(".*?/v2/api-docs-ext.*"); |
||||
urlFilters.add(".*?/swagger-resources.*"); |
||||
urlFilters.add(".*?/swagger-ui\\.html.*"); |
||||
urlFilters.add(".*?/swagger-resources/configuration/ui.*"); |
||||
urlFilters.add(".*?/swagger-resources/configuration/security.*"); |
||||
} |
||||
|
||||
private SwaggerValidator swaggerValidator; |
||||
|
||||
public SwaggerSecurityFilter(boolean swaggerAccessProtected) { |
||||
this.swaggerValidator = new SwaggerValidator(swaggerAccessProtected); |
||||
} |
||||
|
||||
protected boolean match(String uri) { |
||||
boolean match = false; |
||||
if (uri != null) { |
||||
for (String regex : urlFilters) { |
||||
if (uri.matches(regex)) { |
||||
match = true; |
||||
break; |
||||
} |
||||
} |
||||
} |
||||
return match; |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public void init(FilterConfig filterConfig) throws ServletException { |
||||
|
||||
} |
||||
|
||||
@Override |
||||
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { |
||||
if (!swaggerValidator.swaggerAccessProtected()) { |
||||
filterChain.doFilter(servletRequest, servletResponse); |
||||
return; |
||||
} |
||||
HttpServletRequest request = (HttpServletRequest) servletRequest; |
||||
HttpServletResponse response = (HttpServletResponse) servletResponse; |
||||
String uri = request.getRequestURI(); |
||||
// 没有匹配到,直接放行
|
||||
if (!match(uri)) { |
||||
filterChain.doFilter(servletRequest, servletResponse); |
||||
} else { |
||||
if (swaggerValidator.validate(request)) { |
||||
filterChain.doFilter(servletRequest, servletResponse); |
||||
} else { |
||||
swaggerValidator.writeForbidden(response); |
||||
} |
||||
|
||||
} |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public void destroy() { |
||||
|
||||
} |
||||
} |
@ -0,0 +1,53 @@ |
||||
package com.gitee.sop.servercommon.swagger; |
||||
|
||||
import org.apache.commons.lang3.StringUtils; |
||||
import org.springframework.util.DigestUtils; |
||||
|
||||
import javax.servlet.http.HttpServletRequest; |
||||
import javax.servlet.http.HttpServletResponse; |
||||
import java.io.IOException; |
||||
import java.io.PrintWriter; |
||||
|
||||
/** |
||||
* @author tanghc |
||||
*/ |
||||
public class SwaggerValidator { |
||||
|
||||
private String secret = "b749a2ec000f4f29"; |
||||
|
||||
private boolean swaggerAccessProtected = true; |
||||
|
||||
public SwaggerValidator(boolean swaggerAccessProtected) { |
||||
this.swaggerAccessProtected = swaggerAccessProtected; |
||||
} |
||||
|
||||
public SwaggerValidator() { |
||||
} |
||||
|
||||
/** |
||||
* swagger访问是否加密保护 |
||||
* @return |
||||
*/ |
||||
public boolean swaggerAccessProtected() { |
||||
return swaggerAccessProtected; |
||||
} |
||||
|
||||
public boolean validate(HttpServletRequest request) { |
||||
String time = request.getParameter("time"); |
||||
String sign = request.getParameter("sign"); |
||||
if (StringUtils.isAnyBlank(time, sign)) { |
||||
return false; |
||||
} |
||||
String source = secret + time + secret; |
||||
String serverSign = DigestUtils.md5DigestAsHex(source.getBytes()); |
||||
return serverSign.equals(sign); |
||||
} |
||||
|
||||
public void writeForbidden(HttpServletResponse response) throws IOException { |
||||
response.setContentType("text/palin;charset=UTF-8"); |
||||
response.setStatus(403); |
||||
PrintWriter printWriter = response.getWriter(); |
||||
printWriter.write("access forbidden"); |
||||
printWriter.flush(); |
||||
} |
||||
} |
@ -0,0 +1,31 @@ |
||||
package com.gitee.easyopen.server.api; |
||||
|
||||
import com.gitee.easyopen.annotation.Api; |
||||
import com.gitee.easyopen.annotation.ApiService; |
||||
import com.gitee.easyopen.doc.annotation.ApiDoc; |
||||
import com.gitee.easyopen.doc.annotation.ApiDocMethod; |
||||
import com.gitee.easyopen.server.api.param.GoodsParam; |
||||
import com.gitee.easyopen.server.api.result.Goods; |
||||
|
||||
import java.math.BigDecimal; |
||||
|
||||
/** |
||||
* 业务类 |
||||
* |
||||
* @author tanghc |
||||
*/ |
||||
@ApiService |
||||
@ApiDoc("库存接口") |
||||
public class Goods2Api { |
||||
|
||||
@Api(name = "store.get") |
||||
@ApiDocMethod(description = "获取库存") |
||||
Goods getGoods(GoodsParam param) { |
||||
Goods goods = new Goods(); |
||||
goods.setId(1L); |
||||
goods.setGoods_name("苹果iPhoneX"); |
||||
goods.setPrice(new BigDecimal(8000)); |
||||
return goods; |
||||
} |
||||
|
||||
} |
@ -1,11 +1,21 @@ |
||||
package com.gitee.easyopen.server.config; |
||||
|
||||
import com.gitee.sop.servercommon.configuration.EasyopenDocSupportController; |
||||
import com.gitee.sop.servercommon.configuration.EasyopenServiceConfiguration; |
||||
import org.springframework.context.annotation.Configuration; |
||||
import org.springframework.stereotype.Controller; |
||||
|
||||
/** |
||||
* @author tanghc |
||||
*/ |
||||
@Configuration |
||||
public class SopConfig extends EasyopenServiceConfiguration { |
||||
|
||||
@Controller |
||||
public static class SopDocController extends EasyopenDocSupportController { |
||||
@Override |
||||
public String getDocTitle() { |
||||
return "商品API"; |
||||
} |
||||
} |
||||
} |
||||
|
@ -0,0 +1,17 @@ |
||||
eureka: |
||||
client: |
||||
fetch-registry: false |
||||
# 不注册自己 |
||||
register-with-eureka: false |
||||
serviceUrl: |
||||
defaultZone: http://${eureka.host}:${eureka.port}/eureka/ |
||||
# 注册中心地址 |
||||
host: localhost |
||||
port: 1111 |
||||
|
||||
server: |
||||
port: 1111 |
||||
|
||||
spring: |
||||
application: |
||||
name: sop-registry |
@ -1,12 +0,0 @@ |
||||
spring.application.name=sop-registry |
||||
server.port=1111 |
||||
|
||||
# ---- eureka注册中心 ---- |
||||
# 不注册自己 |
||||
eureka.client.register-with-eureka=false |
||||
eureka.client.fetch-registry=false |
||||
# 注册中心地址 |
||||
eureka.host=localhost |
||||
eureka.port=1111 |
||||
eureka.client.serviceUrl.defaultZone=http://${eureka.host}:${eureka.port}/eureka/ |
||||
|
@ -0,0 +1,3 @@ |
||||
spring: |
||||
profiles: |
||||
active: dev |
@ -0,0 +1,14 @@ |
||||
package com.gitee.sop.websiteserver.bean; |
||||
|
||||
import lombok.Data; |
||||
|
||||
import java.util.List; |
||||
|
||||
/** |
||||
* @author tanghc |
||||
*/ |
||||
@Data |
||||
public class DocInfo { |
||||
private String title; |
||||
private List<DocModule> docModuleList; |
||||
} |
@ -0,0 +1,11 @@ |
||||
package com.gitee.sop.websiteserver.bean; |
||||
|
||||
/** |
||||
* @author tanghc |
||||
*/ |
||||
public class WebsiteConstants { |
||||
/** |
||||
* zookeeper存放接口路由信息的根目录 |
||||
*/ |
||||
public static final String SOP_SERVICE_ROUTE_PATH = "/com.gitee.sop.route"; |
||||
} |
@ -0,0 +1,80 @@ |
||||
package com.gitee.sop.websiteserver.bean; |
||||
|
||||
import lombok.extern.slf4j.Slf4j; |
||||
import org.apache.commons.lang.StringUtils; |
||||
import org.apache.commons.lang.math.NumberUtils; |
||||
import org.apache.curator.framework.CuratorFramework; |
||||
import org.apache.curator.framework.CuratorFrameworkFactory; |
||||
import org.apache.curator.framework.recipes.cache.TreeCache; |
||||
import org.apache.curator.framework.recipes.cache.TreeCacheListener; |
||||
import org.apache.curator.retry.ExponentialBackoffRetry; |
||||
import org.springframework.core.env.Environment; |
||||
import org.springframework.util.Assert; |
||||
|
||||
/** |
||||
* @author tanghc |
||||
*/ |
||||
@Slf4j |
||||
public class ZookeeperContext { |
||||
|
||||
private static CuratorFramework client; |
||||
|
||||
public static void setEnvironment(Environment environment) { |
||||
Assert.notNull(environment, "environment不能为null"); |
||||
initZookeeperClient(environment); |
||||
} |
||||
|
||||
public synchronized static void initZookeeperClient(Environment environment) { |
||||
if (client != null) { |
||||
return; |
||||
} |
||||
String zookeeperServerAddr = environment.getProperty("spring.cloud.zookeeper.connect-string"); |
||||
if (StringUtils.isBlank(zookeeperServerAddr)) { |
||||
throw new RuntimeException("未指定spring.cloud.zookeeper.connect-string参数"); |
||||
} |
||||
String baseSleepTimeMs = environment.getProperty("spring.cloud.zookeeper.baseSleepTimeMs"); |
||||
String maxRetries = environment.getProperty("spring.cloud.zookeeper.maxRetries"); |
||||
log.info("初始化zookeeper客户端,zookeeperServerAddr:{}, baseSleepTimeMs:{}, maxRetries:{}", |
||||
zookeeperServerAddr, baseSleepTimeMs, maxRetries); |
||||
CuratorFramework client = CuratorFrameworkFactory.builder() |
||||
.connectString(zookeeperServerAddr) |
||||
.retryPolicy(new ExponentialBackoffRetry(NumberUtils.toInt(baseSleepTimeMs, 3000), NumberUtils.toInt(maxRetries, 3))) |
||||
.build(); |
||||
|
||||
client.start(); |
||||
|
||||
setClient(client); |
||||
} |
||||
|
||||
public static String getRouteRootPath() { |
||||
return WebsiteConstants.SOP_SERVICE_ROUTE_PATH; |
||||
} |
||||
|
||||
public static CuratorFramework getClient() { |
||||
return client; |
||||
} |
||||
|
||||
public static void setClient(CuratorFramework client) { |
||||
ZookeeperContext.client = client; |
||||
} |
||||
|
||||
/** |
||||
* 监听子节点,可以自定义层级 |
||||
* @param parentPath 父节点路径 |
||||
* @param maxDepth 层级,从1开始。比如当前监听节点/t1,目录最深为/t1/t2/t3/t4,则maxDepth=3,说明下面3级子目录全 |
||||
* @param listener |
||||
* @throws Exception |
||||
*/ |
||||
public static void listenChildren(String parentPath, int maxDepth, TreeCacheListener listener) throws Exception { |
||||
final TreeCache treeCache = TreeCache |
||||
.newBuilder(client, parentPath) |
||||
.setCacheData(true) |
||||
.setMaxDepth(maxDepth) |
||||
.build(); |
||||
|
||||
treeCache.getListenable().addListener(listener); |
||||
//没有开启模式作为入参的方法
|
||||
treeCache.start(); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,11 @@ |
||||
package com.gitee.sop.websiteserver.manager; |
||||
|
||||
import com.alibaba.fastjson.JSONObject; |
||||
import com.gitee.sop.websiteserver.bean.DocInfo; |
||||
|
||||
/** |
||||
* @author tanghc |
||||
*/ |
||||
public interface DocParser { |
||||
DocInfo parseJson(JSONObject docRoot); |
||||
} |
@ -0,0 +1,83 @@ |
||||
package com.gitee.sop.websiteserver.manager; |
||||
|
||||
import com.alibaba.fastjson.JSONArray; |
||||
import com.alibaba.fastjson.JSONObject; |
||||
import com.gitee.sop.websiteserver.bean.DocInfo; |
||||
import com.gitee.sop.websiteserver.bean.DocItem; |
||||
import com.gitee.sop.websiteserver.bean.DocModule; |
||||
import com.gitee.sop.websiteserver.bean.DocParameter; |
||||
|
||||
import java.util.ArrayList; |
||||
import java.util.Collections; |
||||
import java.util.List; |
||||
import java.util.stream.Collectors; |
||||
|
||||
/** |
||||
* @author tanghc |
||||
*/ |
||||
public class EasyopenDocParser implements DocParser { |
||||
@Override |
||||
public DocInfo parseJson(JSONObject docRoot) { |
||||
String title = docRoot.getString("title"); |
||||
List<DocItem> docItems = new ArrayList<>(); |
||||
JSONArray apiModules = docRoot.getJSONArray("apiModules"); |
||||
for (int i = 0; i < apiModules.size(); i++) { |
||||
JSONObject module = apiModules.getJSONObject(i); |
||||
JSONArray moduleItems = module.getJSONArray("moduleItems"); |
||||
for (int k = 0; k < moduleItems.size(); k++) { |
||||
JSONObject docInfo = moduleItems.getJSONObject(k); |
||||
DocItem docItem = buildDocItem(docInfo); |
||||
docItem.setModule(module.getString("name")); |
||||
docItems.add(docItem); |
||||
} |
||||
} |
||||
|
||||
List<DocModule> docModuleList = docItems.stream() |
||||
.collect(Collectors.groupingBy(DocItem::getModule)) |
||||
.entrySet() |
||||
.stream() |
||||
.map(entry -> { |
||||
DocModule docModule = new DocModule(); |
||||
docModule.setModule(entry.getKey()); |
||||
docModule.setDocItems(entry.getValue()); |
||||
return docModule; |
||||
}) |
||||
.collect(Collectors.toList()); |
||||
|
||||
DocInfo docInfo = new DocInfo(); |
||||
docInfo.setTitle(title); |
||||
docInfo.setDocModuleList(docModuleList); |
||||
return docInfo; |
||||
} |
||||
|
||||
protected DocItem buildDocItem(JSONObject docInfo) { |
||||
DocItem docItem = new DocItem(); |
||||
docItem.setName(docInfo.getString("name")); |
||||
docItem.setVersion(docInfo.getString("version")); |
||||
docItem.setSummary(docInfo.getString("description")); |
||||
docItem.setDescription(docInfo.getString("description")); |
||||
List<DocParameter> docParameterList = this.buildParameterList(docInfo, "paramDefinitions"); |
||||
docItem.setRequestParameters(docParameterList); |
||||
|
||||
List<DocParameter> responseParameterList = this.buildParameterList(docInfo, "resultDefinitions"); |
||||
docItem.setResponseParameters(responseParameterList); |
||||
|
||||
return docItem; |
||||
} |
||||
|
||||
protected List<DocParameter> buildParameterList(JSONObject docInfo, String key) { |
||||
JSONArray params = docInfo.getJSONArray(key); |
||||
if (params == null) { |
||||
return Collections.emptyList(); |
||||
} |
||||
List<DocParameter> docParameterList = new ArrayList<>(); |
||||
for (int i = 0; i < params.size(); i++) { |
||||
JSONObject jsonObject = params.getJSONObject(i); |
||||
DocParameter docParameter = jsonObject.toJavaObject(DocParameter.class); |
||||
docParameter.setType(jsonObject.getString("dataType")); |
||||
docParameterList.add(docParameter); |
||||
} |
||||
return docParameterList; |
||||
} |
||||
|
||||
} |
@ -0,0 +1,115 @@ |
||||
package com.gitee.sop.websiteserver.manager; |
||||
|
||||
import com.alibaba.fastjson.JSONArray; |
||||
import com.alibaba.fastjson.JSONObject; |
||||
import com.gitee.sop.websiteserver.bean.DocInfo; |
||||
import com.gitee.sop.websiteserver.bean.DocItem; |
||||
import com.gitee.sop.websiteserver.bean.DocModule; |
||||
import com.gitee.sop.websiteserver.bean.DocParameter; |
||||
import org.apache.commons.lang.StringUtils; |
||||
|
||||
import java.util.ArrayList; |
||||
import java.util.List; |
||||
import java.util.Optional; |
||||
import java.util.Set; |
||||
import java.util.stream.Collectors; |
||||
|
||||
/** |
||||
* 解析swagger的json内容 |
||||
* |
||||
* @author tanghc |
||||
*/ |
||||
public class SwaggerDocParser implements DocParser { |
||||
@Override |
||||
public DocInfo parseJson(JSONObject docRoot) { |
||||
String title = docRoot.getJSONObject("info").getString("title"); |
||||
List<DocItem> docItems = new ArrayList<>(); |
||||
|
||||
JSONObject paths = docRoot.getJSONObject("paths"); |
||||
Set<String> pathNameSet = paths.keySet(); |
||||
for (String pathName : pathNameSet) { |
||||
JSONObject pathInfo = paths.getJSONObject(pathName); |
||||
Set<String> pathSet = pathInfo.keySet(); |
||||
Optional<String> first = pathSet.stream().findFirst(); |
||||
if (first.isPresent()) { |
||||
String path = first.get(); |
||||
JSONObject docInfo = pathInfo.getJSONObject(path); |
||||
DocItem docItem = buildDocItem(docInfo, docRoot); |
||||
docItems.add(docItem); |
||||
} |
||||
} |
||||
|
||||
List<DocModule> docModuleList = docItems.stream() |
||||
.collect(Collectors.groupingBy(DocItem::getModule)) |
||||
.entrySet() |
||||
.stream() |
||||
.map(entry -> { |
||||
DocModule docModule = new DocModule(); |
||||
docModule.setModule(entry.getKey()); |
||||
docModule.setDocItems(entry.getValue()); |
||||
return docModule; |
||||
}) |
||||
.collect(Collectors.toList()); |
||||
|
||||
|
||||
DocInfo docInfo = new DocInfo(); |
||||
docInfo.setTitle(title); |
||||
docInfo.setDocModuleList(docModuleList); |
||||
return docInfo; |
||||
} |
||||
|
||||
protected DocItem buildDocItem(JSONObject docInfo, JSONObject docRoot) { |
||||
DocItem docItem = new DocItem(); |
||||
docItem.setName(docInfo.getString("sop_name")); |
||||
docItem.setVersion(docInfo.getString("sop_version")); |
||||
docItem.setSummary(docInfo.getString("summary")); |
||||
docItem.setDescription(docInfo.getString("description")); |
||||
String moduleName = this.buildModuleName(docInfo, docRoot); |
||||
docItem.setModule(moduleName); |
||||
Optional<JSONArray> parametersOptional = Optional.ofNullable(docInfo.getJSONArray("parameters")); |
||||
JSONArray parameters = parametersOptional.orElse(new JSONArray()); |
||||
List<DocParameter> docParameterList = parameters.toJavaList(DocParameter.class); |
||||
docItem.setRequestParameters(docParameterList); |
||||
|
||||
List<DocParameter> responseParameterList = this.buildResponseParameterList(docInfo, docRoot); |
||||
docItem.setResponseParameters(responseParameterList); |
||||
|
||||
return docItem; |
||||
} |
||||
|
||||
protected String buildModuleName(JSONObject docInfo, JSONObject docRoot) { |
||||
String title = docRoot.getJSONObject("info").getString("title"); |
||||
JSONArray tags = docInfo.getJSONArray("tags"); |
||||
if (tags != null && tags.size() > 0) { |
||||
return tags.getString(0); |
||||
} |
||||
return title; |
||||
} |
||||
|
||||
protected List<DocParameter> buildResponseParameterList(JSONObject docInfo, JSONObject docRoot) { |
||||
String responseRef = getResponseRef(docInfo); |
||||
List<DocParameter> respParameterList = new ArrayList<>(); |
||||
if (StringUtils.isNotBlank(responseRef)) { |
||||
JSONObject responseObject = docRoot.getJSONObject("definitions").getJSONObject(responseRef); |
||||
JSONObject properties = responseObject.getJSONObject("properties"); |
||||
Set<String> fieldNames = properties.keySet(); |
||||
for (String fieldName : fieldNames) { |
||||
JSONObject fieldInfo = properties.getJSONObject(fieldName); |
||||
DocParameter respParam = fieldInfo.toJavaObject(DocParameter.class); |
||||
respParam.setName(fieldName); |
||||
respParameterList.add(respParam); |
||||
} |
||||
} |
||||
return respParameterList; |
||||
} |
||||
|
||||
protected String getResponseRef(JSONObject docInfo) { |
||||
String ref = Optional.ofNullable(docInfo.getJSONObject("responses")) |
||||
.flatMap(jsonObject -> Optional.ofNullable(jsonObject.getJSONObject("200"))) |
||||
.flatMap(jsonObject -> Optional.ofNullable(jsonObject.getJSONObject("schema"))) |
||||
.flatMap(jsonObject -> Optional.ofNullable(jsonObject.getString("originalRef"))) |
||||
.orElse(""); |
||||
return ref; |
||||
} |
||||
|
||||
} |
Loading…
Reference in new issue