mirror of
https://gitee.com/durcframework/SOP.git
synced 2025-08-11 21:57:56 +08:00
添加文档
This commit is contained in:
@@ -1,8 +1,11 @@
|
|||||||
* 文档目录
|
* [首页](/?t=1553513181526)
|
||||||
|
* 开发文档
|
||||||
* [快速体验](files/10010_快速体验.md?t=1553485733133)
|
* [快速体验](files/10010_快速体验.md?t=1553513181526)
|
||||||
* [项目接入到SOP](files/10011_项目接入到SOP.md?t=1553485733154)
|
* [项目接入到SOP](files/10011_项目接入到SOP.md?t=1553513181547)
|
||||||
* [新增接口](files/10020_新增接口.md?t=1553485733154)
|
* [新增接口](files/10020_新增接口.md?t=1553513181547)
|
||||||
* [业务参数校验](files/10030_业务参数校验.md?t=1553485733154)
|
* [业务参数校验](files/10030_业务参数校验.md?t=1553513181547)
|
||||||
* [错误处理](files/10040_错误处理.md?t=1553485733154)
|
* [错误处理](files/10040_错误处理.md?t=1553513181547)
|
||||||
* [接口交互详解](files/10050_接口交互详解.md?t=1553485733155)
|
* [接口交互详解](files/10050_接口交互详解.md?t=1553513181547)
|
||||||
|
* 原理分析
|
||||||
|
* [原理分析之@ApiMapping](files/90010_原理分析之@ApiMapping.md?t=1553513181547)
|
||||||
|
* [原理分析之路由存储](files/90011_原理分析之路由存储.md?t=1553513181547)
|
||||||
|
21
doc/docs/files/90010_原理分析之@ApiMapping.md
Normal file
21
doc/docs/files/90010_原理分析之@ApiMapping.md
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
# 原理分析之@ApiMapping注解
|
||||||
|
|
||||||
|
@ApiMapping注解的使用方式参考了Spring自带的@PostMapping注解。
|
||||||
|
|
||||||
|
查看org.springframework.web.bind.annotation.PostMapping的类注释,有这么一句话:
|
||||||
|
|
||||||
|
|
||||||
|
> Specifically, @PostMapping is a composed annotation that acts as a shortcut for @RequestMapping(method = RequestMethod.POST).
|
||||||
|
|
||||||
|
翻译过来就是说,@PostMapping是一个组合模式的注解,可以看成是@RequestMapping(method = RequestMethod.POST)快捷方式。
|
||||||
|
|
||||||
|
如果我们自己定义个Mapping,仿照@PostMapping的方式,然后作用在方法上面会不会成功呢?实践证明是可以的。
|
||||||
|
|
||||||
|
@ApiMapping注解正是仿照了@PostMapping注解,然后再添加了几个自己的属性,比如版本号字段。
|
||||||
|
|
||||||
|
那么如何才能通过path + 版本号来确定一个接口呢?
|
||||||
|
|
||||||
|
springmvc提供了RequestCondition接口来实现这个功能,具体的操作可参考这篇文章:[让SpringMVC支持可版本管理的Restful接口](http://www.cnblogs.com/jcli/p/springmvc_restful_version.html)
|
||||||
|
|
||||||
|
SOP对应的是`com.gitee.sop.servercommon.mapping.ApiMappingRequestCondition`,这个类在com.gitee.sop.servercommon.mapping下。可以从`ApiMappingHandlerMapping`类开始解读。
|
||||||
|
|
25
doc/docs/files/90011_原理分析之路由存储.md
Normal file
25
doc/docs/files/90011_原理分析之路由存储.md
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
# 原理分析之路由存储
|
||||||
|
|
||||||
|
SOP将路由信息存到了zookeeper当中,服务在启动时,将自己的路由信息上传到zookeeper中。
|
||||||
|
网关监听存放路由的节点,动态更新到本地。
|
||||||
|
|
||||||
|
zookeeper存储路由的结构如下:
|
||||||
|
|
||||||
|
```xml
|
||||||
|
/com.gitee.sop.route-<profile> 根节点
|
||||||
|
/serviceId 服务节点,名字为服务名
|
||||||
|
/route1 路由节点,名字为:name+version,存放路由信息
|
||||||
|
/route2
|
||||||
|
/...
|
||||||
|
```
|
||||||
|
|
||||||
|
服务启动时,创建`/serviceId`节点,然后遍历创建`/routeN`节点
|
||||||
|
|
||||||
|
同时,网关监听`服务节点`和`路由节点`,当有新服务加入时,网关会获取到新加入的路由节点信息,
|
||||||
|
同时路由节点下面的子节点也会被监听到。后续子节点的增删改都会被网关监听到,然后更新到本地。
|
||||||
|
|
||||||
|
服务上传路由相关代码在`com.gitee.sop.servercommon.manager.ServiceZookeeperApiMetaManager`类中
|
||||||
|
|
||||||
|
网关监听相关代码在`com.gitee.sop.gatewaycommon.manager.BaseRouteManager`中
|
||||||
|
|
||||||
|
|
@@ -2,19 +2,29 @@ package com.gitee.sop.doc;
|
|||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 生成_sidebar.md文件,直接运行即可
|
* 生成_sidebar.md文件,直接运行即可
|
||||||
|
*
|
||||||
* @author tanghc
|
* @author tanghc
|
||||||
*/
|
*/
|
||||||
public class SidebarTest {
|
public class SidebarTest {
|
||||||
|
|
||||||
static String format = " * [%s](files/%s?t=%s)\r\n";
|
static String format = " * [%s](files/%s?t=%s)\r\n";
|
||||||
static String sidebar_format = "* 文档目录\r\n\r\n%s";
|
static Map<String, Menu> levelMap = new HashMap<>(8);
|
||||||
|
|
||||||
|
static {
|
||||||
|
int i = 0;
|
||||||
|
levelMap.put("1", new Menu("* 开发文档\n", i++));
|
||||||
|
levelMap.put("9", new Menu("* 原理分析\n", i++));
|
||||||
|
}
|
||||||
|
|
||||||
public static void main(String[] args) throws Exception {
|
public static void main(String[] args) throws Exception {
|
||||||
String path = SidebarTest.class.getClassLoader().getResource("").getPath();
|
String path = SidebarTest.class.getClassLoader().getResource("").getPath();
|
||||||
@@ -23,25 +33,59 @@ public class SidebarTest {
|
|||||||
File dir = new File(fileDir);
|
File dir = new File(fileDir);
|
||||||
File[] files = dir.listFiles();
|
File[] files = dir.listFiles();
|
||||||
Stream<File> filesStream = Stream.of(files);
|
Stream<File> filesStream = Stream.of(files);
|
||||||
List<File> fileList = filesStream
|
Map<String, List<FileExt>> menuMap = filesStream
|
||||||
.sorted(Comparator.comparing(File::getName))
|
.sorted(Comparator.comparing(File::getName))
|
||||||
.collect(Collectors.toList());
|
.map(file -> {
|
||||||
|
FileExt fileExt = new FileExt();
|
||||||
|
fileExt.menu = file.getName().substring(0, 1);
|
||||||
|
fileExt.file = file;
|
||||||
|
return fileExt;
|
||||||
|
})
|
||||||
|
.collect(Collectors.groupingBy(FileExt::getMenu));
|
||||||
|
|
||||||
StringBuilder output = new StringBuilder();
|
StringBuilder output = new StringBuilder();
|
||||||
for (File file : fileList) {
|
output.append("* [首页](/?t=" + System.currentTimeMillis() + ")\n");
|
||||||
String filename = file.getName();
|
for (Map.Entry<String, List<FileExt>> entry : menuMap.entrySet()) {
|
||||||
|
Menu menu = levelMap.get(entry.getKey());
|
||||||
|
output.append(menu.parentName);
|
||||||
|
for (FileExt fileExt : entry.getValue()) {
|
||||||
|
String filename = fileExt.file.getName();
|
||||||
String title = filename.substring(filename.indexOf("_") + 1, filename.length() - 3);
|
String title = filename.substring(filename.indexOf("_") + 1, filename.length() - 3);
|
||||||
String line = String.format(format, title, filename, System.currentTimeMillis());
|
String line = String.format(format, title, filename, System.currentTimeMillis());
|
||||||
output.append(line);
|
output.append(line);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
String sidebarContent = String.format(sidebar_format, output.toString());
|
System.out.println(output);
|
||||||
|
|
||||||
System.out.println(sidebarContent);
|
|
||||||
|
|
||||||
String sidebarFilepath = root + "/docs/_sidebar.md";
|
String sidebarFilepath = root + "/docs/_sidebar.md";
|
||||||
|
|
||||||
FileOutputStream out = new FileOutputStream(new File(sidebarFilepath));
|
FileOutputStream out = new FileOutputStream(new File(sidebarFilepath));
|
||||||
out.write(sidebarContent.getBytes());
|
out.write(output.toString().getBytes());
|
||||||
out.close();
|
out.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static class Menu {
|
||||||
|
String parentName;
|
||||||
|
int order;
|
||||||
|
|
||||||
|
public Menu(String parentName, int order) {
|
||||||
|
this.parentName = parentName;
|
||||||
|
this.order = order;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static class FileExt {
|
||||||
|
File file;
|
||||||
|
String menu;
|
||||||
|
|
||||||
|
public File getFile() {
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMenu() {
|
||||||
|
return menu;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user