文档分组显示,代码优化

This commit is contained in:
tanghc
2019-04-19 14:39:45 +08:00
parent e1e7b2c738
commit 5bd787b7e3
25 changed files with 702 additions and 344 deletions

View File

@@ -82,12 +82,6 @@
<blockquote class="layui-elem-quote layui-text sop-description">
</blockquote>
<div class="site-title">
<fieldset class="layui-elem-field layui-field-title site-title">
<legend><a name="use">公共参数</a></legend>
</fieldset>
</div>
<div class="site-text">
<h3>请求地址</h3>
<table class="layui-table">
@@ -106,6 +100,12 @@
</table>
</div>
<div class="site-title">
<fieldset class="layui-elem-field layui-field-title site-title">
<legend><a name="use">公共参数</a></legend>
</fieldset>
</div>
<div class="site-text">
<h3>公共请求参数</h3>
<table class="layui-table">

View File

@@ -0,0 +1,11 @@
package com.gitee.sop.websiteserver.bean;
/**
* @author tanghc
*/
public class WebsiteConstants {
/**
* zookeeper存放接口路由信息的根目录
*/
public static final String SOP_SERVICE_ROUTE_PATH = "/com.gitee.sop.route";
}

View File

@@ -0,0 +1,80 @@
package com.gitee.sop.websiteserver.bean;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.math.NumberUtils;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.recipes.cache.TreeCache;
import org.apache.curator.framework.recipes.cache.TreeCacheListener;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.springframework.core.env.Environment;
import org.springframework.util.Assert;
/**
* @author tanghc
*/
@Slf4j
public class ZookeeperContext {
private static CuratorFramework client;
public static void setEnvironment(Environment environment) {
Assert.notNull(environment, "environment不能为null");
initZookeeperClient(environment);
}
public synchronized static void initZookeeperClient(Environment environment) {
if (client != null) {
return;
}
String zookeeperServerAddr = environment.getProperty("spring.cloud.zookeeper.connect-string");
if (StringUtils.isBlank(zookeeperServerAddr)) {
throw new RuntimeException("未指定spring.cloud.zookeeper.connect-string参数");
}
String baseSleepTimeMs = environment.getProperty("spring.cloud.zookeeper.baseSleepTimeMs");
String maxRetries = environment.getProperty("spring.cloud.zookeeper.maxRetries");
log.info("初始化zookeeper客户端zookeeperServerAddr:{}, baseSleepTimeMs:{}, maxRetries:{}",
zookeeperServerAddr, baseSleepTimeMs, maxRetries);
CuratorFramework client = CuratorFrameworkFactory.builder()
.connectString(zookeeperServerAddr)
.retryPolicy(new ExponentialBackoffRetry(NumberUtils.toInt(baseSleepTimeMs, 3000), NumberUtils.toInt(maxRetries, 3)))
.build();
client.start();
setClient(client);
}
public static String getRouteRootPath() {
return WebsiteConstants.SOP_SERVICE_ROUTE_PATH;
}
public static CuratorFramework getClient() {
return client;
}
public static void setClient(CuratorFramework client) {
ZookeeperContext.client = client;
}
/**
* 监听子节点,可以自定义层级
* @param parentPath 父节点路径
* @param maxDepth 层级从1开始。比如当前监听节点/t1目录最深为/t1/t2/t3/t4,则maxDepth=3,说明下面3级子目录全
* @param listener
* @throws Exception
*/
public static void listenChildren(String parentPath, int maxDepth, TreeCacheListener listener) throws Exception {
final TreeCache treeCache = TreeCache
.newBuilder(client, parentPath)
.setCacheData(true)
.setMaxDepth(maxDepth)
.build();
treeCache.getListenable().addListener(listener);
//没有开启模式作为入参的方法
treeCache.start();
}
}

View File

