优化代码结构

This commit is contained in:
peng
2021-11-11 20:53:02 +08:00
parent 113cb63d62
commit db2341a23d
50 changed files with 1286 additions and 1110 deletions

2
.gitignore vendored
View File

@@ -21,3 +21,5 @@
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
*.idea
logs

View File

@@ -1,40 +1,8 @@
{
"projectName" : "HTTP SERVER 模拟器",
"projectName" : "HTTP SERVER 模拟器 V1.4",
"width" : 1200,
"height" : 800,
"stringLen" : 8,
"intLen" : 8,
"serverConfigs" : [ {
"serverName" : "天津众华WMS",
"port" : 8099,
"serverUrls" : [ {
"urlName" : "入库任务完成上报",
"url" : "/wz/accept/report",
"serverName" : "天津众华WMS",
"requestType" : "POST",
"responseBody" : "{\n\t\"code\": 0,\n\t\"message\": \"success\"\n}",
"headerMap" : null
}, {
"urlName" : "出库任务完成上报",
"url" : "/wz/order/report",
"serverName" : "天津众华WMS",
"requestType" : "POST",
"responseBody" : "{\n\t\"code\": 0,\n \"message\":\"success\"\n}",
"headerMap" : null
}, {
"urlName" : "盘点结果同步",
"url" : "/wz/material/update",
"serverName" : "天津众华WMS",
"requestType" : "POST",
"responseBody" : "{\n\"code\": 0,\n\"message\": \"success\"\n}",
"headerMap" : null
}, {
"urlName" : "物资信息定时同步",
"url" : "/wz/material/infos",
"serverName" : "天津众华WMS",
"requestType" : "POST",
"responseBody" : "{\n\t\"code\": 0,\n\t\"message\": \"success\"\n}",
"headerMap" : null
} ]
} ]
"serverConfigs" : null
}

81
pom.xml Normal file
View File

@@ -0,0 +1,81 @@
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.dayrain</groupId>
<artifactId>http-server-simulator</artifactId>
<version>1.4</version>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.5</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.12.5</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.12.5</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.12.5</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<id>copy-resources</id>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>
${basedir}/target/extra
</outputDirectory>
<resources>
<resource>
<directory>src/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>com.zenjava</groupId>
<artifactId>javafx-maven-plugin</artifactId>
<version>8.8.3</version>
<configuration>
<vendor>dayrain</vendor>
<mainClass>com.dayrain.views.ApplicationStarter</mainClass>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@@ -1,18 +0,0 @@
package com.dayrain;
import com.dayrain.views.HomePage;
import javafx.application.Application;
import javafx.stage.Stage;
public class ApplicationStarter extends Application {
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) throws Exception {
new HomePage(primaryStage).start();
}
}

View File

@@ -1,15 +0,0 @@
package com.dayrain.component;
import javafx.scene.control.TextArea;
public class LogArea extends TextArea {
private String serverName;
public String getServerName() {
return serverName;
}
public void setServerName(String serverName) {
this.serverName = serverName;
}
}

View File

@@ -1,5 +0,0 @@
package com.dayrain.component;
public enum RequestType {
GET, POST;
}

View File

@@ -1,89 +0,0 @@
package com.dayrain.handle;
import com.dayrain.component.ConfigHolder;
import com.dayrain.component.Configuration;
import com.dayrain.component.ServerConfig;
import com.dayrain.style.ButtonFactory;
import com.dayrain.style.LabelFactory;
import com.dayrain.views.HomePage;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.HBox;
import javafx.stage.Modality;
import javafx.stage.Stage;
import java.util.ArrayList;
/**
* 添加server
*
* @author peng
* @date 2021/10/28
*/
public class AddServerHandler implements EventHandler<ActionEvent> {
private final Stage primaryStage;
private final Configuration configuration;
private final HomePage homePage;
public AddServerHandler(Stage primaryStage, Configuration configuration, HomePage homePage) {
this.primaryStage = primaryStage;
this.configuration = configuration;
this.homePage = homePage;
}
@Override
public void handle(ActionEvent event) {
Stage stage = new Stage();
Label nameLabel = LabelFactory.getLabel("服务名称:");
nameLabel.setPrefWidth(80);
TextField nameField = new TextField();
Label portLabel = LabelFactory.getLabel("端口号:");
TextField portField = new TextField();
portField.setPrefWidth(80);
HBox btnHBox = new HBox();
Button saveButton = ButtonFactory.getButton("保存");
btnHBox.getChildren().add(saveButton);
btnHBox.setAlignment(Pos.CENTER_RIGHT);
GridPane gridPane = new GridPane();
gridPane.add(nameLabel, 0, 0);
gridPane.add(nameField, 1, 0);
gridPane.add(portLabel, 0, 1);
gridPane.add(portField, 1, 1);
gridPane.add(btnHBox, 1, 3);
gridPane.setAlignment(Pos.CENTER);
gridPane.setHgap(20d);
gridPane.setVgap(10d);
stage.setWidth(500);
stage.setHeight(400);
stage.initOwner(primaryStage);
stage.initModality(Modality.WINDOW_MODAL);
stage.setScene(new Scene(gridPane));
stage.getIcons().addAll(primaryStage.getIcons());
stage.show();
saveButton.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
String name = nameField.getText();
String port = portField.getText();
ServerConfig serverConfig = new ServerConfig(name, Integer.parseInt(port), new ArrayList<>());
configuration.getServerConfigs().add(serverConfig);
homePage.refreshServerContainer();
ConfigHolder.save();
stage.close();
}
});
}
}

View File

@@ -1,128 +0,0 @@
package com.dayrain.handle;
import com.dayrain.component.ConfigHolder;
import com.dayrain.component.RequestType;
import com.dayrain.component.ServerConfig;
import com.dayrain.component.ServerUrl;
import com.dayrain.server.ServerThread;
import com.dayrain.style.ButtonFactory;
import com.dayrain.style.LabelFactory;
import com.dayrain.utils.ListViewHelper;
import javafx.collections.FXCollections;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ChoiceBox;
import javafx.scene.control.Label;
import javafx.scene.control.ListView;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.HBox;
import javafx.stage.Modality;
import javafx.stage.Stage;
import java.util.HashMap;
import java.util.List;
/**
* 添加路径
*
* @author peng
* @date 2021/10/27
*/
public class AddUrlHandler implements EventHandler<ActionEvent> {
private final ServerConfig serverConfig;
private final ListView<ServerUrl> serverUrlListView;
private final HashMap<String, ServerThread> threadMap;
private final Stage primaryStage;
public AddUrlHandler(ServerConfig serverConfig, ListView<ServerUrl> serverUrlListView, HashMap<String, ServerThread> threadMap, Stage primaryStage) {
this.serverConfig = serverConfig;
this.serverUrlListView = serverUrlListView;
this.threadMap = threadMap;
this.primaryStage = primaryStage;
}
@Override
public void handle(ActionEvent event) {
Stage stage = new Stage();
Label nameLabel = LabelFactory.getLabel("接口名称:");
nameLabel.setPrefWidth(80);
TextField nameField = new TextField();
Label urlLabel = LabelFactory.getLabel("接口地址:");
TextField urlField = new TextField();
urlField.setPrefWidth(80);
Label methodLabel = LabelFactory.getLabel("请求方式:");
ChoiceBox<String> choiceBox = new ChoiceBox<>();
choiceBox.setItems(FXCollections.observableArrayList("POST", "GET"));
choiceBox.setValue("POST");
urlField.setPrefWidth(80);
Label respLabel = LabelFactory.getLabel("返回结果:");
TextArea textArea = new TextArea();
textArea.setPrefWidth(80);
HBox btnHBox = new HBox();
Button saveButton = ButtonFactory.getButton("保存");
btnHBox.getChildren().add(saveButton);
btnHBox.setAlignment(Pos.CENTER_RIGHT);
GridPane gridPane = new GridPane();
gridPane.add(methodLabel, 0, 0);
gridPane.add(choiceBox, 1, 0);
gridPane.add(nameLabel, 0, 1);
gridPane.add(nameField, 1, 1);
gridPane.add(urlLabel, 0, 2);
gridPane.add(urlField, 1, 2);
gridPane.add(respLabel, 0, 3);
gridPane.add(textArea, 1, 3);
gridPane.add(btnHBox, 1, 4);
gridPane.setAlignment(Pos.CENTER);
gridPane.setHgap(20d);
gridPane.setVgap(10d);
stage.setWidth(550);
stage.setHeight(500);
stage.initOwner(primaryStage);
stage.initModality(Modality.WINDOW_MODAL);
stage.setScene(new Scene(gridPane));
stage.getIcons().addAll(primaryStage.getIcons());
stage.show();
saveButton.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
String name = nameField.getText();
List<ServerUrl> serverUrls = serverConfig.getServerUrls();
for (ServerUrl serverUrl : serverUrls) {
if (serverUrl.getUrlName().equals(name)) {
return;
}
}
String url = urlField.getText();
String resp = textArea.getText();
String type = choiceBox.getValue();
ServerUrl serverUrl = new ServerUrl(serverConfig.getServerName(), name, url, type.equals(RequestType.POST.name()) ? RequestType.POST : RequestType.GET, resp);
serverUrls.add(serverUrl);
ServerThread serverThread = threadMap.getOrDefault(serverConfig.getServerName(), null);
if (serverThread != null) {
serverThread.addContext(serverUrl);
}
ListViewHelper.addAndRefresh(serverUrl, serverUrlListView);
ConfigHolder.save();
stage.close();
}
});
}
}

