Compare commits
8 Commits
db9a3c2272
...
1e104c499d
Author | SHA1 | Date | |
---|---|---|---|
1e104c499d | |||
6a702a1f89 | |||
c1651beebd | |||
d5079f909d | |||
0c7d8a4121 | |||
4c28c0e322 | |||
74b3418193 | |||
bf64df28f1 |
44
.gitignore
vendored
Normal file
44
.gitignore
vendored
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
.mvn/
|
||||||
|
mvnw
|
||||||
|
mvnw.cmd
|
||||||
|
log/
|
||||||
|
target/
|
||||||
|
!.mvn/wrapper/maven-wrapper.jar
|
||||||
|
!**/src/main/**/target/
|
||||||
|
!**/src/test/**/target/
|
||||||
|
/bin/
|
||||||
|
|
||||||
|
### IntelliJ IDEA ###
|
||||||
|
.idea/
|
||||||
|
.idea/modules.xml
|
||||||
|
.idea/jarRepositories.xml
|
||||||
|
.idea/compiler.xml
|
||||||
|
.idea/libraries/
|
||||||
|
*.iws
|
||||||
|
*.iml
|
||||||
|
*.ipr
|
||||||
|
|
||||||
|
### Eclipse ###
|
||||||
|
.apt_generated
|
||||||
|
.classpath
|
||||||
|
.factorypath
|
||||||
|
.project
|
||||||
|
.settings
|
||||||
|
.springBeans
|
||||||
|
.sts4-cache
|
||||||
|
|
||||||
|
### NetBeans ###
|
||||||
|
/nbproject/private/
|
||||||
|
/nbbuild/
|
||||||
|
/dist/
|
||||||
|
/nbdist/
|
||||||
|
/.nb-gradle/
|
||||||
|
build/
|
||||||
|
!**/src/main/**/build/
|
||||||
|
!**/src/test/**/build/
|
||||||
|
|
||||||
|
### VS Code ###
|
||||||
|
.vscode/
|
||||||
|
|
||||||
|
### Mac OS ###
|
||||||
|
.DS_Store
|
31
README.md
31
README.md
@ -1,37 +1,36 @@
|
|||||||
# YanFrp
|
# YanFrp
|
||||||
|
|
||||||
基于javafx开发的 frp 客户端
|
基于javafx开发的 frp 客户端
|
||||||
后台管理面板使用的是开源的 frp 管理面板 [SakuraPanel](https://github.com/ZeroDream-CN/SakuraPanel)
|
|
||||||
|
|
||||||
ps:为了方便 YanFrp 我自己修改了些面板代码,如果想自己搭建需要改造
|
### 说明:
|
||||||
|
|
||||||
管理面板网址:https://frp.octopusyan.top/?page=login
|
- 后台管理面板使用的是开源的 frp 管理面板 [SakuraPanel](https://github.com/ZeroDream-CN/SakuraPanel)
|
||||||
|
- 管理面板网址:https://frp.octopusyan.top/?page=login
|
||||||
|
|
||||||
# 说明:
|
### 安装教程
|
||||||
|
|
||||||
1.
|
1. git clone https://gitee.com/octopus_yan/yan-frp.git
|
||||||
|
2. mvn jfx:jar
|
||||||
|
|
||||||
# 后续开发计划
|
### 后续?
|
||||||
|
|
||||||
- ~~HTTP Basic Auth~~ (已完成)
|
- ~~HTTP Basic Auth~~
|
||||||
- ~~添加p2p连接方式(xtcp,stcp)~~ (已完成)
|
- ~~添加连接方式(xtcp,stcp)~~
|
||||||
|
- ~~删除隧道~~
|
||||||
- HTTP URL路由
|
- HTTP URL路由
|
||||||
- 待添加...
|
- 待添加...
|
||||||
|
|
||||||
# 界面:
|
|
||||||
|
|
||||||
登录
|
### 界面:
|
||||||
|
|
||||||
|
#### 登录
|
||||||
![Image text](https://git.octopusyan.top/octopus_yan/YanFrp/raw/branch/master/readme/login.png)
|
![Image text](https://git.octopusyan.top/octopus_yan/YanFrp/raw/branch/master/readme/login.png)
|
||||||
|
|
||||||
注册
|
#### 注册
|
||||||
|
|
||||||
![Image text](https://git.octopusyan.top/octopus_yan/YanFrp/raw/branch/master/readme/register.png)
|
![Image text](https://git.octopusyan.top/octopus_yan/YanFrp/raw/branch/master/readme/register.png)
|
||||||
|
|
||||||
主界面
|
#### 主界面
|
||||||
|
|
||||||
![Image text](https://git.octopusyan.top/octopus_yan/YanFrp/raw/branch/master/readme/main.png)
|
![Image text](https://git.octopusyan.top/octopus_yan/YanFrp/raw/branch/master/readme/main.png)
|
||||||
|
|
||||||
主界面-运行
|
#### 主界面-运行
|
||||||
|
|
||||||
![Image text](https://git.octopusyan.top/octopus_yan/YanFrp/raw/branch/master/readme/main-run.png)
|
![Image text](https://git.octopusyan.top/octopus_yan/YanFrp/raw/branch/master/readme/main-run.png)
|
||||||
|
6
pom.xml
6
pom.xml
@ -5,9 +5,9 @@
|
|||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
<groupId>top.octopusyan</groupId>
|
<groupId>top.octopusyan</groupId>
|
||||||
<artifactId>YanFrp</artifactId>
|
<artifactId>yanfrp</artifactId>
|
||||||
<version>1.1.2</version>
|
<version>1.1.4</version>
|
||||||
<name>YanFrp</name>
|
<name>yanfrp</name>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
@ -55,7 +55,7 @@ public class YanFrpApplication extends Application {
|
|||||||
HttpLoggingInterceptor.Level.HEADERS
|
HttpLoggingInterceptor.Level.HEADERS
|
||||||
))
|
))
|
||||||
// 请求服务地址
|
// 请求服务地址
|
||||||
.serverPath("https://frp.octopusyan.top")
|
.serverPath("https://example.com")
|
||||||
// 是否打印日志
|
// 是否打印日志
|
||||||
.setLogEnabled(true)
|
.setLogEnabled(true)
|
||||||
// 设置日志打印策略
|
// 设置日志打印策略
|
||||||
|
@ -82,7 +82,7 @@ public abstract class BaseController<P extends Pane> implements Initializable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// app 版本信息
|
// app 版本信息
|
||||||
if (getAppVersionLabel() != null) getAppVersionLabel().setText("version : v" + ApplicatonStore.APP_VERSION);
|
if (getAppVersionLabel() != null) getAppVersionLabel().setText("v" + ApplicatonStore.APP_VERSION);
|
||||||
|
|
||||||
// 这个位置的左边第一个 JFXBtn 会莫名其妙会的焦点效果,启动时禁用焦点,取消按钮效果
|
// 这个位置的左边第一个 JFXBtn 会莫名其妙会的焦点效果,启动时禁用焦点,取消按钮效果
|
||||||
if (getFirstBtn() != null) getFirstBtn().setDisableVisualFocus(true);
|
if (getFirstBtn() != null) getFirstBtn().setDisableVisualFocus(true);
|
||||||
|
@ -20,18 +20,18 @@ public class ProxyConfig {
|
|||||||
private static final Map<String, Integer> typePort = new HashMap<>();
|
private static final Map<String, Integer> typePort = new HashMap<>();
|
||||||
|
|
||||||
static {
|
static {
|
||||||
serverPath.put("香港", "xg.frp.octopusyan.top");
|
serverPath.put("香港", "example.com");
|
||||||
serverPath.put("北京", "bj.frp.octopusyan.top");
|
serverPath.put("北京", "example.com");
|
||||||
serverPath.put("上海", "frp.octopusyan.top");
|
serverPath.put("上海", "example.com");
|
||||||
|
|
||||||
serverIp.put("香港", "101.32.202.135");
|
serverIp.put("香港", "127.0.0.1");
|
||||||
serverIp.put("北京", "112.125.120.135");
|
serverIp.put("北京", "127.0.0.1");
|
||||||
serverIp.put("上海", "81.68.214.67");
|
serverIp.put("上海", "127.0.0.1");
|
||||||
|
|
||||||
typePort.put("http", 80);
|
typePort.put("http", 80);
|
||||||
typePort.put("https", 80);
|
typePort.put("https", 443);
|
||||||
typePort.put("tcp", 0);
|
typePort.put("tcp", 25565);
|
||||||
typePort.put("udp", 0);
|
typePort.put("udp", 53);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -63,7 +63,7 @@ public class ProxyConfig {
|
|||||||
UDP,
|
UDP,
|
||||||
STCP,
|
STCP,
|
||||||
XTCP,
|
XTCP,
|
||||||
;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getServerPath(String serverName) {
|
public static String getServerPath(String serverName) {
|
||||||
|
@ -88,7 +88,7 @@ public class TextValidate {
|
|||||||
static {
|
static {
|
||||||
EmailFormat.setRegexPattern("^\\s*\\w+(?:\\.{0,1}[\\w-]+)*@[a-zA-Z0-9]+(?:[-.][a-zA-Z0-9]+)*\\.[a-zA-Z]+\\s*$");
|
EmailFormat.setRegexPattern("^\\s*\\w+(?:\\.{0,1}[\\w-]+)*@[a-zA-Z0-9]+(?:[-.][a-zA-Z0-9]+)*\\.[a-zA-Z]+\\s*$");
|
||||||
AccoountValidator.setRegexPattern("^[a-zA-Z0-9_-]*$");
|
AccoountValidator.setRegexPattern("^[a-zA-Z0-9_-]*$");
|
||||||
PortFormat.setRegexPattern("^([0-9]|[1-9]\\d{1,3}|[1-5]\\d{4}|6[0-4]\\d{4}|65[0-4]\\d{2}|655[0-2]\\d|6553[0-5])$");
|
PortFormat.setRegexPattern("^([1-9]|[1-9]\\d{1,3}|[1-5]\\d{4}|6[0-4]\\d{4}|65[0-4]\\d{2}|655[0-2]\\d|6553[0-5])$");
|
||||||
IpFormat.setRegexPattern("^(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])\\" +
|
IpFormat.setRegexPattern("^(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])\\" +
|
||||||
".(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])$");
|
".(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])$");
|
||||||
HttpUserFormat.setRegexPattern("^[a-zA-Z0-9_-]*$");
|
HttpUserFormat.setRegexPattern("^[a-zA-Z0-9_-]*$");
|
||||||
@ -113,7 +113,7 @@ public class TextValidate {
|
|||||||
|
|
||||||
RegexValidator validator = new RegexValidator(message);
|
RegexValidator validator = new RegexValidator(message);
|
||||||
|
|
||||||
validator.setRegexPattern("[a-zA-Z0-9_-]{" + min + "," + max + "}$");
|
validator.setRegexPattern("[\\w@-_\\.]{" + min + "," + max + "}$");
|
||||||
|
|
||||||
return validator;
|
return validator;
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,7 @@ import javafx.scene.input.KeyCode;
|
|||||||
import javafx.scene.layout.AnchorPane;
|
import javafx.scene.layout.AnchorPane;
|
||||||
import javafx.scene.layout.StackPane;
|
import javafx.scene.layout.StackPane;
|
||||||
import javafx.scene.paint.Color;
|
import javafx.scene.paint.Color;
|
||||||
|
import okhttp3.Call;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.kordamp.ikonli.javafx.FontIcon;
|
import org.kordamp.ikonli.javafx.FontIcon;
|
||||||
@ -162,8 +163,8 @@ public class LoginController extends BaseController<StackPane> implements Initia
|
|||||||
|
|
||||||
// 添加文本校验
|
// 添加文本校验
|
||||||
accountTextField.getValidators().add(TextValidate.AccoountRequired);
|
accountTextField.getValidators().add(TextValidate.AccoountRequired);
|
||||||
accountTextField.getValidators().add(TextValidate.AccoountValidator);
|
// accountTextField.getValidators().add(TextValidate.AccoountValidator);
|
||||||
accountTextField.getValidators().add(TextValidate.getLengthValidator(6, 18, "账号"));
|
accountTextField.getValidators().add(TextValidate.getLengthValidator(6, 25, "账号"));
|
||||||
passwordTextField.getValidators().add(TextValidate.PasswordRequired);
|
passwordTextField.getValidators().add(TextValidate.PasswordRequired);
|
||||||
seePwdTextField.getValidators().add(TextValidate.PasswordRequired);
|
seePwdTextField.getValidators().add(TextValidate.PasswordRequired);
|
||||||
|
|
||||||
@ -261,6 +262,11 @@ public class LoginController extends BaseController<StackPane> implements Initia
|
|||||||
.api(Api.Login)
|
.api(Api.Login)
|
||||||
.param(new LoginParam(accountTextField.getText(), tmpPwd.get()))
|
.param(new LoginParam(accountTextField.getText(), tmpPwd.get()))
|
||||||
.request(new OnHttpListener<String>() {
|
.request(new OnHttpListener<String>() {
|
||||||
|
@Override
|
||||||
|
public void onStart(Call call) {
|
||||||
|
Platform.runLater(() -> loginBtn.setDisable(true));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSucceed(String result) {
|
public void onSucceed(String result) {
|
||||||
// 登录出错
|
// 登录出错
|
||||||
@ -270,6 +276,8 @@ public class LoginController extends BaseController<StackPane> implements Initia
|
|||||||
}
|
}
|
||||||
// 登录成功
|
// 登录成功
|
||||||
setCsrf();
|
setCsrf();
|
||||||
|
// 用户token
|
||||||
|
setUSerToken();
|
||||||
// 记住我
|
// 记住我
|
||||||
ApplicatonStore.rememberMe(tmpPwd.get());
|
ApplicatonStore.rememberMe(tmpPwd.get());
|
||||||
// 跳转
|
// 跳转
|
||||||
@ -286,6 +294,30 @@ public class LoginController extends BaseController<StackPane> implements Initia
|
|||||||
public void onFail(Exception e) {
|
public void onFail(Exception e) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onEnd(Call call) {
|
||||||
|
Platform.runLater(() -> loginBtn.setDisable(false));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setUSerToken() {
|
||||||
|
EasyHttp.builder()
|
||||||
|
.api(Api.getServerConfiguration(1))
|
||||||
|
.request(new OnHttpListener<String>() {
|
||||||
|
@Override
|
||||||
|
public void onSucceed(String result) {
|
||||||
|
String config = JsoupUtil.getServerConfiguration(result);
|
||||||
|
int start = config.indexOf("user = ");
|
||||||
|
String userToken = config.substring(start + 7, config.indexOf("\n", start));
|
||||||
|
Platform.runLater(() -> ApplicatonStore.setUserToken(userToken));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFail(Exception e) {
|
||||||
|
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,17 +5,12 @@ import com.alibaba.fastjson.JSONObject;
|
|||||||
import com.jfoenix.controls.*;
|
import com.jfoenix.controls.*;
|
||||||
import com.jfoenix.validation.base.ValidatorBase;
|
import com.jfoenix.validation.base.ValidatorBase;
|
||||||
import javafx.application.Platform;
|
import javafx.application.Platform;
|
||||||
import javafx.beans.InvalidationListener;
|
|
||||||
import javafx.beans.Observable;
|
|
||||||
import javafx.beans.property.BooleanProperty;
|
import javafx.beans.property.BooleanProperty;
|
||||||
import javafx.beans.property.SimpleBooleanProperty;
|
import javafx.beans.property.SimpleBooleanProperty;
|
||||||
import javafx.beans.value.ObservableValue;
|
import javafx.beans.value.ObservableValue;
|
||||||
import javafx.collections.ObservableList;
|
import javafx.collections.ObservableList;
|
||||||
import javafx.fxml.FXMLLoader;
|
|
||||||
import javafx.fxml.Initializable;
|
import javafx.fxml.Initializable;
|
||||||
import javafx.scene.Node;
|
import javafx.scene.Node;
|
||||||
import javafx.scene.control.Button;
|
|
||||||
import javafx.scene.control.Label;
|
|
||||||
import javafx.scene.control.*;
|
import javafx.scene.control.*;
|
||||||
import javafx.scene.layout.AnchorPane;
|
import javafx.scene.layout.AnchorPane;
|
||||||
import javafx.scene.layout.HBox;
|
import javafx.scene.layout.HBox;
|
||||||
@ -35,9 +30,9 @@ import top.octopusyan.manager.http.request.ProxySetup;
|
|||||||
import top.octopusyan.model.ApplicatonStore;
|
import top.octopusyan.model.ApplicatonStore;
|
||||||
import top.octopusyan.model.ProxySetupModel;
|
import top.octopusyan.model.ProxySetupModel;
|
||||||
import top.octopusyan.utils.*;
|
import top.octopusyan.utils.*;
|
||||||
|
import top.octopusyan.view.ProxyListItemView;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.List;
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
import static top.octopusyan.model.ApplicatonStore.*;
|
import static top.octopusyan.model.ApplicatonStore.*;
|
||||||
@ -51,9 +46,6 @@ import static top.octopusyan.model.ApplicatonStore.*;
|
|||||||
public class MainController extends BaseController<StackPane> implements Initializable {
|
public class MainController extends BaseController<StackPane> implements Initializable {
|
||||||
|
|
||||||
public static final String PROXY_LIST_ITEM_CLASS = "proxyListItem";
|
public static final String PROXY_LIST_ITEM_CLASS = "proxyListItem";
|
||||||
public static final String PROXY_LIST_ITEM_STOP_CLASS = "proxyListItem-stop";
|
|
||||||
public static final String PROXY_LIST_ITEM_RUN_CLASS = "proxyListItem-run";
|
|
||||||
public static final String PROXY_LIST_ITEM_CLOSE_CLASS = "proxyListItem-close";
|
|
||||||
public static final String PROXY_LIST_ITEM_SELECT_CLASS = "proxyListItem-select";
|
public static final String PROXY_LIST_ITEM_SELECT_CLASS = "proxyListItem-select";
|
||||||
|
|
||||||
|
|
||||||
@ -88,7 +80,7 @@ public class MainController extends BaseController<StackPane> implements Initial
|
|||||||
public JFXButton copyDomainBtn;
|
public JFXButton copyDomainBtn;
|
||||||
|
|
||||||
/* 隧道列表控件 */
|
/* 隧道列表控件 */
|
||||||
public JFXListView<Label> proxyListView;
|
public JFXListView<ProxyListItemView> proxyListView;
|
||||||
public JFXButton addProxyBtn;
|
public JFXButton addProxyBtn;
|
||||||
|
|
||||||
/* 日志帮助面板控件 */
|
/* 日志帮助面板控件 */
|
||||||
@ -376,7 +368,8 @@ public class MainController extends BaseController<StackPane> implements Initial
|
|||||||
copyP2pConfig.setVisible(false);
|
copyP2pConfig.setVisible(false);
|
||||||
importP2pConfig.setVisible(true);
|
importP2pConfig.setVisible(true);
|
||||||
if (!children.contains(serverNamePane)) children.add(children.size() - 3, serverNamePane);
|
if (!children.contains(serverNamePane)) children.add(children.size() - 3, serverNamePane);
|
||||||
proxySetupModel.setServerName("");
|
String serverName = proxySetupModel.getServerName();
|
||||||
|
proxySetupModel.setServerName("提供者".equals(serverName) ? "" : serverName);
|
||||||
}
|
}
|
||||||
ObservableList<Node> children = p2pRolePane.getChildren();
|
ObservableList<Node> children = p2pRolePane.getChildren();
|
||||||
JFXButton remove = proxySetupModel.isProvider ? importP2pConfig : copyP2pConfig;
|
JFXButton remove = proxySetupModel.isProvider ? importP2pConfig : copyP2pConfig;
|
||||||
@ -388,7 +381,7 @@ public class MainController extends BaseController<StackPane> implements Initial
|
|||||||
// 隧道名称
|
// 隧道名称
|
||||||
proxySetupModel.proxyNameProperty().addListener((observable, oldValue, newValue) -> {
|
proxySetupModel.proxyNameProperty().addListener((observable, oldValue, newValue) -> {
|
||||||
if (proxyListView.getItems().size() > 0)
|
if (proxyListView.getItems().size() > 0)
|
||||||
proxyListView.getItems().get(selectProxy()).setText(newValue);
|
proxyListView.getItems().get(selectProxy()).setName(newValue);
|
||||||
});
|
});
|
||||||
|
|
||||||
// 运行状态监听
|
// 运行状态监听
|
||||||
@ -401,11 +394,8 @@ public class MainController extends BaseController<StackPane> implements Initial
|
|||||||
startProxyBtn.getStyleClass().add(newValue ? stopClass : startClass);
|
startProxyBtn.getStyleClass().add(newValue ? stopClass : startClass);
|
||||||
startProxyBtn.setText(newValue ? "停止" : "启动");
|
startProxyBtn.setText(newValue ? "停止" : "启动");
|
||||||
// 列表显示
|
// 列表显示
|
||||||
ObservableList<String> styleClass = proxyListView.getItems().get(selectProxy()).getStyleClass();
|
ProxyListItemView itemView = proxyListView.getItems().get(selectProxy());
|
||||||
styleClass.remove(PROXY_LIST_ITEM_RUN_CLASS);
|
itemView.setStatus(newValue);
|
||||||
styleClass.remove(PROXY_LIST_ITEM_STOP_CLASS);
|
|
||||||
styleClass.add(newValue ? PROXY_LIST_ITEM_RUN_CLASS : PROXY_LIST_ITEM_STOP_CLASS);
|
|
||||||
|
|
||||||
setDomainLink();
|
setDomainLink();
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -434,11 +424,11 @@ public class MainController extends BaseController<StackPane> implements Initial
|
|||||||
* 设置访问链接
|
* 设置访问链接
|
||||||
*/
|
*/
|
||||||
private void setDomainLink() {
|
private void setDomainLink() {
|
||||||
|
domainLink.setVisible(true);
|
||||||
|
copyDomainBtn.setVisible(true);
|
||||||
// 外网访问连接
|
// 外网访问连接
|
||||||
if (ProxyConfig.isHttp(proxySetupModel)) {
|
if (ProxyConfig.isHttp(proxySetupModel)) {
|
||||||
runingLabel.setText("启动成功!立即访问 ");
|
runingLabel.setText("启动成功!立即访问 ");
|
||||||
domainLink.setVisible(true);
|
|
||||||
copyDomainBtn.setVisible(true);
|
|
||||||
// http / https
|
// http / https
|
||||||
String prefix = proxySetupModel.getProxyType() + "://";
|
String prefix = proxySetupModel.getProxyType() + "://";
|
||||||
domainLink.textProperty().set(prefix + proxySetupModel.getDomain() + proxySetupModel.getDomainSuffix());
|
domainLink.textProperty().set(prefix + proxySetupModel.getDomain() + proxySetupModel.getDomainSuffix());
|
||||||
@ -450,7 +440,9 @@ public class MainController extends BaseController<StackPane> implements Initial
|
|||||||
copyDomainBtn.setVisible(false);
|
copyDomainBtn.setVisible(false);
|
||||||
} else {
|
} else {
|
||||||
// ssh / tcp
|
// ssh / tcp
|
||||||
domainLink.textProperty().set(ProxyConfig.getServerIP(ProxyConfig.getServerNode(proxySetupModel.getServer())) + ":" + proxySetupModel.getRemotePort());
|
domainLink.textProperty().set(
|
||||||
|
ProxyConfig.getServerIP(proxySetupModel.getServer()) + ":" + proxySetupModel.getRemotePort()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -545,9 +537,9 @@ public class MainController extends BaseController<StackPane> implements Initial
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
ProxySetup setup = proxySetupModel.get();
|
ProxySetup setup = proxySetupModel.get();
|
||||||
|
// 整理服务设置
|
||||||
String serverName = getAccount() + "_" + setup.getSort();
|
String serverName = setup.getProxy_name() + "_" + setup.getSort();
|
||||||
setup.setServer_name(EncryptionUtil.MD5_16(serverName));
|
setup.setServer_name(ApplicatonStore.getUserToken() + "." + EncryptionUtil.MD5_16(serverName));
|
||||||
setup.setId(null);
|
setup.setId(null);
|
||||||
setup.setRuning(false);
|
setup.setRuning(false);
|
||||||
setup.setSort(null);
|
setup.setSort(null);
|
||||||
@ -605,11 +597,11 @@ public class MainController extends BaseController<StackPane> implements Initial
|
|||||||
|
|
||||||
// 点击隧道列表
|
// 点击隧道列表
|
||||||
proxyListView.getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) -> {
|
proxyListView.getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) -> {
|
||||||
ObservableList<Label> items = proxyListView.getItems();
|
ObservableList<ProxyListItemView> items = proxyListView.getItems();
|
||||||
|
|
||||||
if (items.size() == 0) return;
|
if (items.size() == 0) return;
|
||||||
|
|
||||||
for (Label item : items) {
|
for (HBox item : items) {
|
||||||
item.getStyleClass().remove(PROXY_LIST_ITEM_SELECT_CLASS);
|
item.getStyleClass().remove(PROXY_LIST_ITEM_SELECT_CLASS);
|
||||||
}
|
}
|
||||||
if (newValue != null) {
|
if (newValue != null) {
|
||||||
@ -625,10 +617,9 @@ public class MainController extends BaseController<StackPane> implements Initial
|
|||||||
Platform.runLater(() -> {
|
Platform.runLater(() -> {
|
||||||
setup.set(false);
|
setup.set(false);
|
||||||
proxySetupModel.set(proxySetup);
|
proxySetupModel.set(proxySetup);
|
||||||
if (proxySetup.getId() != null) {
|
// 设置日志面板
|
||||||
FrpManager frpManager = frpUtilMap.get(proxySetup.getId().toString());
|
FrpManager frpManager = frpUtilMap.get(String.valueOf(proxySetup.getId()));
|
||||||
proxyLogPane.contentProperty().set(frpManager == null ? null : frpManager.getConsole());
|
proxyLogPane.contentProperty().set(frpManager == null ? null : frpManager.getConsole());
|
||||||
}
|
|
||||||
setup.set(true);
|
setup.set(true);
|
||||||
setDomainLink();
|
setDomainLink();
|
||||||
});
|
});
|
||||||
@ -725,20 +716,15 @@ public class MainController extends BaseController<StackPane> implements Initial
|
|||||||
p2pRoleView.setDisable(close); // p2p角色
|
p2pRoleView.setDisable(close); // p2p角色
|
||||||
p2pPwdTextField.setDisable(close); // p2p访问面板
|
p2pPwdTextField.setDisable(close); // p2p访问面板
|
||||||
|
|
||||||
ObservableList<String> styleClass = proxyListView.getItems().get(selectProxy()).getStyleClass();
|
// 运行状态
|
||||||
styleClass.remove(PROXY_LIST_ITEM_STOP_CLASS);
|
ProxyListItemView itemView = proxyListView.getItems().get(selectProxy());
|
||||||
styleClass.remove(PROXY_LIST_ITEM_RUN_CLASS);
|
itemView.setStatus(close ? null : proxySetupModel.isRunning());
|
||||||
styleClass.remove(PROXY_LIST_ITEM_CLOSE_CLASS);
|
|
||||||
if (close) {
|
|
||||||
styleClass.add(PROXY_LIST_ITEM_CLOSE_CLASS);
|
|
||||||
} else {
|
|
||||||
styleClass.add(proxySetupModel.isRunning() ? PROXY_LIST_ITEM_RUN_CLASS : PROXY_LIST_ITEM_STOP_CLASS);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initProxyListView() {
|
private void initProxyListView() {
|
||||||
ObservableList<ProxySetup> proxyList = proxyList();
|
ObservableList<ProxySetup> proxyList = proxyList();
|
||||||
for (ProxySetup proxy : proxyList.subList(proxyListView.getItems().size(), proxyList.size())) {
|
for (ProxySetup proxy : proxyList) {
|
||||||
setProxyListView(proxyList.indexOf(proxy), proxy);
|
setProxyListView(proxyList.indexOf(proxy), proxy);
|
||||||
}
|
}
|
||||||
// 设置选中
|
// 设置选中
|
||||||
@ -746,21 +732,57 @@ public class MainController extends BaseController<StackPane> implements Initial
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void setProxyListView(int index, ProxySetup setup) {
|
private void setProxyListView(int index, ProxySetup setup) {
|
||||||
ObservableList<Label> items = proxyListView.getItems();
|
ObservableList<ProxyListItemView> items = proxyListView.getItems();
|
||||||
try {
|
// 是否添加
|
||||||
Label label = FXMLLoader.load(getClass().getResource("/fxml/proxyItem.fxml"));
|
boolean isNew = index >= items.size();
|
||||||
label.textProperty().set(setup.getProxy_name());
|
ProxyListItemView itemView;
|
||||||
ObservableList<String> styleClass = label.getStyleClass();
|
if (isNew) {
|
||||||
styleClass.addAll(PROXY_LIST_ITEM_CLASS, setup.isRuning() ? PROXY_LIST_ITEM_RUN_CLASS : PROXY_LIST_ITEM_STOP_CLASS);
|
itemView = new ProxyListItemView();
|
||||||
if (selectProxy() == index) styleClass.add(PROXY_LIST_ITEM_SELECT_CLASS);
|
itemView.setName(setup.getProxy_name());
|
||||||
if (index < items.size()) {
|
|
||||||
items.set(index, label);
|
|
||||||
} else {
|
} else {
|
||||||
items.add(label);
|
itemView = items.get(index);
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
// 运行状态
|
||||||
e.printStackTrace();
|
itemView.setStatus(setup.isRuning());
|
||||||
|
// 点击删除
|
||||||
|
itemView.getDeleteBtn().setOnMouseClicked(event -> deleteProxyListItem(itemView));
|
||||||
|
// 是否选中
|
||||||
|
if (selectProxy() == index) itemView.getStyleClass().add(PROXY_LIST_ITEM_SELECT_CLASS);
|
||||||
|
// 添加
|
||||||
|
if (isNew) items.add(index, itemView);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void deleteProxyListItem(ProxyListItemView itemView) {
|
||||||
|
ObservableList<ProxyListItemView> items = proxyListView.getItems();
|
||||||
|
int index = items.indexOf(itemView);
|
||||||
|
if (index < 0) return;
|
||||||
|
if (items.size() == 1) {
|
||||||
|
AlertUtil.error("最后一个连接不可删除!").show();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ProxySetup setup = proxyList().get(index);
|
||||||
|
|
||||||
|
// 关闭连接
|
||||||
|
String key = String.valueOf(setup.getId());
|
||||||
|
FrpManager frpManager = frpUtilMap.get(key);
|
||||||
|
if (setup.isRuning() || frpManager != null) {
|
||||||
|
frpManager.stop();
|
||||||
|
frpUtilMap.remove(key);
|
||||||
|
}
|
||||||
|
// 调用删除接口
|
||||||
|
if (setup.getId() != null) {
|
||||||
|
ProxyManager.delete(setup.getId());
|
||||||
|
}
|
||||||
|
// 列表删除
|
||||||
|
items.remove(itemView);
|
||||||
|
proxyList().remove(setup);
|
||||||
|
// 重新选择
|
||||||
|
if (selectProxy() == index) {
|
||||||
|
proxyListView.getSelectionModel().select(-1);
|
||||||
|
proxyListView.getSelectionModel().select(index < items.size() ? index : items.size() - 1);
|
||||||
|
} else if (selectProxy() > index)
|
||||||
|
selectProxy(selectProxy() - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -4,6 +4,7 @@ import javafx.application.Platform;
|
|||||||
import javafx.scene.control.TextArea;
|
import javafx.scene.control.TextArea;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.commons.io.FileUtils;
|
import org.apache.commons.io.FileUtils;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import top.octopusyan.http.EasyHttp;
|
import top.octopusyan.http.EasyHttp;
|
||||||
@ -16,6 +17,7 @@ import top.octopusyan.utils.JsoupUtil;
|
|||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.nio.file.Files;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -24,6 +26,7 @@ import java.util.*;
|
|||||||
* @description : frp 客户端 工具
|
* @description : frp 客户端 工具
|
||||||
* @create : 2022-4-7 23:19
|
* @create : 2022-4-7 23:19
|
||||||
*/
|
*/
|
||||||
|
@Slf4j
|
||||||
public class FrpManager {
|
public class FrpManager {
|
||||||
public static final String serverConfigHeader = "yanfrp://";
|
public static final String serverConfigHeader = "yanfrp://";
|
||||||
public static List<FrpManager> frpcList = new ArrayList<>();
|
public static List<FrpManager> frpcList = new ArrayList<>();
|
||||||
@ -94,6 +97,7 @@ public class FrpManager {
|
|||||||
Platform.runLater(() -> {
|
Platform.runLater(() -> {
|
||||||
model.setRunning(false);
|
model.setRunning(false);
|
||||||
console.appendText("yan-frp-info:已停止\n");
|
console.appendText("yan-frp-info:已停止\n");
|
||||||
|
log.info("yan-frp-info-" + model.getProxyName() + ":已停止");
|
||||||
});
|
});
|
||||||
|
|
||||||
// 尝试删除缓存配置文件
|
// 尝试删除缓存配置文件
|
||||||
@ -129,6 +133,7 @@ public class FrpManager {
|
|||||||
}
|
}
|
||||||
frpcConfigFile.deleteOnExit();
|
frpcConfigFile.deleteOnExit();
|
||||||
|
|
||||||
|
|
||||||
// 写入服务配置
|
// 写入服务配置
|
||||||
FileUtils.write(frpcConfigFile, getUserFrpServerConfig(model.get().getNode()), StandardCharsets.UTF_8);
|
FileUtils.write(frpcConfigFile, getUserFrpServerConfig(model.get().getNode()), StandardCharsets.UTF_8);
|
||||||
// 写入隧道配置
|
// 写入隧道配置
|
||||||
@ -136,17 +141,25 @@ public class FrpManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static String getUserFrpServerConfig(int node) {
|
public String getUserFrpServerConfig(int node) {
|
||||||
|
boolean isp2p = "xtcp".equals(model.getProxyType()) || "stcp".equals(model.getProxyType());
|
||||||
String config = serverConfigraution.get(node);
|
String config = serverConfigraution.get(node);
|
||||||
if (StringUtils.isNotEmpty(config)) return config;
|
if (StringUtils.isNotEmpty(config) && !isp2p) return config;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
if (StringUtils.isEmpty(config)) {
|
||||||
String result = EasyHttp.builder()
|
String result = EasyHttp.builder()
|
||||||
.api(Api.getServerConfiguration(node))
|
.api(Api.getServerConfiguration(node))
|
||||||
.pathParam(String.valueOf(node))
|
|
||||||
.execute(new ResponseClass<String>() {
|
.execute(new ResponseClass<String>() {
|
||||||
});
|
});
|
||||||
config = JsoupUtil.getServerConfiguration(result);
|
config = JsoupUtil.getServerConfiguration(result);
|
||||||
if (StringUtils.isNotEmpty(config)) serverConfigraution.put(node, config);
|
if (StringUtils.isNotEmpty(config)) serverConfigraution.put(node, config);
|
||||||
|
}
|
||||||
|
|
||||||
|
// user配置 会加在访问服务端名称的前边 , 清空让访问到
|
||||||
|
if (isp2p && !model.isProvider())
|
||||||
|
config = config.replaceAll("user = .*", "");
|
||||||
|
|
||||||
return config;
|
return config;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
@ -154,14 +167,14 @@ public class FrpManager {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getProxyFrpConfig(ProxySetupModel setup) {
|
public String getProxyFrpConfig(ProxySetupModel setup) {
|
||||||
String n = "\n";
|
String n = "\n";
|
||||||
boolean ishttp = setup.getProxyType().contains("http");
|
boolean ishttp = setup.getProxyType().contains("http");
|
||||||
boolean isp2p = "xtcp".equals(setup.getProxyType()) || "stcp".equals(setup.getProxyType());
|
boolean isp2p = "xtcp".equals(setup.getProxyType()) || "stcp".equals(setup.getProxyType());
|
||||||
// 基础配置
|
// 基础配置
|
||||||
StringBuilder stringBuilder = new StringBuilder("[");
|
StringBuilder stringBuilder = new StringBuilder("[");
|
||||||
// 服务名称
|
// 服务名称
|
||||||
StringBuilder serverName = new StringBuilder(ApplicatonStore.getAccount()+"_"+setup.getSort());
|
StringBuilder serverName = new StringBuilder(setup.getProxyName()).append("_").append(setup.getSort());
|
||||||
// p2p 服务名
|
// p2p 服务名
|
||||||
if (isp2p) {
|
if (isp2p) {
|
||||||
if (setup.isProvider()) {
|
if (setup.isProvider()) {
|
||||||
@ -169,10 +182,8 @@ public class FrpManager {
|
|||||||
serverName = new StringBuilder(EncryptionUtil.MD5_16(serverName.toString()));
|
serverName = new StringBuilder(EncryptionUtil.MD5_16(serverName.toString()));
|
||||||
} else {
|
} else {
|
||||||
// 访问者
|
// 访问者
|
||||||
serverName.append(setup.getServerName()).append("_visitor");
|
serverName = new StringBuilder(setup.getServerName()).append("_visitor");
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
serverName.append(ApplicatonStore.getAccount()).append("_").append(setup.getSort());
|
|
||||||
}
|
}
|
||||||
stringBuilder.append(serverName).append("]\n");
|
stringBuilder.append(serverName).append("]\n");
|
||||||
stringBuilder.append("privilege_mode = true\n")
|
stringBuilder.append("privilege_mode = true\n")
|
||||||
@ -274,7 +285,7 @@ public class FrpManager {
|
|||||||
throws IOException {
|
throws IOException {
|
||||||
OutputStream output = null;
|
OutputStream output = null;
|
||||||
try {
|
try {
|
||||||
output = new FileOutputStream(FrpManager.frpc);
|
output = Files.newOutputStream(FrpManager.frpc.toPath());
|
||||||
byte[] buf = new byte[1024];
|
byte[] buf = new byte[1024];
|
||||||
int bytesRead;
|
int bytesRead;
|
||||||
while ((bytesRead = input.read(buf)) > 0) {
|
while ((bytesRead = input.read(buf)) > 0) {
|
||||||
@ -293,6 +304,7 @@ public class FrpManager {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
|
log.info("yan-frp-info:正在启动");
|
||||||
Platform.runLater(() -> console.appendText("yan-frp-info:正在启动\n"));
|
Platform.runLater(() -> console.appendText("yan-frp-info:正在启动\n"));
|
||||||
try {
|
try {
|
||||||
// 检查客户端文件
|
// 检查客户端文件
|
||||||
@ -303,7 +315,7 @@ public class FrpManager {
|
|||||||
|
|
||||||
// 执行命令
|
// 执行命令
|
||||||
String command = FRPC_CLIENT_FILE_PATH + " -c " + getConfigFilePath();
|
String command = FRPC_CLIENT_FILE_PATH + " -c " + getConfigFilePath();
|
||||||
System.out.println(command);
|
log.info(command);
|
||||||
exec = Runtime.getRuntime().exec(command, null, frpconfigDir);
|
exec = Runtime.getRuntime().exec(command, null, frpconfigDir);
|
||||||
|
|
||||||
// 设置运行状态
|
// 设置运行状态
|
||||||
@ -316,7 +328,7 @@ public class FrpManager {
|
|||||||
String line;
|
String line;
|
||||||
while ((line = readStdout.readLine()) != null && !exit) {
|
while ((line = readStdout.readLine()) != null && !exit) {
|
||||||
String finalLine = line;
|
String finalLine = line;
|
||||||
System.out.println(line);
|
log.info(line);
|
||||||
Platform.runLater(() -> console.appendText(finalLine + "\n"));
|
Platform.runLater(() -> console.appendText(finalLine + "\n"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -325,6 +337,8 @@ public class FrpManager {
|
|||||||
// TODO 报错
|
// TODO 报错
|
||||||
Platform.runLater(() -> console.appendText("yan-frp-error:" + e.getMessage() + "\n"));
|
Platform.runLater(() -> console.appendText("yan-frp-error:" + e.getMessage() + "\n"));
|
||||||
Platform.runLater(() -> console.appendText("yan-frp-error:启动失败\n"));
|
Platform.runLater(() -> console.appendText("yan-frp-error:启动失败\n"));
|
||||||
|
log.info("yan-frp-error:" + e.getMessage());
|
||||||
|
log.info("yan-frp-error:启动失败");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -61,9 +61,9 @@ public class ProxyManager {
|
|||||||
EasyHttp.builder()
|
EasyHttp.builder()
|
||||||
.api(Api.DeleteProxy())
|
.api(Api.DeleteProxy())
|
||||||
.pathParam(String.valueOf(id), csrf)
|
.pathParam(String.valueOf(id), csrf)
|
||||||
.request(new OnHttpListener<Void>() {
|
.request(new OnHttpListener<String>() {
|
||||||
@Override
|
@Override
|
||||||
public void onSucceed(Void result) {
|
public void onSucceed(String result) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,8 +44,8 @@ public class Api {
|
|||||||
);
|
);
|
||||||
|
|
||||||
/** 获取服务器配置 */
|
/** 获取服务器配置 */
|
||||||
public static PathParamApi<String> getServerConfiguration(int node){
|
public static NotParamApi<String> getServerConfiguration(int node){
|
||||||
return new PathParamApi<>(
|
return new NotParamApi<>(
|
||||||
"/?page=panel&module=configuration&server="+node,
|
"/?page=panel&module=configuration&server="+node,
|
||||||
HttpConstant.Method.GET
|
HttpConstant.Method.GET
|
||||||
);
|
);
|
||||||
@ -75,7 +75,7 @@ public class Api {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** 删除隧道 */
|
/** 删除隧道 */
|
||||||
public static PathParamApi<Void> DeleteProxy() {
|
public static PathParamApi<String> DeleteProxy() {
|
||||||
return new PathParamApi<>(
|
return new PathParamApi<>(
|
||||||
"/?page=panel&module=proxies&delete={0}&csrf=" + ProxyManager.getCsrf(),
|
"/?page=panel&module=proxies&delete={0}&csrf=" + ProxyManager.getCsrf(),
|
||||||
HttpConstant.Method.GET
|
HttpConstant.Method.GET
|
||||||
|
@ -43,6 +43,7 @@ public class ApplicatonStore {
|
|||||||
private static final SimpleBooleanProperty registerSuccess = new SimpleBooleanProperty();
|
private static final SimpleBooleanProperty registerSuccess = new SimpleBooleanProperty();
|
||||||
private static final ObservableList<ProxySetup> proxyList = FXCollections.observableList(new ArrayList<>());
|
private static final ObservableList<ProxySetup> proxyList = FXCollections.observableList(new ArrayList<>());
|
||||||
private static final SimpleIntegerProperty selectProxy = new SimpleIntegerProperty(0);
|
private static final SimpleIntegerProperty selectProxy = new SimpleIntegerProperty(0);
|
||||||
|
private static final SimpleStringProperty userToken = new SimpleStringProperty();
|
||||||
public static String selectProxyName = null;
|
public static String selectProxyName = null;
|
||||||
|
|
||||||
public static void setAccount(String account) {
|
public static void setAccount(String account) {
|
||||||
@ -121,6 +122,18 @@ public class ApplicatonStore {
|
|||||||
proxyList.add(proxySetup);
|
proxyList.add(proxySetup);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static SimpleStringProperty userTokenProperty() {
|
||||||
|
return userToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getUserToken() {
|
||||||
|
return userToken.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setUserToken(String token) {
|
||||||
|
userToken.set(token);
|
||||||
|
}
|
||||||
|
|
||||||
public static void selectProxy(int selectProxy) {
|
public static void selectProxy(int selectProxy) {
|
||||||
ApplicatonStore.selectProxy.set(selectProxy);
|
ApplicatonStore.selectProxy.set(selectProxy);
|
||||||
}
|
}
|
||||||
|
80
src/main/java/top/octopusyan/view/ProxyListItemView.java
Normal file
80
src/main/java/top/octopusyan/view/ProxyListItemView.java
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
package top.octopusyan.view;
|
||||||
|
|
||||||
|
import com.jfoenix.controls.JFXButton;
|
||||||
|
import javafx.beans.property.StringProperty;
|
||||||
|
import javafx.fxml.FXML;
|
||||||
|
import javafx.fxml.FXMLLoader;
|
||||||
|
import javafx.scene.control.Label;
|
||||||
|
import javafx.scene.layout.HBox;
|
||||||
|
import org.kordamp.ikonli.javafx.FontIcon;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 隧道列表视图子项
|
||||||
|
*
|
||||||
|
* @author : octopus yan
|
||||||
|
* @email : octopus_yan@foxmail.com
|
||||||
|
* @description :
|
||||||
|
* @create : 2022-4-23 16:40
|
||||||
|
*/
|
||||||
|
public class ProxyListItemView extends HBox {
|
||||||
|
private String style = null;
|
||||||
|
@FXML
|
||||||
|
private Label proxyName;
|
||||||
|
@FXML
|
||||||
|
private FontIcon statusIcon;
|
||||||
|
@FXML
|
||||||
|
private JFXButton deleteBtn;
|
||||||
|
|
||||||
|
public ProxyListItemView() {
|
||||||
|
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("/fxml/proxyItem.fxml"));
|
||||||
|
fxmlLoader.setRoot(this);
|
||||||
|
fxmlLoader.setController(this);
|
||||||
|
|
||||||
|
try {
|
||||||
|
fxmlLoader.load();
|
||||||
|
} catch (IOException exception) {
|
||||||
|
throw new RuntimeException(exception);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置运行状态
|
||||||
|
* <p> true:run false:stop null:disable
|
||||||
|
*
|
||||||
|
* @param status 运行状态
|
||||||
|
*/
|
||||||
|
public void setStatus(Boolean status) {
|
||||||
|
// 初始化样式
|
||||||
|
if (style == null) style = statusIcon.getStyle();
|
||||||
|
|
||||||
|
if (status == null) {
|
||||||
|
statusIcon.setStyle(style + "-fx-icon-color: linear-gradient(grey, #524e50);");
|
||||||
|
} else if (status) {
|
||||||
|
statusIcon.setStyle(style + "-fx-icon-color: linear-gradient(#95f257, #91e5ac);");
|
||||||
|
} else {
|
||||||
|
statusIcon.setStyle(style + "-fx-icon-color: linear-gradient(#f25757, #e591b1);");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String proxyName) {
|
||||||
|
this.proxyName.setText(proxyName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public StringProperty textProperty() {
|
||||||
|
return proxyName.textProperty();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Label getProxyName() {
|
||||||
|
return proxyName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JFXButton getDeleteBtn() {
|
||||||
|
return deleteBtn;
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum Status {
|
||||||
|
RUN, STOP, DISABLED
|
||||||
|
}
|
||||||
|
}
|
@ -51,26 +51,10 @@
|
|||||||
-fx-opacity: 0.7;
|
-fx-opacity: 0.7;
|
||||||
-fx-background-color: linear-gradient(#9198e5, #57b4f2);
|
-fx-background-color: linear-gradient(#9198e5, #57b4f2);
|
||||||
}
|
}
|
||||||
#proxyListView .list-cell:hover lable, #proxyListView .list-cell:selected label, .proxyListItem-select{
|
#proxyListView .list-cell:hover lable, #proxyListView .list-cell:selected label, .proxyListItem-select label{
|
||||||
-fx-text-fill: white;
|
-fx-text-fill: white;
|
||||||
}
|
}
|
||||||
|
|
||||||
.proxyListItemLabel {
|
|
||||||
-fx-font-size: 16px;
|
|
||||||
}
|
|
||||||
.proxyListItemIcon {
|
|
||||||
-fx-font-size: 14px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.proxyListItem-run FontIcon {
|
|
||||||
-fx-icon-color: linear-gradient(#95f257, #91e5ac);
|
|
||||||
}
|
|
||||||
.proxyListItem-stop FontIcon {
|
|
||||||
-fx-icon-color: linear-gradient(#f25757, #e591b1);
|
|
||||||
}
|
|
||||||
.proxyListItem-close FontIcon {
|
|
||||||
-fx-icon-color: linear-gradient(grey, #524e50);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 面板背景 */
|
/* 面板背景 */
|
||||||
#proxySetupPane, #proxyListPane, .whitePane {
|
#proxySetupPane, #proxyListPane, .whitePane {
|
||||||
|
@ -157,7 +157,7 @@
|
|||||||
<Cursor fx:constant="HAND"/>
|
<Cursor fx:constant="HAND"/>
|
||||||
</cursor>
|
</cursor>
|
||||||
</JFXButton>
|
</JFXButton>
|
||||||
<JFXButton fx:id="importP2pConfig" text="从剪切板导入">
|
<JFXButton fx:id="importP2pConfig" text="导入">
|
||||||
<HBox.margin>
|
<HBox.margin>
|
||||||
<Insets left="10.0"/>
|
<Insets left="10.0"/>
|
||||||
</HBox.margin>
|
</HBox.margin>
|
||||||
@ -190,7 +190,6 @@
|
|||||||
</HBox>
|
</HBox>
|
||||||
</HBox>
|
</HBox>
|
||||||
<HBox fx:id="serverNamePane" alignment="CENTER_LEFT" styleClass="proxySetupItemBox">
|
<HBox fx:id="serverNamePane" alignment="CENTER_LEFT" styleClass="proxySetupItemBox">
|
||||||
<children>
|
|
||||||
<Label alignment="CENTER_RIGHT" prefHeight="Infinity" prefWidth="100.0"
|
<Label alignment="CENTER_RIGHT" prefHeight="Infinity" prefWidth="100.0"
|
||||||
styleClass="proxySetupLabel" text="服务名称">
|
styleClass="proxySetupLabel" text="服务名称">
|
||||||
<HBox.margin>
|
<HBox.margin>
|
||||||
@ -220,7 +219,6 @@
|
|||||||
<Insets left="10.0"/>
|
<Insets left="10.0"/>
|
||||||
</HBox.margin>
|
</HBox.margin>
|
||||||
</JFXButton>
|
</JFXButton>
|
||||||
</children>
|
|
||||||
</HBox>
|
</HBox>
|
||||||
<HBox fx:id="p2pPwdPane" alignment="CENTER_LEFT" styleClass="proxySetupItemBox">
|
<HBox fx:id="p2pPwdPane" alignment="CENTER_LEFT" styleClass="proxySetupItemBox">
|
||||||
<Label alignment="CENTER_RIGHT" prefHeight="Infinity" prefWidth="100.0"
|
<Label alignment="CENTER_RIGHT" prefHeight="Infinity" prefWidth="100.0"
|
||||||
@ -356,7 +354,6 @@
|
|||||||
</VBox>
|
</VBox>
|
||||||
<AnchorPane prefHeight="Infinity" prefWidth="Infinity" GridPane.rowIndex="1">
|
<AnchorPane prefHeight="Infinity" prefWidth="Infinity" GridPane.rowIndex="1">
|
||||||
<JFXTabPane fx:id="tabPane" prefHeight="200.0" prefWidth="520.0" styleClass="mainPane">
|
<JFXTabPane fx:id="tabPane" prefHeight="200.0" prefWidth="520.0" styleClass="mainPane">
|
||||||
<tabs>
|
|
||||||
<Tab fx:id="proxyLogPane" text=" 日志 "/>
|
<Tab fx:id="proxyLogPane" text=" 日志 "/>
|
||||||
<Tab text="常见问题">
|
<Tab text="常见问题">
|
||||||
<VBox minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0"
|
<VBox minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0"
|
||||||
@ -376,7 +373,6 @@
|
|||||||
|
|
||||||
<!-- </VBox>-->
|
<!-- </VBox>-->
|
||||||
<!-- </Tab>-->
|
<!-- </Tab>-->
|
||||||
</tabs>
|
|
||||||
</JFXTabPane>
|
</JFXTabPane>
|
||||||
<JFXButton fx:id="clearLogBtn" layoutX="480.0" layoutY="-1.0" prefHeight="35.0" prefWidth="26.0"
|
<JFXButton fx:id="clearLogBtn" layoutX="480.0" layoutY="-1.0" prefHeight="35.0" prefWidth="26.0"
|
||||||
text="">
|
text="">
|
||||||
@ -412,7 +408,7 @@
|
|||||||
<Insets top="80.0"/>
|
<Insets top="80.0"/>
|
||||||
</VBox.margin>
|
</VBox.margin>
|
||||||
<font>
|
<font>
|
||||||
<Font size="11.0"/>
|
<Font size="12.0"/>
|
||||||
</font>
|
</font>
|
||||||
<opaqueInsets>
|
<opaqueInsets>
|
||||||
<Insets/>
|
<Insets/>
|
||||||
|
@ -1,12 +1,18 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
|
|
||||||
|
<?import com.jfoenix.controls.JFXButton?>
|
||||||
<?import javafx.geometry.Insets?>
|
<?import javafx.geometry.Insets?>
|
||||||
<?import javafx.scene.control.Label?>
|
<?import javafx.scene.control.Label?>
|
||||||
|
<?import javafx.scene.layout.HBox?>
|
||||||
<?import javafx.scene.text.Font?>
|
<?import javafx.scene.text.Font?>
|
||||||
<?import org.kordamp.ikonli.javafx.FontIcon?>
|
<?import org.kordamp.ikonli.javafx.FontIcon?>
|
||||||
<Label text=" 默认连接" xmlns="http://javafx.com/javafx/8.0.171" xmlns:fx="http://javafx.com/fxml/1">
|
<?import javafx.scene.Cursor?>
|
||||||
|
<fx:root xmlns="http://javafx.com/javafx/8.0.171" xmlns:fx="http://javafx.com/fxml/1"
|
||||||
|
prefWidth="170.0" maxWidth="170.0" type="HBox">
|
||||||
|
<Label fx:id="proxyName" text="默认连接" prefWidth="150" maxWidth="150">
|
||||||
<graphic>
|
<graphic>
|
||||||
<FontIcon iconLiteral="fa-circle" iconSize="14"/>
|
<FontIcon fx:id="statusIcon" iconLiteral="fa-circle" iconSize="14"/>
|
||||||
</graphic>
|
</graphic>
|
||||||
<font>
|
<font>
|
||||||
<Font size="16.0"/>
|
<Font size="16.0"/>
|
||||||
@ -15,3 +21,12 @@
|
|||||||
<Insets left="10.0"/>
|
<Insets left="10.0"/>
|
||||||
</padding>
|
</padding>
|
||||||
</Label>
|
</Label>
|
||||||
|
<JFXButton fx:id="deleteBtn" text="">
|
||||||
|
<graphic>
|
||||||
|
<FontIcon iconLiteral="fa-close" iconSize="14" iconColor="grey"/>
|
||||||
|
</graphic>
|
||||||
|
<cursor>
|
||||||
|
<Cursor fx:constant="HAND"/>
|
||||||
|
</cursor>
|
||||||
|
</JFXButton>
|
||||||
|
</fx:root>
|
||||||
|
@ -1,14 +1,18 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
<?import com.jfoenix.controls.*?>
|
<?import com.jfoenix.controls.JFXButton?>
|
||||||
|
<?import com.jfoenix.controls.JFXPasswordField?>
|
||||||
|
<?import com.jfoenix.controls.JFXTextField?>
|
||||||
<?import javafx.scene.control.Label?>
|
<?import javafx.scene.control.Label?>
|
||||||
<?import javafx.scene.image.ImageView?>
|
<?import javafx.scene.image.ImageView?>
|
||||||
<?import javafx.scene.layout.*?>
|
<?import javafx.scene.layout.AnchorPane?>
|
||||||
|
<?import javafx.scene.layout.HBox?>
|
||||||
|
<?import javafx.scene.layout.StackPane?>
|
||||||
|
<?import javafx.scene.layout.VBox?>
|
||||||
<?import javafx.scene.shape.Rectangle?>
|
<?import javafx.scene.shape.Rectangle?>
|
||||||
<?import javafx.scene.text.*?>
|
<?import javafx.scene.text.Font?>
|
||||||
<StackPane fx:id="root" prefHeight="330.0" prefWidth="430.0" stylesheets="@../css/register.css"
|
|
||||||
xmlns="http://javafx.com/javafx/8.0.171" xmlns:fx="http://javafx.com/fxml/1"
|
<StackPane fx:id="root" prefHeight="330.0" prefWidth="430.0" stylesheets="@../css/register.css" xmlns="http://javafx.com/javafx/8.0.171" xmlns:fx="http://javafx.com/fxml/1" fx:controller="top.octopusyan.controller.RegisterController">
|
||||||
fx:controller="top.octopusyan.controller.RegisterController">
|
|
||||||
<ImageView fx:id="registBkgPane" fitHeight="330.0" fitWidth="430.0">
|
<ImageView fx:id="registBkgPane" fitHeight="330.0" fitWidth="430.0">
|
||||||
<clip>
|
<clip>
|
||||||
<Rectangle height="330" width="430">
|
<Rectangle height="330" width="430">
|
||||||
@ -17,26 +21,24 @@
|
|||||||
</Rectangle>
|
</Rectangle>
|
||||||
</clip>
|
</clip>
|
||||||
</ImageView>
|
</ImageView>
|
||||||
<VBox fx:id="registMainPane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity"
|
<VBox fx:id="registMainPane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="330.0" prefWidth="430.0">
|
||||||
prefHeight="330.0" prefWidth="430.0">
|
|
||||||
<AnchorPane fx:id="registTopPane" prefHeight="130.0" prefWidth="430.0">
|
<AnchorPane fx:id="registTopPane" prefHeight="130.0" prefWidth="430.0">
|
||||||
<JFXButton fx:id="titleLable" disable="true" prefHeight="35.0" prefWidth="64.0" text="YanFrp" />
|
<JFXButton fx:id="titleLable" disable="true" prefHeight="35.0" prefWidth="64.0" text="YanFrp" />
|
||||||
<JFXButton fx:id="minimizeBtn" layoutX="360.0" prefHeight="35.0" prefWidth="36.0" text="—" />
|
<JFXButton fx:id="minimizeBtn" layoutX="360.0" prefHeight="35.0" prefWidth="36.0" text="—" />
|
||||||
<JFXButton fx:id="closeBtn" layoutX="395.0" prefHeight="35.0" prefWidth="36.0" text="X" />
|
<JFXButton fx:id="closeBtn" layoutX="395.0" prefHeight="35.0" prefWidth="36.0" text="X" />
|
||||||
</AnchorPane>
|
</AnchorPane>
|
||||||
<AnchorPane fx:id="registBottomPane" prefHeight="200.0" prefWidth="430.0">
|
<AnchorPane fx:id="registBottomPane" prefHeight="200.0" prefWidth="430.0">
|
||||||
<JFXTextField fx:id="accooundTextField" labelFloat="true" layoutX="25.0" layoutY="21.0" prefHeight="29.0"
|
<JFXTextField fx:id="accooundTextField" labelFloat="true" layoutX="25.0" layoutY="15.0" prefHeight="29.0" prefWidth="279.0" promptText="请输入6-18位账号,支持大小写数字下划线">
|
||||||
prefWidth="279.0" promptText="请输入6-18位账号,支持大小写数字下划线">
|
|
||||||
<font>
|
<font>
|
||||||
<Font size="14.0" />
|
<Font size="14.0" />
|
||||||
</font>
|
</font>
|
||||||
</JFXTextField>
|
</JFXTextField>
|
||||||
<JFXTextField fx:id="emailTf" labelFloat="true" layoutX="25.0" layoutY="70.0" promptText="请输入邮箱">
|
<JFXTextField fx:id="emailTf" labelFloat="true" layoutX="25.0" layoutY="80.0" promptText="请输入邮箱">
|
||||||
<font>
|
<font>
|
||||||
<Font size="14.0" />
|
<Font size="14.0" />
|
||||||
</font>
|
</font>
|
||||||
</JFXTextField>
|
</JFXTextField>
|
||||||
<HBox layoutX="25.0" layoutY="127.0" prefHeight="30.0" prefWidth="170.0">
|
<HBox layoutX="25.0" layoutY="140.0" prefHeight="30.0" prefWidth="170.0">
|
||||||
<JFXTextField fx:id="emailCheckCodeTf" prefHeight="30.0" prefWidth="94.0" promptText="6位验证号码">
|
<JFXTextField fx:id="emailCheckCodeTf" prefHeight="30.0" prefWidth="94.0" promptText="6位验证号码">
|
||||||
<font>
|
<font>
|
||||||
<Font size="14.0" />
|
<Font size="14.0" />
|
||||||
@ -44,20 +46,18 @@
|
|||||||
</JFXTextField>
|
</JFXTextField>
|
||||||
<JFXButton fx:id="sendCheckCodeBtn" buttonType="RAISED" prefHeight="30.0" text="发送验证码" />
|
<JFXButton fx:id="sendCheckCodeBtn" buttonType="RAISED" prefHeight="30.0" text="发送验证码" />
|
||||||
</HBox>
|
</HBox>
|
||||||
<JFXPasswordField fx:id="passwordTextField" labelFloat="true" layoutX="233.0" layoutY="70.0"
|
<JFXPasswordField fx:id="passwordTextField" labelFloat="true" layoutX="233.0" layoutY="60.0" promptText="请输入密码,不少于6位">
|
||||||
promptText="请输入密码不少于6位">
|
|
||||||
<font>
|
<font>
|
||||||
<Font size="14.0" />
|
<Font size="14.0" />
|
||||||
</font>
|
</font>
|
||||||
</JFXPasswordField>
|
</JFXPasswordField>
|
||||||
<JFXButton fx:id="registerBtn" buttonType="RAISED" layoutX="227.0" layoutY="127.0" prefHeight="51.0"
|
<JFXButton fx:id="registerBtn" buttonType="RAISED" layoutX="227.0" layoutY="110.0" prefHeight="51.0" prefWidth="177.0" text="注册" textFill="WHITE">
|
||||||
prefWidth="177.0" text="注册" textFill="WHITE">
|
|
||||||
<font>
|
<font>
|
||||||
<Font size="15.0" />
|
<Font size="15.0" />
|
||||||
</font>
|
</font>
|
||||||
</JFXButton>
|
</JFXButton>
|
||||||
<JFXButton fx:id="loginBtn" layoutX="306.0" layoutY="24.0" text="已有账号,去登录" textFill="#00000080"/>
|
<JFXButton fx:id="loginBtn" layoutX="306.0" layoutY="24.0" text="已有账号?去登录" textFill="#00000080" />
|
||||||
<Label fx:id="appVersionLabel" disable="true" layoutX="80.0" layoutY="171.0" text="Label">
|
<Label fx:id="appVersionLabel" disable="true" layoutX="380.0" layoutY="175.0" text="Label">
|
||||||
<font>
|
<font>
|
||||||
<Font size="14.0" />
|
<Font size="14.0" />
|
||||||
</font>
|
</font>
|
||||||
|
@ -1,39 +1,36 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<configuration scan="true" scanPeriod="60 seconds" debug="false">
|
<configuration scan="true" scanPeriod="60 seconds" debug="false">
|
||||||
<contextName>febs</contextName>
|
|
||||||
<property name="log.path" value="log" />
|
|
||||||
<property name="log.maxHistory" value="30" />
|
|
||||||
<property name="log.colorPattern" value="%date{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n"/>
|
|
||||||
<property name="log.pattern" value="%date{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n" />
|
|
||||||
|
|
||||||
<!--输出到控制台-->
|
<property name="logback.logdir" value="log"/>
|
||||||
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
|
<property name="logback.app" value="yanfrp"/>
|
||||||
<Encoding>UTF-8</Encoding>
|
|
||||||
<encoder>
|
<!--输出到控制台 ConsoleAppender-->
|
||||||
<pattern>${log.colorPattern}</pattern>
|
<appender name="consoleLog" class="ch.qos.logback.core.ConsoleAppender">
|
||||||
</encoder>
|
<!--展示格式 layout-->
|
||||||
<!--
|
|
||||||
日志输出格式:%d表示日期时间,%thread表示线程名,%-5level:级别从左显示5个字符宽度
|
|
||||||
%logger{50} 表示logger名字最长50个字符,否则按照句点分割。 %msg:日志消息,%n是换行符
|
|
||||||
-->
|
|
||||||
<layout class="ch.qos.logback.classic.PatternLayout">
|
<layout class="ch.qos.logback.classic.PatternLayout">
|
||||||
<pattern>${log.colorPattern}</pattern>
|
<pattern>%d{HH:mm:ss.SSS} ${logback.app} [%thread] %-5level %logger{36} - %mdc{client} [%X{trace_id}] %msg%n</pattern>
|
||||||
</layout>
|
</layout>
|
||||||
</appender>
|
</appender>
|
||||||
|
|
||||||
<!--输出到文件-->
|
<!--输出到文件 fileLog-->
|
||||||
<appender name="file_info" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
<appender name="fileLog" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||||
|
<!--如果只是想要 Error 级别的日志,那么需要过滤一下,默认是 info 级别的,ThresholdFilter-->
|
||||||
|
<filter class="ch.qos.logback.classic.filter.ThresholdFilter"/>
|
||||||
|
<File>${logback.logdir}/${logback.app}.info.log</File>
|
||||||
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
||||||
<fileNamePattern>${log.path}/info/info.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
|
<!--文件路径,定义了日志的切分方式——把每一天的日志归档到一个文件中,以防止日志填满整个磁盘空间-->
|
||||||
<MaxHistory>${log.maxHistory}</MaxHistory>
|
<FileNamePattern>${logback.logdir}/${logback.app}_%d{yyyy-MM-dd}.info.log</FileNamePattern>
|
||||||
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
|
<!--只保留最近30天的日志-->
|
||||||
<!-- 日志文件的最大大小 -->
|
<maxHistory>30</maxHistory>
|
||||||
<maxFileSize>5MB</maxFileSize>
|
<!--用来指定日志文件的上限大小,那么到了这个值,就会删除旧的日志-->
|
||||||
</timeBasedFileNamingAndTriggeringPolicy>
|
<totalSizeCap>1GB</totalSizeCap>
|
||||||
</rollingPolicy>
|
</rollingPolicy>
|
||||||
|
<!--日志输出编码格式化-->
|
||||||
<encoder>
|
<encoder>
|
||||||
<pattern>${log.pattern}</pattern>
|
<charset>UTF-8</charset>
|
||||||
|
<pattern>%d [%thread] %-5level %logger{36} %line - %mdc{client} [%X{trace_id}] %msg%n</pattern>
|
||||||
</encoder>
|
</encoder>
|
||||||
|
<!--只打印错误日志-->
|
||||||
<filter class="ch.qos.logback.classic.filter.LevelFilter">
|
<filter class="ch.qos.logback.classic.filter.LevelFilter">
|
||||||
<level>INFO</level>
|
<level>INFO</level>
|
||||||
<onMatch>ACCEPT</onMatch>
|
<onMatch>ACCEPT</onMatch>
|
||||||
@ -41,17 +38,44 @@
|
|||||||
</filter>
|
</filter>
|
||||||
</appender>
|
</appender>
|
||||||
|
|
||||||
<appender name="file_error" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
<appender name="fileLog-debug" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||||
|
<!--如果只是想要 Error 级别的日志,那么需要过滤一下,默认是 info 级别的,ThresholdFilter-->
|
||||||
|
<filter class="ch.qos.logback.classic.filter.ThresholdFilter"/>
|
||||||
|
<File>${logback.logdir}/${logback.app}.debug.log</File>
|
||||||
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
||||||
<fileNamePattern>${log.path}/error/error.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
|
<!--文件路径,定义了日志的切分方式——把每一天的日志归档到一个文件中,以防止日志填满整个磁盘空间-->
|
||||||
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
|
<FileNamePattern>${logback.logdir}/${logback.app}_%d{yyyy-MM-dd}.debug.log</FileNamePattern>
|
||||||
<!-- 日志文件的最大大小 -->
|
<!--只保留最近30天的日志-->
|
||||||
<maxFileSize>5MB</maxFileSize>
|
<maxHistory>30</maxHistory>
|
||||||
</timeBasedFileNamingAndTriggeringPolicy>
|
<!--用来指定日志文件的上限大小,那么到了这个值,就会删除旧的日志-->
|
||||||
|
<totalSizeCap>1GB</totalSizeCap>
|
||||||
|
</rollingPolicy>
|
||||||
|
<!--日志输出编码格式化-->
|
||||||
|
<encoder>
|
||||||
|
<charset>UTF-8</charset>
|
||||||
|
<pattern>%d [%thread] %-5level %logger{36} %line - %mdc{client} [%X{trace_id}] %msg%n</pattern>
|
||||||
|
</encoder>
|
||||||
|
<!--只打印错误日志-->
|
||||||
|
<filter class="ch.qos.logback.classic.filter.LevelFilter">
|
||||||
|
<level>DEBUG</level>
|
||||||
|
<onMatch>ACCEPT</onMatch>
|
||||||
|
<onMismatch>DENY</onMismatch>
|
||||||
|
</filter>
|
||||||
|
</appender>
|
||||||
|
|
||||||
|
<!-- 错误日志 -->
|
||||||
|
<appender name="fileLog-err" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||||
|
<File>${logback.logdir}/${logback.app}.err.log</File>
|
||||||
|
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
||||||
|
<FileNamePattern>${logback.logdir}/${logback.app}_%d{yyyy-MM-dd}.err.log</FileNamePattern>
|
||||||
|
<maxHistory>7</maxHistory>
|
||||||
|
<totalSizeCap>1GB</totalSizeCap>
|
||||||
</rollingPolicy>
|
</rollingPolicy>
|
||||||
<encoder>
|
<encoder>
|
||||||
<pattern>${log.pattern}</pattern>
|
<charset>UTF-8</charset>
|
||||||
|
<pattern>%d [%thread] %-5level %logger{36} %line - %mdc{client} [%X{trace_id}] %msg%n</pattern>
|
||||||
</encoder>
|
</encoder>
|
||||||
|
<!--只打印错误日志-->
|
||||||
<filter class="ch.qos.logback.classic.filter.LevelFilter">
|
<filter class="ch.qos.logback.classic.filter.LevelFilter">
|
||||||
<level>ERROR</level>
|
<level>ERROR</level>
|
||||||
<onMatch>ACCEPT</onMatch>
|
<onMatch>ACCEPT</onMatch>
|
||||||
@ -59,12 +83,13 @@
|
|||||||
</filter>
|
</filter>
|
||||||
</appender>
|
</appender>
|
||||||
|
|
||||||
<root level="debug">
|
<!--指定最基础的日志输出级别-->
|
||||||
<appender-ref ref="console" />
|
<root level="INFO">
|
||||||
|
<!--appender将会添加到这个loger-->
|
||||||
|
<appender-ref ref="consoleLog"/>
|
||||||
|
<appender-ref ref="fileLog"/>
|
||||||
|
<appender-ref ref="fileLog-debug"/>
|
||||||
|
<appender-ref ref="fileLog-err"/>
|
||||||
</root>
|
</root>
|
||||||
|
|
||||||
<root level="info">
|
|
||||||
<appender-ref ref="file_info" />
|
|
||||||
<appender-ref ref="file_error" />
|
|
||||||
</root>
|
|
||||||
</configuration>
|
</configuration>
|
Loading…
Reference in New Issue
Block a user