Merge branch 'upstream_develop' into fix/1002

# Conflicts:
#	hippo4j-spring-boot/hippo4j-config-spring-boot-starter/src/main/java/cn/hippo4j/config/springboot/starter/refresher/NacosCloudRefresherHandler.java
#	hippo4j-spring-boot/hippo4j-config-spring-boot-starter/src/main/java/cn/hippo4j/config/springboot/starter/refresher/NacosRefresherHandler.java
pull/1010/head
李剑鑫 3 years ago
commit a1593881b2

@ -3,4 +3,4 @@ Fixes #ISSUSE_ID
Changes proposed in this pull request:
-
> Check mailbox configuration when submitting. [Contributor Guide](https://hippo4j.cn/docs/community/contributor)
> Check mailbox configuration when submitting. [Contributor Guide](https://hippo4j.cn/community/contributor-guide)

@ -4,7 +4,7 @@ sidebar_position: 1
# 接入流程
Nacos、Apollo、Zookeeper、ETCD、Polaris 配置中心任选其一。
Nacos、Apollo、Zookeeper、ETCD、Polaris、Consul 配置中心任选其一。
## hippo4j 配置
@ -59,7 +59,7 @@ spring:
secret: xxx # 加签专属
- platform: 'LARK'
token: xxx
# Nacos、Apollo、Zookeeper、ETCD、Polaris 任选其一
# Nacos、Apollo、Zookeeper、ETCD、Polaris、Consul 任选其一
nacos:
data-id: xxx
group: xxx

@ -4,34 +4,34 @@ sidebar_position: 0
# 运行模式介绍
1.1.0 版本发布后Hippo-4J 分为两种使用模式:轻量级依赖配置中心以及无中间件依赖版本。
1.1.0 版本发布后Hippo4j 分为两种使用模式:轻量级依赖配置中心以及无中间件依赖版本。
![](https://images-machen.oss-cn-beijing.aliyuncs.com/image-20220319154626314.png)
### hippo4j-config
### Hippo4j config
**轻量级动态线程池管理**,依赖 Nacos、Apollo、Zookeeper、ETCD、Polaris 等三方配置中心(任选其一)完成线程池参数动态变更,支持运行时报警、监控等功能。
**轻量级动态线程池管理**,依赖 Nacos、Apollo、Zookeeper、ETCD、Polaris、Consul 等三方配置中心(任选其一)完成线程池参数动态变更,支持运行时报警、监控等功能。
> 监控功能配置详见:[线程池监控](/docs/user_docs/getting_started/config/hippo4j-config-monitor)
![](https://images-machen.oss-cn-beijing.aliyuncs.com/20220814_hippo4j_monitor.jpg)
### hippo4j-server
### Hippo4j server
**部署 hippo4j-server 服务**,通过可视化 Web 界面完成线程池的创建、变更以及查看,不依赖三方中间件。
**部署 Hippo4j server 服务**,通过可视化 Web 界面完成线程池的创建、变更以及查看,不依赖三方中间件。
相比较 hippo4j-config功能会更强大但同时也引入了一定的复杂性。需要部署一个 Java 服务,以及依赖 MySQL 数据库。
相比较 Hippo4j config功能会更强大但同时也引入了一定的复杂性。需要部署一个 Java 服务,以及依赖 MySQL 数据库。
![](https://images-machen.oss-cn-beijing.aliyuncs.com/1644032018254-min.gif)
### 使用总结
| | hippo4j-config | hippo4j-server |
| ---- | ---------------------------------------------------- | ------------------------------------------------------------ |
| 依赖 | Nacos、Apollo、Zookeeper、ETCD、Polaris 配置中心(任选其一) | 部署 Hippo-4J Server内部无依赖中间件 |
| 使用 | 配置中心补充线程池相关参数 | Hippo-4J Server Web 控制台添加线程池记录 |
| 功能 | 包含基础功能:参数动态化、运行时监控、报警等 | 基础功能之外扩展控制台界面、线程池堆栈查看、线程池运行信息实时查看、历史运行信息查看、线程池配置集群个性化等 |
| | Hippo4j config | Hippo4j server |
| ---- |-------------------------------------------------------|--------------------------------------------------------|
| 依赖 | Nacos、Apollo、Zookeeper、ETCD、Polaris、Consul 配置中心(任选其一) | 部署 Hippo4j server内部无依赖中间件 |
| 使用 | 配置中心补充线程池相关参数 | Hippo4j server web 控制台添加线程池记录 |
| 功能 | 包含基础功能:参数动态化、运行时监控、报警等 | 基础功能之外扩展控制台界面、线程池堆栈查看、线程池运行信息实时查看、历史运行信息查看、线程池配置集群个性化等 |
使用建议:根据公司情况选择,如果基本功能可以满足使用,选择 hippo4j-config 使用即可;如果希望更多的功能,可以选择 hippo4j-server。
使用建议:根据公司情况选择,如果基本功能可以满足使用,选择 Hippo4j config 使用即可;如果希望更多的功能,可以选择 Hippo4j server。
**两者在进行替换的时候,无需修改业务代码**。

@ -4,7 +4,7 @@ sidebar_position: 1
# 接入流程
Nacos、Apollo、Zookeeper、ETCD、Polaris 配置中心任选其一。
Nacos、Apollo、Zookeeper、ETCD、Polaris、Consul 配置中心任选其一。
## hippo4j 配置
@ -59,7 +59,7 @@ spring:
secret: xxx # 加签专属
- platform: 'LARK'
token: xxx
# Nacos、Apollo、Zookeeper、ETCD、Polaris 任选其一
# Nacos、Apollo、Zookeeper、ETCD、Polaris、Consul 任选其一
nacos:
data-id: xxx
group: xxx

@ -4,34 +4,34 @@ sidebar_position: 0
# 运行模式介绍
1.1.0 版本发布后Hippo-4J 分为两种使用模式:轻量级依赖配置中心以及无中间件依赖版本。
1.1.0 版本发布后Hippo4j 分为两种使用模式:轻量级依赖配置中心以及无中间件依赖版本。
![](https://images-machen.oss-cn-beijing.aliyuncs.com/image-20220319154626314.png)
### hippo4j-config
### Hippo4j config
**轻量级动态线程池管理**,依赖 Nacos、Apollo、Zookeeper、ETCD、Polaris 等三方配置中心(任选其一)完成线程池参数动态变更,支持运行时报警、监控等功能。
**轻量级动态线程池管理**,依赖 Nacos、Apollo、Zookeeper、ETCD、Polaris、Consul 等三方配置中心(任选其一)完成线程池参数动态变更,支持运行时报警、监控等功能。
> 监控功能配置详见:[线程池监控](/docs/user_docs/getting_started/config/hippo4j-config-monitor)
![](https://images-machen.oss-cn-beijing.aliyuncs.com/20220814_hippo4j_monitor.jpg)
### hippo4j-server
### Hippo4j server
**部署 hippo4j-server 服务**,通过可视化 Web 界面完成线程池的创建、变更以及查看,不依赖三方中间件。
**部署 Hippo4j server 服务**,通过可视化 Web 界面完成线程池的创建、变更以及查看,不依赖三方中间件。
相比较 hippo4j-config功能会更强大但同时也引入了一定的复杂性。需要部署一个 Java 服务,以及依赖 MySQL 数据库。
相比较 Hippo4j config功能会更强大但同时也引入了一定的复杂性。需要部署一个 Java 服务,以及依赖 MySQL 数据库。
![](https://images-machen.oss-cn-beijing.aliyuncs.com/1644032018254-min.gif)
### 使用总结
| | hippo4j-config | hippo4j-server |
| ---- | ---------------------------------------------------- | ------------------------------------------------------------ |
| 依赖 | Nacos、Apollo、Zookeeper、ETCD、Polaris 配置中心(任选其一) | 部署 Hippo-4J Server内部无依赖中间件 |
| 使用 | 配置中心补充线程池相关参数 | Hippo-4J Server Web 控制台添加线程池记录 |
| 功能 | 包含基础功能:参数动态化、运行时监控、报警等 | 基础功能之外扩展控制台界面、线程池堆栈查看、线程池运行信息实时查看、历史运行信息查看、线程池配置集群个性化等 |
| | Hippo4j config | Hippo4j server |
| ---- |-------------------------------------------------------|--------------------------------------------------------|
| 依赖 | Nacos、Apollo、Zookeeper、ETCD、Polaris、Consul 配置中心(任选其一) | 部署 Hippo4j server内部无依赖中间件 |
| 使用 | 配置中心补充线程池相关参数 | Hippo4j server web 控制台添加线程池记录 |
| 功能 | 包含基础功能:参数动态化、运行时监控、报警等 | 基础功能之外扩展控制台界面、线程池堆栈查看、线程池运行信息实时查看、历史运行信息查看、线程池配置集群个性化等 |
使用建议:根据公司情况选择,如果基本功能可以满足使用,选择 hippo4j-config 使用即可;如果希望更多的功能,可以选择 hippo4j-server。
使用建议:根据公司情况选择,如果基本功能可以满足使用,选择 Hippo4j config 使用即可;如果希望更多的功能,可以选择 Hippo4j server。
**两者在进行替换的时候,无需修改业务代码**。

@ -72,6 +72,13 @@ sidebar_position: 1
<td align="center" ><a href="https://blog.xiajibagao.top">Createsequence's Blog</a></td>
<td align="center" >841396397@qq.com</td>
</tr>
<tr>
<td align="center"><a href="https://github.com/road2master"><img src="https://avatars.githubusercontent.com/u/53806703?v=4" width="64px;"/></ a></td>
<td align="center">黎金星</td>
<td align="center"><a href="https://github.com/road2master">road2master</a></td>
<td align="center"><a href="https://www.cnblogs.com/road2master/">road2master's Blog</a></td>
<td align="center">lijinxingerm@gmail.com</td>
</tr>
</table>
## 贡献者

@ -5,7 +5,7 @@ title: 采用公司
## 谁在使用 Hippo4j
共计 23+ 家公司生产接入 Hippo4j。按照公司登记时间排序。
共计 25+ 家公司生产接入 Hippo4j。按照公司登记时间排序。
- [身边云](https://serviceshare.com)
- [思派健康科技](https://www.medbanks.cn)
@ -30,6 +30,8 @@ title: 采用公司
- [三立人(深圳)科技有限公司-焦内](https://www.bananain.com/)
- [上海天猫好房添玑网络服务有限公司](http://www.eju.com/)
- [郑州力通水务](http://www.zzltsw.com/)
- [北京自如信息科技有限公司](https://www.ziroom.com/)
- [易车](https://www.yiche.com/)
## 登记

@ -79,6 +79,13 @@ sidebar_position: 1
<td align="center" >-</td>
<td align="center" >sanliangitch@foxmail.com</td>
</tr>
<tr>
<td align="center"><a href="https://github.com/road2master"><img src="https://avatars.githubusercontent.com/u/53806703?v=4" width="64px;"/></ a></td>
<td align="center">黎金星</td>
<td align="center"><a href="https://github.com/road2master">road2master</a></td>
<td align="center"><a href="https://www.cnblogs.com/road2master/">road2master's Blog</a></td>
<td align="center">lijinxingerm@gmail.com</td>
</tr>
</table>
## 贡献者

@ -5,7 +5,7 @@ title: 采用公司
## 谁在使用 Hippo4j
共计 23+ 家公司生产接入 Hippo4j。按照公司登记时间排序。
共计 25+ 家公司生产接入 Hippo4j。按照公司登记时间排序。
- [身边云](https://serviceshare.com)
- [思派健康科技](https://www.medbanks.cn)
@ -30,6 +30,8 @@ title: 采用公司
- [三立人(深圳)科技有限公司-焦内](https://www.bananain.com/)
- [上海天猫好房添玑网络服务有限公司](http://www.eju.com/)
- [郑州力通水务](http://www.zzltsw.com/)
- [北京自如信息科技有限公司](https://www.ziroom.com/)
- [易车](https://www.yiche.com/)
## 登记

@ -0,0 +1,102 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.hippo4j.common.web.base;
import cn.hippo4j.common.toolkit.Assert;
import cn.hippo4j.common.web.exception.AbstractException;
import cn.hippo4j.common.web.exception.ErrorCode;
import org.junit.jupiter.api.Test;
import static cn.hippo4j.common.web.exception.ErrorCodeEnum.SERVICE_ERROR;
public class ResultsTest {
@Test
public void success() {
Assert.isTrue(Result.SUCCESS_CODE.equals(Results.success().getCode()));
}
@Test
public void testSuccess() {
Object o = new Object();
Assert.isTrue(o.equals(Results.success(o).getData()));
Assert.isTrue(Result.SUCCESS_CODE.equals(Results.success().getCode()));
}
@Test
public void failure() {
Assert.isTrue(SERVICE_ERROR.getCode().equals(Results.failure().getCode()));
Assert.isTrue(SERVICE_ERROR.getMessage().equals(Results.failure().getMessage()));
}
@Test
public void testFailure() {
String code = "500";
String msg = "message";
AbstractException abstractException = new AbstractException(msg, new Throwable(), new ErrorCode() {
@Override
public String getCode() {
return code;
}
@Override
public String getMessage() {
return "errorMsg";
}
});
Assert.isTrue(code.equals(Results.failure(abstractException).getCode()));
Assert.isTrue(msg.equals(Results.failure(abstractException).getMessage()));
}
@Test
public void testFailure1() {
String msg = "throwableMsg";
Throwable throwable = new Throwable(msg);
Assert.isTrue(SERVICE_ERROR.getCode().equals(Results.failure(throwable).getCode()));
Assert.isTrue(msg.equals(Results.failure(throwable).getMessage()));
}
@Test
public void testFailure2() {
String code = "500";
String msg = "message";
ErrorCode errorCode = new ErrorCode() {
@Override
public String getCode() {
return code;
}
@Override
public String getMessage() {
return msg;
}
};
Assert.isTrue(code.equals(Results.failure(errorCode).getCode()));
Assert.isTrue(msg.equals(Results.failure(errorCode).getMessage()));
}
@Test
public void testFailure3() {
String code = "500";
String msg = "message";
Assert.isTrue(code.equals(Results.failure(code, msg).getCode()));
Assert.isTrue(msg.equals(Results.failure(code, msg).getMessage()));
}
}

@ -0,0 +1,45 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>cn.hippo4j</groupId>
<artifactId>hippo4j-example</artifactId>
<version>${revision}</version>
</parent>
<artifactId>hippo4j-config-consul-spring-boot-starter-example</artifactId>
<properties>
<maven.deploy.skip>true</maven.deploy.skip>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>cn.hippo4j</groupId>
<artifactId>hippo4j-example-core</artifactId>
<version>${revision}</version>
</dependency>
<dependency>
<groupId>cn.hippo4j</groupId>
<artifactId>hippo4j-config-spring-boot-starter</artifactId>
<version>${revision}</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-config</artifactId>
<version>${consul.version}</version>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
</dependencies>
</project>

@ -15,37 +15,17 @@
* limitations under the License.
*/
package cn.hippo4j.common.api;
package cn.hippo4j.example.config.consul;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import cn.hippo4j.core.enable.EnableDynamicThreadPool;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* when init thread-pool dynamic refresh.
*/
public interface ThreadPoolInitRefresh extends ApplicationRunner {
/**
* Initializes the thread pool after system startup
*
* @param context new properties
*/
void initRefresh(String context);
/**
* get from the Configuration center
*
* @return new properties
* @throws Exception exception
*/
String getProperties() throws Exception;
@EnableDynamicThreadPool
@SpringBootApplication(scanBasePackages = "cn.hippo4j.example")
public class ConfigConsulExampleApplication {
@Override
default void run(ApplicationArguments args) throws Exception {
String properties = getProperties();
if (properties == null) {
return;
}
initRefresh(properties);
public static void main(String[] args) {
SpringApplication.run(ConfigConsulExampleApplication.class, args);
}
}

@ -0,0 +1,18 @@
server:
port: 8091
spring:
application:
name: hippo4j-config-consul-spring-boot-starter-example
profiles:
active: dev
cloud:
consul:
host: 127.0.0.1
port: 8500
config:
enabled: true
format: yaml
data-key: hippo4j-consul
default-context: application
prefix: config

@ -21,6 +21,7 @@
<module>hippo4j-config-nacos-spring-boot-starter-example</module>
<module>hippo4j-config-apollo-spring-boot-starter-example</module>
<module>hippo4j-config-zookeeper-spring-boot-starter-example</module>
<module>hippo4j-config-consul-spring-boot-starter-example</module>
<module>hippo4j-spring-boot-starter-adapter-rabbitmq-example</module>
<module>hippo4j-spring-boot-starter-adapter-spring-cloud-stream-rabbitmq-example</module>
<module>hippo4j-spring-boot-starter-adapter-spring-cloud-stream-rocketmq-example</module>

@ -17,5 +17,59 @@
package cn.hippo4j.auth.toolkit;
import cn.hippo4j.common.toolkit.Assert;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
public final class JwtTokenUtilTest {
private Long userId = 1L;
private String username = "baymax";
private String role = "";
private boolean isRememberMe = true;
private String token;
@BeforeEach
public void setUp() {
token = JwtTokenUtil.createToken(userId, username, role, isRememberMe);
}
@Test
public void createToken() {
String name = JwtTokenUtil.getUsername(token);
Assert.isTrue(username.equals(name));
Integer userId = JwtTokenUtil.getUserId(token);
String userRole = JwtTokenUtil.getUserRole(token);
Assert.isTrue(username.equals(name));
Assert.isTrue(this.userId.intValue() == userId);
Assert.isTrue(role.equals(userRole));
}
@Test
public void getUsername() {
String name = JwtTokenUtil.getUsername(token);
Assert.isTrue(username.equals(name));
}
@Test
public void getUserId() {
Integer id = JwtTokenUtil.getUserId(token);
Assert.isTrue(userId.intValue() == id);
}
@Test
public void getUserRole() {
String userRole = JwtTokenUtil.getUserRole(token);
Assert.isTrue(role.equals(userRole));
}
@Test
public void isExpiration() {
boolean isExpiration = JwtTokenUtil.isExpiration(token);
Assert.isTrue(!isExpiration);
}
}

File diff suppressed because one or more lines are too long

@ -1 +1 @@
.social-signup-container[data-v-7309fbbb]{margin:20px 0}.social-signup-container .sign-btn[data-v-7309fbbb]{display:inline-block;cursor:pointer}.social-signup-container .icon[data-v-7309fbbb]{color:#fff;font-size:24px;margin-top:8px}.social-signup-container .qq-svg-container[data-v-7309fbbb],.social-signup-container .wx-svg-container[data-v-7309fbbb]{display:inline-block;width:40px;height:40px;line-height:40px;text-align:center;padding-top:1px;border-radius:4px;margin-bottom:20px;margin-right:5px}.social-signup-container .wx-svg-container[data-v-7309fbbb]{background-color:#24da70}.social-signup-container .qq-svg-container[data-v-7309fbbb]{background-color:#6ba2d6;margin-left:50px}@supports(-webkit-mask:none) and (not (cater-color:#fff)){.login-container .el-input input{color:#fff}}.login-container .el-input{display:inline-block;height:47px;width:85%}.login-container .el-input input{background:transparent;border:0;-webkit-appearance:none;border-radius:0;padding:12px 5px 12px 15px;color:#fff;height:47px;caret-color:#fff}.login-container .el-input input:-webkit-autofill{-webkit-box-shadow:0 0 0 1000px #283443 inset!important;box-shadow:inset 0 0 0 1000px #283443!important;-webkit-text-fill-color:#fff!important}.login-container .el-form-item{border:1px solid hsla(0,0%,100%,.1);background:rgba(0,0,0,.1);border-radius:5px;color:#454545}.login-container[data-v-13dcd441]{min-height:100%;width:100%;background-color:#2d3a4b;overflow:hidden}.login-container .login-form[data-v-13dcd441]{position:relative;width:520px;max-width:100%;padding:160px 35px 0;margin:0 auto;overflow:hidden}.login-container .tips[data-v-13dcd441]{font-size:14px;color:#fff;margin-bottom:10px}.login-container .tips span[data-v-13dcd441]:first-of-type{margin-right:16px}.login-container .svg-container[data-v-13dcd441]{padding:6px 5px 6px 15px;color:#889aa4;vertical-align:middle;width:30px;display:inline-block}.login-container .title-container[data-v-13dcd441]{position:relative}.login-container .title-container .title[data-v-13dcd441]{font-size:26px;color:#eee;margin:0 auto 40px auto;text-align:center;font-weight:700}.login-container .show-pwd[data-v-13dcd441]{position:absolute;right:10px;top:7px;font-size:16px;color:#889aa4;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.login-container .thirdparty-button[data-v-13dcd441]{position:absolute;right:0;bottom:6px}@media only screen and (max-width:470px){.login-container .thirdparty-button[data-v-13dcd441]{display:none}}
.social-signup-container[data-v-7309fbbb]{margin:20px 0}.social-signup-container .sign-btn[data-v-7309fbbb]{display:inline-block;cursor:pointer}.social-signup-container .icon[data-v-7309fbbb]{color:#fff;font-size:24px;margin-top:8px}.social-signup-container .qq-svg-container[data-v-7309fbbb],.social-signup-container .wx-svg-container[data-v-7309fbbb]{display:inline-block;width:40px;height:40px;line-height:40px;text-align:center;padding-top:1px;border-radius:4px;margin-bottom:20px;margin-right:5px}.social-signup-container .wx-svg-container[data-v-7309fbbb]{background-color:#24da70}.social-signup-container .qq-svg-container[data-v-7309fbbb]{background-color:#6ba2d6;margin-left:50px}@supports(-webkit-mask:none) and (not (cater-color:#fff)){.login-container .el-input input{color:#fff}}.login-container .el-input{display:inline-block;height:47px;width:85%}.login-container .el-input input{background:transparent;border:0;-webkit-appearance:none;border-radius:0;padding:12px 5px 12px 15px;color:#fff;height:47px;caret-color:#fff}.login-container .el-input input:-webkit-autofill{-webkit-box-shadow:0 0 0 1000px #283443 inset!important;box-shadow:inset 0 0 0 1000px #283443!important;-webkit-text-fill-color:#fff!important}.login-container .el-form-item{border:1px solid hsla(0,0%,100%,.1);background:rgba(0,0,0,.1);border-radius:5px;color:#454545}.login-container[data-v-7cb824ba]{min-height:100%;width:100%;background-color:#2d3a4b;overflow:hidden}.login-container .login-form[data-v-7cb824ba]{position:relative;width:520px;max-width:100%;padding:160px 35px 0;margin:0 auto;overflow:hidden}.login-container .tips[data-v-7cb824ba]{font-size:14px;color:#fff;margin-bottom:10px}.login-container .tips span[data-v-7cb824ba]:first-of-type{margin-right:16px}.login-container .svg-container[data-v-7cb824ba]{padding:6px 5px 6px 15px;color:#889aa4;vertical-align:middle;width:30px;display:inline-block}.login-container .title-container[data-v-7cb824ba]{position:relative}.login-container .title-container .title[data-v-7cb824ba]{font-size:26px;color:#eee;margin:0 auto 40px auto;text-align:center;font-weight:700}.login-container .show-pwd[data-v-7cb824ba]{position:absolute;right:10px;top:7px;font-size:16px;color:#889aa4;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.login-container .thirdparty-button[data-v-7cb824ba]{position:absolute;right:0;bottom:6px}@media only screen and (max-width:470px){.login-container .thirdparty-button[data-v-7cb824ba]{display:none}}

@ -1 +0,0 @@
.github-corner:hover .octo-arm[data-v-fedac698]{-webkit-animation:octocat-wave-data-v-fedac698 .56s ease-in-out;animation:octocat-wave-data-v-fedac698 .56s ease-in-out}@-webkit-keyframes octocat-wave-data-v-fedac698{0%,to{-webkit-transform:rotate(0);transform:rotate(0)}20%,60%{-webkit-transform:rotate(-25deg);transform:rotate(-25deg)}40%,80%{-webkit-transform:rotate(10deg);transform:rotate(10deg)}}@keyframes octocat-wave-data-v-fedac698{0%,to{-webkit-transform:rotate(0);transform:rotate(0)}20%,60%{-webkit-transform:rotate(-25deg);transform:rotate(-25deg)}40%,80%{-webkit-transform:rotate(10deg);transform:rotate(10deg)}}@media (max-width:500px){.github-corner:hover .octo-arm[data-v-fedac698]{-webkit-animation:none;animation:none}.github-corner .octo-arm[data-v-fedac698]{-webkit-animation:octocat-wave-data-v-fedac698 .56s ease-in-out;animation:octocat-wave-data-v-fedac698 .56s ease-in-out}}.panel-group[data-v-787f9ab2]{margin-top:18px}.panel-group .card-panel-col[data-v-787f9ab2]{margin-bottom:32px}.panel-group .card-panel[data-v-787f9ab2]{height:108px;cursor:pointer;font-size:12px;position:relative;overflow:hidden;color:#666;background:#fff;-webkit-box-shadow:4px 4px 40px rgba(0,0,0,.05);box-shadow:4px 4px 40px rgba(0,0,0,.05);border-color:rgba(0,0,0,.05)}.panel-group .card-panel:hover .card-panel-icon-wrapper[data-v-787f9ab2]{color:#fff}.panel-group .card-panel:hover .icon-people[data-v-787f9ab2]{background:#dae8d6}.panel-group .card-panel:hover .icon-message[data-v-787f9ab2]{background:#36a3f7}.panel-group .card-panel:hover .icon-money[data-v-787f9ab2]{background:#a0a6f4}.panel-group .card-panel:hover .icon-shopping[data-v-787f9ab2]{background:#dae8d6}.panel-group .card-panel .icon-people[data-v-787f9ab2]{color:#40c9c6}.panel-group .card-panel .icon-message[data-v-787f9ab2]{color:#36a3f7}.panel-group .card-panel .icon-money[data-v-787f9ab2]{color:#a0a6f4}.panel-group .card-panel .icon-shopping[data-v-787f9ab2]{color:#34bfa3}.panel-group .card-panel .card-panel-icon-wrapper[data-v-787f9ab2]{float:left;margin:14px 0 0 14px;padding:16px;-webkit-transition:all .38s ease-out;transition:all .38s ease-out;border-radius:6px}.panel-group .card-panel .card-panel-icon[data-v-787f9ab2]{float:left;font-size:48px}.panel-group .card-panel .card-panel-description[data-v-787f9ab2]{float:right;font-weight:700;margin:26px;margin-left:0}.panel-group .card-panel .card-panel-description .card-panel-text[data-v-787f9ab2]{line-height:18px;color:rgba(0,0,0,.45);font-size:16px;margin-bottom:12px}.panel-group .card-panel .card-panel-description .card-panel-num[data-v-787f9ab2]{font-size:20px}@media(max-width:550px){.card-panel-description[data-v-787f9ab2]{display:none}.card-panel-icon-wrapper[data-v-787f9ab2]{float:none!important;width:100%;height:100%;margin:0!important}.card-panel-icon-wrapper .svg-icon[data-v-787f9ab2]{display:block;margin:14px auto!important;float:none!important}}.dashboard-editor-container[data-v-73ee0239]{padding:32px;background-color:#f0f2f5;position:relative}.dashboard-editor-container .github-corner[data-v-73ee0239]{position:absolute;top:0;border:0;right:0}.dashboard-editor-container .el-form-item[data-v-73ee0239]{margin-bottom:5px!important;padding-bottom:20px}.dashboard-editor-container .chart-wrapper[data-v-73ee0239]{background:#fff;padding:16px 16px 0;margin-bottom:32px}@media(max-width:1024px){.chart-wrapper[data-v-73ee0239]{padding:8px}}

@ -0,0 +1 @@
.github-corner:hover .octo-arm[data-v-fedac698]{-webkit-animation:octocat-wave-data-v-fedac698 .56s ease-in-out;animation:octocat-wave-data-v-fedac698 .56s ease-in-out}@-webkit-keyframes octocat-wave-data-v-fedac698{0%,to{-webkit-transform:rotate(0);transform:rotate(0)}20%,60%{-webkit-transform:rotate(-25deg);transform:rotate(-25deg)}40%,80%{-webkit-transform:rotate(10deg);transform:rotate(10deg)}}@keyframes octocat-wave-data-v-fedac698{0%,to{-webkit-transform:rotate(0);transform:rotate(0)}20%,60%{-webkit-transform:rotate(-25deg);transform:rotate(-25deg)}40%,80%{-webkit-transform:rotate(10deg);transform:rotate(10deg)}}@media (max-width:500px){.github-corner:hover .octo-arm[data-v-fedac698]{-webkit-animation:none;animation:none}.github-corner .octo-arm[data-v-fedac698]{-webkit-animation:octocat-wave-data-v-fedac698 .56s ease-in-out;animation:octocat-wave-data-v-fedac698 .56s ease-in-out}}.panel-group[data-v-78d00531]{margin-top:18px}.panel-group .card-panel-col[data-v-78d00531]{margin-bottom:32px}.panel-group .card-panel[data-v-78d00531]{height:108px;cursor:pointer;font-size:12px;position:relative;overflow:hidden;color:#666;background:#fff;-webkit-box-shadow:4px 4px 40px rgba(0,0,0,.05);box-shadow:4px 4px 40px rgba(0,0,0,.05);border-color:rgba(0,0,0,.05)}.panel-group .card-panel:hover .card-panel-icon-wrapper[data-v-78d00531]{color:#fff}.panel-group .card-panel:hover .icon-people[data-v-78d00531]{background:#dae8d6}.panel-group .card-panel:hover .icon-message[data-v-78d00531]{background:#36a3f7}.panel-group .card-panel:hover .icon-money[data-v-78d00531]{background:#a0a6f4}.panel-group .card-panel:hover .icon-shopping[data-v-78d00531]{background:#dae8d6}.panel-group .card-panel .icon-people[data-v-78d00531]{color:#40c9c6}.panel-group .card-panel .icon-message[data-v-78d00531]{color:#36a3f7}.panel-group .card-panel .icon-money[data-v-78d00531]{color:#a0a6f4}.panel-group .card-panel .icon-shopping[data-v-78d00531]{color:#34bfa3}.panel-group .card-panel .card-panel-icon-wrapper[data-v-78d00531]{float:left;margin:14px 0 0 14px;padding:16px;-webkit-transition:all .38s ease-out;transition:all .38s ease-out;border-radius:6px}.panel-group .card-panel .card-panel-icon[data-v-78d00531]{float:left;font-size:48px}.panel-group .card-panel .card-panel-description[data-v-78d00531]{float:right;font-weight:700;margin:26px;margin-left:0}.panel-group .card-panel .card-panel-description .card-panel-text[data-v-78d00531]{line-height:18px;color:rgba(0,0,0,.45);font-size:16px;margin-bottom:12px}.panel-group .card-panel .card-panel-description .card-panel-num[data-v-78d00531]{font-size:20px}@media(max-width:550px){.card-panel-description[data-v-78d00531]{display:none}.card-panel-icon-wrapper[data-v-78d00531]{float:none!important;width:100%;height:100%;margin:0!important}.card-panel-icon-wrapper .svg-icon[data-v-78d00531]{display:block;margin:14px auto!important;float:none!important}}.dashboard-editor-container[data-v-6e862226]{padding:32px;background-color:#f0f2f5;position:relative}.dashboard-editor-container .github-corner[data-v-6e862226]{position:absolute;top:0;border:0;right:0}.dashboard-editor-container .el-form-item[data-v-6e862226]{margin-bottom:5px!important;padding-bottom:20px}.dashboard-editor-container .chart-wrapper[data-v-6e862226]{background:#fff;padding:16px 16px 0;margin-bottom:32px}@media(max-width:1024px){.chart-wrapper[data-v-6e862226]{padding:8px}}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -1 +0,0 @@
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-04a4268a"],{"386d":function(n,t,e){"use strict";var r=e("cb7c"),a=e("83a1"),i=e("5f1b");e("214f")("search",1,(function(n,t,e,o){return[function(e){var r=n(this),a=void 0==e?void 0:e[t];return void 0!==a?a.call(e,r):new RegExp(e)[t](String(r))},function(n){var t=o(e,n,this);if(t.done)return t.value;var c=r(n),u=String(this),d=c.lastIndex;a(d,0)||(c.lastIndex=0);var l=i(c,u);return a(c.lastIndex,d)||(c.lastIndex=d),null===l?-1:l.index}]}))},"83a1":function(n,t){n.exports=Object.is||function(n,t){return n===t?0!==n||1/n===1/t:n!=n&&t!=t}},b829:function(n,t,e){"use strict";e.r(t);e("386d");var r,a,i={name:"AuthRedirect",created:function(){var n=window.location.search.slice(1);window.localStorage&&(window.localStorage.setItem("x-admin-oauth-code",n),window.close())},render:function(n){return n()}},o=i,c=e("2877"),u=Object(c["a"])(o,r,a,!1,null,null,null);t["default"]=u.exports}}]);

@ -1 +0,0 @@
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-2d230a36"],{ecac:function(e,t,a){"use strict";a.r(t);var s=function(){var e=this,t=e.$createElement,a=e._self._c||t;return a("div",{staticClass:"app-container"},[e.user?a("div",[a("el-row",{attrs:{gutter:20}},[a("el-col",{attrs:{span:6,xs:24}},[a("user-card",{attrs:{user:e.user}})],1),e._v(" "),a("el-col",{attrs:{span:18,xs:24}},[a("el-card",[a("el-tabs",{model:{value:e.activeTab,callback:function(t){e.activeTab=t},expression:"activeTab"}},[a("el-tab-pane",{attrs:{label:"Account",name:"account"}},[a("account",{attrs:{user:e.user}})],1)],1)],1)],1)],1)],1):e._e()])},n=[],r=(a("7f7f"),a("db72")),l=a("2f62"),c=function(){var e=this,t=e.$createElement,a=e._self._c||t;return a("el-form",[a("el-form-item",{attrs:{label:"Name"}},[a("el-input",{model:{value:e.user.name,callback:function(t){e.$set(e.user,"name","string"===typeof t?t.trim():t)},expression:"user.name"}})],1),e._v(" "),a("el-form-item",{attrs:{label:"Email"}},[a("el-input",{model:{value:e.user.email,callback:function(t){e.$set(e.user,"email","string"===typeof t?t.trim():t)},expression:"user.email"}})],1),e._v(" "),a("el-form-item",[a("el-button",{attrs:{type:"primary"},on:{click:e.submit}},[e._v("Update")])],1)],1)},i=[],u={props:{user:{type:Object,default:function(){return{name:"",email:""}}}},methods:{submit:function(){this.$message({message:"User information has been updated successfully",type:"success",duration:5e3})}}},o=u,m=a("2877"),p=Object(m["a"])(o,c,i,!1,null,null,null),f=p.exports,b={name:"Profile",components:{Account:f},data:function(){return{user:{},activeTab:"activity"}},computed:Object(r["a"])({},Object(l["b"])(["name","avatar","roles"])),created:function(){this.getUser()},methods:{getUser:function(){this.user={name:this.name,role:this.roles.join(" | "),email:"admin@test.com",avatar:this.avatar}}}},d=b,v=Object(m["a"])(d,s,n,!1,null,null,null);t["default"]=v.exports}}]);

@ -0,0 +1 @@
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-2d230a36"],{ecac:function(e,t,a){"use strict";a.r(t);var s=function(){var e=this,t=e.$createElement,a=e._self._c||t;return a("div",{staticClass:"app-container"},[e.user?a("div",[a("el-row",{attrs:{gutter:20}},[a("el-col",{attrs:{span:6,xs:24}},[a("user-card",{attrs:{user:e.user}})],1),e._v(" "),a("el-col",{attrs:{span:18,xs:24}},[a("el-card",[a("el-tabs",{model:{value:e.activeTab,callback:function(t){e.activeTab=t},expression:"activeTab"}},[a("el-tab-pane",{attrs:{label:"Account",name:"account"}},[a("account",{attrs:{user:e.user}})],1)],1)],1)],1)],1)],1):e._e()])},n=[],r=a("5530"),l=(a("b0c0"),a("a15b"),a("2f62")),c=function(){var e=this,t=e.$createElement,a=e._self._c||t;return a("el-form",[a("el-form-item",{attrs:{label:"Name"}},[a("el-input",{model:{value:e.user.name,callback:function(t){e.$set(e.user,"name","string"===typeof t?t.trim():t)},expression:"user.name"}})],1),e._v(" "),a("el-form-item",{attrs:{label:"Email"}},[a("el-input",{model:{value:e.user.email,callback:function(t){e.$set(e.user,"email","string"===typeof t?t.trim():t)},expression:"user.email"}})],1),e._v(" "),a("el-form-item",[a("el-button",{attrs:{type:"primary"},on:{click:e.submit}},[e._v("Update")])],1)],1)},i=[],u={props:{user:{type:Object,default:function(){return{name:"",email:""}}}},methods:{submit:function(){this.$message({message:"User information has been updated successfully",type:"success",duration:5e3})}}},o=u,m=a("2877"),p=Object(m["a"])(o,c,i,!1,null,null,null),b=p.exports,f={name:"Profile",components:{Account:b},data:function(){return{user:{},activeTab:"activity"}},computed:Object(r["a"])({},Object(l["b"])(["name","avatar","roles"])),created:function(){this.getUser()},methods:{getUser:function(){this.user={name:this.name,role:this.roles.join(" | "),email:"admin@test.com",avatar:this.avatar}}}},d=f,v=Object(m["a"])(d,s,n,!1,null,null,null);t["default"]=v.exports}}]);

@ -1 +0,0 @@
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-2d230fe7"],{ef3c:function(e,r,n){"use strict";n.r(r);n("a481");var t,u,a={created:function(){var e=this.$route,r=e.params,n=e.query,t=r.path;this.$router.replace({path:"/"+t,query:n})},render:function(e){return e()}},c=a,o=n("2877"),p=Object(o["a"])(c,t,u,!1,null,null,null);r["default"]=p.exports}}]);

@ -0,0 +1 @@
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-2d230fe7"],{ef3c:function(e,r,n){"use strict";n.r(r);n("ac1f"),n("5319");var t,u,a={created:function(){var e=this.$route,r=e.params,n=e.query,t=r.path;this.$router.replace({path:"/"+t,query:n})},render:function(e){return e()}},c=a,o=n("2877"),p=Object(o["a"])(c,t,u,!1,null,null,null);r["default"]=p.exports}}]);

@ -0,0 +1 @@
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-9472305a"],{"129f":function(n,e){n.exports=Object.is||function(n,e){return n===e?0!==n||1/n===1/e:n!=n&&e!=e}},"841c":function(n,e,t){"use strict";var a=t("c65b"),c=t("d784"),r=t("825a"),o=t("7234"),i=t("1d80"),u=t("129f"),d=t("577e"),l=t("dc4a"),s=t("14c3");c("search",(function(n,e,t){return[function(e){var t=i(this),c=o(e)?void 0:l(e,n);return c?a(c,e,t):new RegExp(e)[n](d(t))},function(n){var a=r(this),c=d(n),o=t(e,a,c);if(o.done)return o.value;var i=a.lastIndex;u(i,0)||(a.lastIndex=0);var l=s(a,c);return u(a.lastIndex,i)||(a.lastIndex=i),null===l?-1:l.index}]}))},b829:function(n,e,t){"use strict";t.r(e);t("fb6a"),t("ac1f"),t("841c");var a,c,r={name:"AuthRedirect",created:function(){var n=window.location.search.slice(1);window.localStorage&&(window.localStorage.setItem("x-admin-oauth-code",n),window.close())},render:function(n){return n()}},o=r,i=t("2877"),u=Object(i["a"])(o,a,c,!1,null,null,null);e["default"]=u.exports}}]);

@ -1 +1 @@
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-ef888edc"],{"24e2":function(t,a,i){"use strict";i.r(a);var e=function(){var t=this,a=t.$createElement,i=t._self._c||a;return i("div",{staticClass:"errPage-container"},[i("el-button",{staticClass:"pan-back-btn",attrs:{icon:"arrow-left"},on:{click:t.back}},[t._v("\n 返回\n ")]),t._v(" "),i("el-row",[i("el-col",{attrs:{span:12}},[i("h1",{staticClass:"text-jumbo text-ginormous"},[t._v("\n Oops!\n ")]),t._v("\n gif来源"),i("a",{attrs:{href:"https://zh.airbnb.com/",target:"_blank"}},[t._v("airbnb")]),t._v(" 页面\n "),i("h2",[t._v("你没有权限去该页面")]),t._v(" "),i("h6",[t._v("如有不满请联系你领导")]),t._v(" "),i("ul",{staticClass:"list-unstyled"},[i("li",[t._v("或者你可以去:")]),t._v(" "),i("li",{staticClass:"link-type"},[i("router-link",{attrs:{to:"/dashboard"}},[t._v("\n 回首页\n ")])],1),t._v(" "),i("li",{staticClass:"link-type"},[i("a",{attrs:{href:"https://www.taobao.com/"}},[t._v("随便看看")])]),t._v(" "),i("li",[i("a",{attrs:{href:"#"},on:{click:function(a){a.preventDefault(),t.dialogVisible=!0}}},[t._v("点我看图")])])])]),t._v(" "),i("el-col",{attrs:{span:12}},[i("img",{attrs:{src:t.errGif,width:"313",height:"428",alt:"Girl has dropped her ice cream."}})])],1),t._v(" "),i("el-dialog",{attrs:{visible:t.dialogVisible,title:"随便看"},on:{"update:visible":function(a){t.dialogVisible=a}}},[i("img",{staticClass:"pan-img",attrs:{src:t.ewizardClap}})])],1)},s=[],n=i("cc6c"),r=i.n(n),l={name:"Page401",data:function(){return{errGif:r.a+"?"+ +new Date,ewizardClap:"https://wpimg.wallstcn.com/007ef517-bafd-4066-aae4-6883632d9646",dialogVisible:!1}},methods:{back:function(){this.$route.query.noGoBack?this.$router.push({path:"/dashboard"}):this.$router.go(-1)}}},c=l,o=(i("6f5a"),i("2877")),u=Object(o["a"])(c,e,s,!1,null,"6fb1594e",null);a["default"]=u.exports},"6f5a":function(t,a,i){"use strict";i("a68a")},a68a:function(t,a,i){},cc6c:function(t,a,i){t.exports=i.p+"static/img/401.089007e7.gif"}}]);
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-ef888edc"],{"24e2":function(t,a,i){"use strict";i.r(a);var e=function(){var t=this,a=t.$createElement,i=t._self._c||a;return i("div",{staticClass:"errPage-container"},[i("el-button",{staticClass:"pan-back-btn",attrs:{icon:"arrow-left"},on:{click:t.back}},[t._v("\n 返回\n ")]),t._v(" "),i("el-row",[i("el-col",{attrs:{span:12}},[i("h1",{staticClass:"text-jumbo text-ginormous"},[t._v("\n Oops!\n ")]),t._v("\n gif来源"),i("a",{attrs:{href:"https://zh.airbnb.com/",target:"_blank"}},[t._v("airbnb")]),t._v(" 页面\n "),i("h2",[t._v("你没有权限去该页面")]),t._v(" "),i("h6",[t._v("如有不满请联系你领导")]),t._v(" "),i("ul",{staticClass:"list-unstyled"},[i("li",[t._v("或者你可以去:")]),t._v(" "),i("li",{staticClass:"link-type"},[i("router-link",{attrs:{to:"/dashboard"}},[t._v("\n 回首页\n ")])],1),t._v(" "),i("li",{staticClass:"link-type"},[i("a",{attrs:{href:"https://www.taobao.com/"}},[t._v("随便看看")])]),t._v(" "),i("li",[i("a",{attrs:{href:"#"},on:{click:function(a){a.preventDefault(),t.dialogVisible=!0}}},[t._v("点我看图")])])])]),t._v(" "),i("el-col",{attrs:{span:12}},[i("img",{attrs:{src:t.errGif,width:"313",height:"428",alt:"Girl has dropped her ice cream."}})])],1),t._v(" "),i("el-dialog",{attrs:{visible:t.dialogVisible,title:"随便看"},on:{"update:visible":function(a){t.dialogVisible=a}}},[i("img",{staticClass:"pan-img",attrs:{src:t.ewizardClap}})])],1)},s=[],n=(i("14d9"),i("cc6c")),r=i.n(n),l={name:"Page401",data:function(){return{errGif:r.a+"?"+ +new Date,ewizardClap:"https://wpimg.wallstcn.com/007ef517-bafd-4066-aae4-6883632d9646",dialogVisible:!1}},methods:{back:function(){this.$route.query.noGoBack?this.$router.push({path:"/dashboard"}):this.$router.go(-1)}}},c=l,o=(i("6f5a"),i("2877")),u=Object(o["a"])(c,e,s,!1,null,"6fb1594e",null);a["default"]=u.exports},"6f5a":function(t,a,i){"use strict";i("a68a")},a68a:function(t,a,i){},cc6c:function(t,a,i){t.exports=i.p+"static/img/401.089007e7.gif"}}]);

@ -47,6 +47,13 @@
<version>${apollo.version}</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-config</artifactId>
<version>${consul.version}</version>
<scope>compile</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>

@ -30,6 +30,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.cloud.consul.config.ConsulConfigProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@ -47,6 +48,8 @@ public class ConfigHandlerConfiguration {
private static final String APOLLO_NAMESPACE_KEY = "apollo.namespace";
private static final String CONSUL_DATA_KEY = "consul.data-key";
private static final String ZOOKEEPER_CONNECT_STR_KEY = "zookeeper.zk-connect-str";
private static final String ETCD = "etcd.endpoints";
@ -91,6 +94,16 @@ public class ConfigHandlerConfiguration {
}
}
@ConditionalOnClass(ConsulConfigProperties.class)
@ConditionalOnProperty(prefix = BootstrapConfigProperties.PREFIX, name = CONSUL_DATA_KEY)
static class EmbeddedConsul {
@Bean
public ConsulRefresherHandler consulRefresher() {
return new ConsulRefresherHandler();
}
}
@ConditionalOnClass(CuratorFramework.class)
@ConditionalOnProperty(prefix = BootstrapConfigProperties.PREFIX, name = ZOOKEEPER_CONNECT_STR_KEY)
static class EmbeddedZookeeper {

@ -18,7 +18,6 @@
package cn.hippo4j.config.springboot.starter.refresher;
import cn.hippo4j.common.api.ThreadPoolDynamicRefresh;
import cn.hippo4j.common.api.ThreadPoolInitRefresh;
import cn.hippo4j.common.config.ApplicationContextHolder;
import cn.hippo4j.common.toolkit.CollectionUtil;
import cn.hippo4j.config.springboot.starter.config.BootstrapConfigProperties;
@ -27,6 +26,8 @@ import cn.hippo4j.config.springboot.starter.refresher.event.Hippo4jConfigDynamic
import cn.hippo4j.core.executor.support.ThreadPoolBuilder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import java.util.Map;
import java.util.Optional;
@ -36,7 +37,7 @@ import java.util.concurrent.ExecutorService;
* Abstract core thread-pool dynamic refresh.
*/
@Slf4j
public abstract class AbstractConfigThreadPoolDynamicRefresh implements ThreadPoolDynamicRefresh, ThreadPoolInitRefresh, InitializingBean {
public abstract class AbstractConfigThreadPoolDynamicRefresh implements ThreadPoolDynamicRefresh, InitializingBean, ApplicationRunner {
private final BootstrapConfigPropertiesBinderAdapt bootstrapConfigPropertiesBinderAdapt;
@ -49,10 +50,10 @@ public abstract class AbstractConfigThreadPoolDynamicRefresh implements ThreadPo
bootstrapConfigPropertiesBinderAdapt = ApplicationContextHolder.getBean(BootstrapConfigPropertiesBinderAdapt.class);
}
@Override
public void initRefresh(String context) {
dynamicRefresh(context);
}
/**
* Init register listener.
*/
protected abstract void initRegisterListener();
@Override
public void dynamicRefresh(String configContent) {
@ -67,9 +68,31 @@ public abstract class AbstractConfigThreadPoolDynamicRefresh implements ThreadPo
Optional.ofNullable(configInfo).ifPresent(each -> each.putAll(newValueChangeMap));
}
BootstrapConfigProperties binderCoreProperties = bootstrapConfigPropertiesBinderAdapt.bootstrapCorePropertiesBinder(configInfo, bootstrapConfigProperties);
ApplicationContextHolder.getInstance().publishEvent(new Hippo4jConfigDynamicRefreshEvent(this, binderCoreProperties));
publishDynamicThreadPoolEvent(binderCoreProperties);
} catch (Exception ex) {
log.error("Hippo4j config mode dynamic refresh failed.", ex);
}
}
private void publishDynamicThreadPoolEvent(BootstrapConfigProperties configProperties) {
ApplicationContextHolder.getInstance().publishEvent(new Hippo4jConfigDynamicRefreshEvent(this, configProperties));
}
@Override
public void afterPropertiesSet() {
try {
initRegisterListener();
} catch (Exception ex) {
log.error("Hippo4j failed to initialize register listener.", ex);
}
}
@Override
public void run(ApplicationArguments args) {
try {
publishDynamicThreadPoolEvent(bootstrapConfigProperties);
} catch (Exception ex) {
log.error("Hippo-4J core dynamic refresh failed.", ex);
log.error("Hippo4j failed to initialize update configuration.", ex);
}
}
}

@ -42,17 +42,7 @@ public class ApolloRefresherHandler extends AbstractConfigThreadPoolDynamicRefre
private String namespace;
@Override
public String getProperties() {
String[] apolloNamespaces = this.namespace.split(",");
this.namespace = apolloNamespaces[0];
String copyNamespace = this.namespace.replaceAll("." + bootstrapConfigProperties.getConfigFileType().getValue(), "");
ConfigFileFormat configFileFormat = ConfigFileFormat.fromString(bootstrapConfigProperties.getConfigFileType().getValue());
ConfigFile configFile = ConfigService.getConfigFile(copyNamespace, configFileFormat);
return configFile.getContent();
}
@Override
public void afterPropertiesSet() {
public void initRegisterListener() {
String[] apolloNamespaces = this.namespace.split(",");
this.namespace = apolloNamespaces[0];
Config config = ConfigService.getConfig(String.format("%s.%s", namespace, bootstrapConfigProperties.getConfigFileType().getValue()));

@ -0,0 +1,79 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.hippo4j.config.springboot.starter.refresher;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.boot.env.OriginTrackedMapPropertySource;
import org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext;
import org.springframework.cloud.bootstrap.config.BootstrapPropertySource;
import org.springframework.cloud.consul.config.ConsulPropertySource;
import org.springframework.cloud.context.environment.EnvironmentChangeEvent;
import org.springframework.context.event.EventListener;
import org.springframework.core.env.AbstractEnvironment;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
/**
* Consul refresher handler.
*/
@Slf4j
public class ConsulRefresherHandler extends AbstractConfigThreadPoolDynamicRefresh {
@EventListener(EnvironmentChangeEvent.class)
public void refreshed(EnvironmentChangeEvent event) {
Map<String, Object> configInfo = extractLatestConfigInfo(event);
dynamicRefresh(StringUtils.EMPTY, configInfo);
}
private Map<String, Object> extractLatestConfigInfo(EnvironmentChangeEvent event) {
AbstractEnvironment environment = (AbstractEnvironment) ((AnnotationConfigServletWebServerApplicationContext) event.getSource()).getEnvironment();
String activeProfile = Optional.ofNullable(environment.getActiveProfiles().length > 0 ? environment.getActiveProfiles()[0] : null)
.orElseGet(() -> String.valueOf(getApplicationConfigDefaultContext(environment)));
List<BootstrapPropertySource<?>> bootstrapPropertySourceList = environment.getPropertySources().stream()
.filter(propertySource -> propertySource instanceof BootstrapPropertySource)
.map(propertySource -> (BootstrapPropertySource<?>) propertySource).collect(Collectors.toList());
Optional<BootstrapPropertySource<?>> bootstrapPropertySource = bootstrapPropertySourceList.stream()
.filter(source -> source.getName().contains(activeProfile) && source.getPropertyNames().length != 0).findFirst();
Map<String, Object> configInfo = new HashMap<>(64);
if (bootstrapPropertySource.isPresent()) {
ConsulPropertySource consulPropertySource = (ConsulPropertySource) bootstrapPropertySource.get().getDelegate();
String[] propertyNames = consulPropertySource.getPropertyNames();
for (String propertyName : propertyNames) {
configInfo.put(propertyName, consulPropertySource.getProperty(propertyName));
}
}
return configInfo;
}
private CharSequence getApplicationConfigDefaultContext(AbstractEnvironment environment) {
return environment.getPropertySources().stream()
.filter(propertySource -> propertySource instanceof OriginTrackedMapPropertySource)
.map(propertySource -> ((Map<String, CharSequence>) propertySource.getSource()).get("spring.cloud.consul.config.default-context"))
.findFirst().orElse(StringUtils.EMPTY);
}
@Override
protected void initRegisterListener() {
// The listener has been registered by annotation.
}
}

@ -23,12 +23,14 @@ import io.etcd.jetcd.*;
import io.etcd.jetcd.kv.GetResponse;
import io.etcd.jetcd.watch.WatchEvent;
import io.etcd.jetcd.watch.WatchResponse;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ExecutionException;
/**
* Etcd refresher handler.
@ -50,19 +52,9 @@ public class EtcdRefresherHandler extends AbstractConfigThreadPoolDynamicRefresh
private static final String KEY = "key";
@SneakyThrows(value = {InterruptedException.class, ExecutionException.class})
@Override
public String getProperties() throws Exception {
Map<String, String> etcd = bootstrapConfigProperties.getEtcd();
Charset charset = StringUtil.isBlank(etcd.get(CHARSET)) ? StandardCharsets.UTF_8 : Charset.forName(etcd.get(CHARSET));
initClient(etcd, charset);
String key = etcd.get(KEY);
GetResponse getResponse = client.getKVClient().get(ByteSequence.from(key, charset)).get();
KeyValue keyValue = getResponse.getKvs().get(0);
return Objects.isNull(keyValue) ? null : keyValue.getValue().toString(charset);
}
@Override
public void afterPropertiesSet() throws Exception {
public void initRegisterListener() {
Map<String, String> etcd = bootstrapConfigProperties.getEtcd();
String key = etcd.get(KEY);
Charset charset = StringUtil.isBlank(etcd.get(CHARSET)) ? StandardCharsets.UTF_8 : Charset.forName(etcd.get(CHARSET));

@ -21,6 +21,8 @@ import cn.hippo4j.common.config.ApplicationContextHolder;
import com.alibaba.cloud.nacos.NacosConfigProperties;
import com.alibaba.nacos.api.config.ConfigService;
import com.alibaba.nacos.api.config.listener.Listener;
import com.alibaba.nacos.api.exception.NacosException;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import java.util.Map;
@ -42,16 +44,9 @@ public class NacosCloudRefresherHandler extends AbstractConfigThreadPoolDynamicR
configService = ApplicationContextHolder.getBean(NacosConfigProperties.class).configServiceInstance();
}
@SneakyThrows(NacosException.class)
@Override
public String getProperties() throws Exception {
Map<String, String> nacosConfig = bootstrapConfigProperties.getNacos();
String dataId = nacosConfig.get(DATA_ID);
String group = nacosConfig.get(GROUP);
return configService.getConfig(dataId, group, 5000L);
}
@Override
public void afterPropertiesSet() throws Exception {
public void initRegisterListener() {
Map<String, String> nacosConfig = bootstrapConfigProperties.getNacos();
configService.addListener(nacosConfig.get(DATA_ID),
nacosConfig.get(GROUP), new Listener() {

@ -20,6 +20,8 @@ package cn.hippo4j.config.springboot.starter.refresher;
import com.alibaba.nacos.api.annotation.NacosInjected;
import com.alibaba.nacos.api.config.ConfigService;
import com.alibaba.nacos.api.config.listener.Listener;
import com.alibaba.nacos.api.exception.NacosException;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import java.util.Map;
@ -42,16 +44,9 @@ public class NacosRefresherHandler extends AbstractConfigThreadPoolDynamicRefres
super();
}
@SneakyThrows(NacosException.class)
@Override
public String getProperties() throws Exception {
Map<String, String> nacosConfig = bootstrapConfigProperties.getNacos();
String dataId = nacosConfig.get(DATA_ID);
String group = nacosConfig.get(GROUP);
return configService.getConfig(dataId, group, 60 * 10000);
}
@Override
public void afterPropertiesSet() throws Exception {
public void initRegisterListener() {
Map<String, String> nacosConfig = bootstrapConfigProperties.getNacos();
configService.addListener(nacosConfig.get(DATA_ID), nacosConfig.get(GROUP),

@ -54,14 +54,7 @@ public class PolarisRefresherHandler extends AbstractConfigThreadPoolDynamicRefr
private String fileName;
@Override
public String getProperties() {
ConfigKVFile configFile = getConfigKVFile();
configFile.getContent();
return configFile.getContent();
}
@Override
public void afterPropertiesSet() {
public void initRegisterListener() {
ConfigKVFile configFile = getConfigKVFile();
configFile.addChangeListener((ConfigKVFileChangeListener) event -> {
String content = configFile.getContent();

@ -52,15 +52,7 @@ public class ZookeeperRefresherHandler extends AbstractConfigThreadPoolDynamicRe
private CuratorFramework curatorFramework;
@Override
public String getProperties() {
Map<String, String> zkConfigs = bootstrapConfigProperties.getZookeeper();
String nodePath = ZKPaths.makePath(ZKPaths.makePath(zkConfigs.get(ROOT_NODE),
zkConfigs.get(CONFIG_VERSION)), zkConfigs.get(NODE));
return nodePathResolver(nodePath);
}
@Override
public void afterPropertiesSet() {
public void initRegisterListener() {
Map<String, String> zkConfigs = bootstrapConfigProperties.getZookeeper();
curatorFramework = CuratorFrameworkFactory.newClient(zkConfigs.get(ZK_CONNECT_STR),
new ExponentialBackoffRetry(1000, 3));

@ -0,0 +1 @@
<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M108.8 44.322H89.6v-5.36c0-9.04-3.308-24.163-25.6-24.163-23.145 0-25.6 16.881-25.6 24.162v5.361H19.2v-5.36C19.2 15.281 36.798 0 64 0c27.202 0 44.8 15.281 44.8 38.961v5.361zm-32 39.356c0-5.44-5.763-9.832-12.8-9.832-7.037 0-12.8 4.392-12.8 9.832 0 3.682 2.567 6.808 6.407 8.477v11.205c0 2.718 2.875 4.962 6.4 4.962 3.524 0 6.4-2.244 6.4-4.962V92.155c3.833-1.669 6.393-4.795 6.393-8.477zM128 64v49.201c0 8.158-8.645 14.799-19.2 14.799H19.2C8.651 128 0 121.359 0 113.201V64c0-8.153 8.645-14.799 19.2-14.799h89.6c10.555 0 19.2 6.646 19.2 14.799z"/></svg>

After

Width:  |  Height:  |  Size: 623 B

@ -9,29 +9,38 @@ export default {
// 信息
message: {
requiredError: 'this is required',
success: 'Success',
createdSuccess: 'Created Successfully',
deleteMessage: 'This action will delete {name}, Do you want to continue?'
updateSuccess: 'Update Successfully',
deleteSuccess: 'Delete Successfully',
deleteMessage: 'This action will delete {name}, Do you want to continue?',
selectMessage: 'Please select a {target}',
NoDeletionPermissionTip: 'Contact the administrator to delete it',
emptyWarning: "The '{name}' cannot be empty",
queryFailure: 'The query fails. Please refresh the page'
},
// 公共
common: {
query: 'Query',
insert: 'Insert',
serialNumber: 'Serial Number',
operation: 'Operation',
create: 'Create',
edit: 'Edit',
delete: 'Delete',
detail: 'Detail',
cancel: 'Cancel',
confirm: 'Confirm',
reset: 'Reset',
ok: 'Ok',
threadPool: 'Thread Pool',
num: 'Num',
close: 'Close',
refresh: 'Refresh',
createTime: 'Create Time',
updateTime: 'Update Time',
requiredError: 'this is required',
hint: 'Warning'
hint: 'Warning',
info: 'Info'
},
// 运行报表
@ -45,6 +54,7 @@ export default {
// 租户管理
tenantManage: {
tenant: 'Tenant',
tenantRequired: 'Tenant(Required)',
tenantName: 'Tenant Name',
owner: 'Owner',
tenantIntro: 'Tenant Intro'
@ -53,15 +63,67 @@ export default {
// 项目管理
projectManage: {
item: 'Item',
itemRequired: 'Item(Required)',
itemName: 'Item Name',
owner: 'Owner',
itemIntro: 'Item Intro'
},
// 线程池
// 线程池管理
threadPool: {
tenant: 'Tenant',
project: 'Project',
threadPool: 'Thread Pool',
threadPoolRequired: 'ThreadPool(Required)',
coreSize: 'Core Size',
maximumSize: 'Maximum Size',
queueType: 'Queue Type',
queueCapacity: 'Queue Capacity',
rejectedHandler: 'Rejected Handler',
executionTimeout: 'Execution Timeout',
executionTimeoutUnit: 'Execution Timeout ms',
keepAliveTime: 'Keep Alive Time',
keepAliveTimeUnit: 'Keep Alive Timeseconds',
isTimeout: 'Is Timeout',
timeout: 'Timeout',
noTimeout: 'No Timeout',
isAlarm: 'Is Alarm',
alarm: 'Alarm',
noAlarm: 'No Alarm',
activeAlarm: 'Active Alarm',
capacityAlarm: 'Capacity Alarm',
customRejectedHandler: 'Custom Rejected Handler',
customRejectedHandlerTip: 'Please enter a custom SPI Deny Policy ID',
threadsNumErrorTip: 'The maximum thread must be greater than or equal to the core thread'
},
// 线程池实例
threadPoolInstance: {
instanceID: 'Instance ID',
active: 'Active',
stack: 'Stack',
basicInformation: 'Basic Information',
runningState: 'Running state',
activeID: 'Active',
instanceHost: 'Instance Host',
threadPoolID: 'ThreadPool ID',
LoadInformation: 'Load Information',
CurrentLoad: 'Current Load',
PeakLoad: 'Peak Load',
RemainingMemory: 'Remaining Memory',
MemoryRatio: 'Memory Ratio',
threadInformation: 'Thread Information',
currentSize: 'Current Size',
activeSize: 'Active Size',
largestSize: 'Largest Size',
queueInformation: 'Queue Information',
queueCount: 'Queue Count',
queueRemainingCapacity: 'Queue Remaining Capacity',
queueType: 'Queue Type',
otherInformation: 'Other Information',
totalTask: 'Total Task',
totalRejection: 'Total Rejection',
lastUpdateTime: 'Last update time',
allowCoreThreadTimeOut: 'Allow Core Thread Time Out',
changeAll: 'Change All',
stackRequestFail: 'The current thread pool has no stack information'
}
}

@ -9,29 +9,38 @@ export default {
// 信息
message: {
requiredError: '这是必填项',
success: '成功',
createdSuccess: '创建成功',
deleteMessage: '此操作将删除 {name}, 是否继续?'
updateSuccess: '更新成功',
deleteSuccess: '删除成功',
deleteMessage: '此操作将删除 {name}, 是否继续?',
selectMessage: '请选择{target}',
NoDeletionPermissionTip: '请联系管理员删除',
emptyWarning: "{name}不允许为空",
queryFailure: '查询失败,请尝试刷新页面'
},
// 公共
common: {
query: '搜索',
insert: '添加',
serialNumber: '序号',
operation: '操作',
create: '创建',
edit: '编辑',
delete: '删除',
detail: '查看',
cancel: '取消',
confirm: '确认',
reset: '重置',
close: '关闭',
refresh: '刷新',
ok: '确定',
threadPool: '线程池',
num: '序号',
createTime: '创建时间',
updateTime: '修改时间',
requiredError: '这是必填项',
hint: '提示'
hint: '提示',
info: '详情'
},
// 运行报表
@ -45,6 +54,7 @@ export default {
// 租户管理
tenantManage: {
tenant: '租户',
tenantRequired: '租户(必填)',
tenantName: '租户名称',
owner: '负责人',
tenantIntro: '租户简介'
@ -53,14 +63,68 @@ export default {
// 项目管理
projectManage: {
item: '项目',
itemRequired: '项目(必填)',
itemName: '项目名称',
owner: '负责人',
itemIntro: '项目简介'
},
// 线程池
// 线程池管理
threadPool: {
tenant: '租户',
project: '项目',
threadPool: '线程池',
threadPoolRequired: '线程池(必填)',
coreSize: '核心线程',
maximumSize: '最大线程',
queueType: '队列类型',
queueCapacity: '队列容量',
rejectedHandler: '拒绝策略',
executionTimeout: '执行超时',
executionTimeoutUnit: '执行超时 (毫秒)',
keepAliveTime: '空闲回收',
keepAliveTimeUnit: '空闲回收(秒)',
isTimeout: '是否超时',
timeout: '超时',
noTimeout: '不超时',
isAlarm: '是否报警',
alarm: '报警',
noAlarm: '不报警',
activeAlarm: '活跃报警',
capacityAlarm: '容量报警',
customRejectedHandler: '自定义拒绝策略',
customRejectedHandlerTip: '请输入自定义 SPI 拒绝策略标识',
threadsNumErrorTip: '最大线程必须大于等于核心线程'
},
// 线程池实例
threadPoolInstance: {
instanceID: '实例标识',
active: 'Active',
stack: '堆栈',
basicInformation: '基础信息',
runningState: '运行状态',
activeID: '环境标识',
instanceHost: '实例Host',
threadPoolID: '线程池',
LoadInformation: '负载信息',
CurrentLoad: '当前负载',
PeakLoad: '峰值负载',
RemainingMemory: '剩余内存',
MemoryRatio: '内存占比',
threadInformation: '线程信息',
currentSize: '当前线程',
activeSize: '活跃线程',
largestSize: '同存最大线程',
queueInformation: '队列信息',
queueCount: '队列元素',
queueRemainingCapacity: '队列剩余容量',
queueType: '阻塞队列',
otherInformation: '其它信息',
totalTask: '任务总量',
totalRejection: '拒绝次数',
lastUpdateTime: '最后更新时间',
allowCoreThreadTimeOut: '线程超时',
changeAll: '全部修改',
stackRequestFail: '当前线程池暂无堆栈信息'
}
}

@ -18,6 +18,7 @@ import './permission'; // permission control
// import './utils/error-log' // error log
import i18n from '@/locale'
import '@/utils/i18n-utils'
import * as filters from './filters'; // global filters
import echarts from 'echarts';
Vue.prototype.$echarts = echarts;

@ -0,0 +1,20 @@
import Vue from 'vue'
import i18n from '@/locale'
/**
* @param langMap {[lang]: any} object
* @param [defaultText] any
* @returns any
*/
export function langMatch(langMap, defaultText = undefined) {
if (Object.prototype.toString.call(langMap) !== '[object Object]') {
throw Error('The first argument to the langMatch method must be the object type')
}
const lang = i18n.locale
return Object.prototype.hasOwnProperty.call(langMap, lang) ? langMap[lang] : defaultText
}
Vue.prototype.$langMatch = langMatch

@ -33,7 +33,7 @@
</div>
<div class="card-panel-description">
<div class="card-panel-text">
{{ $t('common.threadPool') }}
{{ $t('threadPool.threadPool') }}
</div>
<count-to :start-val="0" :end-val="runningCount" :duration="3200" class="card-panel-num" />
</div>

@ -3,7 +3,7 @@
<div class="filter-container">
<el-select
v-model="listQuery.tenantId"
placeholder="租户(必填)"
:placeholder="$t('tenantManage.tenantRequired')"
style="width: 220px"
filterable
class="filter-item"
@ -18,7 +18,7 @@
</el-select>
<el-select
v-model="listQuery.itemId"
placeholder="项目 (必填)"
:placeholder="$t('projectManage.itemRequired')"
style="width: 220px"
filterable
class="filter-item"
@ -33,7 +33,7 @@
</el-select>
<el-select
v-model="listQuery.tpId"
placeholder="线程池 (必填)"
:placeholder="$t('threadPool.threadPoolRequired')"
style="width: 220px"
filterable
class="filter-item"
@ -54,7 +54,7 @@
icon="el-icon-search"
@click="fetchData"
>
搜索
{{ $t('common.query') }}
</el-button>
<el-button
v-waves
@ -64,7 +64,7 @@
icon="el-icon-refresh"
@click="refreshData"
>
重置
{{ $t('common.reset') }}
</el-button>
</div>
@ -73,51 +73,52 @@
border
:data="list"
element-loading-text="Loading"
fit
:fit="true"
max-height="714"
highlight-current-row
header-row-name="headerRowName"
>
<el-table-column label="序号" fixed width="95">
<el-table-column :label="$t('common.num')" fixed="left" width="95">
<template slot-scope="scope">{{ scope.$index + 1 }}</template>
</el-table-column>
<el-table-column label="实例标识" width="260">
<el-table-column :label="$t('threadPoolInstance.instanceID')" width="260">
<template slot-scope="scope">
<el-link type="primary" :underline="false">{{ scope.row.identify }}</el-link>
</template>
</el-table-column>
<el-table-column label="Active" width="120">
<el-table-column :label="$t('threadPoolInstance.active')" width="120">
<template slot-scope="scope">
<el-tag :type="scope.row.active | statusFilter">
{{ scope.row.active }}
</el-tag>
</template>
</el-table-column>
<el-table-column label="核心线程" width="100">
<el-table-column :label="$t('threadPool.coreSize')" width="100">
<template slot-scope="scope">
<el-link type="success" :underline="false">{{ scope.row.coreSize }}</el-link>
</template>
</el-table-column>
<el-table-column label="最大线程" width="100">
<el-table-column :label="$t('threadPool.maximumSize')" :width="$langMatch({ zh: '100', en: '150' }, 'auto')">
<template slot-scope="scope">
<el-link type="danger" :underline="false">{{ scope.row.maxSize }}</el-link>
</template>
</el-table-column>
<el-table-column label="队列类型" width="260">
<el-table-column :label="$t('threadPool.queueType')" width="260">
<template slot-scope="scope">{{ scope.row.queueType | queueFilter }}</template>
</el-table-column>
<el-table-column label="队列容量" width="100">
<el-table-column :label="$t('threadPool.queueCapacity')" :width="$langMatch({ zh: '100', en: '160' }, 'auto')">
<template slot-scope="scope">{{ scope.row.capacity }}</template>
</el-table-column>
<el-table-column label="拒绝策略" width="260">
<el-table-column :label="$t('threadPool.rejectedHandler')" width="260">
<template slot-scope="scope">{{ scope.row.rejectedType | rejectedFilter }}</template>
</el-table-column>
<el-table-column label="执行超时" width="100">
<el-table-column :label="$t('threadPool.executionTimeout')" :width="$langMatch({ zh: '100', en: '160' }, 'auto')">
<template slot-scope="scope">
{{ scope.row.executeTimeOut }}
</template>
</el-table-column>
<el-table-column label="空闲回收" width="100">
<el-table-column :label="$t('threadPool.keepAliveTime')" :width="$langMatch({ zh: '100', en: '160' }, 'auto')">
<template slot-scope="scope">
{{ scope.row.keepAliveTime }}
</template>
@ -129,7 +130,7 @@
</template>
</el-table-column>-->
<el-table-column
label="操作"
:label="$t('common.operation')"
fixed="right"
width="120"
align="center"
@ -148,9 +149,9 @@
</el-dropdown>
</template>-->
<template slot-scope="{ row }">
<el-button type="text" size="small" @click="handleInfo(row)"> </el-button>
<el-button type="text" size="small" @click="handleShowStack(row)"> </el-button>
<el-button type="text" size="small" @click="handleUpdate(row)"> </el-button>
<el-button type="text" size="small" @click="handleInfo(row)"> {{ $t('common.detail') }} </el-button>
<el-button type="text" size="small" @click="handleShowStack(row)"> {{ $t('common.stack') }} </el-button>
<el-button type="text" size="small" @click="handleUpdate(row)"> {{ $t('common.edit') }} </el-button>
</template>
</el-table-column>
</el-table>
@ -168,111 +169,111 @@
width="1000px"
>
<template>
<el-descriptions class="margin-top" title="基础信息" :column="3" :size="size" border>
<el-descriptions class="margin-top" :title="$t('threadPoolInstance.basicInformation')" :column="3" :size="size" border>
<el-descriptions-item>
<template slot="label"> 线程池 </template>
<template slot="label"> {{ $t('threadPoolInstance.threadPoolID') }} </template>
{{ runTimeTemp.tpId }}
</el-descriptions-item>
<el-descriptions-item>
<template slot="label"> 环境标识 </template>
<template slot="label"> {{ $t('threadPoolInstance.activeID') }} </template>
<el-tag :type="runTimeTemp.active | statusFilter">
{{ runTimeTemp.active }}
</el-tag>
</el-descriptions-item>
<el-descriptions-item>
<template slot="label"> 运行状态 </template>
<template slot="label"> {{ $t('threadPoolInstance.runningState') }} </template>
<el-tag>{{ runTimeTemp.state }}</el-tag>
</el-descriptions-item>
<el-descriptions-item>
<template slot="label"> 实例Host </template>
<template slot="label"> {{ $t('threadPoolInstance.instanceHost') }} </template>
{{ runTimeTemp.host }}
</el-descriptions-item>
<el-descriptions-item>
<template slot="label"> 实例标识 </template>
<template slot="label"> {{ $t('threadPoolInstance.instanceID') }} </template>
{{ runTimeTemp.identify }}
</el-descriptions-item>
</el-descriptions>
<br />
<br />
<el-descriptions class="margin-top" title="负载信息" :column="3" :size="size" border>
<el-descriptions class="margin-top" :title="$t('threadPoolInstance.LoadInformation')" :column="3" :size="size" border>
<el-descriptions-item>
<template slot="label"> 当前负载 </template>
<template slot="label"> {{ $t('threadPoolInstance.CurrentLoad') }} </template>
{{ runTimeTemp.currentLoad }}
</el-descriptions-item>
<el-descriptions-item>
<template slot="label"> 峰值负载 </template>
<template slot="label"> {{ $t('threadPoolInstance.PeakLoad') }} </template>
{{ runTimeTemp.peakLoad }}
</el-descriptions-item>
<el-descriptions-item>
<template slot="label"> 剩余内存 </template>
<template slot="label"> {{ $t('threadPoolInstance.RemainingMemory') }} </template>
{{ runTimeTemp.freeMemory }}
</el-descriptions-item>
<el-descriptions-item>
<template slot="label"> 内存占比 </template>
<template slot="label"> {{ $t('threadPoolInstance.MemoryRatio') }} </template>
{{ runTimeTemp.memoryProportion }}
</el-descriptions-item>
</el-descriptions>
<br />
<br />
<el-descriptions class="margin-top" title="线程信息" :column="3" :size="size" border>
<el-descriptions class="margin-top" :title="$t('threadPoolInstance.threadInformation')" :column="3" :size="size" border>
<el-descriptions-item>
<template slot="label"> 核心线程 </template>
<template slot="label"> {{ $t('threadPool.coreSize') }} </template>
{{ runTimeTemp.coreSize }}
</el-descriptions-item>
<el-descriptions-item>
<template slot="label"> 当前线程 </template>
<template slot="label"> {{ $t('threadPoolInstance.currentSize') }} </template>
{{ runTimeTemp.poolSize }}
</el-descriptions-item>
<el-descriptions-item>
<template slot="label"> 最大线程 </template>
<template slot="label"> {{ $t('threadPool.maximumSize') }} </template>
{{ runTimeTemp.maximumSize }}
</el-descriptions-item>
<el-descriptions-item>
<template slot="label"> 活跃线程 </template>
<template slot="label"> {{ $t('threadPoolInstance.activeSize') }} </template>
{{ runTimeTemp.activeSize }}
</el-descriptions-item>
<el-descriptions-item>
<template slot="label"> 同存最大线程 </template>
<template slot="label"> {{ $t('threadPoolInstance.largestSize') }} </template>
{{ runTimeTemp.largestPoolSize }}
</el-descriptions-item>
</el-descriptions>
<br />
<br />
<el-descriptions class="margin-top" title="队列信息" :column="3" :size="size" border>
<el-descriptions class="margin-top" :title="$t('threadPoolInstance.queueInformation')" :column="3" :size="size" border>
<el-descriptions-item>
<template slot="label"> 队列容量 </template>
<template slot="label"> {{ $t('threadPool.queueCapacity') }} </template>
{{ runTimeTemp.queueCapacity }}
</el-descriptions-item>
<el-descriptions-item>
<template slot="label"> 队列元素 </template>
<template slot="label"> {{ $t('threadPoolInstance.queueCount') }} </template>
{{ runTimeTemp.queueSize }}
</el-descriptions-item>
<el-descriptions-item>
<template slot="label"> 队列剩余容量 </template>
<template slot="label"> {{ $t('threadPoolInstance.queueRemainingCapacity') }} </template>
{{ runTimeTemp.queueRemainingCapacity }}
</el-descriptions-item>
<el-descriptions-item>
<template slot="label"> 阻塞队列 </template>
<template slot="label"> {{ $t('threadPoolInstance.queueType') }} </template>
{{ runTimeTemp.queueType }}
</el-descriptions-item>
</el-descriptions>
<br />
<br />
<el-descriptions class="margin-top" title="其它信息" :column="3" :size="size" border>
<el-descriptions class="margin-top" :title="$t('threadPoolInstance.otherInformation')" :column="3" :size="size" border>
<el-descriptions-item>
<template slot="label"> 任务总量 </template>
<template slot="label"> {{ $t('threadPoolInstance.totalTask') }} </template>
{{ runTimeTemp.completedTaskCount }}
</el-descriptions-item>
<el-descriptions-item>
<template slot="label"> 拒绝次数 </template>
<template slot="label"> {{ $t('threadPoolInstance.totalRejection') }} </template>
<el-link type="danger" :underline="false">{{ runTimeTemp.rejectCount }}</el-link>
</el-descriptions-item>
<el-descriptions-item>
<template slot="label"> 最后更新时间 </template>
<template slot="label"> {{ $t('threadPoolInstance.lastUpdateTime') }} </template>
{{ runTimeTemp.clientLastRefreshTime }}
</el-descriptions-item>
<el-descriptions-item>
<template slot="label"> 拒绝策略 </template>
<template slot="label"> {{ $t('threadPool.rejectedHandler') }} </template>
{{ runTimeTemp.rejectedName }}
</el-descriptions-item>
</el-descriptions>
@ -280,11 +281,11 @@
<div slot="footer" class="dialog-footer">
<el-button @click="instanceDialogFormVisible = false">
<i class="el-icon-close" />
{{ $t('common.close') }}
</el-button>
<el-button type="primary" @click="handleInfo()">
<i class="el-icon-refresh-right" />
{{ $t('common.refresh') }}
</el-button>
</div>
</el-dialog>
@ -295,31 +296,31 @@
style="width: 500px; margin-left: 50px"
:rules="rules"
:model="temp"
label-width="80px"
:label-width="$langMatch({ zh: '80px', en: '150px' })"
>
<el-form-item label="核心线程" prop="coreSize">
<el-form-item :label="$t('threadPool.coreSize')" prop="coreSize">
<el-input-number
v-model="temp.coreSize"
placeholder="核心线程"
:placeholder="$t('threadPool.coreSize')"
controls-position="right"
:min="1"
:max="9999"
></el-input-number>
</el-form-item>
<el-form-item label="最大线程" prop="maxSize">
<el-form-item :label="$t('threadPool.maximumSize')" prop="maxSize">
<el-input-number
v-model="temp.maxSize"
placeholder="最大线程"
:placeholder="$t('threadPool.maximumSize')"
controls-position="right"
:min="1"
:max="9999"
/>
</el-form-item>
<el-form-item label="队列类型" prop="queueType">
<el-form-item :label="$t('threadPool.queueType')" prop="queueType">
<el-select
v-model="temp.queueType"
placeholder="队列类型"
:placeholder="$t('threadPool.queueType')"
:disabled="true"
style="display: block"
@change="selectQueueType"
@ -332,49 +333,49 @@
/>
</el-select>
</el-form-item>
<el-form-item label="队列容量" prop="capacity">
<el-form-item :label="$t('threadPool.queueCapacity')" prop="capacity">
<el-input-number
v-model="temp.capacity"
placeholder="队列容量"
:placeholder="$t('threadPool.queueCapacity')"
controls-position="right"
:min="0"
:max="2147483647"
:disabled="temp.queueType === 9 ? false : true"
/>
</el-form-item>
<el-form-item label="线程超时" prop="isAlarm">
<el-form-item :label="$t('threadPoolInstance.allowCoreThreadTimeOut')" prop="isAlarm">
<template>
<div>
<el-radio-group v-model="temp.allowCoreThreadTimeOut">
<el-radio-button :label="1">超时</el-radio-button>
<el-radio-button :label="0">不超时</el-radio-button>
<el-radio-button :label="1">{{ $t('threadPool.timeout') }}</el-radio-button>
<el-radio-button :label="0">{{ $t('threadPool.noTimeout') }}</el-radio-button>
</el-radio-group>
</div>
</template>
</el-form-item>
<el-form-item label="执行超时" prop="executeTimeOut">
<el-form-item :label="$t('threadPool.executionTimeout')" prop="executeTimeOut">
<el-input-number
v-model="temp.executeTimeOut"
placeholder="执行超时(毫秒)"
:placeholder="$t('threadPool.executionTimeoutUnit')"
controls-position="right"
:min="0"
:max="999999"
/>
</el-form-item>
<el-form-item label="空闲回收" prop="keepAliveTime">
<el-form-item :label="$t('threadPool.keepAliveTime')" prop="keepAliveTime">
<el-input-number
v-model="temp.keepAliveTime"
placeholder="空闲回收(秒)"
:placeholder="$t('threadPool.keepAliveTimeUnit')"
controls-position="right"
:min="1"
:max="999999"
/>
</el-form-item>
<el-form-item label="拒绝策略" prop="rejectedType">
<el-form-item :label="$t('threadPool.rejectedHandler')" prop="rejectedType">
<el-select
v-model="temp.rejectedType"
style="display: block"
placeholder="拒绝策略"
:placeholder="$t('threadPool.rejectedHandler')"
@change="selectRejectedType"
>
<el-option
@ -385,21 +386,21 @@
/>
</el-select>
</el-form-item>
<el-form-item v-if="isRejectShow" label="自定义拒绝策略" prop="customRejectedType">
<el-form-item v-if="isRejectShow" :label="$t('threadPool.customRejectedHandler')" prop="customRejectedType">
<el-input
v-model="temp.customRejectedType"
placeholder="请输入自定义 SPI 拒绝策略标识"
:placeholder="$t('threadPool.customRejectedHandlerTip')"
@input="onInput()"
/>
</el-form-item>
<el-form-item label="全部修改" prop="allUpdate">
<el-form-item :label="$t('threadPoolInstance.changeAll')" prop="allUpdate">
<el-switch v-model="allUpdate"> </el-switch>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="dialogFormVisible = false"> 取消 </el-button>
<el-button @click="dialogFormVisible = false"> {{ $t('common.cancel') }} </el-button>
<el-button type="primary" @click="dialogStatus === 'create' ? createData() : updateData()">
确认
{{ $t('common.confirm') }}
</el-button>
</div>
</el-dialog>
@ -409,7 +410,7 @@
<el-table-column prop="pv" label="Pv" />
</el-table>
<span slot="footer" class="dialog-footer">
<el-button type="primary" @click="dialogPvVisible = false"> Confirm </el-button>
<el-button type="primary" @click="dialogPvVisible = false"> {{ $t('common.confirm') }} </el-button>
</span>
</el-dialog>
<el-dialog title="Stack Info" :visible.sync="isStackShow" width="60%">
@ -425,10 +426,10 @@
</li>
</ul>
<span slot="footer" class="dialog-footer">
<el-button @click="isStackShow = false"> <i class="el-icon-close" /> </el-button>
<el-button @click="isStackShow = false"> <i class="el-icon-close" />{{ $t('common.close') }}</el-button>
<el-button type="primary" @click="handleStackInfo">
<i class="el-icon-refresh-right" />
{{ $t('common.refresh') }}
</el-button>
</span>
</el-dialog>
@ -564,9 +565,9 @@ export default {
},
dialogStatus: '',
textMap: {
update: 'Edit',
create: 'Create',
info: 'Info',
update: this.$t('common.edit'),
create: this.$t('common.create'),
info: this.$t('common.info'),
},
allUpdate: false,
temp: {
@ -592,15 +593,15 @@ export default {
},
fetchData() {
if (!this.listQuery.tenantId) {
this.$message.warning('租户不允许为空');
this.$message.warning(this.$t('message.emptyWarning', { name: this.$t('tenantManage.tenant') }));
return;
}
if (!this.listQuery.itemId) {
this.$message.warning('项目不允许为空');
this.$message.warning(this.$t('message.emptyWarning', { name: this.$t('projectManage.item') }));
return;
}
if (!this.listQuery.tpId) {
this.$message.warning('线程池不允许为空');
this.$message.warning(this.$t('message.emptyWarning', { name: this.$t('threadPool.threadPool') }));
return;
}
this.listLoading = true;
@ -658,8 +659,8 @@ export default {
this.fetchData();
this.dialogFormVisible = false;
this.$notify({
title: 'Success',
message: 'Created Successfully',
title: this.$t('message.success'),
message: this.$t('message.createdSuccess'),
type: 'success',
duration: 2000,
});
@ -728,7 +729,7 @@ export default {
})
.catch((error) => {
console.log(error);
this.$message.error('查询失败,请尝试刷新页面');
this.$message.error(this.$t('message.queryFailure'));
});
},
handleShowStack(row) {
@ -748,12 +749,12 @@ export default {
this.stackInfo = data;
this.isStackShow = true;
} else {
this.$message.warning('当前线程池暂无堆栈信息');
this.$message.warning(this.$t('threadPoolInstance.stackRequestFail'));
}
})
.catch((error) => {
console.log(error);
this.$message.error('查询失败,请尝试刷新页面');
this.$message.error(this.$t('message.queryFailure'));
});
},
//
@ -762,7 +763,7 @@ export default {
if (valid) {
if (parseInt(this.temp.maxSize) < parseInt(this.temp.coreSize)) {
this.$message({
message: '最大线程必须大于等于核心线程',
message: this.$t('threadPool.threadsNumErrorTip'),
type: 'warning',
});
return;
@ -783,8 +784,8 @@ export default {
.then(() => {
this.dialogFormVisible = false;
this.$notify({
title: 'Success',
message: 'Update Successfully',
title: this.$t('message.success'),
message: this.$t('message.updateSuccess'),
type: 'success',
duration: 2000,
});
@ -853,6 +854,9 @@ export default {
</script>
<style lang="scss" scoped>
.headerRowName{
}
/* 滚动槽 */
::-webkit-scrollbar {
width: 8px;

@ -204,11 +204,11 @@ export default {
create: 'Create',
},
rules: {
tenantId: [{ required: true, message: this.$t('common.requiredError'), trigger: 'blur' }],
itemId: [{ required: true, message: this.$t('common.requiredError'), trigger: 'blur' }],
itemName: [{ required: true, message: this.$t('common.requiredError'), trigger: 'blur' }],
owner: [{ required: true, message: this.$t('common.requiredError'), trigger: 'blur' }],
itemDesc: [{ required: true, message: this.$t('common.requiredError'), trigger: 'blur' }],
tenantId: [{ required: true, message: this.$t('message.requiredError'), trigger: 'blur' }],
itemId: [{ required: true, message: this.$t('message.requiredError'), trigger: 'blur' }],
itemName: [{ required: true, message: this.$t('message.requiredError'), trigger: 'blur' }],
owner: [{ required: true, message: this.$t('message.requiredError'), trigger: 'blur' }],
itemDesc: [{ required: true, message: this.$t('message.requiredError'), trigger: 'blur' }],
},
temp: {
id: undefined,

@ -174,10 +174,10 @@ export default {
create: this.$t('common.create'),
},
rules: {
tenantId: [{ required: true, message: this.$t('common.requiredError'), trigger: 'blur' }],
tenantName: [{ required: true, message: this.$t('common.requiredError'), trigger: 'blur' }],
owner: [{ required: true, message: this.$t('common.requiredError'), trigger: 'blur' }],
tenantDesc: [{ required: true, message: this.$t('common.requiredError'), trigger: 'blur' }],
tenantId: [{ required: true, message: this.$t('message.requiredError'), trigger: 'blur' }],
tenantName: [{ required: true, message: this.$t('message.requiredError'), trigger: 'blur' }],
owner: [{ required: true, message: this.$t('message.requiredError'), trigger: 'blur' }],
tenantDesc: [{ required: true, message: this.$t('message.requiredError'), trigger: 'blur' }],
},
temp: {
id: undefined,

@ -3,7 +3,7 @@
<div class="filter-container">
<el-select
v-model="listQuery.tenantId"
:placeholder="$t('threadPool.tenant')"
:placeholder="$t('tenantManage.tenant')"
style="width: 220px"
filterable
class="filter-item"
@ -18,7 +18,7 @@
</el-select>
<el-select
v-model="listQuery.itemId"
:placeholder="$t('threadPool.project')"
:placeholder="$t('projectManage.item')"
style="width: 220px"
filterable
class="filter-item"
@ -33,7 +33,7 @@
</el-select>
<el-select
v-model="listQuery.tpId"
:placeholder="$t('common.threadPool')"
:placeholder="$t('threadPool.threadPool')"
style="width: 220px"
filterable
class="filter-item"
@ -53,7 +53,7 @@
icon="el-icon-search"
@click="fetchData"
>
{{ $t('common.search') }}
{{ $t('common.query') }}
</el-button>
<el-button
class="filter-item"
@ -63,7 +63,7 @@
@click="handleCreate"
:disabled="isEditDisabled"
>
{{ $t('common.addition') }}
{{ $t('common.insert') }}
</el-button>
</div>
<el-table
@ -74,43 +74,43 @@
fit
highlight-current-row
>
<el-table-column fixed :label="$t('common.serialNumber')" width="80">
<el-table-column fixed :label="$t('common.num')" width="80">
<template slot-scope="scope">{{ scope.$index + 1 }}</template>
</el-table-column>
<el-table-column label="租户" width="150">
<el-table-column :label="$t('tenantManage.tenant')" width="150">
<template slot-scope="scope">{{ scope.row.tenantId }}</template>
</el-table-column>
<el-table-column label="项目" width="260">
<el-table-column :label="$t('projectManage.item')" width="260">
<template slot-scope="scope">{{ scope.row.itemId }}</template>
</el-table-column>
<el-table-column label="线程池" width="260">
<el-table-column :label="$t('threadPool.threadPool')" width="260">
<template slot-scope="scope">{{ scope.row.tpId }}</template>
</el-table-column>
<el-table-column label="核心线程" width="100">
<el-table-column :label="$t('threadPool.coreSize')" width="100">
<template slot-scope="scope">
<el-link type="success" :underline="false">{{ scope.row.coreSize }}</el-link>
</template>
</el-table-column>
<el-table-column label="最大线程" width="100">
<el-table-column :label="$t('threadPool.maximumSize')" :width="$langMatch({ zh: '100', en: '120' })">
<template slot-scope="scope">
<el-link type="danger" :underline="false">{{ scope.row.maxSize }}</el-link>
</template>
</el-table-column>
<el-table-column label="队列类型" width="260">
<el-table-column :label="$t('threadPool.queueType')" width="260">
<template slot-scope="scope">{{ scope.row.queueType | queueFilter }}</template>
</el-table-column>
<el-table-column label="队列容量" width="100">
<el-table-column :label="$t('threadPool.queueCapacity')" :width="$langMatch({ zh: '100', en: '120' })">
<template slot-scope="scope">{{ scope.row.capacity }}</template>
</el-table-column>
<el-table-column label="拒绝策略" width="200">
<el-table-column :label="$t('threadPool.rejectedHandler')" width="200">
<template slot-scope="scope">{{ scope.row.rejectedType | rejectedTypeFilter }}</template>
</el-table-column>
<el-table-column label="执行超时" width="100">
<el-table-column :label="$t('threadPool.executionTimeout')" :width="$langMatch({ zh: '100', en: '150' })">
<template slot-scope="scope">{{
scope.row.executeTimeOut | defaultExecuteTimeoutValue
}}</template>
</el-table-column>
<el-table-column label="是否报警" width="100">
<el-table-column :label="$t('threadPool.isAlarm')" width="100">
<template slot-scope="scope">
<el-switch
v-model="scope.row.isAlarm"
@ -122,10 +122,10 @@
/>
</template>
</el-table-column>
<el-table-column label="创建时间" width="200">
<el-table-column :label="$t('common.createTime')" width="200">
<template slot-scope="scope">{{ scope.row.gmtCreate }}</template>
</el-table-column>
<el-table-column label="修改时间" width="200">
<el-table-column :label="$t('common.updateTime')" width="200">
<template slot-scope="scope">{{ scope.row.gmtModified }}</template>
</el-table-column>
<el-table-column
@ -159,70 +159,73 @@
style="width: 500px; margin-left: 50px"
:rules="rules"
:model="temp"
label-width="80px"
:label-width="$langMatch({ zh: '100px', en: '150px' })"
>
<el-form-item v-if="isEdit" label="租户" prop="tenantId">
<el-select
v-model="temp.tenantId"
placeholder="请选择租户"
style="display: block"
:disabled="dialogStatus === 'create' ? false : true"
@change="tenantTempSelectList()"
>
<el-option
v-for="item in tenantOptions"
:key="item.key"
:label="item.display_name"
:value="item.key"
/>
</el-select>
</el-form-item>
<el-form-item v-if="isEdit" label="项目" prop="itemId">
<el-select
v-model="temp.itemId"
placeholder="请选择项目"
style="display: block"
:disabled="dialogStatus === 'create' ? false : true"
>
<el-option
v-for="item in itemTempOptions"
:key="item.key"
:label="item.display_name"
:value="item.key"
/>
</el-select>
</el-form-item>
<template v-if="isEdit">
<el-form-item :label="$t('tenantManage.tenant')" prop="tenantId">
<el-select
v-model="temp.tenantId"
:placeholder="$t('message.selectMessage', { target: $t('tenantManage.tenant') })"
style="display: block"
:disabled="dialogStatus === 'create' ? false : true"
@change="tenantTempSelectList()"
>
<el-option
v-for="item in tenantOptions"
:key="item.key"
:label="item.display_name"
:value="item.key"
/>
</el-select>
</el-form-item>
<el-form-item :label="$t('projectManage.item')" prop="itemId">
<el-select
v-model="temp.itemId"
:placeholder="$t('message.selectMessage', { target: $t('projectManage.item') })"
style="display: block"
:disabled="dialogStatus === 'create' ? false : true"
>
<el-option
v-for="item in itemTempOptions"
:key="item.key"
:label="item.display_name"
:value="item.key"
/>
</el-select>
</el-form-item>
<el-form-item v-if="isEdit" label="线程池" prop="tpId">
<el-input
v-model="temp.tpId"
size="medium"
placeholder="请输入线程池 "
:disabled="dialogStatus === 'create' ? false : true"
/>
</el-form-item>
<el-form-item label="核心线程" prop="coreSize">
<el-form-item :label="$t('threadPool.threadPool')" prop="tpId">
<el-input
v-model="temp.tpId"
size="medium"
:placeholder="$t('message.selectMessage', { target: $t('threadPool.threadPool') }) "
:disabled="dialogStatus === 'create' ? false : true"
/>
</el-form-item>
</template>
<el-form-item :label="$t('threadPool.coreSize')" prop="coreSize">
<el-input-number
v-model="temp.coreSize"
placeholder="核心线程"
:placeholder="$t('threadPool.coreSize')"
controls-position="right"
:min="1"
:max="9999"
/>
</el-form-item>
<el-form-item label="最大线程" prop="maxSize">
<el-form-item :label="$t('threadPool.maximumSize')" prop="maxSize">
<el-input-number
v-model="temp.maxSize"
placeholder="最大线程"
:placeholder="$t('threadPool.maximumSize')"
controls-position="right"
:min="1"
:max="9999"
/>
</el-form-item>
<el-form-item label="队列类型" prop="queueType">
<el-form-item :label="$t('threadPool.queueType')" prop="queueType">
<el-select
v-model="temp.queueType"
placeholder="队列类型"
:placeholder="$t('threadPool.queueType')"
style="display: block"
@change="selectQueueType"
>
@ -234,57 +237,57 @@
/>
</el-select>
</el-form-item>
<el-form-item label="队列容量" prop="capacity">
<el-form-item :label="$t('threadPool.queueCapacity')" prop="capacity">
<el-input-number
v-model="temp.capacity"
placeholder="队列容量"
:placeholder="$t('threadPool.queueCapacity')"
controls-position="right"
:min="0"
:max="2147483647"
:disabled="temp.queueType === 4 || temp.queueType === 5 ? true : false"
/>
</el-form-item>
<el-form-item label="执行超时" prop="executeTimeOut">
<el-form-item :label="$t('threadPool.executionTimeout')" prop="executeTimeOut">
<el-input-number
v-model="temp.executeTimeOut"
placeholder="执行超时(毫秒)"
:placeholder="$t('threadPool.executionTimeoutUnit')"
controls-position="right"
/>
</el-form-item>
<el-form-item label="空闲回收" prop="keepAliveTime">
<el-form-item :label="$t('threadPool.keepAliveTime')" prop="keepAliveTime">
<el-input-number
v-model="temp.keepAliveTime"
placeholder="空闲回收(秒)"
:placeholder="$t('threadPool.keepAliveTimeUnit')"
controls-position="right"
:min="1"
:max="999999"
/>
</el-form-item>
<el-form-item label="是否超时" prop="allowCoreThreadTimeOut">
<el-form-item :label="$t('threadPool.isTimeout')" prop="allowCoreThreadTimeOut">
<template>
<div>
<el-radio-group v-model="temp.allowCoreThreadTimeOut">
<el-radio-button :label="1">超时</el-radio-button>
<el-radio-button :label="0">不超时</el-radio-button>
<el-radio-button :label="1">{{ $t('threadPool.timeout') }}</el-radio-button>
<el-radio-button :label="0">{{ $t('threadPool.noTimeout') }}</el-radio-button>
</el-radio-group>
</div>
</template>
</el-form-item>
<el-form-item label="是否报警" prop="isAlarm">
<el-form-item :label="$t('threadPool.isAlarm')" prop="isAlarm">
<template>
<div>
<el-radio-group v-model="temp.isAlarm">
<el-radio-button label="1">报警</el-radio-button>
<el-radio-button label="0">不报警</el-radio-button>
<el-radio-button label="1">{{ $t('threadPool.alarm') }}</el-radio-button>
<el-radio-button label="0">{{ $t('threadPool.noAlarm') }}</el-radio-button>
</el-radio-group>
</div>
</template>
</el-form-item>
<el-form-item label="活跃报警" prop="livenessAlarm">
<el-form-item :label="$t('threadPool.activeAlarm')" prop="livenessAlarm">
<template>
<div>
<el-radio-group v-model="temp.livenessAlarm">
<el-radio-button label="0">不报警</el-radio-button>
<el-radio-button label="0">{{ $t('threadPool.noAlarm') }}</el-radio-button>
<el-radio-button label="60">60%</el-radio-button>
<el-radio-button label="80">80%</el-radio-button>
<el-radio-button label="90">90%</el-radio-button>
@ -293,11 +296,11 @@
</template>
</el-form-item>
<el-form-item label="容量报警" prop="capacityAlarm">
<el-form-item :label="$t('threadPool.capacityAlarm')" prop="capacityAlarm">
<template>
<div>
<el-radio-group v-model="temp.capacityAlarm">
<el-radio-button label="0">不报警</el-radio-button>
<el-radio-button label="0">{{ $t('threadPool.noAlarm') }}</el-radio-button>
<el-radio-button label="60">60%</el-radio-button>
<el-radio-button label="80">80%</el-radio-button>
<el-radio-button label="90">90%</el-radio-button>
@ -305,11 +308,11 @@
</div>
</template>
</el-form-item>
<el-form-item label="拒绝策略" prop="rejectedType">
<el-form-item :label="$t('threadPool.rejectedHandler')" prop="rejectedType">
<el-select
v-model="temp.rejectedType"
style="display: block"
placeholder="拒绝策略"
:placeholder="$t('threadPool.rejectedHandler')"
@change="selectRejectedType"
>
<el-option
@ -320,10 +323,10 @@
/>
</el-select>
</el-form-item>
<el-form-item v-if="isRejectShow" label="自定义拒绝策略" prop="customRejectedType">
<el-form-item v-if="isRejectShow" :label="$t('threadPool.customRejectedHandler')" prop="customRejectedType">
<el-input
v-model="temp.customRejectedType"
placeholder="请输入自定义 SPI 拒绝策略标识"
:placeholder="$t('threadPool.customRejectedHandlerTip')"
@input="onInput()"
/>
</el-form-item>
@ -341,7 +344,7 @@
<el-table-column prop="pv" label="Pv" />
</el-table>
<span slot="footer" class="dialog-footer">
<el-button type="primary" @click="dialogPvVisible = false">Confirm</el-button>
<el-button type="primary" @click="dialogPvVisible = false">{{ $t('common.confirm') }}</el-button>
</span>
</el-dialog>
</div>
@ -460,16 +463,16 @@ export default {
size: 500,
dialogStatus: '',
textMap: {
update: 'Edit',
create: 'Create',
update: this.$t('common.edit'),
create: this.$t('common.create'),
},
rules: {
tenantId: [{ required: true, message: 'this is required', trigger: 'blur' }],
itemId: [{ required: true, message: 'this is required', trigger: 'blur' }],
tpId: [{ required: true, message: 'this is required', trigger: 'blur' }],
coreSize: [{ required: true, message: 'this is required', trigger: 'blur' }],
tenantId: [{ required: true, message: this.$t('message.requiredError'), trigger: 'blur' }],
itemId: [{ required: true, message: this.$t('message.requiredError'), trigger: 'blur' }],
tpId: [{ required: true, message: this.$t('message.requiredError'), trigger: 'blur' }],
coreSize: [{ required: true, message: this.$t('message.requiredError'), trigger: 'blur' }],
maxSize: [
{ required: true, message: 'this is required', trigger: 'blur' },
{ required: true, message: this.$t('message.requiredError'), trigger: 'blur' },
// {
// validator: (rule, value, callback) => {
// if (parseInt(value) < parseInt(this.temp.coreSize)) {
@ -481,15 +484,15 @@ export default {
// },
// },
],
queueType: [{ required: true, message: 'this is required', trigger: 'blur' }],
allowCoreThreadTimeOut: [{ required: true, message: 'this is required', trigger: 'blur' }],
keepAliveTime: [{ required: true, message: 'this is required', trigger: 'blur' }],
isAlarm: [{ required: true, message: 'this is required', trigger: 'blur' }],
capacityAlarm: [{ required: true, message: 'this is required', trigger: 'blur' }],
livenessAlarm: [{ required: true, message: 'this is required', trigger: 'blur' }],
rejectedType: [{ required: true, message: 'this is required', trigger: 'blur' }],
capacity: [{ required: true, message: 'this is required', trigger: 'blur' }],
executeTimeOut: [{ required: true, message: 'this is required', trigger: 'blur' }],
queueType: [{ required: true, message: this.$t('message.requiredError'), trigger: 'blur' }],
allowCoreThreadTimeOut: [{ required: true, message: this.$t('message.requiredError'), trigger: 'blur' }],
keepAliveTime: [{ required: true, message: this.$t('message.requiredError'), trigger: 'blur' }],
isAlarm: [{ required: true, message: this.$t('message.requiredError'), trigger: 'blur' }],
capacityAlarm: [{ required: true, message: this.$t('message.requiredError'), trigger: 'blur' }],
livenessAlarm: [{ required: true, message: this.$t('message.requiredError'), trigger: 'blur' }],
rejectedType: [{ required: true, message: this.$t('message.requiredError'), trigger: 'blur' }],
capacity: [{ required: true, message: this.$t('message.requiredError'), trigger: 'blur' }],
executeTimeOut: [{ required: true, message: this.$t('message.requiredError'), trigger: 'blur' }],
},
temp: {
id: undefined,
@ -531,8 +534,8 @@ export default {
threadPoolApi.alarmEnable(row).then(() => {
this.fetchData();
this.$notify({
title: 'Success',
message: 'Update Successfully',
title: this.$t('message.success'),
message: this.$t('message.updateSuccess'),
type: 'success',
duration: 2000,
});
@ -589,7 +592,7 @@ export default {
this.$refs['dataForm'].validate((valid) => {
if (parseInt(this.temp.maxSize) < parseInt(this.temp.coreSize)) {
this.$message({
message: '最大线程必须大于等于核心线程',
message: this.$t('threadPool.threadsNumErrorTip'),
type: 'warning',
});
return;
@ -606,8 +609,8 @@ export default {
this.fetchData();
this.dialogFormVisible = false;
this.$notify({
title: 'Success',
message: 'Created Successfully',
title: this.$t('message.success'),
message: this.$t('message.createdSuccess'),
type: 'success',
duration: 2000,
});
@ -645,7 +648,7 @@ export default {
if (valid) {
if (parseInt(this.temp.maxSize) < parseInt(this.temp.coreSize)) {
this.$message({
message: '最大线程必须大于等于核心线程',
message: this.$t('threadPool.threadsNumErrorTip'),
type: 'warning',
});
return;
@ -668,8 +671,8 @@ export default {
this.fetchData();
this.dialogFormVisible = false;
this.$notify({
title: 'Success',
message: 'Update Successfully',
title: this.$t('message.success'),
message: this.$t('message.updateSuccess'),
type: 'success',
duration: 2000,
});
@ -678,16 +681,16 @@ export default {
});
},
openDelConfirm(name) {
return this.$confirm(`此操作将删除 ${name}, 是否继续?`, '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
return this.$confirm(this.$t('message.deleteMessage', { name }), this.$t('common.hint'), {
confirmButtonText: this.$t('common.ok'),
cancelButtonText: this.$t('common.cancel'),
type: 'warning',
});
},
handleDelete(row) {
const role = localStorage.getItem('USER_ROLE') === 'ROLE_ADMIN' ? true : false;
if (!role) {
this.$message.error('请联系管理员删除');
this.$message.error(this.$t('message.NoDeletionPermissionTip'));
return;
}
@ -695,8 +698,8 @@ export default {
threadPoolApi.deleted(row).then((response) => {
this.fetchData();
this.$notify({
title: 'Success',
message: 'Delete Successfully',
title: this.$t('message.success'),
message: this.$t('message.deleteSuccess'),
type: 'success',
duration: 2000,
});

@ -61,6 +61,7 @@
<mybatis-plus.version>3.4.2</mybatis-plus.version>
<spring-boot.version>2.3.2.RELEASE</spring-boot.version>
<apollo.version>1.9.1</apollo.version>
<consul.version>2.2.4.RELEASE</consul.version>
<jetcd.version>0.7.3</jetcd.version>
<polaris.version>1.7.2</polaris.version>
<rocketmq.version>2.2.2</rocketmq.version>

Loading…
Cancel
Save