View File

@@ -1,45 +0,0 @@
package com.dayrain.handle;
import com.dayrain.component.ConfigHolder;
import com.dayrain.component.Configuration;
import com.dayrain.component.ServerConfig;
import com.dayrain.views.HomePage;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.control.Alert;
import javafx.scene.control.Button;
import javafx.scene.control.ButtonType;
import javafx.scene.image.ImageView;
import javafx.stage.Stage;
public class DeleteServerHandler implements EventHandler<ActionEvent> {
private final ServerConfig serverConfig;
private final Configuration configuration;
private final HomePage homePage;
public DeleteServerHandler(ServerConfig serverConfig, Configuration configuration, HomePage homePage) {
this.serverConfig = serverConfig;
this.configuration = configuration;
this.homePage = homePage;
}
@Override
public void handle(ActionEvent event) {
Alert alert = new Alert(Alert.AlertType.CONFIRMATION);
alert.setGraphic(new ImageView(homePage.getIcon()));
Stage stage = (Stage) alert.getDialogPane().getScene().getWindow();
stage.getIcons().add(homePage.getIcon());
alert.setHeaderText("是否确定删除该服务?");
Button okButton = (Button) alert.getDialogPane().lookupButton(ButtonType.OK);
okButton.setOnAction(event1 -> {
configuration.getServerConfigs().remove(serverConfig);
homePage.refreshServerContainer();
ConfigHolder.save();
});
alert.show();
}
}

View File

@@ -1,57 +0,0 @@
package com.dayrain.handle;
import com.dayrain.component.ConfigHolder;
import com.dayrain.component.ServerConfig;
import com.dayrain.component.ServerUrl;
import com.dayrain.utils.ListViewHelper;
import com.dayrain.views.HomePage;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.control.Alert;
import javafx.scene.control.Button;
import javafx.scene.control.ButtonType;
import javafx.scene.control.ListView;
import javafx.scene.image.ImageView;
import javafx.stage.Stage;
import java.util.List;
/**
* 删除路径
* @author peng
* @date 2021/10/27
*/
public class DeleteUrlHandler implements EventHandler<ActionEvent> {
private final ServerConfig serverConfig;
private final ListView<ServerUrl> serverUrlListView;
private final ServerUrl serverUrl;
private final HomePage homePage;
public DeleteUrlHandler(ServerUrl serverUrl, ServerConfig serverConfig, ListView<ServerUrl> serverUrlListView, HomePage homePage) {
this.serverUrl = serverUrl;
this.serverConfig = serverConfig;
this.serverUrlListView = serverUrlListView;
this.homePage = homePage;
}
@Override
public void handle(ActionEvent event) {
Alert alert = new Alert(Alert.AlertType.CONFIRMATION);
alert.setGraphic(new ImageView(homePage.getIcon()));
Stage stage = (Stage) alert.getDialogPane().getScene().getWindow();
stage.getIcons().add(homePage.getIcon());
alert.setHeaderText("是否确定删除该接口?");
Button okButton = (Button) alert.getDialogPane().lookupButton(ButtonType.OK);
okButton.setOnAction(event1 -> {
List<ServerUrl> serverUrls = serverConfig.getServerUrls();
serverUrls.remove(serverUrl);
ConfigHolder.save();
ListViewHelper.deleteAndRefresh(serverUrl, serverUrlListView);
});
alert.show();
}
}

View File

@@ -1,46 +0,0 @@
package com.dayrain.handle;
import com.dayrain.component.Configuration;
import com.dayrain.utils.FileUtils;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.stage.FileChooser;
import javafx.stage.Stage;
import java.io.File;
/**
* 导出配置文件
*
* @author peng
* @date 2021/10/28
*/
public class ExportConfigHandler implements EventHandler<ActionEvent> {
private final Stage primaryStage;
private final Configuration configuration;
public ExportConfigHandler(Stage primaryStage, Configuration configuration) {
this.primaryStage = primaryStage;
this.configuration = configuration;
}
@Override
public void handle(ActionEvent event) {
Stage stage = new Stage();
stage.initOwner(primaryStage);
FileChooser fileChooser = new FileChooser();
String projectName = configuration.getProjectName();
if (projectName == null) {
projectName = "";
}
projectName += "server";
fileChooser.setTitle("导出配置");
fileChooser.setInitialFileName(projectName + ".json");
File file = fileChooser.showSaveDialog(stage);
if (file != null) {
FileUtils.saveConfig(configuration, file);
}
}
}

View File

@@ -1,49 +0,0 @@
package com.dayrain.handle;
import com.dayrain.component.ConfigHolder;
import com.dayrain.component.Configuration;
import com.dayrain.utils.FileUtils;
import com.dayrain.views.HomePage;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.stage.FileChooser;
import javafx.stage.Stage;
import java.io.File;
/**
* 导入配置文件
*
* @author peng
* @date 2021/10/28
*/
public class ImportConfigHandler implements EventHandler<ActionEvent> {
private final Stage primaryStage;
private final HomePage homePage;
public ImportConfigHandler(Stage primaryStage, HomePage homePage) {
this.primaryStage = primaryStage;
this.homePage = homePage;
}
@Override
public void handle(ActionEvent event) {
Stage stage = new Stage();
stage.initOwner(primaryStage);
FileChooser fileChooser = new FileChooser();
fileChooser.setTitle("选择一个文件");
//过滤器
fileChooser.getExtensionFilters().addAll(new FileChooser.ExtensionFilter("只能导入json文件", "*.json"));
File file = fileChooser.showOpenDialog(stage);
if (file != null) {
Configuration loadConfig = FileUtils.load(file);
ConfigHolder.replace(loadConfig);
FileUtils.saveConfig(loadConfig);
homePage.replaceConfig(loadConfig);
homePage.restart();
}
}
}

View File

@@ -1,56 +0,0 @@
package com.dayrain.handle;
import com.dayrain.component.Server;
import com.dayrain.component.ServerConfig;
import com.dayrain.server.ServerThread;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.control.Button;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import java.util.HashMap;
/**
* 服务启动与关闭控制器
*
* @author peng
* @date 2021/10/27
*/
public class StartServerHandler implements EventHandler<ActionEvent> {
private final Button openButton;
private final Circle statusCircle;
private final ServerConfig serverConfig;
private final HashMap<String, ServerThread> threadMap;
public StartServerHandler(Button openButton, Circle statusCircle, ServerConfig serverConfig, HashMap<String, ServerThread> threadMap) {
this.openButton = openButton;
this.statusCircle = statusCircle;
this.serverConfig = serverConfig;
this.threadMap = threadMap;
}
@Override
public void handle(ActionEvent event) {
String serverName = serverConfig.getServerName();
if (threadMap.containsKey(serverName)) {
ServerThread serverThread = threadMap.get(serverName);
if (serverThread != null) {
serverThread.stopServer();
}
threadMap.remove(serverName);
openButton.setText("开启服务");
statusCircle.setFill(Color.RED);
} else {
ServerThread serverThread = new ServerThread(new Server(serverConfig));
serverThread.start();
threadMap.put(serverName, serverThread);
openButton.setText("关闭服务");
statusCircle.setFill(Color.GREEN);
}
}
}

View File

@@ -1,79 +0,0 @@
package com.dayrain.handle;
import com.dayrain.component.ConfigHolder;
import com.dayrain.component.Configuration;
import com.dayrain.style.ButtonFactory;
import com.dayrain.style.LabelFactory;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.HBox;
import javafx.stage.Modality;
import javafx.stage.Stage;
public class UpdateRandomLenHandler implements EventHandler<ActionEvent> {
private final Stage primaryStage;
public UpdateRandomLenHandler(Stage primaryStage) {
this.primaryStage = primaryStage;
}
@Override
public void handle(ActionEvent event) {
Configuration configuration = ConfigHolder.get();
Stage stage = new Stage();
Label strName = LabelFactory.getLabel("随机字符长度:");
strName.setPrefWidth(150);
TextField strField = new TextField(String.valueOf(configuration.getStringLen()));
Label intName = LabelFactory.getLabel("随机整数长度:");
TextField intField = new TextField(String.valueOf(configuration.getIntLen()));
intField.setPrefWidth(150);
HBox btnHBox = new HBox();
Label saveTips1 = LabelFactory.getLabel("注: $string$代指随机字符串");
Label saveTips2 = LabelFactory.getLabel("$int$代指随机整数");
Button saveButton = ButtonFactory.getButton("保存");
btnHBox.getChildren().addAll(saveButton);
btnHBox.setAlignment(Pos.CENTER_RIGHT);
btnHBox.setSpacing(20d);
GridPane gridPane = new GridPane();
gridPane.add(strName, 0, 0);
gridPane.add(strField, 1, 0);
gridPane.add(intName, 0, 1);
gridPane.add(intField, 1, 1);
gridPane.add(saveTips1, 0, 3);
gridPane.add(saveTips2, 1, 3);
gridPane.add(btnHBox, 1, 4);
gridPane.setAlignment(Pos.CENTER);
gridPane.setHgap(20d);
gridPane.setVgap(10d);
stage.setWidth(500);
stage.setHeight(400);
stage.initOwner(primaryStage);
stage.initModality(Modality.WINDOW_MODAL);
stage.setScene(new Scene(gridPane));
stage.getIcons().addAll(primaryStage.getIcons());
stage.show();
saveButton.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
String strLen = strField.getText();
String intLen = intField.getText();
configuration.setStringLen(Integer.parseInt(strLen));
configuration.setIntLen(Integer.parseInt(intLen));
ConfigHolder.save();
stage.close();
}
});
}
}

