diff --git a/README.md b/README.md index e8b71a1..32a596b 100644 --- a/README.md +++ b/README.md @@ -128,6 +128,18 @@ ![](./src/main/resources/static/redame/img_23.png) +### 8. 服务工具 + +#### 8.1 http 服务工具 + +![](./src/main/resources/static/redame/img_27.png) + +![](./src/main/resources/static/redame/img_28.png) + +##### 8.1.1 静态资源访问 + +![](./src/main/resources/static/redame/img_29.png) + ## 2. 开源项目总览 | 项目名称 |地址| diff --git a/src/main/java/com/zhangmeng/tools/controller/CodecToolsController.java b/src/main/java/com/zhangmeng/tools/controller/CodecToolsController.java index 2b22943..2150483 100644 --- a/src/main/java/com/zhangmeng/tools/controller/CodecToolsController.java +++ b/src/main/java/com/zhangmeng/tools/controller/CodecToolsController.java @@ -84,12 +84,12 @@ public class CodecToolsController { @FXML public void md5_menu_item() { - load_encrypt(); + load_encrypt(0); } @FXML public void spring_security_menu_item() { - load_encrypt(); + load_encrypt(1); } @FXML @@ -262,7 +262,7 @@ public class CodecToolsController { listView.getSelectionModel().select(index); } - public void load_encrypt() { + public void load_encrypt(int index) { Stage stage = (Stage) splitPane.getScene().getWindow(); @@ -274,6 +274,9 @@ public class CodecToolsController { } Scene scene = new Scene(fx); stage.setScene(scene); + + ListView listView = (ListView) fx.lookup("#listView"); + listView.getSelectionModel().select(index); } @FXML diff --git a/src/main/java/com/zhangmeng/tools/controller/FtpServerController.java b/src/main/java/com/zhangmeng/tools/controller/FtpServerController.java new file mode 100644 index 0000000..aba8c4a --- /dev/null +++ b/src/main/java/com/zhangmeng/tools/controller/FtpServerController.java @@ -0,0 +1,14 @@ +package com.zhangmeng.tools.controller; + +import lombok.extern.slf4j.Slf4j; + +/** + * @author : 芊芊墨客 + * @version : 1.0 + * @date : 2023-03-10 11:35 + */ +@Slf4j +public class FtpServerController { + + +} diff --git a/src/main/java/com/zhangmeng/tools/controller/HomeController.java b/src/main/java/com/zhangmeng/tools/controller/HomeController.java index 8e0a170..ebfab01 100644 --- a/src/main/java/com/zhangmeng/tools/controller/HomeController.java +++ b/src/main/java/com/zhangmeng/tools/controller/HomeController.java @@ -439,4 +439,28 @@ public class HomeController implements Serializable { public void mail_menu_item(ActionEvent event) { load_small_tools(7); } + + public void http_server_menu_item(ActionEvent event) { + load_server_tools(0); + } + + public void ftp_server_menu_item(ActionEvent event) { + load_server_tools(1); + } + + public void load_server_tools(int index) { + AnchorPane fx = null; + try { + fx = FXMLLoader.load(ResourcesUtils.getResource("server-tools")); + } catch (IOException e) { + e.printStackTrace(); + } + + Scene scene = new Scene(fx); + Stage stage = (Stage) splitPane.getScene().getWindow(); + stage.setScene(scene); + + ListView listView = (ListView) fx.lookup("#listView"); + listView.getSelectionModel().select(index); + } } \ No newline at end of file diff --git a/src/main/java/com/zhangmeng/tools/controller/HttpServerController.java b/src/main/java/com/zhangmeng/tools/controller/HttpServerController.java new file mode 100644 index 0000000..8fb16a6 --- /dev/null +++ b/src/main/java/com/zhangmeng/tools/controller/HttpServerController.java @@ -0,0 +1,354 @@ +package com.zhangmeng.tools.controller; + +import cn.hutool.core.io.FileUtil; +import com.zhangmeng.tools.server.SimpleServer; +import com.zhangmeng.tools.utils.AlertUtils; +import com.zhangmeng.tools.utils.ImagePath; +import javafx.beans.property.SimpleObjectProperty; +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; +import javafx.fxml.FXML; +import javafx.geometry.Pos; +import javafx.scene.control.*; +import javafx.scene.image.Image; +import javafx.scene.image.ImageView; +import javafx.scene.layout.HBox; +import javafx.stage.FileChooser; +import javafx.stage.Stage; +import javafx.util.Callback; +import lombok.extern.slf4j.Slf4j; + +import java.io.File; +import java.nio.charset.StandardCharsets; + +/** + * @author : 芊芊墨客 + * @version : 1.0 + * @date : 2023-03-10 11:35 + */ +@Slf4j +public class HttpServerController { + + public enum ContentType { + /** + * Rest请求JSON编码 + */ + JSON("application/json"); + + private String value; + + ContentType(String value) { + this.value = value; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + } + + @FXML + public TextField server_port; + + @FXML + public TextField file_dir_root; + + @FXML + public ComboBox data_combox; + + @FXML + public TextField server_api; + + @FXML + public Button add_api; + + @FXML + public Button server; + + @FXML + public Button stop_server; + + @FXML + public RadioButton common_api; + + @FXML + public RadioButton file_api; + + @FXML + public RadioButton res_json; + + @FXML + public RadioButton custom_res; + + @FXML + public ListView api_list; + + @FXML + public TextField custom_res_content; + + @FXML + public Button choose_json_button; + + @FXML + public TextField json_file_path; + + private SimpleServer simpleServer = null; + + private static final int default_port = 8083; + + private final ObservableList data_type_list = FXCollections.observableArrayList(); + private final ObservableList api_data_list = FXCollections.observableArrayList(); + private final SimpleObjectProperty choose_but = new SimpleObjectProperty<>(); + private final SimpleObjectProperty choose_res = new SimpleObjectProperty<>(); + private final SimpleObjectProperty choose_file = new SimpleObjectProperty<>(); + private final SimpleObjectProperty choose_content_type = new SimpleObjectProperty<>(); + + @FXML + public void initialize() { + + choose_json_button.setText(null); + ImageView iv = new ImageView(new Image(ImagePath.path(ImagePath.ImagePathType.IMAGE_FILE))); + iv.setPreserveRatio(true); + iv.setFitWidth(18); + choose_json_button.setGraphic(iv); + choose_json_button.setOnAction(event -> { + Stage stage = new Stage(); + FileChooser fc = new FileChooser(); + fc.setTitle("单选文件"); + fc.getExtensionFilters().addAll( + new FileChooser.ExtensionFilter("文本类型", "*.json") + ); + + File file = fc.showOpenDialog(stage); + + if (file == null) { + return; + } + json_file_path.setText(file.getPath()); + choose_file.set(file); + }); + + //返回数据类型 + data_type_list.addAll(ContentType.values()); + data_combox.setItems(data_type_list); + data_combox.getSelectionModel().select(ContentType.JSON); + choose_content_type.set(ContentType.JSON); + data_combox.setCellFactory(new Callback<>() { + @Override + public ListCell call(ListView param) { + return new ListCell<>() { + @Override + protected void updateItem(ContentType data, boolean b) { + super.updateItem(data, b); + if (!b) { + HBox hBox = new HBox(); + hBox.setAlignment(Pos.CENTER); + hBox.getChildren().add(new Label(data.getValue())); + this.setGraphic(hBox); + } + } + }; + } + }); + + data_combox.getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) -> { + if (newValue != null) { + log.info("ContentType:---{}", newValue); + choose_content_type.setValue(newValue); + } + }); + + api_list.setItems(api_data_list); + api_list.setFixedCellSize(40); + api_list.setCellFactory(new Callback<>() { + @Override + public ListCell call(ListView param) { + return new ListCell<>() { + @Override + protected void updateItem(Data data, boolean b) { + super.updateItem(data, b); + if (!b) { + HBox hBox = new HBox(); + hBox.setAlignment(Pos.CENTER); + if (data.is_json_file) { + hBox.getChildren().add(new Label("==>接口地址:" + data.getApi() + "==>返回类型:json" + "==>是否是文件接口:" + data.isIs_file_api() + "==>是否是json文件:" + data.isIs_json_file() + "==>json文件地址:" + data.file.getPath())); + }else { + hBox.getChildren().add(new Label("==>接口地址:" + data.getApi() + "==>返回类型:json" + "==>是否是文件接口:" + data.isIs_file_api() + "==>是否是json文件:" + data.isIs_json_file())); + } + this.setGraphic(hBox); + } + } + }; + } + }); + + ToggleGroup tg = new ToggleGroup(); + common_api.setToggleGroup(tg); + file_api.setToggleGroup(tg); + tg.selectToggle(common_api);//默认选项 + choose_but.setValue(common_api); + + ToggleGroup tg2 = new ToggleGroup(); + res_json.setToggleGroup(tg2); + custom_res.setToggleGroup(tg2); + tg2.selectToggle(custom_res);//默认选项 + choose_res.setValue(custom_res); + + tg.selectedToggleProperty().addListener((observable, oldValue, newValue) -> { + RadioButton radioButton = (RadioButton) newValue; + choose_but.setValue(radioButton); + }); + + tg2.selectedToggleProperty().addListener((observable, oldValue, newValue) -> { + RadioButton radioButton = (RadioButton) newValue; + choose_res.setValue(radioButton); + }); + + add_api.setOnAction(event -> { + + if (server_api.getText().length() == 0 ){ + AlertUtils.alert_warning("添加的api不能为空!"); + return; + } + + if (data_combox.getSelectionModel().getSelectedItem() == null){ + AlertUtils.alert_warning("请api返回数据类型!"); + return; + } + + Data data = new Data(); + data.setApi(server_api.getText()); + RadioButton value1 = choose_but.getValue(); + data.setIs_file_api(!value1.getId().equals(common_api.getId())); + + RadioButton value = choose_res.getValue(); + if (value.getId().equals(custom_res.getId())){ + if (custom_res_content.getText().length() == 0 ){ + AlertUtils.alert_warning("自定义返回内容不能为空!"); + return; + } + data.setContent(custom_res_content.getText()); + data.setIs_json_file(false); + }else { + File file = choose_file.getValue(); + if (file == null){ + AlertUtils.alert_warning("请选择返回的json文件!"); + return; + } + data.setFile(file); + data.setIs_json_file(true); + } + api_data_list.add(data); + }); + + if (server_port.getText().length() == 0) { + server_port.setText(String.valueOf(HttpServerController.default_port)); + } + + server.setOnAction(event -> { + + if (server_port.getText().length() == 0) { + AlertUtils.alert_warning("请输入服务端口再试!"); + return; + } + + simpleServer = new SimpleServer(Integer.parseInt(server_port.getText())); + + if (file_dir_root.getText().length() > 0) { + simpleServer.setRoot(file_dir_root.getText()); + } + + for (Data item : api_list.getItems()) { + if (item.isIs_file_api()){//文件api + + }else { + String content = null; + if (item.isIs_json_file()){ + File file = item.getFile(); + content = FileUtil.readString(file,StandardCharsets.UTF_8); + }else { + content = item.getContent(); + } + String finalContent = content; + simpleServer.addAction(item.getApi(),(request, response) -> { + response.write(finalContent, "application/json;charset=utf-8"); + }); + } + } + + //启动服务器 + simpleServer.start(); + AlertUtils.alert_msg("服务启动成功!"); + }); + + stop_server.setOnAction(event -> { + simpleServer.stop(); + AlertUtils.alert_msg("服务关闭成功!"); + }); + } + + + public static class Data { + + private String api; + + private File file; + + private String content; + + private boolean is_json_file; + + private boolean is_file_api; + + public boolean isIs_file_api() { + return is_file_api; + } + + public void setIs_file_api(boolean is_file_api) { + this.is_file_api = is_file_api; + } + + public boolean isIs_json_file() { + return is_json_file; + } + + public void setIs_json_file(boolean is_json_file) { + this.is_json_file = is_json_file; + } + + public String getContent() { + return content; + } + + public void setContent(String content) { + this.content = content; + } + + public Data() { + } + + public String getApi() { + return api; + } + + public void setApi(String api) { + this.api = api; + } + + public File getFile() { + return file; + } + + public void setFile(File file) { + this.file = file; + } + + public Data(ContentType contentType, String api, File file) { + this.api = api; + this.file = file; + } + } +} diff --git a/src/main/java/com/zhangmeng/tools/controller/ServerToolsController.java b/src/main/java/com/zhangmeng/tools/controller/ServerToolsController.java new file mode 100644 index 0000000..e409e5e --- /dev/null +++ b/src/main/java/com/zhangmeng/tools/controller/ServerToolsController.java @@ -0,0 +1,440 @@ +package com.zhangmeng.tools.controller; + +import com.zhangmeng.tools.utils.ImagePath; +import com.zhangmeng.tools.utils.ResourcesUtils; +import javafx.beans.property.SimpleDoubleProperty; +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; +import javafx.event.ActionEvent; +import javafx.fxml.FXML; +import javafx.fxml.FXMLLoader; +import javafx.geometry.Pos; +import javafx.scene.Scene; +import javafx.scene.control.Label; +import javafx.scene.control.ListCell; +import javafx.scene.control.ListView; +import javafx.scene.control.SplitPane; +import javafx.scene.image.Image; +import javafx.scene.image.ImageView; +import javafx.scene.layout.AnchorPane; +import javafx.scene.layout.HBox; +import javafx.scene.paint.Paint; +import javafx.scene.text.Font; +import javafx.stage.Stage; +import javafx.util.Callback; +import lombok.extern.slf4j.Slf4j; + +import java.io.IOException; +import java.util.Arrays; + +/** + * @author : 芊芊墨客 + * @version : 1.0 + * @date : 2023-03-10 11:25 + */ +@Slf4j +public class ServerToolsController { + + private SimpleDoubleProperty width = new SimpleDoubleProperty(0.0); + private SimpleDoubleProperty height = new SimpleDoubleProperty(0.0); + private AnchorPane root; + private AnchorPane httpServer; + private AnchorPane ftpServer; + + public static final String color_cell = "#f4f4f4"; + + @FXML + private ListView listView; + + @FXML + private SplitPane splitPane; + + @FXML + public void date_query_menu_item(){ + load_small_tools(5); + } + + @FXML + public void cron_menu_item(){ + load_small_tools(6); + } + + @FXML + public void md5_menu_item() { + load_encrypt(0); + } + + @FXML + public void spring_security_menu_item() { + load_encrypt(1); + } + + @FXML + public void video_menu_item() { + load_player(0); + } + + @FXML + public void music_menu_item() { + load_player(1); + } + + @FXML + public void vip_parser_menu_item() { + load_player(2); + } + + @FXML + public void hex_16(){ + load_small_tools(0); + } + + @FXML + private void hex_16_menu_item(){ + load_small_tools(0); + } + + @FXML + private void unicode_menu_item(){ + load_small_tools(1); + } + + @FXML + private void jwt_menu_item(){ + load_small_tools(2); + } + + @FXML + private void color_choose_menu_item(){ + load_small_tools(3); + } + + @FXML + public void qr_code_menu_item(){ + load_small_tools(4); + } + + @FXML + public void base_62_menu_item(){ + load_codec_tools(0); + } + + @FXML + public void base_64_menu_item(){ + load_codec_tools(1); + } + + @FXML + public void base_32_menu_item(){ + load_codec_tools(2); + } + + @FXML + public void morse_coder_menu_item(){ + load_codec_tools(3); + } + + @FXML + private void sql_code_gen_menu_item(){ + load_sql_tools(0); + } + + @FXML + public void netty_client_menu_item(){ + load_network_tools(0); + } + + public void load_encrypt(int index) { + + Stage stage = (Stage) splitPane.getScene().getWindow(); + + AnchorPane fx = null; + try { + fx = FXMLLoader.load(ResourcesUtils.getResource("home")); + } catch (IOException e) { + e.printStackTrace(); + } + Scene scene = new Scene(fx); + stage.setScene(scene); + + ListView listView = (ListView) fx.lookup("#listView"); + listView.getSelectionModel().select(index); + } + + public void load_network_tools(int index){ + AnchorPane fx = null; + try { + fx = FXMLLoader.load(ResourcesUtils.getResource("network-tools")); + } catch (IOException e) { + e.printStackTrace(); + } + + Scene scene = new Scene(fx); + Stage stage = (Stage) splitPane.getScene().getWindow(); + stage.setScene(scene); + + ListView listView = (ListView) fx.lookup("#listView"); + listView.getSelectionModel().select(index); + } + + public void load_sql_tools(int index){ + AnchorPane fx = null; + try { + fx = FXMLLoader.load(ResourcesUtils.getResource("sql-tools")); + } catch (IOException e) { + e.printStackTrace(); + } + + Scene scene = new Scene(fx); + Stage stage = (Stage) splitPane.getScene().getWindow(); + stage.setScene(scene); + + ListView listView = (ListView) fx.lookup("#listView"); + listView.getSelectionModel().select(index); + } + + public void load_codec_tools(int index){ + AnchorPane fx = null; + try { + fx = FXMLLoader.load(ResourcesUtils.getResource("codec-tools")); + } catch (IOException e) { + e.printStackTrace(); + } + + Scene scene = new Scene(fx); + Stage stage = (Stage) splitPane.getScene().getWindow(); + stage.setScene(scene); + + ListView listView = (ListView) fx.lookup("#listView"); + listView.getSelectionModel().select(index); + } + + public void load_small_tools(int index){ + AnchorPane fx = null; + try { + fx = FXMLLoader.load(ResourcesUtils.getResource("small-tools")); + } catch (IOException e) { + e.printStackTrace(); + } + + Scene scene = new Scene(fx); + Stage stage = (Stage) splitPane.getScene().getWindow(); + stage.setScene(scene); + + ListView listView = (ListView) fx.lookup("#listView"); + listView.getSelectionModel().select(index); + } + + public void load_player(int index) { + AnchorPane fx = null; + try { + fx = FXMLLoader.load(ResourcesUtils.getResource("player")); + } catch (IOException e) { + e.printStackTrace(); + } + + Scene scene = new Scene(fx); + Stage stage = (Stage) splitPane.getScene().getWindow(); + stage.setScene(scene); + + ListView listView = (ListView) fx.lookup("#listView"); + listView.getSelectionModel().select(index); + } + + @FXML + public void initialize() { + init(); + listView.getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) -> { + if (newValue != null) { + boolean flag = false; + + if (newValue.getIndex() == 0) { + if (httpServer != null){ + flag = true; + } + httpServer(flag); + } + if (newValue.getIndex() == 1) { + if (ftpServer != null){ + flag = true; + } + ftpServer(flag); + } + } + }); + } + + private void ftpServer(boolean flag) { + listView.getSelectionModel().select(0); + if (!flag){ + try { + root = FXMLLoader.load(ResourcesUtils.getResource("ftp-server")); + } catch (IOException e) { + e.printStackTrace(); + } + httpServer = root; + }else { + root = httpServer; + } + common_method(); + } + + private void httpServer(boolean flag) { + listView.getSelectionModel().select(0); + if (!flag){ + try { + root = FXMLLoader.load(ResourcesUtils.getResource("http-server")); + } catch (IOException e) { + e.printStackTrace(); + } + httpServer = root; + }else { + root = httpServer; + } + common_method(); + } + + public static Image getImage(ResourcesUtils.ServerTools player){ + return switch (player){ + case Http_Server -> new Image(ImagePath.path(ImagePath.ImagePathType.MD5)); + case Ftp_Server -> new Image(ImagePath.path(ImagePath.ImagePathType.SPRING_SECURITY)); + }; + } + + public void init() { + ResourcesUtils.ServerTools[] values = ResourcesUtils.ServerTools.values(); + ObservableList list = FXCollections.observableArrayList(); + list.addAll(Arrays.asList(values)); + listView.setItems(list); + listView.setFixedCellSize(40); + listView.setCellFactory(new Callback<>() { + private int position; + @Override + public ListCell call(ListView playerListView) { + Label label = new Label(); + label.setPrefWidth(200); + ListCell listCell = new ListCell<>() { + @Override + protected void updateItem(ResourcesUtils.ServerTools player, boolean b) { + super.updateItem(player, b); + if (!b) { + HBox hBox = new HBox(25); + hBox.setAlignment(Pos.CENTER); + label.setText(player.getTitle()); + label.setTextFill(Paint.valueOf("#000000")); + Image im = getImage(player); + ImageView iv = new ImageView(im); + iv.setPreserveRatio(true); + iv.setFitWidth(15); + hBox.getChildren().add(iv); + + hBox.getChildren().add(label); + this.setGraphic(hBox); + } + this.setStyle("-fx-background-color: " + color_cell); + } + }; + + listCell.hoverProperty().addListener((observableValue, aBoolean, t1) -> { + if (t1 && !label.getText().equals("")) { + position = playerListView.getItems().indexOf(label.getText()); + label.setFont(new Font(16)); + playerListView.getFocusModel().focus(position); + listCell.setStyle("-fx-background-color: #369e7d"); + } else { + label.setPrefHeight(20); + label.setFont(new Font(13)); + listCell.setStyle("-fx-background-color: " + color_cell); + } + }); + + return listCell; + } + }); + + httpServer(false); + } + + private void common_method() { + splitPane.getItems().remove(1); + splitPane.getItems().add(1, root); + root.widthProperty().addListener((observable, oldValue, newValue) -> { + if (newValue != null) { + double width = splitPane.getWidth(); + ServerToolsController.this.width.set(width); + log.info("home:--->width:{}", width); + } + }); + root.heightProperty().addListener((observable, oldValue, newValue) -> { + if (newValue != null) { + double height = splitPane.getHeight(); + ServerToolsController.this.height.set(height); + log.info("home:--->height:{}", height); + } + }); + + this.width.addListener((observable, oldValue, newValue) -> { + ServerToolsController.this.root.setPrefWidth(newValue.doubleValue() - listView.getWidth()); + }); + + this.height.addListener((observable, oldValue, newValue) -> { + ServerToolsController.this.root.setPrefHeight(newValue.doubleValue() - listView.getHeight()); + }); + } + + @FXML + public void http_request_menu_item(ActionEvent event) { + load_http_tools(0); + } + + @FXML + public void http_upload_menu_item(ActionEvent event) { + load_http_tools(1); + } + + @FXML + public void http_download_menu_item(ActionEvent event) { + load_http_tools(2); + } + + public void load_http_tools(int index) { + AnchorPane fx = null; + try { + fx = FXMLLoader.load(ResourcesUtils.getResource("http-tools")); + } catch (IOException e) { + e.printStackTrace(); + } + + Scene scene = new Scene(fx); + Stage stage = (Stage) splitPane.getScene().getWindow(); + stage.setScene(scene); + + ListView listView = (ListView) fx.lookup("#listView"); + listView.getSelectionModel().select(index); + } + + @FXML + public void mail_menu_item(ActionEvent event) { + load_small_tools(7); + } + + @FXML + public void http_server_menu_item(ActionEvent event) { + boolean flag = false; + if (httpServer != null){ + flag = true; + } + httpServer(flag); + } + + @FXML + public void ftp_server_menu_item(ActionEvent event) { + boolean flag = false; + if (ftpServer != null){ + flag = true; + } + ftpServer(flag); + } + + +} diff --git a/src/main/java/com/zhangmeng/tools/server/SimpleServer.java b/src/main/java/com/zhangmeng/tools/server/SimpleServer.java new file mode 100644 index 0000000..7f50059 --- /dev/null +++ b/src/main/java/com/zhangmeng/tools/server/SimpleServer.java @@ -0,0 +1,231 @@ +package com.zhangmeng.tools.server; + +import cn.hutool.core.io.IORuntimeException; +import cn.hutool.core.lang.Console; +import cn.hutool.core.thread.GlobalThreadPool; +import cn.hutool.core.util.StrUtil; +import cn.hutool.http.server.HttpServerRequest; +import cn.hutool.http.server.HttpServerResponse; +import cn.hutool.http.server.action.Action; +import cn.hutool.http.server.action.RootAction; +import cn.hutool.http.server.filter.HttpFilter; +import cn.hutool.http.server.filter.SimpleFilter; +import cn.hutool.http.server.handler.ActionHandler; +import com.sun.net.httpserver.*; + +import java.io.File; +import java.io.IOException; +import java.net.InetSocketAddress; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.Executor; + +/** + * @author : 芊芊墨客 + * @version : 1.0 + * @date : 2023-03-10 16:17 + */ +public class SimpleServer { + + private final HttpServer server; + private final List filters; + + /** + * 构造 + * + * @param port 监听端口 + */ + public SimpleServer(int port) { + this(new InetSocketAddress(port)); + } + + /** + * 构造 + * + * @param hostname 监听地址 + * @param port 监听端口 + */ + public SimpleServer(String hostname, int port) { + this(new InetSocketAddress(hostname, port)); + } + + /** + * 构造 + * + * @param address 监听地址 + */ + public SimpleServer(InetSocketAddress address) { + this(address, null); + } + + /** + * 构造 + * + * @param address 监听地址 + * @param configurator https配置信息,用于使用自定义SSL(TLS)证书等 + */ + public SimpleServer(InetSocketAddress address, HttpsConfigurator configurator) { + try { + if(null != configurator){ + final HttpsServer server = HttpsServer.create(address, 0); + server.setHttpsConfigurator(configurator); + this.server = server; + } else{ + this.server = HttpServer.create(address, 0); + } + } catch (IOException e) { + throw new IORuntimeException(e); + } + setExecutor(GlobalThreadPool.getExecutor()); + filters = new ArrayList<>(); + } + + /** + * 增加请求过滤器,此过滤器对所有请求有效
+ * 此方法需在以下方法前之前调用: + * + *
    + *
  • {@link #setRoot(File)}
  • + *
  • {@link #setRoot(String)}
  • + *
  • {@link #createContext(String, HttpHandler)}
  • + *
  • {@link #addHandler(String, HttpHandler)}
  • + *
  • {@link #addAction(String, Action)}
  • + *
+ * + * @param filter {@link Filter} 请求过滤器 + * @return this + * @since 5.5.7 + */ + public SimpleServer addFilter(Filter filter) { + this.filters.add(filter); + return this; + } + + /** + * 增加请求过滤器,此过滤器对所有请求有效
+ * 此方法需在以下方法前之前调用: + * + *
    + *
  • {@link #setRoot(File)}
  • + *
  • {@link #setRoot(String)}
  • + *
  • {@link #createContext(String, HttpHandler)}
  • + *
  • {@link #addHandler(String, HttpHandler)}
  • + *
  • {@link #addAction(String, Action)}
  • + *
+ * + * @param filter {@link Filter} 请求过滤器 + * @return this + * @since 5.5.7 + */ + public SimpleServer addFilter(HttpFilter filter) { + return addFilter(new SimpleFilter() { + @Override + public void doFilter(HttpExchange httpExchange, Chain chain) throws IOException { + filter.doFilter(new HttpServerRequest(httpExchange), new HttpServerResponse(httpExchange), chain); + } + }); + } + + /** + * 增加请求处理规则 + * + * @param path 路径,例如:/a/b 或者 a/b + * @param handler 处理器,包括请求和响应处理 + * @return this + * @see #createContext(String, HttpHandler) + */ + public SimpleServer addHandler(String path, HttpHandler handler) { + createContext(path, handler); + return this; + } + + /** + * 创建请求映射上下文,创建后,用户访问指定路径可使用{@link HttpHandler} 中的规则进行处理 + * + * @param path 路径,例如:/a/b 或者 a/b + * @param handler 处理器,包括请求和响应处理 + * @return {@link HttpContext} + * @since 5.5.7 + */ + public HttpContext createContext(String path, HttpHandler handler) { + // 非/开头的路径会报错 + path = StrUtil.addPrefixIfNot(path, StrUtil.SLASH); + final HttpContext context = this.server.createContext(path, handler); + // 增加整体过滤器 + context.getFilters().addAll(this.filters); + return context; + } + + /** + * 设置根目录,默认的页面从root目录中读取解析返回 + * + * @param root 路径 + * @return this + */ + public SimpleServer setRoot(String root) { + return setRoot(new File(root)); + } + + /** + * 设置根目录,默认的页面从root目录中读取解析返回 + * + * @param root 路径 + * @return this + */ + public SimpleServer setRoot(File root) { + return addAction("/", new RootAction(root)); + } + + /** + * 增加请求处理规则 + * + * @param path 路径 + * @param action 处理器 + * @return this + */ + public SimpleServer addAction(String path, Action action) { + return addHandler(path, new ActionHandler(action)); + } + + /** + * 设置自定义线程池 + * + * @param executor {@link Executor} + * @return this + */ + public SimpleServer setExecutor(Executor executor) { + this.server.setExecutor(executor); + return this; + } + + /** + * 获得原始HttpServer对象 + * + * @return {@link HttpServer} + */ + public HttpServer getRawServer() { + return this.server; + } + + /** + * 获取服务器地址信息 + * + * @return {@link InetSocketAddress} + */ + public InetSocketAddress getAddress() { + return this.server.getAddress(); + } + + /** + * 启动Http服务器,启动后会阻塞当前线程 + */ + public void start() { + final InetSocketAddress address = getAddress(); + Console.log("Hutool Simple Http Server listen on 【{}:{}】", address.getHostName(), address.getPort()); + this.server.start(); + } + + public void stop(){ + this.server.stop(2); + } +} diff --git a/src/main/java/com/zhangmeng/tools/utils/ResourcesUtils.java b/src/main/java/com/zhangmeng/tools/utils/ResourcesUtils.java index 2dded82..0d3341e 100644 --- a/src/main/java/com/zhangmeng/tools/utils/ResourcesUtils.java +++ b/src/main/java/com/zhangmeng/tools/utils/ResourcesUtils.java @@ -269,4 +269,36 @@ public class ResourcesUtils { private String title; private int index; } + + public enum ServerTools{ + + Http_Server("Http Server工具",0), + Ftp_Server("Ftp Server工具",1), + ; + + ServerTools(String title, int index) { + this.title = title; + this.index = index; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public int getIndex() { + return index; + } + + public void setIndex(int index) { + this.index = index; + } + + private String title; + private int index; + } + } diff --git a/src/main/resources/fxml/ftp-server.fxml b/src/main/resources/fxml/ftp-server.fxml new file mode 100644 index 0000000..269db3e --- /dev/null +++ b/src/main/resources/fxml/ftp-server.fxml @@ -0,0 +1,6 @@ + + + + + + diff --git a/src/main/resources/fxml/home.fxml b/src/main/resources/fxml/home.fxml index 930c79e..b931d52 100644 --- a/src/main/resources/fxml/home.fxml +++ b/src/main/resources/fxml/home.fxml @@ -63,6 +63,13 @@ + + + + + + + + + + + + + + + + + + + +