注解优化,grpc开发

This commit is contained in:
暮光:城中城
2019-04-02 20:22:18 +08:00
parent f5e6a5998d
commit 7caebe9eaf
48 changed files with 13154 additions and 283 deletions

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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 {
}

View File

@@ -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());
}
}

View File

@@ -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;
}
}

View File

@@ -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();
}
}

View File

@@ -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());
}
}

View File

@@ -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);
}
}

View File

@@ -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();
// }
//}

View File

@@ -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();
// }
//}

View 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;
}

View 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;
}

View 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>

View File

@@ -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.

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

View File

@@ -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 数据发送的方式有postget方式
* @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;
}

View File

@@ -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

View File

@@ -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("&lt;").split(">").join("&gt;");
}
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;
}
}

File diff suppressed because one or more lines are too long

View File

@@ -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
});
},
};

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long