View File

@@ -1,78 +0,0 @@
package com.dayrain.handle;
import com.dayrain.component.ConfigHolder;
import com.dayrain.component.ServerConfig;
import com.dayrain.style.ButtonFactory;
import com.dayrain.style.LabelFactory;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.HBox;
import javafx.stage.Modality;
import javafx.stage.Stage;
public class UpdateServerConfigHandler implements EventHandler<ActionEvent> {
private final ServerConfig serverConfig;
private final Stage primaryStage;
public UpdateServerConfigHandler(ServerConfig serverConfig, Stage primaryStage) {
this.serverConfig = serverConfig;
this.primaryStage = primaryStage;
}
@Override
public void handle(ActionEvent event) {
Stage stage = new Stage();
Label serverName = LabelFactory.getLabel("服务名称:");
serverName.setPrefWidth(80);
TextField nameField = new TextField(serverConfig.getServerName());
Label portLabel = LabelFactory.getLabel("端口:");
TextField portField = new TextField(String.valueOf(serverConfig.getPort()));
portField.setPrefWidth(80);
HBox btnHBox = new HBox();
Label saveTips = LabelFactory.getLabel("重启后生效");
Button saveButton = ButtonFactory.getButton("保存");
btnHBox.getChildren().addAll(saveTips, saveButton);
btnHBox.setAlignment(Pos.CENTER_RIGHT);
btnHBox.setSpacing(20d);
GridPane gridPane = new GridPane();
gridPane.add(serverName, 0, 0);
gridPane.add(nameField, 1, 0);
gridPane.add(portLabel, 0, 1);
gridPane.add(portField, 1, 1);
gridPane.add(btnHBox, 1, 3);
gridPane.setAlignment(Pos.CENTER);
gridPane.setHgap(20d);
gridPane.setVgap(10d);
stage.setWidth(500);
stage.setHeight(400);
stage.initOwner(primaryStage);
stage.initModality(Modality.WINDOW_MODAL);
stage.setScene(new Scene(gridPane));
stage.getIcons().addAll(primaryStage.getIcons());
stage.show();
saveButton.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
String name = nameField.getText();
int port = Integer.parseInt(portField.getText());
serverConfig.setPort(port);
serverConfig.setServerName(name);
ConfigHolder.save();
stage.close();
}
});
}
}

View File

@@ -1,108 +0,0 @@
package com.dayrain.handle;
import com.dayrain.component.ConfigHolder;
import com.dayrain.component.RequestType;
import com.dayrain.component.ServerUrl;
import com.dayrain.style.ButtonFactory;
import com.dayrain.style.LabelFactory;
import com.dayrain.utils.ListViewHelper;
import javafx.collections.FXCollections;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ChoiceBox;
import javafx.scene.control.Label;
import javafx.scene.control.ListView;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.HBox;
import javafx.stage.Modality;
import javafx.stage.Stage;
public class UpdateUrlHandler implements EventHandler<ActionEvent> {
private final ListView<ServerUrl> serverUrlListView;
private final ServerUrl serverUrl;
private final Stage primaryStage;
public UpdateUrlHandler(ServerUrl serverUrl, ListView<ServerUrl> serverUrlListView, Stage primaryStage) {
this.serverUrl = serverUrl;
this.serverUrlListView = serverUrlListView;
this.primaryStage = primaryStage;
}
@Override
public void handle(ActionEvent event) {
Stage stage = new Stage();
Label nameLabel = LabelFactory.getLabel("接口名称:");
nameLabel.setPrefWidth(80);
TextField nameField = new TextField(serverUrl.getUrlName());
Label urlLabel = LabelFactory.getLabel("接口地址:");
TextField urlField = new TextField(serverUrl.getUrl());
urlField.setEditable(false);
urlField.setPrefWidth(80);
Label methodLabel = LabelFactory.getLabel("请求方式:");
ChoiceBox<String> choiceBox = new ChoiceBox<>();
choiceBox.setItems(FXCollections.observableArrayList("POST", "GET"));
choiceBox.setValue("POST");
urlField.setPrefWidth(80);
Label respLabel = LabelFactory.getLabel("返回结果:");
TextArea textArea = new TextArea(serverUrl.getResponseBody());
textArea.setPrefWidth(80);
HBox btnHBox = new HBox();
Button saveButton = ButtonFactory.getButton("保存");
btnHBox.getChildren().addAll(saveButton);
btnHBox.setAlignment(Pos.CENTER_RIGHT);
btnHBox.setSpacing(20d);
GridPane gridPane = new GridPane();
gridPane.add(methodLabel, 0, 0);
gridPane.add(choiceBox, 1, 0);
gridPane.add(nameLabel, 0, 1);
gridPane.add(nameField, 1, 1);
gridPane.add(urlLabel, 0, 2);
gridPane.add(urlField, 1, 2);
gridPane.add(respLabel, 0, 3);
gridPane.add(textArea, 1, 3);
gridPane.add(btnHBox, 1, 4);
gridPane.setAlignment(Pos.CENTER);
gridPane.setHgap(20d);
gridPane.setVgap(10d);
stage.setWidth(550);
stage.setHeight(450);
stage.initOwner(primaryStage);
stage.initModality(Modality.WINDOW_MODAL);
stage.setScene(new Scene(gridPane));
stage.getIcons().addAll(primaryStage.getIcons());
stage.show();
saveButton.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
String name = nameField.getText();
String url = urlField.getText();
String resp = textArea.getText();
String type = choiceBox.getValue();
serverUrl.setUrlName(name);
serverUrl.setUrl(url);
serverUrl.setResponseBody(resp);
serverUrl.setRequestType(type.equals(RequestType.POST.name()) ? RequestType.POST : RequestType.GET);
ListViewHelper.refresh(serverUrlListView);
ConfigHolder.save();
stage.close();
}
});
}
}

View File

