grpc开发

This commit is contained in:
暮光:城中城
2019-04-02 20:31:25 +08:00
parent 165d282beb
commit 6196238867
29 changed files with 377 additions and 417 deletions

View File

@@ -28,19 +28,23 @@
> 支持zookeeper、nacos的注册中心文档获取支持在线调试接口
##### 六、zyplayer-doc-wiki wiki文档工具
> 暂时处于开发阶段,暂不能使用
> 目标是支持文档创建、展示,文件上传、下载,空间隔离,页面权限控制等
> 支持文档创建、展示,文件上传、下载,空间隔离,开放文档访问等
##### 七、zyplayer-doc-grpc grpc文档工具
> 用比较变态的方式实现了grpc的文档和在线调试功能通过http的方式来请求grpc的接口
> 默认未开启此功能如需使用需要在zyplayer-doc-manage项目中开启@EnableDocGrpc注解
#### 运行方式
1. 创建数据库zyplayer_doc_manage执行脚本[zyplayer_doc_manage.sql](https://gitee.com/zyplayer/zyplayer-doc/blob/master/zyplayer-doc-manage/src/main/resources/sql/zyplayer_doc_manage.sql)
1. 创建数据库zyplayer_doc_manage执行脚本[zyplayer_doc_manage.1.0.1.sql](https://gitee.com/zyplayer/zyplayer-doc/blob/master/zyplayer-doc-manage/src/main/resources/sql/zyplayer_doc_manage.1.0.1.sql)
2. 修改zyplayer-doc-manage项目的application.yml配置文件里面的数据库账号密码
3. 启动zyplayer-doc-manage项目访问地址
http://127.0.0.1:8082/zyplayer-doc-manage/static/manage/home.html
未登录会进入登录页面登陆后自动跳回默认账号zyplayer 密码:123456
> 项目页面全是静态的html如果使用idea启动有可能访问不了静态页面需要在这里配置下工作目录然后重新启动即可
> 注意!!项目页面全是静态的html如果使用idea启动有可能访问不了静态页面需要在这里配置下工作目录然后重新启动即可
![](https://images.gitee.com/uploads/images/2019/0127/222951_4ce343fe_596905.png "配置工作目录")
#### 功能介绍

View File

@@ -2,9 +2,10 @@ package com.zyplayer.doc.grpc.controller;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
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;
@@ -26,6 +27,12 @@ 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 {
@@ -35,15 +42,21 @@ public class GrpcDocController {
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() throws Exception {
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.getDefinitionByJar(service.getClass());
List<GrpcDocInfo> infoList = this.getServiceInfoByJar(service.getClass());
if (infoList != null) {
grpcDocInfoList.addAll(infoList);
}
@@ -60,17 +73,29 @@ public class GrpcDocController {
return DocResponseJson.ok(grpcServiceAndColumn);
}
/**
* 执行grpc请求
*
* @author 暮光:城中城
* @since 2019年3月31日
*/
@RequestMapping("/execute")
public String execute(String service, String params) throws Exception {
List<GrpcDocInfo> grpcDocInfoList = this.getDefinitionByJar(Class.forName(service));
String executeResult = "执行失败";
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 executeResult;
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)) {
@@ -83,10 +108,16 @@ public class GrpcDocController {
}
}
private String executeFunction(GrpcDocInfo grpcDocInfo, JSONObject paramMap) throws Exception {
/**
* 执行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) {
return "组装参数失败";
throw new ConfirmException("参数组装失败");
}
// 创建参数对象
Method build = newBuilder.getClass().getMethod("build");
@@ -108,15 +139,42 @@ public class GrpcDocController {
Method sayHello = blockingStub.getClass().getMethod(grpcDocInfo.getMethod(), Class.forName(grpcDocInfo.getParamType()));
// 执行请求
Object response = sayHello.invoke(blockingStub, request);
// Method messageMethod = response.getClass().getMethod("getMessage");
// Object resultStr = messageMethod.invoke(response);
// return resultStr.toString();
// return JSON.toJSONString(response);
return response.toString();
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);
@@ -127,13 +185,24 @@ public class GrpcDocController {
Class<?> baseTypeClass = Const.BASE_TYPE.get(paramTemp.getType());
if (baseTypeClass != null) {
Method setNameSub = newBuilder.getClass().getMethod(paramTemp.getSetterName(), baseTypeClass);
Object paramObjTemp = paramMap.getObject(paramTemp.getName(), 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);
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);
@@ -147,6 +216,12 @@ public class GrpcDocController {
return null;
}
/**
* 首字母小写
*
* @author 暮光:城中城
* @since 2019年3月31日
*/
private String toLowerCaseFirstOne(String str) {
if (Character.isLowerCase(str.charAt(0))) {
return str;
@@ -155,6 +230,26 @@ public class GrpcDocController {
}
}
/**
* 首字母大写
*
* @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();
@@ -181,10 +276,16 @@ public class GrpcDocController {
}
nameSb.append(methodName).append(",");
}
System.out.println(nameSb);
//System.out.println(nameSb);
return result;
}
/**
* 找到所有的字段信息
*
* @author 暮光:城中城
* @since 2019年3月31日
*/
private ColumnInfo findColumnInfo(String paramType) {
ColumnInfo columnInfo = new ColumnInfo();
try {
@@ -199,6 +300,12 @@ public class GrpcDocController {
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);
@@ -218,7 +325,13 @@ public class GrpcDocController {
return subInfoList;
}
private List<GrpcDocInfo> getDefinitionByJar(Class clazz) {
/**
* 找到服务,组装方法、参数和返回值等
*
* @author 暮光:城中城
* @since 2019年3月31日
*/
private List<GrpcDocInfo> getServiceInfoByJar(Class clazz) {
List<GrpcDocInfo> providerList = new LinkedList<>();
try {
Method[] methods = clazz.getDeclaredMethods();

View File

@@ -2,6 +2,12 @@ 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;

View File

@@ -1,81 +0,0 @@
package com.zyplayer.doc.grpc.controller.po;
import com.alibaba.fastjson.annotation.JSONField;
import java.util.List;
/**
* @author 暮光:城中城
* @since 2019年1月10日
**/
public class GrpcInfo {
@JSONField(name = "interface")
private String interfaceX;
private List<DubboNodeInfo> nodeList;
public static class DubboNodeInfo {
private Integer port;
private String ip;
@JSONField(name = "interface")
private String interfaceX;
private String[] methods;
private String application;
public Integer getPort() {
return port;
}
public void setPort(Integer port) {
this.port = port;
}
public String getIp() {
return ip;
}
public void setIp(String ip) {
this.ip = ip;
}
public String getInterfaceX() {
return interfaceX;
}
public void setInterfaceX(String interfaceX) {
this.interfaceX = interfaceX;
}
public String[] getMethods() {
return methods;
}
public void setMethods(String[] methods) {
this.methods = methods;
}
public String getApplication() {
return application;
}
public void setApplication(String application) {
this.application = application;
}
}
public List<DubboNodeInfo> getNodeList() {
return nodeList;
}
public void setNodeList(List<DubboNodeInfo> nodeList) {
this.nodeList = nodeList;
}
public String getInterfaceX() {
return interfaceX;
}
public void setInterfaceX(String interfaceX) {
this.interfaceX = interfaceX;
}
}

View File

@@ -4,7 +4,7 @@ import java.util.List;
import java.util.Map;
/**
* 请求参数对象
* 服务和字段信息
*
* @author 暮光:城中城
* @since 2019年2月10日

View File

@@ -1,5 +1,11 @@
package com.zyplayer.doc.grpc.controller.po;
/**
* grpc方法信息
*
* @author 暮光:城中城
* @since 2019年3月31日
*/
public class MethodParam {
private String name;
private String type;

View File

@@ -6,6 +6,12 @@ import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
/**
* 开启grpc的注解
*
* @author 暮光:城中城
* @since 2019年3月31日
*/
@Retention(value = java.lang.annotation.RetentionPolicy.RUNTIME)
@Target(value = { java.lang.annotation.ElementType.TYPE })
@Documented

View File

@@ -9,6 +9,12 @@ import org.springframework.context.annotation.Configuration;
import javax.annotation.Resource;
/**
* grpc配置
*
* @author 暮光:城中城
* @since 2019年3月31日
*/
@Configuration
@AutoConfigureAfter(GrpcServerConfiguration.class)
public class GrpcClientConfiguration {

View File

@@ -5,6 +5,12 @@ 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 {

View File

@@ -6,6 +6,12 @@ import org.springframework.context.annotation.Configuration;
import javax.annotation.Resource;
/**
* grpc服务
*
* @author 暮光:城中城
* @since 2019年3月31日
*/
@Configuration
public class GrpcServerConfiguration {

View File

@@ -12,21 +12,24 @@ 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);
}
@@ -37,15 +40,16 @@ public class SpringContextUtil implements ApplicationContextAware {
/**
* 获取类
*
* @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());
}
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

@@ -5,8 +5,13 @@ 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<>();

View File

@@ -1,29 +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;
@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();
}
}
//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

@@ -1,25 +1,40 @@
package com.zyplayer.doc.grpc.service;
import com.nxest.grpc.server.GrpcService;
import com.zyplayer.doc.grpc.proto.ChatMsg;
import com.zyplayer.doc.grpc.proto.ZyplayerChatGrpc;
import io.grpc.stub.StreamObserver;
@GrpcService
public class ZyplayerChatService extends ZyplayerChatGrpc.ZyplayerChatImplBase {
@Override
public void sendText(ChatMsg request, StreamObserver<ChatMsg> responseObserver) {
ChatMsg reply = ChatMsg.newBuilder().setToken("sendMsg").build();
responseObserver.onNext(reply);
responseObserver.onCompleted();
}
@Override
public void sendImage(ChatMsg request, StreamObserver<ChatMsg> responseObserver) {
ChatMsg reply = ChatMsg.newBuilder().setToken("sendImage").build();
responseObserver.onNext(reply);
responseObserver.onCompleted();
}
}
//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

@@ -6,9 +6,9 @@
<!--无论发布在哪、如何修改源码,请勿删除本行原作者信息,感谢-->
<meta name="author" content="开发者列表暮光城中城项目地址https://gitee.com/zyplayer/zyplayer-doc" />
<title>grpc文档管理系统</title>
<link rel="shortcut icon" href="webjars/doc-grpc/img/dubbo.ico"/>
<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-dubbo.css" />
<link rel="stylesheet" href="webjars/doc-grpc/css/doc-grpc.css" />
</head>
<body>
<div id="app">
@@ -16,7 +16,7 @@
<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>
<!-- <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>
@@ -26,50 +26,50 @@
<el-container>
<el-tabs type="border-card" style="width: 100%;">
<el-tab-pane label="接口说明">
<div v-if="!dubboInfo.service">
<div v-if="!grpcInfo.service">
请先选择服务
</div>
<el-form v-else label-width="80px">
<el-form-item label="服务:">
{{dubboInfo.service}}
{{grpcInfo.service}}
</el-form-item>
<el-form-item label="方法:">
{{dubboInfo.method}}
</el-form-item>
<el-form-item label="说明:">
<div v-if="dubboInfoExplainShow">
<pre>{{dubboInfo.docInfo.explain}}<el-button @click.prevent="dubboInfoExplainShow = 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="dubboInfoExplainShow = true;" style="float: right;margin: 5px;">取消</el-button>
<el-button type="primary" @click.prevent="saveDocInfoExplain" style="float: right;margin: 5px;">保存</el-button>
</div>
{{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="dubboInfo.paramColumn"></div>
<div v-html="grpcInfo.paramColumn"></div>
</el-form-item>
<el-form-item label="返回值:">
<div v-html="dubboInfo.resultColumn"></div>
</el-form-item>
<el-form-item label="结果:">
<div v-if="dubboInfoResultShow">
<pre>{{dubboInfo.docInfo.result}}<el-button @click.prevent="dubboInfoResultShow = 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="dubboInfoResultShow = true;" style="float: right;margin: 5px;">取消</el-button>
<el-button type="primary" @click.prevent="saveDocInfoResult" style="float: right;margin: 5px;">保存</el-button>
</div>
<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="!dubboInfo.service">
<div v-if="!grpcInfo.service">
请先选择服务
</div>
<div v-loading="onlineDebugLoading" v-else>
<el-input placeholder="请输入内容" v-model="dubboInfo.function" class="input-with-select">
<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">
@@ -85,7 +85,7 @@
</el-tabs>
</el-container>
</el-container>
<el-dialog title="关于zyplayer-doc-dubbo" :visible.sync="aboutDialogVisible" width="600px">
<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>
@@ -123,10 +123,10 @@
label: 'label'
},
// 展示的信息
dubboInfo: {},
dubboInfoExplainShow: true,
grpcInfo: {},
grpcInfoExplainShow: true,
docInfoExplainInput: "",
dubboInfoResultShow: true,
grpcInfoResultShow: true,
docInfoResultInput: "",
// 请求的IP端口下拉选项
requestResult: "",
@@ -170,25 +170,7 @@
if (data.children == null) {
console.log(data);
var path = data.interface;
var application = data.application;
var docInfo = app.dubboDocMap[path];
this.createDocInfo(path, data.method);
// if (!!docInfo) {
// this.createDocInfo(path, data.method);
// } else {
// var service = path.substring(0, path.lastIndexOf("."));
// var method = path.substring(path.lastIndexOf(".") + 1, path.length);
// var param = {service: service, method: method, application: application};
// ajaxTemp("zyplayer-doc-dubbo/doc-dubbo/findDocInfo", "post", "json", param, function (json) {
// if (validateResult(json)) {
// if (!!json.data) {
// app.dubboDocMap[json.data.function] = json.data;
// }
// app.createDocInfo(path, method);
// }
// });
// }
//console.log(app.dubboInfo);
}
},
createDocInfo(path, method) {
@@ -204,11 +186,11 @@
var resultColumnTemp = this.columnToJsonString(resultColumn || {});
grpcInfo.resultColumn = this.processObjectToHtmlPre(resultColumnTemp);
// 清空再赋值才会重新渲染
app.dubboInfo = {};
app.dubboInfo = grpcInfo;
// app.docInfoExplainInput = dubboInfo.docInfo.explain;
app.grpcInfo = {};
app.grpcInfo = grpcInfo;
// app.docInfoExplainInput = grpcInfo.docInfo.explain;
app.docParamList = [];
// app.docParamList = dubboInfo.docInfo.params || [];
// app.docParamList = grpcInfo.docInfo.params || [];
this.createDocParamRequestList();
// 请求相关
app.requestResult = "";
@@ -284,11 +266,11 @@
},
doSaveDocInfo(explain, params, result, showSuccess){
var param = {
service: app.dubboInfo.interface,
method: app.dubboInfo.method,
resultType: app.dubboInfo.resultType,
paramValue: app.dubboInfo.paramValue,
version: app.dubboInfo.docInfo.version || 0,
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,
@@ -296,9 +278,9 @@
ajaxTemp("zyplayer-doc-dubbo/doc-dubbo/saveDoc", "post", "json", param, function (json) {
if (validateResult(json)) {
app.dubboDocMap[json.data.function] = json.data;
app.dubboInfo.docInfo = json.data;
app.dubboInfoExplainShow = true;
app.dubboInfoResultShow = true;
app.grpcInfo.docInfo = json.data;
app.grpcInfoExplainShow = true;
app.grpcInfoResultShow = true;
app.docParamList = json.data.params || [];
app.createDocParamRequestList();
if (showSuccess) {
@@ -325,7 +307,7 @@
}
},
requestExecute() {
var fuc = app.dubboInfo.function;
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));
@@ -340,8 +322,8 @@
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);
//var paramsJson = JSON.stringify(app.docParamRequestList);
//app.doSaveDocInfo(null, paramsJson, null, false);
} else {
app.requestResult = json;
}
@@ -386,7 +368,7 @@
height: calc(100vh - 100px);overflow-y: auto;
}
.logo{
background: linear-gradient(-90deg, #03DDE4 0%, #30AFED 51%, #8755FF 100%); cursor: pointer;
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>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 371 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@@ -7,9 +7,11 @@ import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @Author
* @Date 2018/11/11
**/
* 开启zyplayer-doc-db服务
*
* @author 暮光:城中城
* @since 2018年11月11日
*/
@EnableDocDb
@Configuration
public class DocDatabaseRegistrationConfig {

View File

@@ -4,9 +4,11 @@ import com.zyplayer.doc.dubbo.framework.config.EnableDocDubbo;
import org.springframework.context.annotation.Configuration;
/**
* @Author
* @Date 2018/11/11
**/
* 开启zyplayer-doc-dubbo服务
*
* @author 暮光:城中城
* @since 2018年11月11日
*/
@EnableDocDubbo
@Configuration
public class DocDubboConfig {

View File

@@ -1,14 +1,13 @@
package com.zyplayer.doc.manage.framework.config;
import com.zyplayer.doc.grpc.framework.config.EnableDocGrpc;
import org.springframework.context.annotation.Configuration;
/**
* @Author
* @Date 2018/11/11
**/
@EnableDocGrpc
@Configuration
* 开启zyplayer-doc-grpc服务
*
* @author 暮光:城中城
* @since 2018年11月11日
*/
//@EnableDocGrpc
//@Configuration
public class DocGrpcConfig {
}

View File

@@ -4,9 +4,11 @@ import com.zyplayer.doc.wiki.framework.config.EnableDocWiki;
import org.springframework.context.annotation.Configuration;
/**
* @Author
* @Date 2018/11/11
**/
* 开启zyplayer-doc-wiki服务
*
* @author 暮光:城中城
* @since 2018年11月11日
*/
@EnableDocWiki
@Configuration
public class DocWikiConfig {

View File

@@ -1,141 +0,0 @@
//package com.zyplayer.doc.manage.framework.config;
//
//import com.atomikos.icatch.jta.UserTransactionImp;
//import com.atomikos.icatch.jta.UserTransactionManager;
//import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
//import com.baomidou.mybatisplus.extension.plugins.PerformanceInterceptor;
//import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
//import com.zyplayer.doc.data.repository.support.interceptor.SqlLogInterceptor;
//import org.apache.ibatis.plugin.Interceptor;
//import org.mybatis.spring.annotation.MapperScan;
//import org.springframework.beans.factory.annotation.Value;
//import org.springframework.boot.jta.atomikos.AtomikosDataSourceBean;
//import org.springframework.context.annotation.Bean;
//import org.springframework.context.annotation.Configuration;
//import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
//import org.springframework.transaction.PlatformTransactionManager;
//import org.springframework.transaction.annotation.EnableTransactionManagement;
//import org.springframework.transaction.jta.JtaTransactionManager;
//
//import javax.sql.DataSource;
//import javax.transaction.TransactionManager;
//import javax.transaction.UserTransaction;
//import java.util.Properties;
//
///**
// * mybatis plus数据库配置
// */
////@Configuration
//public class MybatisPlusConfig {
//
// /**
// * sql日志
// **/
// private static final SqlLogInterceptor SQL_LOG_INTERCEPTOR;
//
// static {
// SQL_LOG_INTERCEPTOR = new SqlLogInterceptor();
// Properties properties = new Properties();
// SQL_LOG_INTERCEPTOR.setProperties(properties);
// }
//
// /**
// * 分布式事务配置
// */
// @Configuration
// static class JTATransactionManagerConfig {
//
// @Bean(name = "userTransaction")
// public UserTransaction userTransaction() throws Throwable {
// UserTransactionImp userTransactionImp = new UserTransactionImp();
// userTransactionImp.setTransactionTimeout(300);
// return userTransactionImp;
// }
//
// @Bean(name = "atomikosTransactionManager")
// public TransactionManager atomikosTransactionManager() {
// UserTransactionManager userTransactionManager = new UserTransactionManager();
// userTransactionManager.setForceShutdown(true);
// return userTransactionManager;
// }
//
// @Bean(name = "transactionManager")
// public PlatformTransactionManager transactionManager() throws Throwable {
// UserTransaction userTransaction = userTransaction();
// TransactionManager atomikosTransactionManager = atomikosTransactionManager();
//
// JtaTransactionManager jtaTransactionManager = new JtaTransactionManager(userTransaction, atomikosTransactionManager);
// jtaTransactionManager.setAllowCustomIsolationLevels(true);
// jtaTransactionManager.setGlobalRollbackOnParticipationFailure(true);
// jtaTransactionManager.setDefaultTimeout(30);
//
// return jtaTransactionManager;
// }
// }
//
// /**
// * 数据库配置
// */
// @Configuration
// @EnableTransactionManagement
// @MapperScan(value = "com.zyplayer.doc.data.repository.manage.mapper", sqlSessionFactoryRef = "manageSqlSessionFactory")
// static class ManageMybatisDbConfig {
//
// @Value("${zyplayer.doc.manage.datasource.driverClassName}")
// private String driverClassName;
// @Value("${zyplayer.doc.manage.datasource.url}")
// private String url;
// @Value("${zyplayer.doc.manage.datasource.username}")
// private String username;
// @Value("${zyplayer.doc.manage.datasource.password}")
// private String password;
//
// @Bean(name = "manageDatasource")
// public DataSource manageDatasource() {
// Properties xaProperties = new Properties();
// xaProperties.setProperty("driverClassName", driverClassName);
// xaProperties.setProperty("url", url);
// xaProperties.setProperty("username", username);
// xaProperties.setProperty("password", password);
// xaProperties.setProperty("maxActive", "500");
// xaProperties.setProperty("testOnBorrow", "true");
// xaProperties.setProperty("testWhileIdle", "true");
// xaProperties.setProperty("validationQuery", "select 'x'");
//
// AtomikosDataSourceBean xaDataSource = new AtomikosDataSourceBean();
// xaDataSource.setXaProperties(xaProperties);
// xaDataSource.setXaDataSourceClassName("com.alibaba.druid.pool.xa.DruidXADataSource");
// xaDataSource.setUniqueResourceName("manageDatasource");
// xaDataSource.setMaxPoolSize(500);
// xaDataSource.setMinPoolSize(1);
// xaDataSource.setMaxLifetime(60);
// return xaDataSource;
// }
//
// @Bean(name = "manageSqlSessionFactory")
// public MybatisSqlSessionFactoryBean manageSqlSessionFactory() throws Exception {
// MybatisSqlSessionFactoryBean sqlSessionFactoryBean = new MybatisSqlSessionFactoryBean();
// sqlSessionFactoryBean.setDataSource(manageDatasource());
// sqlSessionFactoryBean.setPlugins(new Interceptor[]{SQL_LOG_INTERCEPTOR});
//
// PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
// sqlSessionFactoryBean.setMapperLocations(resolver.getResources("classpath:/mapper/manage/*Mapper.xml"));
// return sqlSessionFactoryBean;
// }
// }
//
// @Bean
// public PerformanceInterceptor performanceInterceptor() {
// PerformanceInterceptor performanceInterceptor = new PerformanceInterceptor();
// /* <!-- SQL 执行性能分析,开发环境使用,线上不推荐。 maxTime 指的是 sql 最大执行时长 --> */
// performanceInterceptor.setMaxTime(1000);
// /* <!--SQL是否格式化 默认false--> */
// performanceInterceptor.setFormat(true);
// return performanceInterceptor;
// }
//
// @Bean
// public PaginationInterceptor paginationInterceptor() {
// return new PaginationInterceptor();
// }
//}

View File

@@ -2,7 +2,7 @@
package com.zyplayer.doc.manage.framework.config;
import com.google.common.base.Predicates;
import com.zyplayer.doc.swagger.framework.configuration.EnableSwaggerMgUi;
import com.zyplayer.doc.swagger.framework.configuration.EnableDocSwagger;
import io.swagger.annotations.Api;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@@ -15,17 +15,13 @@ import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
/**
* 不需要管理本项目的文档,只需要开启@EnableSwaggerMgUi即可
* 不需要管理本项目的文档,只需要开启@EnableDocSwagger即可
* @author 暮光:城中城
* @since 2018年11月11日
*/
@Configuration
//@EnableSwagger2
@EnableSwaggerMgUi(
selfDoc = false,// 是否开启自身的文档
defaultLocation = {// 启动后第一次访问没有数据情况下需要加载进来的/v2/doc地址
//"http://localhost:8080/v2/doc"
}
@EnableDocSwagger(
selfDoc = false// 是否开启自身的文档
)
public class SwaggerConfiguration {

View File

@@ -0,0 +1,17 @@
package com.zyplayer.doc.manage.framework.config;
/**
* 开启zyplayer-doc所有的服务
*
* @author 暮光:城中城
* @since 2019年3月31日
*/
//@EnableDocWiki
//@EnableDocDubbo
//@EnableDocDb
////@EnableDocGrpc // 默认不开启
//@EnableDocSwagger(selfDoc = false)
//@Configuration
public class ZyplayerDocConfig {
}

View File

@@ -7,7 +7,7 @@ import com.zyplayer.doc.core.json.ResponseJson;
import com.zyplayer.doc.swagger.controller.vo.LocationListVo;
import com.zyplayer.doc.swagger.controller.vo.SwaggerLocationVo;
import com.zyplayer.doc.swagger.controller.vo.SwaggerResourcesInfoVo;
import com.zyplayer.doc.swagger.framework.configuration.EnableSwaggerMgUi;
import com.zyplayer.doc.swagger.framework.configuration.EnableDocSwagger;
import com.zyplayer.doc.swagger.framework.configuration.SpringContextUtil;
import com.zyplayer.doc.swagger.framework.constant.StorageKeys;
import com.zyplayer.doc.swagger.framework.service.MgStorageService;
@@ -83,7 +83,7 @@ public class MgDocumentController {
+ ":" + request.getServerPort() // 端口号
+ request.getContextPath();
// 是否加入自身的文档
EnableSwaggerMgUi swaggerMgUi = SpringContextUtil.getEnableSwaggerMgUi();
EnableDocSwagger swaggerMgUi = SpringContextUtil.getEnableSwaggerMgUi();
if (swaggerMgUi == null) {
resourcesSet.add(new SwaggerResourcesInfoVo(serverPath + "/swagger-resources"));
} else {
@@ -194,21 +194,21 @@ public class MgDocumentController {
// + ":" + request.getServerPort() // 端口号
// + request.getContextPath();
// // 是否加入自身的文档
// Object enableSwaggerMgUi = SpringContextUtil.getBeanWithAnnotation(EnableSwaggerMgUi.class);
// Object enableSwaggerMgUi = SpringContextUtil.getBeanWithAnnotation(EnableDocSwagger.class);
// if (enableSwaggerMgUi != null) {
// EnableSwaggerMgUi swaggerMgUi = enableSwaggerMgUi.getClass().getAnnotation(EnableSwaggerMgUi.class);
// EnableDocSwagger swaggerMgUi = enableSwaggerMgUi.getClass().getAnnotation(EnableDocSwagger.class);
// if (swaggerMgUi == null) {
// // 直接通过superclass去找
// Class<?> superclass = enableSwaggerMgUi.getClass().getSuperclass();
// if (superclass != null) {
// swaggerMgUi = superclass.getAnnotation(EnableSwaggerMgUi.class);
// swaggerMgUi = superclass.getAnnotation(EnableDocSwagger.class);
// }
// }
// if (swaggerMgUi == null) {
// // 再通过AopUtils去找
// Class<?> targetClass = AopUtils.getTargetClass(enableSwaggerMgUi);
// if (targetClass != null) {
// swaggerMgUi = targetClass.getAnnotation(EnableSwaggerMgUi.class);
// swaggerMgUi = targetClass.getAnnotation(EnableDocSwagger.class);
// }
// }
// if (swaggerMgUi == null) {

View File

@@ -11,7 +11,7 @@ import java.lang.annotation.Target;
@Target(value = {java.lang.annotation.ElementType.TYPE})
@Documented
@Import({SwaggerCommonConfiguration.class, SpringContextUtil.class, ZyplayerProxyFilter.class})
public @interface EnableSwaggerMgUi {
public @interface EnableDocSwagger {
/**
* 是否自动把自身的swagger-resources加进来

View File

@@ -16,7 +16,7 @@ import java.util.Map;
public class SpringContextUtil implements ApplicationContextAware {
public static ApplicationContext context;
private static EnableSwaggerMgUi ENABLE_SWAGGER_MG_UI;
private static EnableDocSwagger ENABLE_SWAGGER_MG_UI;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
@@ -58,25 +58,25 @@ public class SpringContextUtil implements ApplicationContextAware {
* @since 2019/1/29 12:58
* @return EnableSwaggerMgUi注解对象
**/
public static EnableSwaggerMgUi getEnableSwaggerMgUi() {
public static EnableDocSwagger getEnableSwaggerMgUi() {
if (ENABLE_SWAGGER_MG_UI != null) {
return ENABLE_SWAGGER_MG_UI;
}
Object annotation = SpringContextUtil.getBeanWithAnnotation(EnableSwaggerMgUi.class);
Object annotation = SpringContextUtil.getBeanWithAnnotation(EnableDocSwagger.class);
if (annotation != null) {
EnableSwaggerMgUi swaggerMgUi = annotation.getClass().getAnnotation(EnableSwaggerMgUi.class);
EnableDocSwagger swaggerMgUi = annotation.getClass().getAnnotation(EnableDocSwagger.class);
if (swaggerMgUi == null) {
// 直接通过superclass去找
Class<?> superclass = annotation.getClass().getSuperclass();
if (superclass != null) {
swaggerMgUi = superclass.getAnnotation(EnableSwaggerMgUi.class);
swaggerMgUi = superclass.getAnnotation(EnableDocSwagger.class);
}
}
if (swaggerMgUi == null) {
// 再通过AopUtils去找
Class<?> targetClass = AopUtils.getTargetClass(annotation);
if (targetClass != null) {
swaggerMgUi = targetClass.getAnnotation(EnableSwaggerMgUi.class);
swaggerMgUi = targetClass.getAnnotation(EnableDocSwagger.class);
}
}
if (swaggerMgUi != null) {