注解优化,grpc开发
This commit is contained in:
@@ -0,0 +1,368 @@
|
||||
package com.zyplayer.doc.grpc.controller;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.google.protobuf.ByteString;
|
||||
import com.nxest.grpc.client.GrpcChannelFactory;
|
||||
import com.nxest.grpc.server.GrpcService;
|
||||
import com.zyplayer.doc.core.exception.ConfirmException;
|
||||
import com.zyplayer.doc.core.json.DocResponseJson;
|
||||
import com.zyplayer.doc.grpc.controller.po.ColumnInfo;
|
||||
import com.zyplayer.doc.grpc.controller.po.GrpcDocInfo;
|
||||
import com.zyplayer.doc.grpc.controller.po.GrpcServiceAndColumn;
|
||||
import com.zyplayer.doc.grpc.controller.po.MethodParam;
|
||||
import com.zyplayer.doc.grpc.framework.config.SpringContextUtil;
|
||||
import com.zyplayer.doc.grpc.framework.consts.Const;
|
||||
import io.grpc.Channel;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* grpc文档控制器
|
||||
*
|
||||
* @author 暮光:城中城
|
||||
* @since 2019年3月31日
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/zyplayer-doc-grpc")
|
||||
public class GrpcDocController {
|
||||
|
||||
@Resource
|
||||
GrpcChannelFactory grpcChannelFactory;
|
||||
private static Map<String, ColumnInfo> allColumnsMap = new HashMap<>();
|
||||
private static Map<String, Object> allBlockingStubMap = new HashMap<>();
|
||||
|
||||
/**
|
||||
* 查找所有文档
|
||||
*
|
||||
* @author 暮光:城中城
|
||||
* @since 2019年3月31日
|
||||
*/
|
||||
@RequestMapping("/service")
|
||||
public DocResponseJson service() {
|
||||
List<Object> grpcServiceList = SpringContextUtil.getBeanWithAnnotation(GrpcService.class);
|
||||
if (grpcServiceList == null || grpcServiceList.size() <= 0) {
|
||||
return DocResponseJson.ok();
|
||||
}
|
||||
List<GrpcDocInfo> grpcDocInfoList = new LinkedList<>();
|
||||
for (Object service : grpcServiceList) {
|
||||
List<GrpcDocInfo> infoList = this.getServiceInfoByJar(service.getClass());
|
||||
if (infoList != null) {
|
||||
grpcDocInfoList.addAll(infoList);
|
||||
}
|
||||
}
|
||||
// 找所有的参数列表
|
||||
Map<String, ColumnInfo> columnsMap = new HashMap<>();
|
||||
for (GrpcDocInfo grpcDocInfo : grpcDocInfoList) {
|
||||
this.setColumnsInfo(grpcDocInfo.getParamType(), columnsMap);
|
||||
this.setColumnsInfo(grpcDocInfo.getResultType(), columnsMap);
|
||||
}
|
||||
GrpcServiceAndColumn grpcServiceAndColumn = new GrpcServiceAndColumn();
|
||||
grpcServiceAndColumn.setServiceList(grpcDocInfoList);
|
||||
grpcServiceAndColumn.setColumnMap(columnsMap);
|
||||
return DocResponseJson.ok(grpcServiceAndColumn);
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行grpc请求
|
||||
*
|
||||
* @author 暮光:城中城
|
||||
* @since 2019年3月31日
|
||||
*/
|
||||
@RequestMapping("/execute")
|
||||
public DocResponseJson execute(String service, String params) throws Exception {
|
||||
List<GrpcDocInfo> grpcDocInfoList = this.getServiceInfoByJar(Class.forName(service));
|
||||
JSONObject executeResult = null;
|
||||
if (grpcDocInfoList != null && grpcDocInfoList.size() > 0) {
|
||||
JSONObject paramMap = JSON.parseObject(params);
|
||||
executeResult = this.executeFunction(grpcDocInfoList.get(0), paramMap);
|
||||
}
|
||||
return DocResponseJson.ok(executeResult);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置字段信息到map
|
||||
*
|
||||
* @author 暮光:城中城
|
||||
* @since 2019年3月31日
|
||||
*/
|
||||
private void setColumnsInfo(String typeName, Map<String, ColumnInfo> columnsMap) {
|
||||
if (!columnsMap.containsKey(typeName)) {
|
||||
if (allColumnsMap.containsKey(typeName)) {
|
||||
columnsMap.put(typeName, allColumnsMap.get(typeName));
|
||||
} else {
|
||||
ColumnInfo columnInfo = this.findColumnInfo(typeName);
|
||||
columnsMap.put(typeName, columnInfo);
|
||||
allColumnsMap.put(typeName, columnInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行grpc方法
|
||||
*
|
||||
* @author 暮光:城中城
|
||||
* @since 2019年3月31日
|
||||
*/
|
||||
private JSONObject executeFunction(GrpcDocInfo grpcDocInfo, JSONObject paramMap) throws Exception {
|
||||
Object newBuilder = this.createParamBuilder(grpcDocInfo.getParamType(), paramMap);
|
||||
if (newBuilder == null) {
|
||||
throw new ConfirmException("参数组装失败");
|
||||
}
|
||||
// 创建参数对象
|
||||
Method build = newBuilder.getClass().getMethod("build");
|
||||
Object request = build.invoke(newBuilder);
|
||||
System.out.println(request.toString());
|
||||
// 为创建过则创建
|
||||
Object blockingStub = allBlockingStubMap.get(grpcDocInfo.getService());
|
||||
if (blockingStub == null) {
|
||||
// 找到父类
|
||||
Class<?> serviceClass = Class.forName(grpcDocInfo.getService());
|
||||
String serviceSuperName = serviceClass.getSuperclass().getName();
|
||||
String superClassName = serviceSuperName.substring(0, serviceSuperName.indexOf("$"));
|
||||
// 注册
|
||||
Class<?> superClass = Class.forName(superClassName);
|
||||
Method newBlockingStubMethod = superClass.getMethod("newBlockingStub", Channel.class);
|
||||
blockingStub = newBlockingStubMethod.invoke(null, grpcChannelFactory.createChannel());
|
||||
allBlockingStubMap.put(grpcDocInfo.getService(), blockingStub);
|
||||
}
|
||||
Method sayHello = blockingStub.getClass().getMethod(grpcDocInfo.getMethod(), Class.forName(grpcDocInfo.getParamType()));
|
||||
// 执行请求
|
||||
Object response = sayHello.invoke(blockingStub, request);
|
||||
List<ColumnInfo> columnInfos = this.findClassColumns(response.getClass());
|
||||
return this.protobufToJson(response, columnInfos);
|
||||
}
|
||||
|
||||
/**
|
||||
* grpc对象转json字符串
|
||||
*
|
||||
* @author 暮光:城中城
|
||||
* @since 2019年3月31日
|
||||
*/
|
||||
private JSONObject protobufToJson(Object response, List<ColumnInfo> columnInfos) throws Exception {
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
for (ColumnInfo columnInfo : columnInfos) {
|
||||
Method getMethod = response.getClass().getMethod("get" + this.toUpperCaseFirstOne(columnInfo.getName()));
|
||||
Object paramValue = getMethod.invoke(response);
|
||||
if (columnInfo.getParam() != null && columnInfo.getParam().size() > 0) {
|
||||
JSONObject jsonObjectSub = this.protobufToJson(paramValue, columnInfo.getParam());
|
||||
jsonObject.put(columnInfo.getName(), jsonObjectSub);
|
||||
} else {
|
||||
if ("com.google.protobuf.ByteString".equals(columnInfo.getType())) {
|
||||
ByteString byteString = (ByteString) paramValue;
|
||||
jsonObject.put(columnInfo.getName(), byteString.toStringUtf8());
|
||||
} else {
|
||||
jsonObject.put(columnInfo.getName(), paramValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
return jsonObject;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建参数的builder对象
|
||||
*
|
||||
* @author 暮光:城中城
|
||||
* @since 2019年3月31日
|
||||
*/
|
||||
private Object createParamBuilder(String paramType, JSONObject paramMap) {
|
||||
try {
|
||||
Class<?> aClassSub = Class.forName(paramType);
|
||||
Method newBuilderMethod = aClassSub.getMethod("newBuilder");
|
||||
Object newBuilder = newBuilderMethod.invoke(aClassSub);
|
||||
List<MethodParam> functionTemp = this.getSetterFunction(newBuilder.getClass());
|
||||
for (MethodParam paramTemp : functionTemp) {
|
||||
Class<?> baseTypeClass = Const.BASE_TYPE.get(paramTemp.getType());
|
||||
if (baseTypeClass != null) {
|
||||
Method setNameSub = newBuilder.getClass().getMethod(paramTemp.getSetterName(), baseTypeClass);
|
||||
Object paramObjTemp;
|
||||
// 特殊类型参数处理
|
||||
if ("com.google.protobuf.ByteString".equals(paramTemp.getType())) {
|
||||
String stringValue = paramMap.getString(paramTemp.getName());
|
||||
paramObjTemp = ByteString.copyFrom(stringValue, "UTF-8");
|
||||
} else {
|
||||
paramObjTemp = paramMap.getObject(paramTemp.getName(), baseTypeClass);
|
||||
}
|
||||
// 不为空则设置参数值
|
||||
if (paramObjTemp != null) {
|
||||
newBuilder = setNameSub.invoke(newBuilder, paramObjTemp);
|
||||
}
|
||||
} else {
|
||||
Class<?> typeClassSub = Class.forName(paramTemp.getType());
|
||||
Object newBuilderSub = this.createParamBuilder(paramTemp.getType(), paramMap.getJSONObject(paramTemp.getName()));
|
||||
if (newBuilderSub == null) {
|
||||
return null;
|
||||
}
|
||||
Method build = newBuilderSub.getClass().getMethod("build");
|
||||
Object request = build.invoke(newBuilderSub);
|
||||
Method setNameSub = newBuilder.getClass().getMethod(paramTemp.getSetterName(), typeClassSub);
|
||||
newBuilder = setNameSub.invoke(newBuilder, request);
|
||||
}
|
||||
}
|
||||
return newBuilder;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 首字母小写
|
||||
*
|
||||
* @author 暮光:城中城
|
||||
* @since 2019年3月31日
|
||||
*/
|
||||
private String toLowerCaseFirstOne(String str) {
|
||||
if (Character.isLowerCase(str.charAt(0))) {
|
||||
return str;
|
||||
} else {
|
||||
return Character.toLowerCase(str.charAt(0)) + str.substring(1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 首字母大写
|
||||
*
|
||||
* @author 暮光:城中城
|
||||
* @since 2019年3月31日
|
||||
*/
|
||||
private String toUpperCaseFirstOne(String str) {
|
||||
if (Character.isUpperCase(str.charAt(0))) {
|
||||
return str;
|
||||
} else {
|
||||
return Character.toUpperCase(str.charAt(0)) + str.substring(1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 找到所有的setter方法
|
||||
*
|
||||
* @author 暮光:城中城
|
||||
* @since 2019年3月31日
|
||||
*/
|
||||
private List<MethodParam> getSetterFunction(Class clazz) {
|
||||
List<MethodParam> result = new LinkedList<>();
|
||||
Method[] methods = clazz.getDeclaredMethods();
|
||||
StringBuilder nameSb = new StringBuilder();
|
||||
for (Method method : methods) {
|
||||
String methodName = method.getName();
|
||||
if (!methodName.startsWith("set") || methodName.endsWith("Bytes")
|
||||
|| methodName.equals("setField") || methodName.equals("setRepeatedField")
|
||||
|| methodName.equals("setUnknownFields")) {
|
||||
continue;
|
||||
}
|
||||
Type[] parameterTypes = method.getGenericParameterTypes();
|
||||
if (parameterTypes.length == 1) {
|
||||
String typeName = parameterTypes[0].getTypeName();
|
||||
if (typeName.endsWith("$Builder")) {
|
||||
continue;
|
||||
}
|
||||
MethodParam param = new MethodParam();
|
||||
param.setSetterName(methodName);
|
||||
param.setType(typeName);
|
||||
String paramName = methodName.substring(3);
|
||||
param.setName(this.toLowerCaseFirstOne(paramName));
|
||||
result.add(param);
|
||||
}
|
||||
nameSb.append(methodName).append(",");
|
||||
}
|
||||
//System.out.println(nameSb);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 找到所有的字段信息
|
||||
*
|
||||
* @author 暮光:城中城
|
||||
* @since 2019年3月31日
|
||||
*/
|
||||
private ColumnInfo findColumnInfo(String paramType) {
|
||||
ColumnInfo columnInfo = new ColumnInfo();
|
||||
try {
|
||||
String paramName = paramType.substring(paramType.lastIndexOf(".") + 1);
|
||||
columnInfo.setName(this.toLowerCaseFirstOne(paramName));
|
||||
columnInfo.setType(paramType);
|
||||
List<ColumnInfo> columnInfos = this.findClassColumns(Class.forName(paramType));
|
||||
columnInfo.setParam(columnInfos);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return columnInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* 找到所有的字段信息
|
||||
*
|
||||
* @author 暮光:城中城
|
||||
* @since 2019年3月31日
|
||||
*/
|
||||
private List<ColumnInfo> findClassColumns(Class clazz) throws Exception {
|
||||
Method getMoney = clazz.getMethod("newBuilder");
|
||||
Object newBuilder = getMoney.invoke(clazz);
|
||||
|
||||
List<MethodParam> paramList = this.getSetterFunction(newBuilder.getClass());
|
||||
List<ColumnInfo> subInfoList = new LinkedList<>();
|
||||
for (MethodParam param : paramList) {
|
||||
ColumnInfo info = new ColumnInfo();
|
||||
info.setType(param.getType());
|
||||
info.setName(param.getName());
|
||||
if (!Const.BASE_TYPE.containsKey(param.getType())) {
|
||||
List<ColumnInfo> classColumn = this.findClassColumns(Class.forName(param.getType()));
|
||||
info.setParam(classColumn);
|
||||
}
|
||||
subInfoList.add(info);
|
||||
}
|
||||
return subInfoList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 找到服务,组装方法、参数和返回值等
|
||||
*
|
||||
* @author 暮光:城中城
|
||||
* @since 2019年3月31日
|
||||
*/
|
||||
private List<GrpcDocInfo> getServiceInfoByJar(Class clazz) {
|
||||
List<GrpcDocInfo> providerList = new LinkedList<>();
|
||||
try {
|
||||
Method[] methods = clazz.getDeclaredMethods();
|
||||
for (Method method : methods) {
|
||||
String methodName = method.getName();
|
||||
String resultType = "";
|
||||
String paramType = "";
|
||||
Type[] parameterTypes = method.getGenericParameterTypes();
|
||||
for (int i = 0; i < parameterTypes.length; i++) {
|
||||
String typeName = parameterTypes[i].getTypeName();
|
||||
if (i == 0) {
|
||||
paramType = parameterTypes[i].getTypeName();
|
||||
} else if (typeName.matches("io.grpc.stub.StreamObserver<.+>")) {
|
||||
Pattern pattern = Pattern.compile("io.grpc.stub.StreamObserver<(.+)>");
|
||||
Matcher matcher = pattern.matcher(typeName);
|
||||
if (matcher.find()) {
|
||||
resultType = matcher.group(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
GrpcDocInfo grpcDocInfo = new GrpcDocInfo();
|
||||
grpcDocInfo.setMethod(methodName);
|
||||
grpcDocInfo.setService(clazz.getName());
|
||||
grpcDocInfo.setParamType(paramType);
|
||||
grpcDocInfo.setResultType(resultType);
|
||||
providerList.add(grpcDocInfo);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
return providerList;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package com.zyplayer.doc.grpc.controller.po;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* grpc字段信息
|
||||
*
|
||||
* @author 暮光:城中城
|
||||
* @since 2019年3月31日
|
||||
*/
|
||||
public class ColumnInfo {
|
||||
private String name;
|
||||
private String type;
|
||||
private String desc;
|
||||
private List<ColumnInfo> param;
|
||||
|
||||
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 getDesc() {
|
||||
return desc;
|
||||
}
|
||||
|
||||
public void setDesc(String desc) {
|
||||
this.desc = desc;
|
||||
}
|
||||
|
||||
public List<ColumnInfo> getParam() {
|
||||
return param;
|
||||
}
|
||||
|
||||
public void setParam(List<ColumnInfo> param) {
|
||||
this.param = param;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
package com.zyplayer.doc.grpc.controller.po;
|
||||
|
||||
/**
|
||||
* 请求参数对象
|
||||
*
|
||||
* @author 暮光:城中城
|
||||
* @since 2019年2月10日
|
||||
*/
|
||||
public class GrpcDocInfo {
|
||||
private String method;
|
||||
private String service;
|
||||
private String explain;
|
||||
private String result;
|
||||
private String paramType;
|
||||
private String resultType;
|
||||
private Integer version;
|
||||
|
||||
public Integer getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
public void setVersion(Integer version) {
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
public String getService() {
|
||||
return service;
|
||||
}
|
||||
|
||||
public void setService(String service) {
|
||||
this.service = service;
|
||||
}
|
||||
|
||||
public String getExplain() {
|
||||
return explain;
|
||||
}
|
||||
|
||||
public void setExplain(String explain) {
|
||||
this.explain = explain;
|
||||
}
|
||||
|
||||
public String getResult() {
|
||||
return result;
|
||||
}
|
||||
|
||||
public void setResult(String result) {
|
||||
this.result = result;
|
||||
}
|
||||
|
||||
public String getResultType() {
|
||||
return resultType;
|
||||
}
|
||||
|
||||
public void setResultType(String resultType) {
|
||||
this.resultType = resultType;
|
||||
}
|
||||
|
||||
public String getParamType() {
|
||||
return paramType;
|
||||
}
|
||||
|
||||
public void setParamType(String paramType) {
|
||||
this.paramType = paramType;
|
||||
}
|
||||
|
||||
public String getMethod() {
|
||||
return method;
|
||||
}
|
||||
|
||||
public void setMethod(String method) {
|
||||
this.method = method;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.zyplayer.doc.grpc.controller.po;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 服务和字段信息
|
||||
*
|
||||
* @author 暮光:城中城
|
||||
* @since 2019年2月10日
|
||||
*/
|
||||
public class GrpcServiceAndColumn {
|
||||
private List<GrpcDocInfo> serviceList;
|
||||
private Map<String, ColumnInfo> columnMap;
|
||||
|
||||
public List<GrpcDocInfo> getServiceList() {
|
||||
return serviceList;
|
||||
}
|
||||
|
||||
public void setServiceList(List<GrpcDocInfo> serviceList) {
|
||||
this.serviceList = serviceList;
|
||||
}
|
||||
|
||||
public Map<String, ColumnInfo> getColumnMap() {
|
||||
return columnMap;
|
||||
}
|
||||
|
||||
public void setColumnMap(Map<String, ColumnInfo> columnMap) {
|
||||
this.columnMap = columnMap;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package com.zyplayer.doc.grpc.controller.po;
|
||||
|
||||
/**
|
||||
* grpc方法信息
|
||||
*
|
||||
* @author 暮光:城中城
|
||||
* @since 2019年3月31日
|
||||
*/
|
||||
public class MethodParam {
|
||||
private String name;
|
||||
private String type;
|
||||
private String setterName;
|
||||
|
||||
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 getSetterName() {
|
||||
return setterName;
|
||||
}
|
||||
|
||||
public void setSetterName(String setterName) {
|
||||
this.setterName = setterName;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.zyplayer.doc.grpc.framework.config;
|
||||
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* 开启grpc的注解
|
||||
*
|
||||
* @author 暮光:城中城
|
||||
* @since 2019年3月31日
|
||||
*/
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
@Configuration
|
||||
@ComponentScan(basePackages = {
|
||||
"com.zyplayer.doc.grpc",
|
||||
})
|
||||
public @interface EnableDocGrpc {
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package com.zyplayer.doc.grpc.framework.config;
|
||||
|
||||
import com.nxest.grpc.client.*;
|
||||
import com.nxest.grpc.client.configure.GrpcClientProperties;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
/**
|
||||
* grpc配置
|
||||
*
|
||||
* @author 暮光:城中城
|
||||
* @since 2019年3月31日
|
||||
*/
|
||||
@Configuration
|
||||
@AutoConfigureAfter(GrpcServerConfiguration.class)
|
||||
public class GrpcClientConfiguration {
|
||||
|
||||
@Resource
|
||||
private GrpcProperties grpcProperties;
|
||||
|
||||
@Bean
|
||||
public GrpcClientProperties clientProperties() {
|
||||
return grpcProperties.getClient();
|
||||
}
|
||||
|
||||
|
||||
@Bean
|
||||
public GrpcChannelFactory channelFactory() {
|
||||
return new AddressChannelFactory(clientProperties());
|
||||
}
|
||||
|
||||
@Bean
|
||||
public GrpcClientInterceptorDiscoverer clientInterceptorDiscoverer() {
|
||||
return new AnnotationClientInterceptorDiscoverer();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnClass(GrpcClient.class)
|
||||
public GrpcClientBeanPostProcessor grpcClientBeanPostProcessor() {
|
||||
return new GrpcClientBeanPostProcessor(channelFactory(), clientInterceptorDiscoverer());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.zyplayer.doc.grpc.framework.config;
|
||||
|
||||
import com.nxest.grpc.client.configure.GrpcClientProperties;
|
||||
import com.nxest.grpc.server.configure.GrpcServerProperties;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* grpc配置文件
|
||||
*
|
||||
* @author 暮光:城中城
|
||||
* @since 2019年3月31日
|
||||
*/
|
||||
@Configuration
|
||||
@ConfigurationProperties(prefix = "grpc")
|
||||
public class GrpcProperties {
|
||||
|
||||
/**
|
||||
* Grpc server properties
|
||||
*/
|
||||
private final GrpcServerProperties server = new GrpcServerProperties();
|
||||
/**
|
||||
* Grpc client properties
|
||||
*/
|
||||
private final GrpcClientProperties client = new GrpcClientProperties();
|
||||
|
||||
public GrpcServerProperties getServer() {
|
||||
return server;
|
||||
}
|
||||
|
||||
public GrpcClientProperties getClient() {
|
||||
return client;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.zyplayer.doc.grpc.framework.config;
|
||||
|
||||
import com.nxest.grpc.server.*;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
/**
|
||||
* grpc服务
|
||||
*
|
||||
* @author 暮光:城中城
|
||||
* @since 2019年3月31日
|
||||
*/
|
||||
@Configuration
|
||||
public class GrpcServerConfiguration {
|
||||
|
||||
@Resource
|
||||
private GrpcProperties grpcProperties;
|
||||
|
||||
@Bean
|
||||
public GrpcServiceDiscoverer serviceDiscoverer() {
|
||||
return new AnnotationGrpcServiceDiscoverer();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public GrpcServerFactory severFactory() {
|
||||
return new NettyGrpcServerFactory(serviceDiscoverer(), grpcProperties.getServer());
|
||||
}
|
||||
|
||||
@Bean(name = "grpcServer", initMethod = "start", destroyMethod = "destroy")
|
||||
public GrpcServer serverRunner() {
|
||||
return severFactory().createServer();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package com.zyplayer.doc.grpc.framework.config;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* context工具类
|
||||
*
|
||||
* @author 暮光:城中城
|
||||
* @since 2019年3月31日
|
||||
*/
|
||||
@Component
|
||||
public class SpringContextUtil implements ApplicationContextAware {
|
||||
|
||||
public static ApplicationContext context;
|
||||
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
|
||||
context = applicationContext;
|
||||
}
|
||||
|
||||
public static ApplicationContext getApplicationContext() {
|
||||
return context;
|
||||
}
|
||||
|
||||
public static <T> T getBean(Class<T> clz) {
|
||||
return context.getBean(clz);
|
||||
}
|
||||
|
||||
public static Object getBean(String string) {
|
||||
return getApplicationContext().getBean(string);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取类
|
||||
*
|
||||
* @param annotationType annotation
|
||||
* @return 类对象
|
||||
*/
|
||||
public static List<Object> getBeanWithAnnotation(Class<? extends Annotation> annotationType) {
|
||||
if (context == null) {
|
||||
return null;
|
||||
}
|
||||
Map<String, Object> beansWithAnnotation = context.getBeansWithAnnotation(annotationType);
|
||||
return new LinkedList<>(beansWithAnnotation.values());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.zyplayer.doc.grpc.framework.consts;
|
||||
|
||||
import com.google.protobuf.ByteString;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author 暮光:城中城
|
||||
* @since 2019年3月31日
|
||||
*/
|
||||
public class Const {
|
||||
|
||||
/** 所有基础类型 */
|
||||
public static final Map<String, Class<?>> BASE_TYPE;
|
||||
static {
|
||||
BASE_TYPE = new HashMap<>();
|
||||
BASE_TYPE.put(String.class.getName(), String.class);
|
||||
BASE_TYPE.put(Integer.class.getName(), Integer.class);
|
||||
BASE_TYPE.put(Long.class.getName(), Long.class);
|
||||
BASE_TYPE.put(Double.class.getName(), Double.class);
|
||||
BASE_TYPE.put(Date.class.getName(), Date.class);
|
||||
BASE_TYPE.put(Byte.class.getName(), Byte.class);
|
||||
BASE_TYPE.put(Float.class.getName(), Float.class);
|
||||
BASE_TYPE.put(BigDecimal.class.getName(), BigDecimal.class);
|
||||
BASE_TYPE.put(ByteString.class.getName(), ByteString.class);
|
||||
|
||||
BASE_TYPE.put(char.class.getName(), char.class);
|
||||
BASE_TYPE.put(int.class.getName(), int.class);
|
||||
BASE_TYPE.put(long.class.getName(), long.class);
|
||||
BASE_TYPE.put(double.class.getName(), double.class);
|
||||
BASE_TYPE.put(byte.class.getName(), byte.class);
|
||||
BASE_TYPE.put(float.class.getName(), float.class);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
//package com.zyplayer.doc.grpc.service;
|
||||
//
|
||||
//
|
||||
//import com.google.protobuf.Empty;
|
||||
//import com.google.protobuf.Timestamp;
|
||||
//import com.nxest.grpc.server.GrpcService;
|
||||
//import com.zyplayer.doc.grpc.proto.HelloRequest;
|
||||
//import com.zyplayer.doc.grpc.proto.HelloResponse;
|
||||
//import com.zyplayer.doc.grpc.proto.TimeResponse;
|
||||
//import com.zyplayer.doc.grpc.proto.ZyplayerGreeterGrpc;
|
||||
//import io.grpc.stub.StreamObserver;
|
||||
//
|
||||
///**
|
||||
// * grpc服务测试类,需要mvn compile项目
|
||||
// * @author 暮光:城中城
|
||||
// * @since 2019年3月31日
|
||||
// */
|
||||
//@GrpcService
|
||||
//public class HelloWorldService extends ZyplayerGreeterGrpc.ZyplayerGreeterImplBase {
|
||||
//
|
||||
// @Override
|
||||
// public void sayHello(HelloRequest request, StreamObserver<HelloResponse> responseObserver) {
|
||||
// HelloResponse reply = HelloResponse.newBuilder().setMessage("Hello " + request.getName()).build();
|
||||
// responseObserver.onNext(reply);
|
||||
// responseObserver.onCompleted();
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void sayTime(Empty request, StreamObserver<TimeResponse> responseObserver) {
|
||||
// TimeResponse reply = TimeResponse.newBuilder().setTime(Timestamp.newBuilder().build()).build();
|
||||
// responseObserver.onNext(reply);
|
||||
// responseObserver.onCompleted();
|
||||
// }
|
||||
//}
|
||||
@@ -0,0 +1,40 @@
|
||||
//package com.zyplayer.doc.grpc.service;
|
||||
//
|
||||
//
|
||||
//import com.google.protobuf.ByteString;
|
||||
//import com.nxest.grpc.server.GrpcService;
|
||||
//import com.zyplayer.doc.grpc.proto.BaseMsg;
|
||||
//import com.zyplayer.doc.grpc.proto.ChatMsg;
|
||||
//import com.zyplayer.doc.grpc.proto.User;
|
||||
//import com.zyplayer.doc.grpc.proto.ZyplayerChatGrpc;
|
||||
//import io.grpc.stub.StreamObserver;
|
||||
//
|
||||
///**
|
||||
// * grpc服务测试类,需要mvn compile项目
|
||||
// * @author 暮光:城中城
|
||||
// * @since 2019年3月31日
|
||||
// */
|
||||
//@GrpcService
|
||||
//public class ZyplayerChatService extends ZyplayerChatGrpc.ZyplayerChatImplBase {
|
||||
//
|
||||
// @Override
|
||||
// public void sendText(ChatMsg request, StreamObserver<ChatMsg> responseObserver) {
|
||||
// User user = null;
|
||||
// try {
|
||||
// user = User.newBuilder().setCookies(ByteString.copyFrom("xxx", "utf-8")).build();
|
||||
// } catch (Exception e) {
|
||||
// e.printStackTrace();
|
||||
// }
|
||||
// BaseMsg baseMsg = BaseMsg.newBuilder().setCmd(1).setUser(user).build();
|
||||
// ChatMsg reply = ChatMsg.newBuilder().setToken("sendText").setIP("xx.xx.xx.xx").setBaseMsg(baseMsg).build();
|
||||
// responseObserver.onNext(reply);
|
||||
// responseObserver.onCompleted();
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void sendImage(ChatMsg request, StreamObserver<ChatMsg> responseObserver) {
|
||||
// ChatMsg reply = ChatMsg.newBuilder().setToken("sendImage").setIP("xx.xx.xx.xx").build();
|
||||
// responseObserver.onNext(reply);
|
||||
// responseObserver.onCompleted();
|
||||
// }
|
||||
//}
|
||||
36
zyplayer-doc-grpc/src/main/proto/HelloWorld.proto
Normal file
36
zyplayer-doc-grpc/src/main/proto/HelloWorld.proto
Normal file
@@ -0,0 +1,36 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package helloworld;
|
||||
|
||||
import "google/protobuf/empty.proto";
|
||||
import "google/protobuf/timestamp.proto";
|
||||
|
||||
option java_multiple_files = true;
|
||||
option java_package = "com.zyplayer.doc.grpc.proto";
|
||||
option java_outer_classname = "HelloWorldProto";
|
||||
|
||||
// The greeting service definition.
|
||||
service ZyplayerGreeter {
|
||||
// Sends a greeting
|
||||
rpc sayHello (HelloRequest) returns (HelloResponse) {}
|
||||
|
||||
// Sends the current time
|
||||
rpc sayTime (google.protobuf.Empty) returns (TimeResponse) {}
|
||||
}
|
||||
|
||||
// The request message containing the user's name.
|
||||
message HelloRequest {
|
||||
string name = 1;
|
||||
string content = 2;
|
||||
int32 time = 3;
|
||||
}
|
||||
|
||||
// The response message containing the greetings
|
||||
message HelloResponse {
|
||||
string message = 1;
|
||||
}
|
||||
|
||||
// The response message containing the time
|
||||
message TimeResponse {
|
||||
google.protobuf.Timestamp time = 1;
|
||||
}
|
||||
34
zyplayer-doc-grpc/src/main/proto/ZyplayerChat.proto
Normal file
34
zyplayer-doc-grpc/src/main/proto/ZyplayerChat.proto
Normal file
@@ -0,0 +1,34 @@
|
||||
syntax = "proto3";
|
||||
option java_outer_classname = "ChatProto";
|
||||
option java_package = "com.zyplayer.doc.grpc.proto";
|
||||
import "google/protobuf/empty.proto";
|
||||
import "google/protobuf/timestamp.proto";
|
||||
package wechat;
|
||||
option java_multiple_files = true;
|
||||
service ZyplayerChat {
|
||||
// 处理请求
|
||||
rpc sendText (ChatMsg) returns (ChatMsg) {}
|
||||
|
||||
rpc sendImage (ChatMsg) returns (ChatMsg) {}
|
||||
}
|
||||
// 完整的grpc结构体
|
||||
message ChatMsg {
|
||||
BaseMsg baseMsg = 1;
|
||||
string token = 2;
|
||||
string version = 3;
|
||||
int32 timeStamp = 4;
|
||||
string iP = 5;
|
||||
}
|
||||
// 请求消息结构体
|
||||
message BaseMsg {
|
||||
int32 ret = 1;
|
||||
int32 cmd = 2;
|
||||
User user = 3;
|
||||
}
|
||||
// 用户结构体
|
||||
message User {
|
||||
int64 uin = 1;
|
||||
bytes cookies = 2;
|
||||
bytes sessionKey = 3;
|
||||
bytes nickname = 4;
|
||||
}
|
||||
380
zyplayer-doc-grpc/src/main/resources/doc-grpc.html
Normal file
380
zyplayer-doc-grpc/src/main/resources/doc-grpc.html
Normal file
@@ -0,0 +1,380 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
|
||||
<!--无论发布在哪、如何修改源码,请勿删除本行原作者信息,感谢-->
|
||||
<meta name="author" content="开发者列表:暮光:城中城,项目地址:https://gitee.com/zyplayer/zyplayer-doc" />
|
||||
<title>grpc文档管理系统</title>
|
||||
<link rel="shortcut icon" href="webjars/doc-grpc/img/grpc.png"/>
|
||||
<link rel="stylesheet" href="webjars/doc-grpc/css/element-ui.css">
|
||||
<link rel="stylesheet" href="webjars/doc-grpc/css/doc-grpc.css" />
|
||||
</head>
|
||||
<body>
|
||||
<div id="app">
|
||||
<el-container style="height: 100%;">
|
||||
<el-aside width="auto" style="height: 100%;">
|
||||
<div class="logo" @click="aboutDialogVisible = true">zyplayer-doc-grpc</div>
|
||||
<div style="padding: 10px;">
|
||||
<!-- <div align="center"><el-button type="primary" v-on:click="reloadService" icon="el-icon-refresh" style="width: 100%;">重新加载服务列表</el-button></div>-->
|
||||
<el-input v-model="searchKeywords" placeholder="搜索文档" style="margin: 10px 0;">
|
||||
<el-button slot="append" icon="el-icon-search" v-on:click="searchByKeywords"></el-button>
|
||||
</el-input>
|
||||
<el-tree :data="pathIndex" :props="defaultProps" @node-click="handleNodeClick"></el-tree>
|
||||
</div>
|
||||
</el-aside>
|
||||
<el-container>
|
||||
<el-tabs type="border-card" style="width: 100%;">
|
||||
<el-tab-pane label="接口说明">
|
||||
<div v-if="!grpcInfo.service">
|
||||
请先选择服务
|
||||
</div>
|
||||
<el-form v-else label-width="80px">
|
||||
<el-form-item label="服务:">
|
||||
{{grpcInfo.service}}
|
||||
</el-form-item>
|
||||
<el-form-item label="方法:">
|
||||
{{grpcInfo.method}}
|
||||
</el-form-item>
|
||||
<!-- <el-form-item label="说明:">-->
|
||||
<!-- <div v-if="grpcInfoExplainShow">-->
|
||||
<!-- <pre>{{grpcInfo.docInfo.explain}}<el-button @click.prevent="grpcInfoExplainShow = false;" style="float: right;">编辑</el-button></pre>-->
|
||||
<!-- </div>-->
|
||||
<!-- <div v-else>-->
|
||||
<!-- <el-input type="textarea" :rows="4" placeholder="维护人员、使用说明、便于搜索的信息" v-model="docInfoExplainInput"></el-input>-->
|
||||
<!-- <el-button @click.prevent="grpcInfoExplainShow = true;" style="float: right;margin: 5px;">取消</el-button>-->
|
||||
<!-- <el-button type="primary" @click.prevent="saveDocInfoExplain" style="float: right;margin: 5px;">保存</el-button>-->
|
||||
<!-- </div>-->
|
||||
<!-- </el-form-item>-->
|
||||
<el-form-item label="参数:">
|
||||
<div v-html="grpcInfo.paramColumn"></div>
|
||||
</el-form-item>
|
||||
<el-form-item label="返回值:">
|
||||
<div v-html="grpcInfo.resultColumn"></div>
|
||||
</el-form-item>
|
||||
<!-- <el-form-item label="结果:">-->
|
||||
<!-- <div v-if="grpcInfoResultShow">-->
|
||||
<!-- <pre>{{grpcInfo.docInfo.result}}<el-button @click.prevent="grpcInfoResultShow = false;" style="float: right;">编辑</el-button></pre>-->
|
||||
<!-- </div>-->
|
||||
<!-- <div v-else>-->
|
||||
<!-- <el-input type="textarea" :rows="4" placeholder="结果集说明等" v-model="docInfoResultInput"></el-input>-->
|
||||
<!-- <el-button @click.prevent="grpcInfoResultShow = true;" style="float: right;margin: 5px;">取消</el-button>-->
|
||||
<!-- <el-button type="primary" @click.prevent="saveDocInfoResult" style="float: right;margin: 5px;">保存</el-button>-->
|
||||
<!-- </div>-->
|
||||
<!-- </el-form-item>-->
|
||||
</el-form>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="在线调试">
|
||||
<div v-if="!grpcInfo.service">
|
||||
请先选择服务
|
||||
</div>
|
||||
<div v-loading="onlineDebugLoading" v-else>
|
||||
<el-input placeholder="请输入内容" v-model="grpcInfo.function" class="input-with-select">
|
||||
<el-button slot="append" @click.prevent="requestExecute">执行</el-button>
|
||||
</el-input>
|
||||
<el-form label-width="100px" label-position="top">
|
||||
<el-form-item label="请求参数:">
|
||||
<el-input type="textarea" :rows="20" placeholder="请求参数" v-model="paramColumnRequest"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="请求结果:">
|
||||
<div v-html="requestResult"></div>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</el-container>
|
||||
</el-container>
|
||||
<el-dialog title="关于zyplayer-doc-grpc" :visible.sync="aboutDialogVisible" width="600px">
|
||||
<el-form>
|
||||
<el-form-item label="项目地址:">
|
||||
<a target="_blank" href="https://gitee.com/zyplayer/zyplayer-doc">zyplayer-doc</a>
|
||||
</el-form-item>
|
||||
<el-form-item label="开发人员:">
|
||||
<a target="_blank" href="http://zyplayer.com">暮光:城中城</a>
|
||||
</el-form-item>
|
||||
<el-form-item label="">
|
||||
欢迎加群讨论,QQ群号:466363173,欢迎提交需求,欢迎使用和加入开发!
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</body>
|
||||
<script type="text/javascript" src="webjars/doc-grpc/vue/vue.js"></script>
|
||||
<script type="text/javascript" src="webjars/doc-grpc/js/element-ui.js"></script>
|
||||
<!-- ajax 用到了jquery -->
|
||||
<script type="text/javascript" src="webjars/doc-grpc/js/jquery-3.1.0.min.js"></script>
|
||||
<script type="text/javascript" src="webjars/doc-grpc/js/common.js"></script>
|
||||
<script type="text/javascript" src="webjars/doc-grpc/js/toast.js"></script>
|
||||
<script type="text/javascript" src="webjars/doc-grpc/js/formatjson.js"></script>
|
||||
<script type="text/javascript" src="webjars/doc-grpc/js/doc-grpc-tree.js"></script>
|
||||
|
||||
<script>
|
||||
var app = new Vue({
|
||||
el: '#app',
|
||||
data() {
|
||||
return {
|
||||
isCollapse: false,
|
||||
aboutDialogVisible: false,
|
||||
onlineDebugLoading: false,
|
||||
pathIndex: [],
|
||||
defaultProps: {
|
||||
children: 'children',
|
||||
label: 'label'
|
||||
},
|
||||
// 展示的信息
|
||||
grpcInfo: {},
|
||||
grpcInfoExplainShow: true,
|
||||
docInfoExplainInput: "",
|
||||
grpcInfoResultShow: true,
|
||||
docInfoResultInput: "",
|
||||
// 请求的IP端口下拉选项
|
||||
requestResult: "",
|
||||
// 依据目录树存储的map全局对象
|
||||
treePathDataMap: new Map(),
|
||||
// dubbo列表
|
||||
grpcDocList: [],
|
||||
dubboDocMap: [],
|
||||
// 搜索的输入内容
|
||||
searchKeywords: "",
|
||||
docParamList: [],
|
||||
docParamRequestList: [],
|
||||
paramColumnRequest: "",
|
||||
// 参数类型选项
|
||||
paramTypeOptions: [{
|
||||
value: 'java.lang.String'
|
||||
}, {
|
||||
value: 'java.lang.Long'
|
||||
}, {
|
||||
value: 'java.lang.Integer'
|
||||
}],
|
||||
paramTypeValue: "java.lang.String",
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
|
||||
},
|
||||
mounted: function () {
|
||||
// 无论发布在哪、如何修改源码,请勿删除本行原作者信息,感谢
|
||||
console.log("%c项目信息:\n项目地址:https://gitee.com/zyplayer/zyplayer-doc", "color:red");
|
||||
this.doGetServiceList();
|
||||
},
|
||||
methods: {
|
||||
handleOpen(key, keyPath) {
|
||||
console.log(key, keyPath);
|
||||
},
|
||||
handleClose(key, keyPath) {
|
||||
console.log(key, keyPath);
|
||||
},
|
||||
handleNodeClick(data) {
|
||||
if (data.children == null) {
|
||||
console.log(data);
|
||||
var path = data.interface;
|
||||
this.createDocInfo(path, data.method);
|
||||
}
|
||||
},
|
||||
createDocInfo(path, method) {
|
||||
var grpcInfo = app.treePathDataMap.get(path);
|
||||
var paramColumn = app.columnMap[grpcInfo.paramType];
|
||||
var resultColumn = app.columnMap[grpcInfo.resultType];
|
||||
grpcInfo.method = method;
|
||||
grpcInfo.function = path;
|
||||
grpcInfo.docInfo = {};
|
||||
var paramColumnTemp = this.columnToJsonString(paramColumn || {});
|
||||
app.paramColumnRequest = JSON.stringify(paramColumnTemp, null, 4);
|
||||
grpcInfo.paramColumn = this.processObjectToHtmlPre(paramColumnTemp);
|
||||
var resultColumnTemp = this.columnToJsonString(resultColumn || {});
|
||||
grpcInfo.resultColumn = this.processObjectToHtmlPre(resultColumnTemp);
|
||||
// 清空再赋值才会重新渲染
|
||||
app.grpcInfo = {};
|
||||
app.grpcInfo = grpcInfo;
|
||||
// app.docInfoExplainInput = grpcInfo.docInfo.explain;
|
||||
app.docParamList = [];
|
||||
// app.docParamList = grpcInfo.docInfo.params || [];
|
||||
this.createDocParamRequestList();
|
||||
// 请求相关
|
||||
app.requestResult = "";
|
||||
},
|
||||
columnToJsonString(columns){
|
||||
var param = {};
|
||||
if(!!columns.param && columns.param.length > 0) {
|
||||
param = this.columnArrToJsonString(columns.param);
|
||||
}
|
||||
return param;
|
||||
},
|
||||
columnArrToJsonString(columns) {
|
||||
var param = {};
|
||||
for (var i = 0; i < columns.length; i++) {
|
||||
var item = columns[i];
|
||||
if (!!item.param && item.param.length > 0) {
|
||||
param[item.name] = this.columnArrToJsonString(item.param);
|
||||
} else {
|
||||
if (item.type == 'int') {
|
||||
param[item.name] = 0;
|
||||
} else {
|
||||
param[item.name] = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
return param;
|
||||
},
|
||||
reloadService(){
|
||||
ajaxTemp("zyplayer-doc-dubbo/doc-dubbo/reloadService", "post", "json", {}, function (json) {
|
||||
if (validateResult(json)) {
|
||||
app.$message({
|
||||
message: '加载成功!',
|
||||
type: 'success'
|
||||
});
|
||||
app.doGetServiceList();
|
||||
}
|
||||
});
|
||||
},
|
||||
searchByKeywords() {
|
||||
app.pathIndex = createTreeViewByTreeWithMerge(app.grpcDocList, app.searchKeywords);
|
||||
},
|
||||
doGetServiceList() {
|
||||
ajaxTemp("zyplayer-doc-grpc/service", "post", "json", {}, function (json) {
|
||||
if (validateResult(json)) {
|
||||
app.grpcDocList = json.data.serviceList || [];
|
||||
app.columnMap = json.data.columnMap || {};
|
||||
app.pathIndex = createTreeViewByTreeWithMerge(app.grpcDocList);
|
||||
}
|
||||
});
|
||||
},
|
||||
saveDocInfoExplain(){
|
||||
this.doSaveDocInfo(app.docInfoExplainInput, null, null, true);
|
||||
},
|
||||
saveDocInfoResult(){
|
||||
this.doSaveDocInfo(null, null, app.docInfoResultInput, true);
|
||||
},
|
||||
saveDocInfoParam() {
|
||||
var docParamList = [];
|
||||
for (var i = 0; i < app.docParamList.length; i++) {
|
||||
var item = app.docParamList[i];
|
||||
if (isNotEmpty(item.paramType)) {
|
||||
docParamList.push(item);
|
||||
}
|
||||
}
|
||||
var paramsJson = JSON.stringify(docParamList);
|
||||
this.doSaveDocInfo(null, paramsJson, null, true);
|
||||
},
|
||||
createDocParamRequestList() {
|
||||
var docParamList = [];
|
||||
for (var i = 0; i < app.docParamList.length; i++) {
|
||||
var item = app.docParamList[i];
|
||||
if (isNotEmpty(item.paramType) || isNotEmpty(item.paramDesc)) {
|
||||
docParamList.push(item);
|
||||
}
|
||||
}
|
||||
app.docParamRequestList = docParamList;
|
||||
},
|
||||
doSaveDocInfo(explain, params, result, showSuccess){
|
||||
var param = {
|
||||
service: app.grpcInfo.interface,
|
||||
method: app.grpcInfo.method,
|
||||
resultType: app.grpcInfo.resultType,
|
||||
paramValue: app.grpcInfo.paramValue,
|
||||
version: app.grpcInfo.docInfo.version || 0,
|
||||
explain: explain,
|
||||
result: result,
|
||||
paramsJson: params,
|
||||
};
|
||||
ajaxTemp("zyplayer-doc-dubbo/doc-dubbo/saveDoc", "post", "json", param, function (json) {
|
||||
if (validateResult(json)) {
|
||||
app.dubboDocMap[json.data.function] = json.data;
|
||||
app.grpcInfo.docInfo = json.data;
|
||||
app.grpcInfoExplainShow = true;
|
||||
app.grpcInfoResultShow = true;
|
||||
app.docParamList = json.data.params || [];
|
||||
app.createDocParamRequestList();
|
||||
if (showSuccess) {
|
||||
Toast.success("保存成功!");
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
addDocParam() {
|
||||
var leadAdd = app.docParamList.length <= 0;
|
||||
if (!leadAdd) {
|
||||
var last = app.docParamList[app.docParamList.length - 1];
|
||||
if (isNotEmpty(last.paramType) || isNotEmpty(last.paramDesc)) {
|
||||
leadAdd = true;
|
||||
}
|
||||
}
|
||||
if (leadAdd) {
|
||||
app.docParamList.push({
|
||||
paramName: '',
|
||||
paramType: '',
|
||||
paramDesc: '',
|
||||
paramValue: '',
|
||||
});
|
||||
}
|
||||
},
|
||||
requestExecute() {
|
||||
var fuc = app.grpcInfo.function;
|
||||
var service = fuc.substring(0, fuc.lastIndexOf("."));
|
||||
var method = fuc.substring(fuc.lastIndexOf(".") + 1, fuc.length);
|
||||
var paramColumnRequest = JSON.stringify(JSON.parse(app.paramColumnRequest));
|
||||
var param = {
|
||||
service: service,
|
||||
method: method,
|
||||
params: paramColumnRequest,//JSON.stringify(params),
|
||||
};
|
||||
app.requestResult = "";
|
||||
app.onlineDebugLoading = true;
|
||||
ajaxTemp("zyplayer-doc-grpc/execute", "post", "json", param, function (json) {
|
||||
app.onlineDebugLoading = false;
|
||||
if (json.errCode == 200) {
|
||||
app.requestResult = app.processObjectToHtmlPre(json.data);
|
||||
//var paramsJson = JSON.stringify(app.docParamRequestList);
|
||||
//app.doSaveDocInfo(null, paramsJson, null, false);
|
||||
} else {
|
||||
app.requestResult = json;
|
||||
}
|
||||
});
|
||||
},
|
||||
processObjectToHtmlPre(data){
|
||||
var requestResult = "";
|
||||
try {
|
||||
requestResult = Formatjson.processObjectToHtmlPre(JSON.parse(data), 0, false, false, false, false);
|
||||
} catch (e) {
|
||||
try {
|
||||
requestResult = Formatjson.processObjectToHtmlPre(data, 0, false, false, false, false);
|
||||
} catch (e) {
|
||||
requestResult = data;
|
||||
}
|
||||
}
|
||||
return requestResult;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
</script>
|
||||
<style>
|
||||
html,body,#app {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
height: 100%;
|
||||
}
|
||||
pre{margin: 0;}
|
||||
.el-menu {
|
||||
box-sizing: border-box;
|
||||
border-right: 0;
|
||||
margin-right: 3px;
|
||||
}
|
||||
.el-tree{
|
||||
margin-right: 3px;
|
||||
}
|
||||
.el-tree-node__content{
|
||||
padding-right: 20px;
|
||||
}
|
||||
.el-tabs--border-card>.el-tabs__content{
|
||||
height: calc(100vh - 100px);overflow-y: auto;
|
||||
}
|
||||
.logo{
|
||||
background: url("webjars/doc-grpc/img/grpc-bg.png") no-repeat; cursor: pointer;
|
||||
width: 100%; height:60px;line-height:60px;font-size: 25px;color: #fff;text-align: center;
|
||||
}
|
||||
</style>
|
||||
</html>
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
|
||||
/* S-JSON展示的样式 */
|
||||
pre.json {
|
||||
display: block;
|
||||
padding: 9.5px;
|
||||
margin: 0 0 0 10px;
|
||||
font-size: 12px;
|
||||
line-height: 1.38461538;
|
||||
color: #333;
|
||||
word-break: break-all;
|
||||
word-wrap: break-word;
|
||||
background-color: #f5f5f5;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 4px;
|
||||
}
|
||||
pre.json .canvas{font:10pt georgia;background-color:#ececec;color:#000000;border:1px solid #cecece;}
|
||||
pre.json .object-brace{color:#00aa00;font-weight:bold;}
|
||||
pre.json .array-brace{color:#0033ff;font-weight:bold;}
|
||||
pre.json .property-name{color:#cc0000;font-weight:bold;}
|
||||
pre.json .string{color:#007777;}
|
||||
pre.json .number{color:#aa00aa;}
|
||||
pre.json .boolean{color:#0000ff;}
|
||||
pre.json .function{color:#aa6633;text-decoration:italic;}
|
||||
pre.json .null{color:#0000ff;}
|
||||
pre.json .comma{color:#000000;font-weight:bold;}
|
||||
pre.json .annotation{color:#aaa;}
|
||||
pre img{cursor: pointer;}
|
||||
/* E-JSON展示的样式 */
|
||||
|
||||
File diff suppressed because one or more lines are too long
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 340 B |
Binary file not shown.
|
After Width: | Height: | Size: 331 B |
Binary file not shown.
|
After Width: | Height: | Size: 371 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 1.6 KiB |
@@ -0,0 +1,306 @@
|
||||
/**
|
||||
* 一些公用方法
|
||||
* @author 暮光:城中城
|
||||
* @since 2017年5月7日
|
||||
*/
|
||||
|
||||
function serialize(value) {
|
||||
if (typeof value === 'string') {
|
||||
return value;
|
||||
}
|
||||
return JSON.stringify(value);
|
||||
}
|
||||
|
||||
function deserialize(value) {
|
||||
if (typeof value !== 'string' || isEmpty(value)) {
|
||||
return value;
|
||||
}
|
||||
try {
|
||||
return JSON.parse(value);
|
||||
} catch (e) {
|
||||
try {
|
||||
return eval('(' + value + ')');// 处理变态的单双引号共存字符串
|
||||
} catch (e) {
|
||||
return value || undefined;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function validateResult(result) {
|
||||
if(result.errCode == 200) {
|
||||
return true;
|
||||
} else {
|
||||
Toast.error(result.errMsg);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function getNowDate() {
|
||||
var date = new Date();
|
||||
var month = date.getMonth() + 1;
|
||||
var strDate = date.getDate();
|
||||
if (month >= 1 && month <= 9) {
|
||||
month = "0" + month;
|
||||
}
|
||||
if (strDate >= 0 && strDate <= 9) {
|
||||
strDate = "0" + strDate;
|
||||
}
|
||||
var currentdate = date.getFullYear() + "-" + month + "-" + strDate;
|
||||
return currentdate;
|
||||
}
|
||||
|
||||
function getNowTime() {
|
||||
var date = new Date();
|
||||
var hours = date.getHours();
|
||||
var minutes = date.getMinutes();
|
||||
var seconds = date.getSeconds();
|
||||
if (hours >= 1 && hours <= 9) {
|
||||
hours = "0" + hours;
|
||||
}
|
||||
if (minutes >= 0 && minutes <= 9) {
|
||||
minutes = "0" + minutes;
|
||||
}
|
||||
if (seconds >= 0 && seconds <= 9) {
|
||||
seconds = "0" + seconds;
|
||||
}
|
||||
var currentdate = hours + ":" + minutes + ":" + seconds;
|
||||
return currentdate;
|
||||
}
|
||||
|
||||
function getNowDateTime() {
|
||||
var currentdate = getNowDate() + " " + getNowTime();
|
||||
return currentdate;
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回不为空的字符串,为空返回def
|
||||
*/
|
||||
function getNotEmptyStr(str, def) {
|
||||
if (isEmpty(str)) {
|
||||
return isEmpty(def) ? "" : def;
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否是空对象
|
||||
* @param obj
|
||||
* @returns
|
||||
*/
|
||||
function isEmptyObject(obj){
|
||||
return isEmpty(obj) || $.isEmptyObject(obj);
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否是空字符串
|
||||
* @param str
|
||||
* @returns
|
||||
*/
|
||||
function isEmpty(str){
|
||||
return (str == "" || str == null || str == undefined);
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否不是空字符串
|
||||
* @param str
|
||||
* @returns
|
||||
*/
|
||||
function isNotEmpty(str){
|
||||
return !isEmpty(str);
|
||||
}
|
||||
|
||||
/**
|
||||
* 数组转字符串,使用空格分隔
|
||||
* @param array
|
||||
* @returns
|
||||
*/
|
||||
function arrToString(array){
|
||||
var temStr = "";
|
||||
if(isEmpty(array)){
|
||||
return temStr;
|
||||
}
|
||||
array.forEach(function(e){
|
||||
if(isNotEmpty(temStr)) {
|
||||
temStr += " ";
|
||||
}
|
||||
temStr += e;
|
||||
});
|
||||
return temStr;
|
||||
}
|
||||
|
||||
/**
|
||||
* 数组array中是否包含str字符串
|
||||
* @param array
|
||||
* @param str
|
||||
* @returns
|
||||
*/
|
||||
function haveString(array, str){
|
||||
if(isEmpty(array)) {
|
||||
return false;
|
||||
}
|
||||
for (var i = 0; i < array.length; i++) {
|
||||
if(array[i] == str) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 直接返回对象的第一个属性
|
||||
* @param data
|
||||
* @returns
|
||||
*/
|
||||
function getObjectFirstAttribute(data) {
|
||||
for ( var key in data) {
|
||||
return data[key];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 如果对象只有一个属性则返回第一个属性,否则返回null
|
||||
* @param data
|
||||
* @returns
|
||||
*/
|
||||
function getObjectFirstAttributeIfOnly(data) {
|
||||
var len = 0, value = "";
|
||||
for ( var key in data) {
|
||||
if (++len > 1) {
|
||||
return null;
|
||||
}
|
||||
value = data[key];
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* ajax处理事件模板
|
||||
*
|
||||
* @url 后台处理的url,即action
|
||||
* @dataSentType 数据发送的方式,有post,get方式
|
||||
* @dataReceiveType 数据接收格式,有html json text等
|
||||
* @paramsStr 传入后台的参数
|
||||
* @successFunction ajax成功后执行的函数名 ajaxTemp("", "GET", "html", {}, function(){},
|
||||
* function(){}, "");
|
||||
*/
|
||||
function ajaxTemp(url, dataSentType, dataReceiveType, paramsStr, successFunction, errorFunction, completeFunction, id) {
|
||||
$.ajax({
|
||||
url : url, // 后台处理程序
|
||||
sync : false,
|
||||
type : dataSentType, // 数据发送方式
|
||||
dataType : dataReceiveType, // 接受数据格式
|
||||
traditional: true,
|
||||
data : eval(paramsStr),
|
||||
contentType : "application/x-www-form-urlencoded; charset=UTF-8",
|
||||
success : function(msg) {
|
||||
if(typeof successFunction == "function") {
|
||||
successFunction(msg,id);
|
||||
}
|
||||
},
|
||||
beforeSend : function() {
|
||||
|
||||
},
|
||||
complete : function(msg) {
|
||||
if(typeof completeFunction == "function") {
|
||||
completeFunction(msg,id);
|
||||
}
|
||||
},
|
||||
error : function(msg) {
|
||||
if(typeof errorFunction == "function") {
|
||||
errorFunction(msg,id);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function postWithFile(url, paramsStr, successFunction, errorFunction, completeFunction, id) {
|
||||
$.ajax({
|
||||
url: url, // 后台处理程序
|
||||
sync: false,
|
||||
type: "POST", // 数据发送方式
|
||||
dataType: "JSON", // 接受数据格式
|
||||
data: eval(paramsStr),
|
||||
processData: false,
|
||||
contentType: false,
|
||||
success: function (msg) {
|
||||
if (typeof successFunction == "function") {
|
||||
successFunction(msg, id);
|
||||
}
|
||||
},
|
||||
beforeSend: function () {
|
||||
|
||||
},
|
||||
complete: function (msg) {
|
||||
if (typeof completeFunction == "function") {
|
||||
completeFunction(msg, id);
|
||||
}
|
||||
},
|
||||
error: function (msg) {
|
||||
if (typeof errorFunction == "function") {
|
||||
errorFunction(msg, id);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取cookie
|
||||
* @param name
|
||||
* @returns
|
||||
*/
|
||||
function getCookie(name) {
|
||||
var arr,reg=new RegExp("(^| )"+name+"=([^;]*)(;|$)");
|
||||
if(arr=document.cookie.match(reg)){
|
||||
return unescape(arr[2]);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 字符串格式化
|
||||
*/
|
||||
String.prototype.format = function(args) {
|
||||
if (arguments.length > 0) {
|
||||
var result = this;
|
||||
if (arguments.length == 1 && typeof (args) == "object") {
|
||||
for ( var key in args) {
|
||||
var reg = new RegExp("({" + key + "})", "g");
|
||||
result = result.replace(reg, args[key]);
|
||||
}
|
||||
} else {
|
||||
for (var i = 0; i < arguments.length; i++) {
|
||||
if (arguments[i] == undefined) {
|
||||
return "";
|
||||
} else {
|
||||
var reg = new RegExp("({[" + i + "]})", "g");
|
||||
result = result.replace(reg, arguments[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
} else {
|
||||
return this;
|
||||
}
|
||||
};
|
||||
|
||||
String.prototype.endWith = function(str) {
|
||||
if (str == null || str == "" || this.length == 0 || str.length > this.length) {
|
||||
return false;
|
||||
}
|
||||
return (this.substring(this.length - str.length) == str);
|
||||
};
|
||||
|
||||
String.prototype.startWith = function(str) {
|
||||
if (str == null || str == "" || this.length == 0 || str.length > this.length) {
|
||||
return false;
|
||||
}
|
||||
return (this.substr(0, str.length) == str);
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取父窗口的exports
|
||||
* @returns
|
||||
*/
|
||||
function getExport(){
|
||||
return window.parent.window.exports;
|
||||
}
|
||||
@@ -0,0 +1,138 @@
|
||||
/**
|
||||
* 以树形方式生成并展示:
|
||||
* /api
|
||||
* /data
|
||||
* /getDateList
|
||||
* post
|
||||
* get
|
||||
* @author 暮光:城中城
|
||||
* @since 2018年5月26日
|
||||
*/
|
||||
|
||||
/**
|
||||
* 把原始的json字符串转换成对象列表的方式,方便后续使用
|
||||
* @param json swagger的原始对象
|
||||
* @returns
|
||||
*/
|
||||
function createTreeViewByTree(json, keywords) {
|
||||
var pathIndex = [];
|
||||
if (isEmptyObject(json)) {
|
||||
return;
|
||||
}
|
||||
//console.log(paths);
|
||||
var lastId = "";
|
||||
for (var i = 0; i < json.length; i++) {
|
||||
var service = json[i].service;
|
||||
var method = json[i].method;
|
||||
//console.log(key, paths[key]);
|
||||
if (!findInPathsValue(json[i], keywords)) {
|
||||
continue;
|
||||
}
|
||||
var interfaceTemp = service + "." + method;
|
||||
var keyArr = interfaceTemp.split(".");
|
||||
var nowPathObj = null;
|
||||
keyArr.forEach(function(val, index) {
|
||||
//console.log(val, index);
|
||||
if(isEmpty(val) && index == 0) {
|
||||
return;
|
||||
}
|
||||
var nowPath = val;
|
||||
if (nowPathObj == null) {
|
||||
nowPathObj = findNode(pathIndex, nowPath);
|
||||
if (nowPathObj == null) {
|
||||
nowPathObj = {
|
||||
id: pathIndex.length,
|
||||
label: nowPath, children: []
|
||||
};
|
||||
pathIndex.push(nowPathObj);
|
||||
}
|
||||
lastId = nowPathObj.id;
|
||||
nowPathObj = nowPathObj.children;
|
||||
} else {
|
||||
var tempPathObj = findNode(nowPathObj, nowPath);
|
||||
if(tempPathObj == null) {
|
||||
tempPathObj = {
|
||||
id: lastId + "." + nowPathObj.length,
|
||||
label: nowPath, children: []
|
||||
};
|
||||
nowPathObj.push(tempPathObj);
|
||||
}
|
||||
lastId = tempPathObj.id;
|
||||
nowPathObj = tempPathObj.children;
|
||||
if (index == keyArr.length - 1) {
|
||||
var tempPath = interfaceTemp;
|
||||
tempPathObj.children = null;
|
||||
tempPathObj.method = method;
|
||||
tempPathObj.interface = tempPath;
|
||||
app.treePathDataMap.set(tempPath, json[i]);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
// console.log(pathIndex);
|
||||
return pathIndex;
|
||||
}
|
||||
|
||||
function createTreeViewByTreeWithMerge(json, keywords) {
|
||||
var pathIndex = createTreeViewByTree(json, keywords);
|
||||
mergeNode(pathIndex);
|
||||
return pathIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查找node节点
|
||||
*/
|
||||
function findNode(arr, service){
|
||||
for (var i = 0; i < arr.length; i++) {
|
||||
if(arr[i].label == service) {
|
||||
return arr[i];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 多层级合并
|
||||
*/
|
||||
function mergeNode(node) {
|
||||
for (var i = 0; i < node.length; i++) {
|
||||
var tempNode = node[i];
|
||||
if (tempNode.children == null
|
||||
|| tempNode.children[0].children == null
|
||||
|| tempNode.children[0].children[0].children == null) {
|
||||
continue;
|
||||
}
|
||||
if (tempNode.children.length == 1) {
|
||||
tempNode.label = tempNode.label + "." + tempNode.children[0].label;
|
||||
tempNode.children = tempNode.children[0].children;
|
||||
i--;
|
||||
}
|
||||
mergeNode(tempNode.children);
|
||||
}
|
||||
}
|
||||
|
||||
function findInPathsValue(pathsValue, keywords) {
|
||||
if (isEmpty(keywords)) {
|
||||
return true;
|
||||
}
|
||||
keywords = keywords.toLowerCase();
|
||||
// 找路径和说明里面包含关键字的
|
||||
var service = pathsValue.service;
|
||||
if (isNotEmpty(service) && service.toLowerCase().indexOf(keywords) >= 0) {
|
||||
return true;
|
||||
}
|
||||
var paramType = pathsValue.paramType;
|
||||
if (getNotEmptyStr(paramType).toLowerCase().indexOf(keywords) >= 0) {
|
||||
return true;
|
||||
}
|
||||
var resultType = pathsValue.resultType;
|
||||
if (getNotEmptyStr(resultType).toLowerCase().indexOf(keywords) >= 0) {
|
||||
return true;
|
||||
}
|
||||
var method = pathsValue.method;
|
||||
if (getNotEmptyStr(method).toLowerCase().indexOf(keywords) >= 0) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,125 @@
|
||||
|
||||
/**
|
||||
* 将对象处理成json格式化和着色的html
|
||||
* @author 暮光:城中城
|
||||
* @since 2017年5月7日
|
||||
*/
|
||||
var Formatjson = {
|
||||
// 需要在对象或列表后面添加注释的对象,例:{userList: "用户列表"}
|
||||
// 那么在名字为userList的对象或列表后面都会加上:“用户列表” 这个注释
|
||||
annotationObject: {},
|
||||
tabStr: " ",
|
||||
isArray: function(obj) {
|
||||
return obj && typeof obj === 'object' && typeof obj.length === 'number'
|
||||
&& !(obj.propertyIsEnumerable('length'));
|
||||
},
|
||||
processObjectToHtmlPre: function(obj, indent, addComma, isArray, isPropertyContent, showAnnotation) {
|
||||
var htmlStr = this.processObject(obj, "", indent, addComma, isArray, isPropertyContent, showAnnotation);
|
||||
htmlStr = '<pre class="json">' + htmlStr + '</pre>';
|
||||
return htmlStr;
|
||||
},
|
||||
processObject: function(obj, keyName, indent, addComma, isArray, isPropertyContent, showAnnotation) {
|
||||
var html = "";
|
||||
var comma = (addComma) ? "<span class='comma'>,</span> " : "";
|
||||
var type = typeof obj;
|
||||
if (this.isArray(obj)) {
|
||||
if (obj.length == 0) {
|
||||
html += this.getRow(indent, "<span class='array-brace'>[ ]</span>" + comma, isPropertyContent);
|
||||
} else {
|
||||
var clpsHtml = '<span><img class="option-img" src="webjars/doc-dubbo/img/expanded.png" onClick="Formatjson.expImgClicked(this);" /></span><span class="collapsible">';
|
||||
var annotation = '';
|
||||
if(showAnnotation && isNotEmpty(keyName) && isNotEmpty(this.annotationObject[keyName])) {
|
||||
annotation = '<span class="annotation">// '+this.annotationObject[keyName]+'</span>';
|
||||
}
|
||||
html += this.getRow(indent, "<span class='array-brace'>[</span>"+clpsHtml+annotation, isPropertyContent);
|
||||
for (var i = 0; i < obj.length; i++) {
|
||||
html += this.processObject(obj[i], "", indent + 1, i < (obj.length - 1), true, false, showAnnotation);
|
||||
}
|
||||
clpsHtml = "</span>";
|
||||
html += this.getRow(indent, clpsHtml + "<span class='array-brace'>]</span>" + comma);
|
||||
}
|
||||
} else if (type == 'object' && obj == null) {
|
||||
html += this.formatLiteral("null", "", comma, indent, isArray, "null");
|
||||
} else if (type == 'object') {
|
||||
var numProps = 0;
|
||||
for ( var prop in obj) {
|
||||
numProps++;
|
||||
}
|
||||
if (numProps == 0) {
|
||||
html += this.getRow(indent, "<span class='object-brace'>{ }</span>" + comma, isPropertyContent);
|
||||
} else {
|
||||
var clpsHtml = '<span><img class="option-img" src="webjars/doc-dubbo/img/expanded.png" onClick="Formatjson.expImgClicked(this);" /></span><span class="collapsible">';
|
||||
var annotation = '';
|
||||
if(showAnnotation && isNotEmpty(keyName) && isNotEmpty(this.annotationObject[keyName])) {
|
||||
annotation = '<span class="annotation">// '+this.annotationObject[keyName]+'</span>';
|
||||
}
|
||||
html += this.getRow(indent, "<span class='object-brace'>{</span>"+clpsHtml+annotation, isPropertyContent);
|
||||
var j = 0;
|
||||
for ( var prop in obj) {
|
||||
var processStr = '<span class="property-name">"' + prop + '"</span>: ' + this.processObject(obj[prop], prop, indent + 1, ++j < numProps, false, true, showAnnotation);
|
||||
html += this.getRow(indent + 1, processStr);
|
||||
}
|
||||
clpsHtml = "</span>";
|
||||
html += this.getRow(indent, clpsHtml + "<span class='object-brace'>}</span>" + comma);
|
||||
}
|
||||
} else if (type == 'number') {
|
||||
html += this.formatLiteral(obj, "", comma, indent, isArray, "number");
|
||||
} else if (type == 'boolean') {
|
||||
html += this.formatLiteral(obj, "", comma, indent, isArray, "boolean");
|
||||
} else if (type == 'function') {
|
||||
obj = this.formatFunction(indent, obj);
|
||||
html += this.formatLiteral(obj, "", comma, indent, isArray, "function");
|
||||
} else if (type == 'undefined') {
|
||||
html += this.formatLiteral("undefined", "", comma, indent, isArray, "null");
|
||||
} else {
|
||||
html += this.formatLiteral(obj, "\"", comma, indent, isArray, "string");
|
||||
}
|
||||
return html;
|
||||
},
|
||||
expImgClicked: function(img){
|
||||
var container = img.parentNode.nextSibling;
|
||||
if(!container) return;
|
||||
var disp = "none";
|
||||
var src = "webjars/doc-dubbo/img/collapsed.png";
|
||||
if(container.style.display == "none"){
|
||||
disp = "inline";
|
||||
src = "webjars/doc-dubbo/img/expanded.png";
|
||||
}
|
||||
container.style.display = disp;
|
||||
img.src = src;
|
||||
},
|
||||
formatLiteral: function(literal, quote, comma, indent, isArray, style) {
|
||||
if (typeof literal == 'string') {
|
||||
literal = literal.split("<").join("<").split(">").join(">");
|
||||
}
|
||||
var str = "<span class='" + style + "'>" + quote + literal + quote + comma + "</span>";
|
||||
if (isArray) {
|
||||
str = this.getRow(indent, str);
|
||||
}
|
||||
return str;
|
||||
},
|
||||
formatFunction: function(indent, obj) {
|
||||
var tabs = "";
|
||||
for (var i = 0; i < indent; i++) {
|
||||
tabs += this.tabStr;
|
||||
}
|
||||
var funcStrArray = obj.toString().split("\n");
|
||||
var str = "";
|
||||
for (var i = 0; i < funcStrArray.length; i++) {
|
||||
str += ((i == 0) ? "" : tabs) + funcStrArray[i] + "\n";
|
||||
}
|
||||
return str;
|
||||
},
|
||||
getRow: function(indent, data, isPropertyContent) {
|
||||
var tabs = "";
|
||||
for (var i = 0; i < indent && !isPropertyContent; i++) {
|
||||
tabs += this.tabStr;
|
||||
}
|
||||
if (data != null && data.length > 0 && data.charAt(data.length - 1) != "\n") {
|
||||
data = data + "\n";
|
||||
}
|
||||
return tabs + data;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
4
zyplayer-doc-grpc/src/main/resources/webjars/doc-grpc/js/jquery-3.1.0.min.js
vendored
Normal file
4
zyplayer-doc-grpc/src/main/resources/webjars/doc-grpc/js/jquery-3.1.0.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
@@ -0,0 +1,38 @@
|
||||
/**
|
||||
* 提示工具类
|
||||
* @author 暮光:城中城
|
||||
* @since 2017年5月7日
|
||||
*/
|
||||
var Toast = {
|
||||
notOpen: function () {
|
||||
app.$message({
|
||||
message: '该功能暂未开放,敬请期待!',
|
||||
type: 'warning',
|
||||
showClose: true
|
||||
});
|
||||
},
|
||||
success: function (msg, time) {
|
||||
app.$message({
|
||||
message: msg,
|
||||
duration: time || 3000,
|
||||
type: 'success',
|
||||
showClose: true
|
||||
});
|
||||
},
|
||||
warn: function (msg, time) {
|
||||
app.$message({
|
||||
message: msg,
|
||||
duration: time || 3000,
|
||||
type: 'warning',
|
||||
showClose: true
|
||||
});
|
||||
},
|
||||
error: function (msg, time) {
|
||||
app.$message({
|
||||
message: msg,
|
||||
duration: time || 3000,
|
||||
type: 'error',
|
||||
showClose: true
|
||||
});
|
||||
},
|
||||
};
|
||||
10947
zyplayer-doc-grpc/src/main/resources/webjars/doc-grpc/vue/vue.js
Normal file
10947
zyplayer-doc-grpc/src/main/resources/webjars/doc-grpc/vue/vue.js
Normal file
File diff suppressed because it is too large
Load Diff
6
zyplayer-doc-grpc/src/main/resources/webjars/doc-grpc/vue/vue.min.js
vendored
Normal file
6
zyplayer-doc-grpc/src/main/resources/webjars/doc-grpc/vue/vue.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user