@@ -1,282 +0,0 @@
package com.dayrain.views;
import com.dayrain.component.ConfigHolder;
import com.dayrain.component.Configuration;
import com.dayrain.component.ConsoleLog;
import com.dayrain.component.LogArea;
import com.dayrain.component.ServerConfig;
import com.dayrain.component.ServerUrl;
import com.dayrain.handle.AddServerHandler;
import com.dayrain.handle.AddUrlHandler;
import com.dayrain.handle.DeleteServerHandler;
import com.dayrain.handle.DeleteUrlHandler;
import com.dayrain.handle.ExportConfigHandler;
import com.dayrain.handle.ImportConfigHandler;
import com.dayrain.handle.StartServerHandler;
import com.dayrain.handle.UpdateRandomLenHandler;
import com.dayrain.handle.UpdateServerConfigHandler;
import com.dayrain.handle.UpdateUrlHandler;
import com.dayrain.server.ServerThread;
import com.dayrain.style.ButtonFactory;
import com.dayrain.style.LabelFactory;
import javafx.beans.binding.Bindings;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.ListCell;
import javafx.scene.control.ListView;
import javafx.scene.control.Menu;
import javafx.scene.control.MenuBar;
import javafx.scene.control.MenuItem;
import javafx.scene.control.TitledPane;
import javafx.scene.image.Image;
import javafx.scene.layout.Background;
import javafx.scene.layout.BackgroundFill;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.CornerRadii;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.scene.text.Font;
import javafx.stage.Stage;
import javafx.util.Callback;
import java.awt.*;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
public class HomePage {
private Stage primaryStage;
private Configuration configuration = ConfigHolder.init();
private HashMap<String, ServerThread> threadMap = new HashMap<>();
private VBox serverContainer;
private LogArea logArea;
public HomePage(Stage primaryStage) {
this.primaryStage = primaryStage;
}
public void start() {
BorderPane borderPane = new BorderPane();
//菜单栏
MenuBar menuBar = new MenuBar();
Menu menu1 = new Menu("文件");
MenuItem menuItem1 = new MenuItem("新建");
MenuItem menuItem2 = new MenuItem("导入");
MenuItem menuItem3 = new MenuItem("导出");
menu1.getItems().addAll(menuItem1, menuItem2, menuItem3);
Menu menu2 = new Menu("设置");
MenuItem menuItem21 = new MenuItem("随机值长度");
menu2.getItems().add(menuItem21);
Menu menu3 = new Menu("帮助");
MenuItem menuItem31 = new MenuItem("说明书");
menuItem31.setOnAction(event -> {
try {
Desktop.getDesktop().browse(new URI("https://blog.csdn.net/qq_37855749/article/details/121030800"));
} catch (IOException | URISyntaxException e) {
e.printStackTrace();
}
});
MenuItem menuItem32 = new MenuItem("源码地址");
menuItem32.setOnAction(event -> {
try {
Desktop.getDesktop().browse(new URI("https://github.com/DayRain/http-server-simulator"));
} catch (IOException | URISyntaxException e) {
e.printStackTrace();
}
});
menu3.getItems().addAll(menuItem31, menuItem32);
menuBar.getMenus().addAll(menu1, menu2, menu3);
borderPane.setTop(menuBar);
//渲染服务列表
this.serverContainer = new VBox();
refreshServerContainer();
menuItem1.setOnAction(new AddServerHandler(primaryStage, configuration, this));
menuItem2.setOnAction(new ImportConfigHandler(primaryStage, this));
menuItem3.setOnAction(new ExportConfigHandler(primaryStage, configuration));
menuItem21.setOnAction(new UpdateRandomLenHandler(primaryStage));
borderPane.setLeft(serverContainer);
//日志
logArea = new LogArea();
logArea.setEditable(false);
logArea.setFont(Font.font("Microsoft YaHei", 20));
logArea.setPrefWidth(582);
logArea.setPrefHeight(600);
ConsoleLog.setTextArea(logArea);
borderPane.setRight(logArea);
menuBar.setBackground(getBackGround());
Scene scene = new Scene(borderPane);
primaryStage.setTitle(configuration.getProjectName());
primaryStage.setScene(scene);
primaryStage.setWidth(configuration.getWidth());
primaryStage.setHeight(configuration.getHeight());
primaryStage.getIcons().add(getIcon());
primaryStage.show();
primaryStage.setOnCloseRequest(event -> {
ConfigHolder.save();
if(threadMap.size() > 0) {
for (String serverName : threadMap.keySet()) {
ServerThread serverThread = threadMap.get(serverName);
serverThread.stopServer();
}
}
});
}
public void drawServerPanel(VBox serverContainer, ServerConfig serverConfig, Stage primaryStage) {
VBox vBox = new VBox();
HBox headBox = new HBox();
Button editButton = ButtonFactory.getButton("修改配置");
Button openButton = ButtonFactory.getButton("开启服务");
Button deleteButton = ButtonFactory.getButton("删除服务");
Button addButton = ButtonFactory.getButton("添加接口");
Circle statusCircle = new Circle();
statusCircle.setRadius(10);
statusCircle.setFill(Color.RED);
//设置服务启动与关闭
openButton.setOnAction(new StartServerHandler(openButton, statusCircle, serverConfig, threadMap));
editButton.setOnAction(new UpdateServerConfigHandler(serverConfig, primaryStage));
deleteButton.setOnAction(new DeleteServerHandler(serverConfig, configuration, this));
headBox.getChildren().addAll(openButton, editButton, deleteButton, addButton, statusCircle);
HBox.setMargin(statusCircle, new Insets(0, 0, 0, 30));
headBox.setSpacing(20d);
headBox.setAlignment(Pos.CENTER);
//添加url
ListView<ServerUrl> serverUrlListView = drawUrlPanel(serverConfig.getServerUrls(), serverConfig);
addButton.setOnAction(new AddUrlHandler(serverConfig, serverUrlListView, threadMap, primaryStage));
vBox.getChildren().addAll(headBox, serverUrlListView);
vBox.setSpacing(10d);
VBox.setMargin(headBox, new Insets(10, 0, 0, 0));
vBox.setPadding(Insets.EMPTY);
TitledPane titledPane = new TitledPane(serverConfig.getServerName(), vBox);
titledPane.setFont(Font.font("Microsoft YaHei", 18));
titledPane.setPrefWidth(600d);
titledPane.setExpanded(false);
titledPane.setBackground(getBackGround());
titledPane.setOnMouseClicked(event -> {
if (!serverConfig.getServerName().equals(logArea.getServerName())) {
ConsoleLog.resetTextArea(serverConfig.getServerName());
}
});
HBox hBox = new HBox();
hBox.setPrefHeight(60d);
titledPane.setGraphic(hBox);
serverContainer.getChildren().add(titledPane);
}
public ListView<ServerUrl> drawUrlPanel(List<ServerUrl> serverUrls, ServerConfig serverConfig) {
ObservableList<ServerUrl> urlList = FXCollections.observableArrayList(serverUrls);
ListView<ServerUrl> serverListViews = new ListView<>(urlList);
serverListViews.setCellFactory(new Callback<ListView<ServerUrl>, ListCell<ServerUrl>>() {
@Override
public ListCell<ServerUrl> call(ListView<ServerUrl> param) {
return new ListCell<ServerUrl>() {
@Override
protected void updateItem(ServerUrl item, boolean empty) {
super.updateItem(item, empty);
if (empty || item == null) {
setText(null);
setGraphic(null);
} else {
BorderPane urlPane = new BorderPane();
HBox labelBox = new HBox();
Label nameLabel = LabelFactory.getLabel(item.getUrlName());
nameLabel.setPrefWidth(150d);
Label urlLabel = LabelFactory.getLabel(item.getUrl());
labelBox.getChildren().addAll(nameLabel, urlLabel);
labelBox.setAlignment(Pos.CENTER_LEFT);
HBox btnBox = new HBox();
Button configButton = ButtonFactory.getButton("配置");
Button deleteButton = ButtonFactory.getButton("删除");
btnBox.setSpacing(10d);
btnBox.getChildren().addAll(configButton, deleteButton);
HBox.setMargin(deleteButton, new Insets(0, 5, 0, 0));
deleteButton.setOnAction(new DeleteUrlHandler(item, serverConfig, serverListViews, HomePage.this));
configButton.setOnAction(new UpdateUrlHandler(item, serverListViews, primaryStage));
urlPane.setLeft(labelBox);
urlPane.setRight(btnBox);
this.setGraphic(urlPane);
}
}
};
}
});
serverListViews.prefHeightProperty().bind(Bindings.size(urlList).multiply(60));
serverListViews.setFocusTraversable(false);
return serverListViews;
}
public void refreshServerContainer() {
serverContainer.getChildren().removeAll(serverContainer.getChildren());
List<ServerConfig> serverConfigs = configuration.getServerConfigs();
if (serverConfigs == null || serverConfigs.size() == 0) {
serverConfigs = new ArrayList<>();
configuration.setServerConfigs(serverConfigs);
}
for (ServerConfig serverConfig : serverConfigs) {
drawServerPanel(serverContainer, serverConfig, primaryStage);
}
}
public void restart() {
cleanUp();
start();
}
public void cleanUp() {
for (String name : threadMap.keySet()) {
threadMap.get(name).stopServer();
}
}
public void replaceConfig(Configuration configuration) {
this.configuration = configuration;
}
public Image getIcon() {
return new Image("resources/panda.png");
}
public Background getBackGround() {
BackgroundFill backgroundFill = new BackgroundFill(Color.GRAY, new CornerRadii(1),
new Insets(0.0, 0.0, 0.0, 0.0));
return new Background(backgroundFill);
}
}

View File