@@ -65,10 +65,13 @@ public class DocController {
}
@GetMapping("/doc/reload")
public void reload(String pwd) {
if (StringUtils.equals(this.pwd, pwd)) {
// 后门地址,可手动更新文档内容,一般情况下用不到
@GetMapping("/reload")
public String reload(String pwd) {
boolean correct = StringUtils.equals(this.pwd, pwd);
if (correct) {
docManager.load();
}
return String.valueOf(correct);
}
}

View File

@@ -8,12 +8,14 @@ import com.gitee.sop.websiteserver.bean.EurekaApplication;
import com.gitee.sop.websiteserver.bean.EurekaApps;
import com.gitee.sop.websiteserver.bean.EurekaInstance;
import com.gitee.sop.websiteserver.bean.EurekaUri;
import com.gitee.sop.websiteserver.bean.ZookeeperContext;
import com.gitee.sop.websiteserver.vo.ServiceInfoVO;
import lombok.extern.slf4j.Slf4j;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import org.apache.commons.lang.StringUtils;
import org.apache.curator.framework.recipes.cache.TreeCacheEvent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.http.HttpStatus;
@@ -29,6 +31,11 @@ import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.DelayQueue;
import java.util.concurrent.Delayed;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
/**
@@ -53,13 +60,19 @@ public class DocManagerImpl implements DocManager {
DocParser easyopenDocParser = new EasyopenDocParser();
private String secret = "b749a2ec000f4f29p";
ExecutorService executorService = Executors.newSingleThreadExecutor();
DelayQueue<Msg> queue = new DelayQueue<>();
private String secret = "b749a2ec000f4f29";
@Autowired
private Environment environment;
private String eurekaUrl;
private volatile boolean listenInited;
@Override
public void load() {
try {
@@ -70,7 +83,7 @@ public class DocManagerImpl implements DocManager {
ServiceInfoVO serviceInfoVo = entry.getValue().get(0);
loadDocInfo(serviceInfoVo);
}
} catch (IOException e) {
} catch (Exception e) {
log.error("加载失败", e);
}
}
@@ -136,11 +149,13 @@ public class DocManagerImpl implements DocManager {
.forEach(eurekaApplication -> {
List<EurekaInstance> instanceList = eurekaApplication.getInstance();
for (EurekaInstance instance : instanceList) {
ServiceInfoVO vo = new ServiceInfoVO();
vo.setName(eurekaApplication.getName());
vo.setIpAddr(instance.getIpAddr());
vo.setServerPort(instance.fetchPort());
serviceInfoVoList.add(vo);
if ("UP".equals(instance.getStatus())) {
ServiceInfoVO vo = new ServiceInfoVO();
vo.setName(eurekaApplication.getName());
vo.setIpAddr(instance.getIpAddr());
vo.setServerPort(instance.fetchPort());
serviceInfoVoList.add(vo);
}
}
});
@@ -162,7 +177,7 @@ public class DocManagerImpl implements DocManager {
}
@PostConstruct
protected void after() {
protected void after() throws Exception {
String eurekaUrls = environment.getProperty("eureka.client.serviceUrl.defaultZone");
if (StringUtils.isBlank(eurekaUrls)) {
throw new IllegalArgumentException("未指定eureka.client.serviceUrl.defaultZone参数");
@@ -172,5 +187,82 @@ public class DocManagerImpl implements DocManager {
url = eurekaUrls.substring(0, eurekaUrls.length() - 1);
}
this.eurekaUrl = url;
this.listenServiceId();
}
/**
* 监听serviceId更改
*
* @throws Exception
*/
protected void listenServiceId() throws Exception {
executorService.execute(new Consumer(queue, this));
ZookeeperContext.setEnvironment(environment);
String routeRootPath = ZookeeperContext.getRouteRootPath();
// 如果节点内容有变化则自动更新文档
ZookeeperContext.listenChildren(routeRootPath, 1, (client, event) -> {
if (listenInited) {
long id = System.currentTimeMillis();
// 延迟20秒执行
queue.offer(new Msg(id, 1000 * 20));
}
TreeCacheEvent.Type type = event.getType();
if (type == TreeCacheEvent.Type.INITIALIZED) {
listenInited = true;
}
});
}
static class Msg implements Delayed {
private long id;
private long delay;
// 自定义实现比较方法返回 1 0 -1三个参数
public Msg(long id, long delay) {
this.id = id;
this.delay = delay + System.currentTimeMillis();
}
@Override
public int compareTo(Delayed delayed) {
Msg msg = (Msg) delayed;
return Long.valueOf(this.id) > Long.valueOf(msg.id) ? 1
: (Long.valueOf(this.id) < Long.valueOf(msg.id) ? -1 : 0);
}
// 延迟任务是否到时就是按照这个方法判断如果返回的是负数则说明到期否则还没到期
@Override
public long getDelay(TimeUnit unit) {
return unit.convert(this.delay - System.currentTimeMillis(), TimeUnit.MILLISECONDS);
}
}
@Slf4j
static class Consumer implements Runnable {
private DelayQueue<Msg> queue;
private DocManager docManager;
public Consumer(DelayQueue<Msg> queue, DocManager docManager) {
this.queue = queue;
this.docManager = docManager;
}
@Override
public void run() {
while (true) {
try {
queue.take();
log.info("延迟队列触发--重新加载文档信息");
docManager.load();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}