@@ -1,8 +1,13 @@
package com.dayrain.component;
import com.dayrain.utils.FileUtils;
/**
* 配置类句柄
* @author peng
* @date 2021/11/8
*/
public class ConfigHolder {
private static Configuration configuration;
private ConfigHolder() {
@@ -13,15 +18,18 @@ public class ConfigHolder {
return configuration;
}
public static void save() {
public synchronized static void save() {
FileUtils.saveConfig(configuration);
}
public static Configuration get() {
public synchronized static Configuration get() {
if(configuration == null) {
init();
}
return configuration;
}
public static void replace(Configuration config) {
public synchronized static void replace(Configuration config) {
configuration = config;
}
}

View File

@@ -1,10 +1,14 @@
package com.dayrain.component;
import java.util.List;
/**
* 配置文件
* @author peng
* @date 2021/11/8
*/
public class Configuration {
private String projectName = "HTTP SERVER 模拟器";
private String projectName = "HTTP SERVER 模拟器 V1.4";
private int width;

View File

@@ -1,9 +1,15 @@
package com.dayrain.component;
import com.dayrain.views.LogArea;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
/**
* 请求日志打印
* @author peng
* @date 2021/11/8
*/
public class ConsoleLog {
private static final HashMap<String, String> logs = new HashMap<>();
@@ -12,11 +18,11 @@ public class ConsoleLog {
private static LogArea logArea;
public static void setTextArea(LogArea area) {
public static void initTextArea(LogArea area) {
logArea = area;
}
public static void log(ServerUrl serverUrl, String params, String resp) {
public synchronized static void log(ServerUrl serverUrl, String params, String resp) {
String log = logs.getOrDefault(serverUrl.getServerName(), null);
if (log == null || NO_REQUEST.equals(log)) {
log = "";
@@ -36,19 +42,26 @@ public class ConsoleLog {
stringBuilder.append("\n\n");
log += stringBuilder.toString();
if(log.length() > 5000) {
log = log.substring(log.length() - 5000);
System.out.println(log.length());
}
logs.put(serverUrl.getServerName(), log);
if (serverUrl.getServerName().equals(logArea.getServerName())) {
if (NO_REQUEST.equals(logArea.getText())) {
logArea.setText(log);
} else {
logArea.setText("");
logArea.appendText(log);
}
logArea.setScrollTop(Double.MAX_VALUE);
}
}
public static void resetTextArea(String serverName) {
public synchronized static void resetTextArea(String serverName) {
if (!logs.containsKey(serverName)) {
logs.put(serverName, NO_REQUEST);
}

View File

@@ -8,10 +8,15 @@ import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.util.UUID;
/**
* 请求处理
* @author peng
* @date 2021/11/8
*/
public class RequestHandler implements HttpHandler {
private static final String STRING_PATTERN = "$string$";
private static final String INT_PATTERN = "$int$";
private final ServerUrl serverUrl;
@@ -21,7 +26,7 @@ public class RequestHandler implements HttpHandler {
}
@Override
public void handle(HttpExchange exchange) throws IOException {
public void handle(HttpExchange exchange) {
RequestType requestType = serverUrl.getRequestType();
String param = null;
if (RequestType.GET.equals(requestType)) {
@@ -49,7 +54,8 @@ public class RequestHandler implements HttpHandler {
private void response(HttpExchange exchange, String jsonBody) {
try {
exchange.sendResponseHeaders(200, jsonBody.length());
byte[] bytes = jsonBody.getBytes(StandardCharsets.UTF_8);
exchange.sendResponseHeaders(200, bytes.length);
exchange.setAttribute("Content-Type", "application/json; charset=utf-8");
OutputStream outputStream = exchange.getResponseBody();
outputStream.write(jsonBody.getBytes(StandardCharsets.UTF_8));

View File

@@ -0,0 +1,9 @@
package com.dayrain.component;
/**
* 请求方式
* @author peng
* @date 2021/11/8
*/
public enum RequestType {
GET, POST
}

View File

@@ -1,19 +1,23 @@
package com.dayrain.component;
import com.sun.net.httpserver.HttpServer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
/**
* 服务
*
* @author peng
* @date 2021/10/25
*/
public class Server implements Runnable {
private static final Logger logger = LoggerFactory.getLogger(Server.class);
private final ServerConfig serverConfig;
private HttpServer httpServer;
@@ -25,6 +29,11 @@ public class Server implements Runnable {
@Override
public void run() {
start();
System.out.println("" + serverConfig.getServerName() + "】服务已开启...");
}
public synchronized void start() {
try {
this.httpServer = HttpServer.create(new InetSocketAddress(serverConfig.getPort()), 0);
httpServer.setExecutor(Executors.newCachedThreadPool());
@@ -32,20 +41,36 @@ public class Server implements Runnable {
addContext(serverUrl);
}
httpServer.start();
System.out.println("" + serverConfig.getServerName() + "】服务已开启...");
} catch (IOException e) {
e.printStackTrace();
logger.error(e.getMessage());
}
}
public void stop() {
public synchronized void stop() {
if (httpServer != null) {
System.out.println("" + serverConfig.getServerName() + "】服务已关闭...");
httpServer.stop(0);
}
}
public void addContext(ServerUrl serverUrl) {
public synchronized void restart() {
stop();
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
start();
}
public synchronized void addContext(ServerUrl serverUrl) {
httpServer.createContext(serverUrl.getUrl(), new RequestHandler(serverUrl));
}
public void removeContext(String url) {
httpServer.removeContext(url);
}
}

View File

@@ -1,7 +1,11 @@
package com.dayrain.component;
import java.util.List;
/**
* 服务配置
* @author peng
* @date 2021/11/8
*/
public class ServerConfig {
/**
* 服务名
@@ -48,4 +52,5 @@ public class ServerConfig {
public void setServerUrls(List<ServerUrl> serverUrls) {
this.serverUrls = serverUrls;
}
}

View File

@@ -0,0 +1,68 @@
package com.dayrain.component;
import com.dayrain.server.ServerThread;
import java.util.HashMap;
/**
* 正在运行的 server 线程组
* @author peng
* @date 2021/11/8
*/
public class ServerThreadHolder {
private static final HashMap<String, ServerThread> threadMap = new HashMap<>();
/**
* 停止所有线程
*/
public synchronized static void stopAll() {
if(threadMap.size() > 0) {
for (String serverName : threadMap.keySet()) {
ServerThread serverThread = threadMap.get(serverName);
serverThread.stopServer();
}
}
}
public synchronized static void add(String serverName, ServerThread serverThread) {
if(!threadMap.containsKey(serverName)) {
serverThread.start();
threadMap.put(serverName, serverThread);
}
}
public synchronized static void remove(String serverName) {
if(contains(serverName)) {
threadMap.get(serverName).stopServer();
threadMap.remove(serverName);
}
}
public synchronized static boolean contains(String key) {
return threadMap.containsKey(key);
}
public synchronized static void addUrl(ServerUrl serverUrl) {
if(serverUrl == null || !contains(serverUrl.getServerName())) {
return;
}
ServerThread serverThread = threadMap.get(serverUrl.getServerName());
serverThread.addContext(serverUrl);
}
public synchronized static void restart(String serverName) {
if(contains(serverName)) {
ServerThread serverThread = threadMap.get(serverName);
serverThread.restartServer();
}
}
public static void replaceUrl(String beforeName, String beforeUrl, ServerUrl serverUrl) {
if(contains(beforeName)) {
ServerThread serverThread = threadMap.get(beforeName);
serverThread.replaceUrl(beforeUrl, serverUrl);
}
}
}

View File

@@ -1,7 +1,11 @@
package com.dayrain.component;
import java.util.Map;
/**
* 请求路径
* @author peng
* @date 2021/11/8
*/
public class ServerUrl {
/**

View File

@@ -4,6 +4,7 @@ import com.dayrain.component.Server;
import com.dayrain.component.ServerUrl;
public class ServerThread extends Thread {
private final Server server;
public ServerThread(Server server) {
@@ -15,7 +16,20 @@ public class ServerThread extends Thread {
server.stop();
}
public void restartServer() {
server.restart();
}
public void addContext(ServerUrl serverUrl) {
server.addContext(serverUrl);
}
public void removeContext(String url) {
server.removeContext(url);
}
public void replaceUrl(String beforeUrl, ServerUrl serverUrl) {
removeContext(beforeUrl);
addContext(serverUrl);
}
}

View File

@@ -0,0 +1,15 @@
package com.dayrain.style;
import javafx.geometry.Insets;
import javafx.scene.layout.Background;
import javafx.scene.layout.BackgroundFill;
import javafx.scene.layout.CornerRadii;
import javafx.scene.paint.Color;
public class BackGroundFactory {
public static Background getBackGround() {
BackgroundFill backgroundFill = new BackgroundFill(Color.GRAY, new CornerRadii(1),
new Insets(0.0, 0.0, 0.0, 0.0));
return new Background(backgroundFill);
}
}

View File

@@ -0,0 +1,18 @@
package com.dayrain.style;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
/**
* 圆
* @author peng
* @date 2021/11/11
*/
public class CircleFactory {
public static Circle getLightCircle(Color color) {
Circle circle = new Circle();
circle.setRadius(10);
circle.setFill(color);
return circle;
}
}

View File

@@ -0,0 +1,30 @@
package com.dayrain.style;
import javafx.geometry.Pos;
import javafx.scene.control.Button;
import javafx.scene.control.Control;
import javafx.scene.control.Label;
import javafx.scene.layout.HBox;
public class FormFactory {
public static HBox getLine(Label label, Control control, double labelWidth, double nodeWidth, double maxWidth) {
HBox hBox = new HBox();
label.setPrefWidth(labelWidth);
control.setPrefWidth(nodeWidth);
hBox.getChildren().addAll(label, control);
hBox.setAlignment(Pos.CENTER_LEFT);
hBox.setMaxWidth(maxWidth);
return hBox;
}
public static HBox getButtonLine(Button button, double labelWidth, double width) {
HBox hBox = new HBox();
Label label = LabelFactory.getLabel("");
label.setPrefWidth(labelWidth);
hBox.getChildren().addAll(label, button);
hBox.setAlignment(Pos.CENTER_RIGHT);
hBox.setMaxWidth(width);
return hBox;
}
}

View File

@@ -0,0 +1,10 @@
package com.dayrain.style;
import javafx.scene.image.Image;
public class IconFactory {
public static Image getIcon() {
return new Image("panda.png");
}
}

View File

@@ -0,0 +1,30 @@
package com.dayrain.style;
import com.dayrain.views.ViewHolder;
import javafx.scene.Scene;
import javafx.stage.Modality;
import javafx.stage.Stage;
/**
* 窗口
* @author peng
* @date 2021/11/11
*/
public class StageFactory {
/**
* 获取标准弹窗
* @author peng
* @date 2021/11/11
*/
public static Stage getPopStage(String name, Scene scene) {
Stage stage = new Stage();
stage.setTitle(name);
stage.setWidth(700);
stage.setHeight(500);
stage.initOwner(ViewHolder.getPrimaryStage());
stage.initModality(Modality.WINDOW_MODAL);
stage.getIcons().addAll(IconFactory.getIcon());
stage.setScene(scene);
return stage;
}
}

View File

@@ -56,7 +56,7 @@ public class FileUtils {
while ((buf = bufferedReader.readLine()) != null) {
configStr.append(buf);
}
return "".equals(configStr.toString()) ? new Configuration(1200, 800, 8, 8) : new ObjectMapper().readValue(configStr.toString(), Configuration.class);
return "".equals(configStr.toString()) ? new Configuration(1400, 800, 8, 8) : new ObjectMapper().readValue(configStr.toString(), Configuration.class);
} catch (IOException e) {
e.printStackTrace();
} finally {
@@ -75,7 +75,7 @@ public class FileUtils {
public static String getFromInputStream(InputStream inputStream) {
try {
byte[] buf = new byte[4096];
int len = 0;
int len;
StringBuilder stringBuilder = new StringBuilder();
while ((len = inputStream.read(buf)) != -1) {
stringBuilder.append(new String(buf, 0, len));

View File

@@ -0,0 +1,32 @@
package com.dayrain.views;
import com.dayrain.component.ConfigHolder;
import javafx.application.Application;
import javafx.stage.Stage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* 启动入口
* @author peng
* @date 2021/11/11
*/
public class ApplicationStarter extends Application {
private static final Logger logger = LoggerFactory.getLogger(ApplicationStarter.class);
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) {
try {
ConfigHolder.init();
ViewHolder.setPrimaryStage(primaryStage);
new HomeView().start();
}catch (Exception e) {
e.printStackTrace();
logger.error(e.getMessage());
}
}
}

View File

@@ -0,0 +1,85 @@
package com.dayrain.views;
import com.dayrain.component.ConfigHolder;
import com.dayrain.component.ConsoleLog;
import com.dayrain.component.ServerConfig;
import com.dayrain.component.ServerThreadHolder;
import com.dayrain.style.IconFactory;
import javafx.application.Platform;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.scene.Scene;
import javafx.scene.control.SplitPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import java.util.ArrayList;
import java.util.List;
/**
* 主页
* @author peng
* @date 2021/11/11
*/
public class HomeView {
private final Stage primaryStage;
public HomeView() {
this.primaryStage = ViewHolder.getPrimaryStage();
}
/**
* 启动程序
*/
public void start() {
VBox vBox = new VBox();
//菜单栏
MenuBarView menuBar = new MenuBarView();
SplitPane splitPane = new SplitPane();
//日志
LogArea logArea = new LogArea();
ConsoleLog.initTextArea(logArea);
ViewHolder.setLogArea(logArea);
//server
ServerContainer serverContainer = initServer();
ViewHolder.setServerContainer(serverContainer);
splitPane.getItems().addAll(serverContainer, logArea);
splitPane.setDividerPositions(0.55f, 0.45f);
vBox.getChildren().addAll(menuBar, splitPane);
primaryStage.setTitle(ConfigHolder.get().getProjectName());
primaryStage.setScene(new Scene(vBox));
primaryStage.setWidth(ConfigHolder.get().getWidth());
primaryStage.setHeight(ConfigHolder.get().getHeight());
primaryStage.getIcons().add(IconFactory.getIcon());
primaryStage.show();
primaryStage.setOnCloseRequest(event -> {
ConfigHolder.save();
ServerThreadHolder.stopAll();
Platform.exit();
});
}
/**
* 初始化服务列表
* @return 服务的容器
*/
private ServerContainer initServer() {
List<ServerConfig> serverConfigs = ConfigHolder.get().getServerConfigs();
List<ServerPane>serverPanes = new ArrayList<>();
if(serverConfigs != null) {
for (ServerConfig serverConfig : serverConfigs) {
ServerPane serverPane = new ServerPane(serverConfig);
serverPanes.add(serverPane);
}
}
return new ServerContainer(serverPanes);
}
public void restart() {
//停止所有线程
ServerThreadHolder.stopAll();
start();
}
}

View File

@@ -0,0 +1,34 @@
package com.dayrain.views;
import com.dayrain.component.ConfigHolder;
import javafx.scene.control.TextArea;
import javafx.scene.text.Font;
/**
* 打印日志的组件
* 每个服务都有各自的组件
* @author peng
* @date 2021/11/8
*/
public class LogArea extends TextArea {
private String serverName;
public LogArea() {
createView();
}
public void createView() {
this.setEditable(false);
this.setFont(Font.font("Microsoft YaHei", 16));
this.setPrefWidth(582);
this.setPrefHeight(ConfigHolder.get().getHeight());
}
public String getServerName() {
return serverName;
}
public void setServerName(String serverName) {
this.serverName = serverName;
}
}

View File

@@ -0,0 +1,210 @@
package com.dayrain.views;
import com.dayrain.component.ConfigHolder;
import com.dayrain.component.Configuration;
import com.dayrain.component.ServerConfig;
import com.dayrain.style.BackGroundFactory;
import com.dayrain.style.ButtonFactory;
import com.dayrain.style.LabelFactory;
import com.dayrain.style.StageFactory;
import com.dayrain.utils.FileUtils;
import javafx.event.ActionEvent;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.Menu;
import javafx.scene.control.MenuBar;
import javafx.scene.control.MenuItem;
import javafx.scene.control.TextField;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.HBox;
import javafx.stage.FileChooser;
import javafx.stage.Stage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.awt.Desktop;
import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
/**
* 菜单栏
* @author peng
* @date 2021/11/11
*/
public class MenuBarView extends MenuBar {
private static final Logger logger = LoggerFactory.getLogger(MenuBarView.class);
private final Menu menu1 = new Menu("文件");
private final Menu menu2 = new Menu("设置");
private final Menu menu3 = new Menu("帮助");
public MenuBarView() {
creatView();
}
private void creatView() {
MenuItem menuItem11 = new MenuItem("新建");
MenuItem menuItem12 = new MenuItem("导入");
MenuItem menuItem13 = new MenuItem("导出");
menu1.getItems().addAll(menuItem11, menuItem12, menuItem13);
menuItem11.setOnAction(this::addServer);
menuItem12.setOnAction(this::importConfig);
menuItem13.setOnAction(this::exportConfig);
MenuItem menuItem21 = new MenuItem("随机值长度");
menu2.getItems().addAll(menuItem21);
menuItem21.setOnAction(this::updateRandomLength);
MenuItem menuItem31 = new MenuItem("说明书");
MenuItem menuItem32 = new MenuItem("源码地址");
menu3.getItems().addAll(menuItem31, menuItem32);
menuItem31.setOnAction(this::linkIntroduce);
menuItem32.setOnAction(this::linkGithub);
this.setBackground(BackGroundFactory.getBackGround());
this.getMenus().addAll(menu1, menu2, menu3);
}
public void updateRandomLength(ActionEvent evt) {
Configuration configuration = ConfigHolder.get();
Label strName = LabelFactory.getLabel("随机字符长度:");
strName.setPrefWidth(150);
TextField strField = new TextField(String.valueOf(configuration.getStringLen()));
Label intName = LabelFactory.getLabel("随机整数长度:");
javafx.scene.control.TextField intField = new TextField(String.valueOf(configuration.getIntLen()));
intField.setPrefWidth(150);
HBox btnHBox = new HBox();
Label saveTips1 = LabelFactory.getLabel("注: $string$代指随机字符串");
Label saveTips2 = LabelFactory.getLabel("$int$代指随机整数");
Button saveButton = ButtonFactory.getButton("保存");
btnHBox.getChildren().addAll(saveButton);
btnHBox.setAlignment(Pos.CENTER_RIGHT);
btnHBox.setSpacing(20d);
GridPane gridPane = new GridPane();
gridPane.add(strName, 0, 0);
gridPane.add(strField, 1, 0);
gridPane.add(intName, 0, 1);
gridPane.add(intField, 1, 1);
gridPane.add(saveTips1, 0, 3);
gridPane.add(saveTips2, 1, 3);
gridPane.add(btnHBox, 1, 4);
gridPane.setAlignment(Pos.CENTER);
gridPane.setHgap(20d);
gridPane.setVgap(10d);
Stage stage = StageFactory.getPopStage("更改随机值配置", new Scene(gridPane));
stage.show();
saveButton.setOnAction(event -> {
String strLen = strField.getText();
String intLen = intField.getText();
configuration.setStringLen(Integer.parseInt(strLen));
configuration.setIntLen(Integer.parseInt(intLen));
ConfigHolder.save();
stage.close();
});
}
public void exportConfig(ActionEvent evt) {
Stage stage = new Stage();
stage.initOwner(ViewHolder.getPrimaryStage());
FileChooser fileChooser = new FileChooser();
String projectName = ConfigHolder.get().getProjectName();
if (projectName == null) {
projectName = "";
}
projectName += "server";
fileChooser.setTitle("导出配置");
fileChooser.setInitialFileName(projectName + ".json");
File file = fileChooser.showSaveDialog(stage);
if (file != null) {
FileUtils.saveConfig(ConfigHolder.get(), file);
}
}
private void importConfig(ActionEvent evt) {
Stage stage = new Stage();
stage.initOwner(ViewHolder.getPrimaryStage());
FileChooser fileChooser = new FileChooser();
fileChooser.setTitle("选择一个文件");
//过滤器
fileChooser.getExtensionFilters().addAll(new FileChooser.ExtensionFilter("只能导入json文件", "*.json"));
File file = fileChooser.showOpenDialog(stage);
if (file != null) {
Configuration loadConfig = FileUtils.load(file);
ConfigHolder.replace(loadConfig);
FileUtils.saveConfig(loadConfig);
ConfigHolder.replace(loadConfig);
ViewHolder.getHomeView().restart();
}
}
/**
* 添加服务
*/
private void addServer(ActionEvent evt) {
Label nameLabel = LabelFactory.getLabel("服务名称:");
nameLabel.setPrefWidth(80);
javafx.scene.control.TextField nameField = new javafx.scene.control.TextField();
javafx.scene.control.Label portLabel = LabelFactory.getLabel("端口号:");
javafx.scene.control.TextField portField = new javafx.scene.control.TextField();
portField.setPrefWidth(80);
HBox btnHBox = new HBox();
Button saveButton = ButtonFactory.getButton("保存");
btnHBox.getChildren().add(saveButton);
btnHBox.setAlignment(Pos.CENTER_RIGHT);
GridPane gridPane = new GridPane();
gridPane.add(nameLabel, 0, 0);
gridPane.add(nameField, 1, 0);
gridPane.add(portLabel, 0, 1);
gridPane.add(portField, 1, 1);
gridPane.add(btnHBox, 1, 3);
gridPane.setAlignment(Pos.CENTER);
gridPane.setHgap(20d);
gridPane.setVgap(10d);
Stage stage = StageFactory.getPopStage("添加服务", new Scene(gridPane));
stage.show();
saveButton.setOnAction(event -> {
String name = nameField.getText();
String port = portField.getText();
ServerConfig serverConfig = new ServerConfig(name, Integer.parseInt(port), new ArrayList<>());
ConfigHolder.get().getServerConfigs().add(serverConfig);
ViewHolder.getServerContainer().refresh();
ConfigHolder.save();
stage.close();
});
}
private void linkGithub(ActionEvent evt) {
try {
Desktop.getDesktop().browse(new URI("https://github.com/DayRain/http-server-simulator"));
} catch (IOException | URISyntaxException e) {
logger.error("跳转到github时发生了错误: {}", e.getMessage());
e.printStackTrace();
}
}
private void linkIntroduce(ActionEvent evt){
try {
Desktop.getDesktop().browse(new URI("https://blog.csdn.net/qq_37855749/article/details/121030800"));
} catch (IOException | URISyntaxException e) {
logger.error("跳转到csdn时发生了错误: {}", e.getMessage());
e.printStackTrace();
}
}
}

View File

@@ -0,0 +1,28 @@
package com.dayrain.views;
import javafx.scene.layout.VBox;
import java.util.List;
/**
* server容器
* @author peng
* @date 2021/11/11
*/
public class ServerContainer extends VBox {
private List<ServerPane> serverPanes;
public ServerContainer(List<ServerPane> serverPanes) {
this.serverPanes = serverPanes;
createView();
}
public void createView() {
getChildren().addAll(serverPanes);
}
public void refresh() {
getChildren().removeAll();
getChildren().addAll(serverPanes);
}
}

View File

@@ -0,0 +1,239 @@
package com.dayrain.views;
import com.dayrain.component.ConfigHolder;
import com.dayrain.component.ConsoleLog;
import com.dayrain.component.RequestType;
import com.dayrain.component.Server;
import com.dayrain.component.ServerConfig;
import com.dayrain.component.ServerThreadHolder;
import com.dayrain.component.ServerUrl;
import com.dayrain.server.ServerThread;
import com.dayrain.style.BackGroundFactory;
import com.dayrain.style.ButtonFactory;
import com.dayrain.style.CircleFactory;
import com.dayrain.style.FormFactory;
import com.dayrain.style.IconFactory;
import com.dayrain.style.LabelFactory;
import com.dayrain.style.StageFactory;
import com.dayrain.utils.ListViewHelper;
import javafx.collections.FXCollections;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Alert;
import javafx.scene.control.Button;
import javafx.scene.control.ButtonType;
import javafx.scene.control.ChoiceBox;
import javafx.scene.control.Label;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.scene.control.TitledPane;
import javafx.scene.image.ImageView;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.scene.text.Font;
import javafx.stage.Modality;
import javafx.stage.Stage;
import java.util.List;
/**
* server容器
* @author peng
* @date 2021/11/11
*/
public class ServerPane extends TitledPane {
private final ServerConfig serverConfig;
private ServerUrlListView serverUrlListView;
private final Circle statusCircle;
private final Button editButton;
private final Button openButton;
private final Button deleteButton;
private final Button addButton;
public ServerPane(ServerConfig serverConfig) {
this.serverConfig = serverConfig;
this.statusCircle = CircleFactory.getLightCircle(ServerThreadHolder.contains(serverConfig.getServerName()) ? Color.GREEN : Color.RED);
this.editButton = ButtonFactory.getButton("修改配置");
this.openButton = ButtonFactory.getButton("开启服务");
this.deleteButton = ButtonFactory.getButton("删除服务");
this.addButton = ButtonFactory.getButton("添加接口");
createView();
}
public void createView() {
VBox vBox = new VBox();
HBox headBox = new HBox();
//设置服务启动与关闭
openButton.setOnAction(this::startServer);
editButton.setOnAction(this::updateServer);
deleteButton.setOnAction(this::deleteSever);
headBox.getChildren().addAll(openButton, editButton, deleteButton, addButton, statusCircle);
HBox.setMargin(statusCircle, new Insets(0, 0, 0, 30));
headBox.setSpacing(20d);
headBox.setAlignment(Pos.CENTER);
//添加url
this.serverUrlListView = new ServerUrlListView(serverConfig);
addButton.setOnAction(this::addUrl);
vBox.getChildren().addAll(headBox, serverUrlListView);
vBox.setSpacing(10d);
VBox.setMargin(headBox, new Insets(10, 0, 0, 0));
vBox.setPadding(Insets.EMPTY);
setText(serverConfig.getServerName());
this.setContent(vBox);
this.setFont(Font.font("Microsoft YaHei", 18));
this.setPrefWidth(600d);
this.setExpanded(false);
this.setBackground(BackGroundFactory.getBackGround());
this.setOnMouseClicked(event -> {
if (!serverConfig.getServerName().equals(ViewHolder.getLogArea().getServerName())) {
ConsoleLog.resetTextArea(serverConfig.getServerName());
}
});
HBox hBox = new HBox();
hBox.setPrefHeight(60d);
this.setGraphic(hBox);
}
/**
* 启动服务
*/
private void startServer(ActionEvent evt) {
String serverName = serverConfig.getServerName();
if (ServerThreadHolder.contains(serverName)) {
ServerThreadHolder.remove(serverName);
openButton.setText("开启服务");
statusCircle.setFill(Color.RED);
} else {
ServerThreadHolder.add(serverName, new ServerThread(new Server(serverConfig)));
openButton.setText("关闭服务");
statusCircle.setFill(Color.GREEN);
}
}
/**
* 更新服务
*/
private void updateServer(ActionEvent evt) {
Label serverName = LabelFactory.getLabel("服务名称:");
serverName.setPrefWidth(80);
TextField nameField = new TextField(serverConfig.getServerName());
Label portLabel = LabelFactory.getLabel("端口:");
TextField portField = new TextField(String.valueOf(serverConfig.getPort()));
portField.setPrefWidth(80);
HBox btnHBox = new HBox();
Label saveTips = LabelFactory.getLabel("重启后生效");
Button saveButton = ButtonFactory.getButton("保存");
btnHBox.getChildren().addAll(saveTips, saveButton);
btnHBox.setAlignment(Pos.CENTER_RIGHT);
btnHBox.setSpacing(20d);
GridPane gridPane = new GridPane();
gridPane.add(serverName, 0, 0);
gridPane.add(nameField, 1, 0);
gridPane.add(portLabel, 0, 1);
gridPane.add(portField, 1, 1);
gridPane.add(btnHBox, 1, 3);
gridPane.setAlignment(Pos.CENTER);
gridPane.setHgap(20d);
gridPane.setVgap(10d);
Stage stage = StageFactory.getPopStage("更新服务配置", new Scene(gridPane));
stage.show();
saveButton.setOnAction(event -> {
String name = nameField.getText();
int port = Integer.parseInt(portField.getText());
serverConfig.setPort(port);
serverConfig.setServerName(name);
ConfigHolder.save();
stage.close();
});
}
/**
* 删除服务
*/
private void deleteSever(ActionEvent evt) {
Alert alert = new Alert(Alert.AlertType.CONFIRMATION);
alert.setGraphic(new ImageView(IconFactory.getIcon()));
Stage stage = (Stage) alert.getDialogPane().getScene().getWindow();
stage.getIcons().add(IconFactory.getIcon());
alert.setHeaderText("是否确定删除该服务?");
Button okButton = (Button) alert.getDialogPane().lookupButton(ButtonType.OK);
okButton.setOnAction(event1 -> {
ConfigHolder.get().getServerConfigs().remove(serverConfig);
ViewHolder.getServerContainer().refresh();
ConfigHolder.save();
});
alert.show();
}
private void addUrl(ActionEvent evt) {
VBox vBox = new VBox();
Label nameLabel = LabelFactory.getLabel("接口名称:");
TextField nameField = new TextField();
HBox hBox1 = FormFactory.getLine(nameLabel, nameField, 120, 300, 500);
Label urlLabel = LabelFactory.getLabel("接口地址:");
TextField urlField = new TextField();
HBox hBox2 = FormFactory.getLine(urlLabel, urlField, 120, 300, 500);
Label typeLabel = LabelFactory.getLabel("请求方式:");
ChoiceBox<String> choiceBox = new ChoiceBox<>();
choiceBox.setItems(FXCollections.observableArrayList("POST", "GET"));
choiceBox.setValue("POST");
HBox hBox3 = FormFactory.getLine(typeLabel, choiceBox, 120, 70, 500);
Label respLabel = LabelFactory.getLabel("返回结果:");
TextArea textArea = new TextArea();
HBox hBox4 = FormFactory.getLine(respLabel, textArea, 120, 300, 500);
Button saveButton = ButtonFactory.getButton("保存");
HBox hBox5 = FormFactory.getButtonLine(saveButton, 120, 500);
vBox.getChildren().addAll(hBox1, hBox2, hBox3, hBox4, hBox5);
vBox.setSpacing(20d);
vBox.setAlignment(Pos.CENTER);
Stage stage = StageFactory.getPopStage("新增接口信息", new Scene(vBox));
stage.show();
saveButton.setOnAction(event1 -> {
String name = nameField.getText();
List<ServerUrl> serverUrls = serverConfig.getServerUrls();
for (ServerUrl serverUrl : serverUrls) {
if (serverUrl.getUrlName().equals(name)) {
return;
}
}
String url = urlField.getText();
String resp = textArea.getText();
String type = choiceBox.getValue();
ServerUrl serverUrl = new ServerUrl(serverConfig.getServerName(), name, url, type.equals(RequestType.POST.name()) ? RequestType.POST : RequestType.GET, resp);
serverUrls.add(serverUrl);
ServerThreadHolder.addUrl(serverUrl);
ListViewHelper.addAndRefresh(serverUrl, serverUrlListView);
ConfigHolder.save();
stage.close();
});
}
}

View File

@@ -0,0 +1,54 @@
package com.dayrain.views;
import com.dayrain.component.ServerConfig;
import com.dayrain.component.ServerUrl;
import javafx.beans.binding.Bindings;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.control.ListCell;
import javafx.scene.control.ListView;
import javafx.stage.Stage;
import javafx.util.Callback;
/**
* server 列表
* @author peng
* @date 2021/11/11
*/
public class ServerUrlListView extends ListView<ServerUrl> {
private ServerConfig serverConfig;
public ServerUrlListView(ServerConfig serverConfig) {
this.serverConfig = serverConfig;
createView();
}
private void createView() {
ObservableList<ServerUrl> urlList = FXCollections.observableArrayList(serverConfig.getServerUrls());
setItems(urlList);
this.setCellFactory(new Callback<ListView<ServerUrl>, ListCell<ServerUrl>>() {
@Override
public ListCell<ServerUrl> call(ListView<ServerUrl> param) {
return new ListCell<ServerUrl>() {
@Override
protected void updateItem(ServerUrl item, boolean empty) {
super.updateItem(item, empty);
if (empty || item == null) {
setText(null);
setGraphic(null);
} else {
ServerUrlPaneView urlPane = new ServerUrlPaneView(item, serverConfig, ServerUrlListView.this);
this.setGraphic(urlPane);
}
}
};
}
});
this.prefHeightProperty().bind(Bindings.size(urlList).multiply(60));
this.setFocusTraversable(false);
}
}

View File

@@ -0,0 +1,156 @@
package com.dayrain.views;
import com.dayrain.component.ConfigHolder;
import com.dayrain.component.RequestType;
import com.dayrain.component.ServerConfig;
import com.dayrain.component.ServerThreadHolder;
import com.dayrain.component.ServerUrl;
import com.dayrain.style.ButtonFactory;
import com.dayrain.style.FormFactory;
import com.dayrain.style.IconFactory;
import com.dayrain.style.LabelFactory;
import com.dayrain.style.StageFactory;
import com.dayrain.utils.ListViewHelper;
import javafx.collections.FXCollections;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Alert;
import javafx.scene.control.Button;
import javafx.scene.control.ButtonType;
import javafx.scene.control.ChoiceBox;
import javafx.scene.control.Label;
import javafx.scene.control.ListView;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.scene.image.ImageView;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import java.util.List;
/**
* url面板
* @author peng
* @date 2021/11/11
*/
public class ServerUrlPaneView extends BorderPane {
private final ServerUrl serverUrl;
private final ServerConfig serverConfig;
private final ListView<ServerUrl> serverListViews;
public ServerUrlPaneView(ServerUrl serverUrl, ServerConfig serverConfig, ListView<ServerUrl> serverListViews) {
this.serverUrl = serverUrl;
this.serverConfig = serverConfig;
this.serverListViews = serverListViews;
createView();
}
public void createView() {
HBox labelBox = new HBox();
Label nameLabel = LabelFactory.getLabel(serverUrl.getUrlName());
nameLabel.setPrefWidth(180d);
nameLabel.setMaxWidth(180d);
Label typeLabel = LabelFactory.getLabel(serverUrl.getRequestType().name());
typeLabel.setPrefWidth(65d);
Label urlLabel = LabelFactory.getLabel(serverUrl.getUrl());
urlLabel.setMaxWidth(220d);
labelBox.getChildren().addAll(nameLabel, typeLabel, urlLabel);
labelBox.setAlignment(Pos.CENTER_LEFT);
HBox btnBox = new HBox();
Button configButton = ButtonFactory.getButton("配置");
Button deleteButton = ButtonFactory.getButton("删除");
btnBox.setSpacing(10d);
btnBox.getChildren().addAll(configButton, deleteButton);
HBox.setMargin(deleteButton, new Insets(0, 5, 0, 0));
deleteButton.setOnAction(this::deleteUrl);
configButton.setOnAction(this::updateUrl);
this.setLeft(labelBox);
this.setRight(btnBox);
}
private void deleteUrl(ActionEvent event) {
Alert alert = new Alert(Alert.AlertType.CONFIRMATION);
alert.setGraphic(new ImageView(IconFactory.getIcon()));
Stage stage = (Stage) alert.getDialogPane().getScene().getWindow();
stage.getIcons().add(IconFactory.getIcon());
alert.setHeaderText("是否确定删除该接口?");
Button okButton = (Button) alert.getDialogPane().lookupButton(ButtonType.OK);
okButton.setOnAction(event1 -> {
List<ServerUrl> serverUrls = serverConfig.getServerUrls();
serverUrls.remove(serverUrl);
ConfigHolder.save();
ListViewHelper.deleteAndRefresh(serverUrl, serverListViews);
});
alert.show();
}
private void updateUrl(ActionEvent event) {
VBox vBox = new VBox();
Label nameLabel = LabelFactory.getLabel("接口名称:");
TextField nameField = new TextField(serverUrl.getUrlName());
HBox hBox1 = FormFactory.getLine(nameLabel, nameField, 120, 300, 500);
Label urlLabel = LabelFactory.getLabel("接口地址:");
TextField urlField = new TextField(serverUrl.getUrl());
HBox hBox2 = FormFactory.getLine(urlLabel, urlField, 120, 300, 500);
Label typeLabel = LabelFactory.getLabel("请求方式:");
ChoiceBox<String> choiceBox = new ChoiceBox<>();
choiceBox.setItems(FXCollections.observableArrayList("POST", "GET"));
choiceBox.setValue(serverUrl.getRequestType().name());
HBox hBox3 = FormFactory.getLine(typeLabel, choiceBox, 120, 70, 500);
Label respLabel = LabelFactory.getLabel("返回结果:");
TextArea textArea = new TextArea(serverUrl.getResponseBody());
HBox hBox4 = FormFactory.getLine(respLabel, textArea, 120, 300, 500);
Button saveButton = ButtonFactory.getButton("保存");
HBox hBox5 = FormFactory.getButtonLine(saveButton, 120, 500);
vBox.getChildren().addAll(hBox1, hBox2, hBox3, hBox4, hBox5);
vBox.setSpacing(20d);
vBox.setAlignment(Pos.CENTER);
Stage stage = StageFactory.getPopStage("更新接口信息", new Scene(vBox));
stage.show();
saveButton.setOnAction(event1 -> {
String name = nameField.getText();
String url = urlField.getText();
String resp = textArea.getText();
String type = choiceBox.getValue();
if(url == null) {
return;
}
if(!url.startsWith("/")) {
url = "/" + url;
}
String beforeUrl = serverUrl.getUrl();
serverUrl.setUrlName(name);
serverUrl.setUrl(url);
serverUrl.setResponseBody(resp);
serverUrl.setRequestType(type.equals(RequestType.POST.name()) ? RequestType.POST : RequestType.GET);
ListViewHelper.refresh(serverListViews);
ConfigHolder.save();
ServerThreadHolder.replaceUrl(serverUrl.getServerName(), beforeUrl, serverUrl);
stage.close();
});
}
}

View File

@@ -0,0 +1,50 @@
package com.dayrain.views;
import javafx.stage.Stage;
/**
* 主要视图的句柄
* @author peng
* @date 2021/11/11
*/
public class ViewHolder {
private static Stage primaryStage;
private static LogArea logArea;
private static ServerContainer serverContainer;
private static HomeView homeView;
static void setPrimaryStage(Stage primaryStage) {
ViewHolder.primaryStage = primaryStage;
}
public static Stage getPrimaryStage() {
return primaryStage;
}
static void setLogArea(LogArea logArea) {
ViewHolder.logArea = logArea;
}
public static LogArea getLogArea() {
return logArea;
}
public static ServerContainer getServerContainer() {
return serverContainer;
}
static void setServerContainer(ServerContainer serverContainer) {
ViewHolder.serverContainer = serverContainer;
}
static void setHomePage(HomeView homeView) {
ViewHolder.homeView = homeView;
}
public static HomeView getHomeView() {
return ViewHolder.homeView;
}
}

View File

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

View File

@@ -0,0 +1,33 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="false">
<property name="LOG_HOME" value="./logs" />
<!-- 控制台输出 -->
<appender name="STDOUT"
class="ch.qos.logback.core.ConsoleAppender">
<encoder
class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<!--格式化输出:%d表示日期%thread表示线程名%-5level级别从左显示5个字符宽度%msg日志消息%n是换行符 -->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
</encoder>
</appender>
<appender name="errorFile"
class="ch.qos.logback.core.FileAppender">
<file>${LOG_HOME}/error.log</file>
<encoder
class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<!--格式化输出:%d表示日期%thread表示线程名%-5level级别从左显示5个字符宽度%msg日志消息%n是换行符 -->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
</encoder>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>ERROR</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<logger name="com.dayrain" level="ERROR" additivity="false">
<appender-ref ref="STDOUT" />
<appender-ref ref="errorFile" />
</logger>
</configuration>

View File

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB