Java实验三 基于GUI的网络通信程序设计【代码构建逻辑】【双向通信】【超多细节优化!!】

本文主要是介绍Java实验三 基于GUI的网络通信程序设计【代码构建逻辑】【双向通信】【超多细节优化!!】,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

写在前面:这次实验代码的构建主要是更加熟练的运用socket网络编程、文件输入输出流、GUI设计、容器的使用、多线程的运用等等多方面的知识,是综合类题型,做完受益身心的类型。

题目如下:

编写程序完成以下功能:

1.设计一个基于GUI的客户-服务器的通信应用程序,如图1,图2所示。

图1 Socket通信服务器端界面

图2 Socket通信客户端界面

2.图1为Socket通信服务器端界面,点击该界面中的【Start】按钮,启动服务器监听服务(在图1界面中间的多行文本区域显示“Server starting…”字样)。图2为Socket通信客户端界面,点击该界面中的【Connect】按钮与服务器建立链接,并在图2所示界面中间的多行文本区域显“Connect to server…”字样,当服务器端监听到客户端的连接后,在图1界面中间的多行文本区域追加一行“Client connected…”字样,并与客户端建立Socket连接。

3.当图1所示的服务器端和图2所示的客户机端建立Socket连接后,编程实现服务端、客户端之间的“单向通信”:在客户端的输入界面发送消息,在服务端接收该消息,并将接收到对方的数据追加显示在多行文本框中。


 下面开始做题:

一、学习基础知识

(如果想要学到什么的话,可以根据清单去学,不花很多时间

首先主要需要了解socket的知识,包括但不限于下列:(以下为最主要、基础的知识

1. ServerSocket、Socket的构造函数,需要什么东西来构造

2. 了解服务器与客户端之间依靠中间Socket连接,获取输入输出流

3. 为什么需要多线程,以及多线程的两种基本操作方法

        1) implements Runnable 

        2) extends Thread 

4. 在服务器与客户端通信的过程中,会引起阻塞的操作有哪几种。

了解完一些基本知识,发车,冲!!~

二、代码逻辑构建与代码包细节

之后,做出如下代码构建逻辑  (无GUI版 先设计这版的更容易理解基础知识。

 然后用如下代码包体现上面的逻辑构建

(无GUI版) 具体代码如下:(很多很多,我自己都不爱看  不过也不需要看,毕竟是我写的 :) 但是看一遍逻辑会清楚很多

因为比较大,所以分开服务端、客户端截图。

只是看起来很复杂,因为具体代码怎么写的都基本写出来,所以会显得很多。

 


但是毕竟我们的作业是有GUI版,所以再次进行代码逻辑构建

(有了上面一版的理解,有GUI版仅仅是多了GUI的代码设计而已

 

 上图知识点解释来啦:

1. 因为代码为了区分功能开了很多的类和文件 所以main函数主要用来组织这些类的发生。

2. 输出不需要等待scanner类的键盘输入了,只需要判断文本框内有没有东西然后直接输出就行,然后就直接send就可以了。

3. 因为服务器的启动时间由start组件来监听开启,所以相比于无GUI版代码直接使用start组件的类兼职accept(),意思是服务器默认永久等待客户端连接。

4. 和3一样,connect类相当于客户端的main函数,而且因为输出仅仅需要send来等待,所以这个时候使用connect兼职一下监听。

5. 为什么start和connect的里面的actionperformed不可以直接进行accept和监听呢?

因为在actionPerformed中体现点击事件,如果actionPerformed过长会一直假卡死,即该UI界面无法发生其他事件,无法进入下个动作,所以类似于accept和监听这样长时间的会阻塞线程的动作我们单独开启一个工作线程就不放在actionperformed里面了。

 代码包以及代码作用如下:(可以放大查看,代码思路都交代了

  注意:本来这里可以不使用接口类,其实没有必要,但是当时自己想实践一下面向接口的思想,并且让代码更有逻辑有利于后期维护,所以采用了很多接口类。

其实如果为了让actionperformed函数分开功能的话只需要直接写一个类进行了。不需要再写接口了。


有GUI版代码相比于无GUI版改进了很多用户交互的内容,做了很多优化包括但不限于:

1. 双向通信 2.选择不同客户发送消息 3.按钮事件的控制以及很多事件源监视器的委派 4.默认本地服务器等等。

三、具体成果显示

1. 可以连接多个客户

细节的优化:按钮事件的控制,不可调整窗口大小,默认本机地址、不同客户有自己的名字、且存在于下拉菜单中等等

2. 双向通信

细节的优化:区分客户发送的消息、分别发送给不同客户、 按钮点击文本框的清空等等

 

 3. 客户断开连接


附完整可运行代码:

代码逻辑如图: 

C_MyCommandSurveillanceForConnect接口
package Client;import javax.swing.*;
import java.awt.event.ActionListener;
import java.net.Socket;public interface C_MyCommandSurveillanceForConnect extends ActionListener {void setJTextField_IP(JTextField jTextField);void setJTextField_Port(JTextField jTextField);void setJTextArea(JTextArea jTextArea);void setSocket(Socket socket);void setBtn(JButton jButton);
}

C_MyCommandSurveillanceForSend接口
package Client;import javax.swing.*;
import java.awt.event.ActionListener;
import java.net.Socket;public interface C_MyCommandSurveillanceForSend extends ActionListener {void setJTextField(JTextField jTextField);void setSocket(Socket socket);
}

C_MySurveillanceForConnect类
package Client;import javax.swing.*;
import java.awt.event.ActionEvent;
import java.io.DataInputStream;
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.UnknownHostException;//根据输入的IP地址与端口号进行连接、监听信息线程 Client、ClientListen
public class C_MySurveillanceForConnect extends Thread implements C_MyCommandSurveillanceForConnect{JTextField jTextField_IP;JTextField jTextField_Port;JTextArea jTextArea;JButton btn;Socket client;DataInputStream in;String str;public void setJTextField_IP(JTextField jTextField){this.jTextField_IP = jTextField;}public void setJTextField_Port(JTextField jTextField){this.jTextField_Port = jTextField;}public void setBtn(JButton jButton){this.btn = jButton;}public void setJTextArea(JTextArea jTextArea){this.jTextArea = jTextArea;}public void setSocket(Socket socket){this.client = socket;}public void actionPerformed(ActionEvent e){btn.setEnabled(false);//判断IP与Port都填写完整,进行连接String IP, Port;if((Port = jTextField_Port.getText()) != null){InetAddress address;//开始进行连接try {if((IP = jTextField_IP.getText()) == null){address = InetAddress.getLocalHost();}else{address = InetAddress.getByName(IP);}}catch (UnknownHostException ex) {throw new RuntimeException(ex);}InetSocketAddress socketAddress = new InetSocketAddress(address, Integer.parseInt(Port));try {client.connect(socketAddress);jTextArea.append("Connecting to server...\n");jTextArea.paintImmediately(jTextArea.getBounds());in = new DataInputStream(client.getInputStream());Thread thread = this;thread.start();} catch (IOException ex) {throw new RuntimeException(ex);}}else{jTextArea.append("Please enter right IP and Port...\n");jTextArea.paintImmediately(jTextArea.getBounds());}}public void run(){while(true){try {str = in.readUTF();jTextArea.append("From server: " + str + "\n");} catch (IOException ex) {jTextArea.append("Disconnected to server...");jTextArea.paintImmediately(jTextArea.getBounds());break;}}}
}

C_MySurveillanceForSend类
package Client;import javax.swing.*;
import java.awt.event.ActionEvent;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;//发送信息  ClientTxpublic class C_MySurveillanceForSend implements C_MyCommandSurveillanceForSend {JTextField jTextField;Socket client;DataOutputStream out;public void setJTextField(JTextField jTextField){this.jTextField = jTextField;}public void setSocket(Socket socket){this.client = socket;}public void actionPerformed(ActionEvent e){try {out = new DataOutputStream(client.getOutputStream());} catch (IOException ex) {throw new RuntimeException(ex);}try {out.writeUTF(jTextField.getText());jTextField.setText(null);} catch (IOException ex) {throw new RuntimeException(ex);}}
}
C_MyGUI类
package Client;import javax.swing.*;
import java.awt.*;
import java.net.Socket;import static java.awt.Font.ITALIC;//设置页面 添加监视器
public class C_MyGUI extends JFrame {JFrame jFrame = new JFrame();JTextField textF_IP, textF_port, textF_send;JButton btn_Connect, btn_send;JTextArea textArea;JPanel jPanel01;JPanel jPanel02;JPanel jPanel03;JPanel jPanel;//监视器接口C_MyCommandSurveillanceForSend myCommandSurveillanceForSend;C_MyCommandSurveillanceForConnect myCommandSurveillanceForConnect;//一个对象Socket client;//构造函数完成窗口的主流操作public C_MyGUI(){client = new Socket();init();jFrame.setResizable(false);jFrame.setBounds(100,100,460,360);jFrame.setTitle("客户端");jFrame.setVisible(true);jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);}void init(){//服务器设置框jPanel = new JPanel();jPanel01 = new JPanel();jPanel02 = new JPanel();jPanel03 = new JPanel();textF_IP = new JTextField(10);textF_IP.setFont(new Font(null, Font.BOLD, 13));textF_port = new JTextField(8);textF_port.setFont(new Font(null, Font.BOLD, 13));btn_Connect = new JButton("Connect");jPanel01.add(new JLabel("Server IP: "));jPanel01.add(textF_IP);jPanel01.add(new JLabel("Port: "));jPanel01.add(textF_port);jPanel01.add(btn_Connect);jPanel01.setBorder(BorderFactory.createTitledBorder("客户机设置:"));//中间文本框textArea = new JTextArea(9,30);textArea.setLineWrap(true);textArea.setFont(new Font(null, Font.BOLD+ITALIC, 15));JScrollPane jScrollPane = new JScrollPane();jScrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);jScrollPane.setViewportView(textArea);jPanel02.add(jScrollPane);//send发送信息栏textF_send = new JTextField(23);textF_send.setFont(new Font(null, Font.BOLD, 13));btn_send = new JButton("Send");jPanel03.add(new JLabel("Send: "));jPanel03.add(textF_send);jPanel03.add(btn_send);//将上中下三个组件存放如jPaneljPanel.add(jPanel01,BorderLayout.NORTH);jPanel.add(jPanel02,BorderLayout.CENTER);jPanel.add(jPanel03,BorderLayout.SOUTH);jFrame.setContentPane(jPanel);}//设置监视器void setMyCommandSurveillanceForConnect(C_MyCommandSurveillanceForConnect myCommandSurveillanceForConnect){//利用组合设置对象this.myCommandSurveillanceForConnect = myCommandSurveillanceForConnect;myCommandSurveillanceForConnect.setJTextField_Port(textF_port);myCommandSurveillanceForConnect.setJTextField_IP(textF_IP);myCommandSurveillanceForConnect.setJTextArea(textArea);myCommandSurveillanceForConnect.setSocket(client);myCommandSurveillanceForConnect.setBtn(btn_Connect);//为事件源添加监视器  用户点击按钮才能够触发事件textF_port.addActionListener(myCommandSurveillanceForConnect);textF_IP.addActionListener(myCommandSurveillanceForConnect);btn_Connect.addActionListener(myCommandSurveillanceForConnect);}void setMyCommandSurveillanceForSend(C_MyCommandSurveillanceForSend myCommandSurveillanceForSend){this.myCommandSurveillanceForSend = myCommandSurveillanceForSend;myCommandSurveillanceForSend.setJTextField(textF_send);myCommandSurveillanceForSend.setSocket(client);//为事件源添加监视器textF_send.addActionListener(myCommandSurveillanceForSend);btn_send.addActionListener(myCommandSurveillanceForSend);}}
Client_main类(可以设置多个相同的main类想起来连接了多个客户
package Client;//192.168.197.121public class Client_main {public static void main(String[] args){//设置GUI界面C_MyGUI myGui = new C_MyGUI();//设置监视器C_MySurveillanceForConnect MySurveillanceForConnect = new C_MySurveillanceForConnect();C_MySurveillanceForSend mySurveillanceForSend = new C_MySurveillanceForSend();myGui.setMyCommandSurveillanceForConnect(MySurveillanceForConnect);myGui.setMyCommandSurveillanceForSend(mySurveillanceForSend);}
}

S_MyCommandSurveillanceForStart接口
package Server;import javax.swing.*;
import java.awt.event.ActionListener;public interface S_MyCommandSurveillanceForStart extends ActionListener {void setJTextField(JTextField jTextField);void setJTextArea(JTextArea jTextArea);void setJBtn(JButton jButton);}

S_MyCommandSurveillanceForSend接口
package Server;import javax.swing.*;
import java.awt.event.ActionListener;public interface S_MyCommandSurveillanceForSend extends ActionListener {void setJTextField(JTextField jTextField);void setJComboBox(JComboBox<String> jComboBox);
}

S_MySurveillanceForStart类
package Server;import javax.swing.*;
import java.awt.event.ActionEvent;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Objects;import static Server.S_MyGUI.socket_name;
import static Server.S_MyGUI.scs;//accept工作线程 作用:基于GUI,读取port框内内容进行连接操作
//为客户取名,并且为每一位用户开启监听线程public class S_MySurveillanceForStart extends Thread implements S_MyCommandSurveillanceForStart{JTextField Port;JTextArea jTextArea;JButton jButton;ServerSocket serverSocket;Socket sc;String client = "Client";String Client_name = null;static int client_num = 1;public void setJTextField(JTextField jTextField){this.Port = jTextField;}public void setJTextArea(JTextArea TextArea){this.jTextArea = TextArea;}public void setJBtn(JButton jButton){ this.jButton = jButton;}public void actionPerformed(ActionEvent e){Thread thread = this;thread.start();}public void run(){while(true){try{if(Port.getText() != null){serverSocket = new ServerSocket(Integer.parseInt(Port.getText()));}else{jTextArea.append("Please enter right Port...");jTextArea.paintImmediately(jTextArea.getBounds());break;}}catch (IOException exception){jTextArea.append("Server listening..."+ "\n");jTextArea.paintImmediately(jTextArea.getBounds());}try {if(client_num == 1){jTextArea.append("Server starting..."+ "\n");jTextArea.paintImmediately(jTextArea.getBounds());}sc = serverSocket.accept();scs.add(sc);if(Objects.equals(socket_name.get(0), "null")){socket_name.remove(0);}Client_name = client + client_num;jTextArea.append(Client_name+" connected..."+ "\n");socket_name.add(Client_name);jTextArea.paintImmediately(jTextArea.getBounds());} catch (IOException even) {jTextArea.append("Server waiting..."+ "\n");jTextArea.paintImmediately(jTextArea.getBounds());}if(sc != null){client_num++;new ServerListenThread(sc, jTextArea, Client_name).start();}}}}

S_MySurveillanceForSend类
package Server;import javax.swing.*;
import java.awt.event.ActionEvent;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;import static Server.S_MyGUI.scs;public class S_MySurveillanceForSend implements S_MyCommandSurveillanceForSend{JTextField jTextField;JComboBox<String> jComboBox;Socket sc;DataOutputStream out;public void setJTextField(JTextField jTextField){this.jTextField = jTextField;}public void setJComboBox(JComboBox<String> jComboBox){this.jComboBox = jComboBox;}public void actionPerformed(ActionEvent e){sc = scs.elementAt(jComboBox.getSelectedIndex());try {out = new DataOutputStream(sc.getOutputStream());out.writeUTF(jTextField.getText());jTextField.setText(null);} catch (IOException ex) {throw new RuntimeException(ex);}}
}

S_MyGUI类
package Server;import javax.swing.*;
import java.awt.*;
import java.net.Socket;
import java.util.Vector;
import static java.awt.Font.ITALIC;//设置GUI界面 添加监视器 + 建立通信
public class S_MyGUI extends JFrame {//组件static Vector<String> socket_name;static Vector<Socket> scs;JFrame jFrame = new JFrame();JTextField textF_port, textF_send;JButton btn_start, btn_send;JTextArea textArea;JPanel jPanel01;JPanel jPanel02;JPanel jPanel03;JPanel jPanel;JComboBox<String> comboBox;//监视器接口S_MyCommandSurveillanceForStart myCommandSurveillanceForStart;S_MyCommandSurveillanceForSend myCommandSurveillanceForSend;//对象//构造函数完成窗口的主流操作public S_MyGUI(){socket_name = new Vector<>();scs = new Vector<>();socket_name.add("null");init();jFrame.setResizable(false);jFrame.setBounds(100,100,460,360);jFrame.setTitle("服务器");jFrame.setVisible(true);jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);}void init(){//服务器设置框jPanel = new JPanel();jPanel01 = new JPanel();jPanel02 = new JPanel();jPanel03 = new JPanel();textF_port = new JTextField(23);textF_port.setFont(new Font(null, Font.BOLD, 13));btn_start = new JButton("Start");jPanel01.add(new JLabel("Port: "));jPanel01.add(textF_port);jPanel01.add(btn_start);jPanel01.setBorder(BorderFactory.createTitledBorder("服务器设置:"));//中间文本框textArea = new JTextArea(9,30);textArea.setLineWrap(true);textArea.setFont(new Font(null, Font.BOLD+ITALIC, 15));JScrollPane jScrollPane = new JScrollPane();JScrollBar jscrollBar = jScrollPane.getVerticalScrollBar();if (jscrollBar != null) {// 必须先获取一次jScrollBar.getMaximum(),否则滚动不到最底部, swing bugjscrollBar.setValue(jscrollBar.getMaximum());jScrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);}jScrollPane.setViewportView(textArea);jPanel02.add(jScrollPane);//send发送信息栏textF_send = new JTextField(18);comboBox = new JComboBox<>(socket_name);textF_send.setFont(new Font(null, Font.BOLD, 13));btn_send = new JButton("Send");jPanel03.add(new JLabel("SendTo: "));jPanel03.add(comboBox);jPanel03.add(textF_send);jPanel03.add(btn_send);//将上中下三个组件存放如jPaneljPanel.add(jPanel01,BorderLayout.NORTH);jPanel.add(jPanel02,BorderLayout.CENTER);jPanel.add(jPanel03,BorderLayout.SOUTH);jFrame.setContentPane(jPanel);}//设置监视器void setMyCommandSurveillanceForStart(S_MyCommandSurveillanceForStart myCommandSurveillanceForStart){//利用组合设置对象this.myCommandSurveillanceForStart = myCommandSurveillanceForStart;myCommandSurveillanceForStart.setJTextField(textF_port);myCommandSurveillanceForStart.setJTextArea(textArea);myCommandSurveillanceForStart.setJBtn(btn_start);//为事件源添加监视器  用户按回车键、按钮都能够触发事件textF_port.addActionListener(myCommandSurveillanceForStart);btn_start.addActionListener(myCommandSurveillanceForStart);}void setMyCommandSurveillanceForSend(S_MyCommandSurveillanceForSend myCommandSurveillanceForSend){this.myCommandSurveillanceForSend = myCommandSurveillanceForSend;myCommandSurveillanceForSend.setJTextField(textF_send);myCommandSurveillanceForSend.setJComboBox(comboBox);//为事件源添加监视器textF_send.addActionListener(myCommandSurveillanceForSend);btn_send.addActionListener(myCommandSurveillanceForSend);}}

ServerListenThread类
package Server;import javax.swing.*;
import java.io.DataInputStream;
import java.io.IOException;
import java.net.Socket;
import static Server.S_MyGUI.scs;
import static Server.S_MyGUI.socket_name;//服务器输入流监听线程 作用:进行输入流的监听
public class ServerListenThread extends Thread{Socket sc;JTextArea jTextArea;DataInputStream in;String str;ServerListenThread(Socket socket, JTextArea jTextArea, String string){super(string);this.sc = socket;this.jTextArea = jTextArea;try {in = new DataInputStream(sc.getInputStream());} catch (IOException e) {throw new RuntimeException(e);}}//后台死循环进行监听public void run(){while(true){try {str = in.readUTF();jTextArea.append(getName() + ": " + str + "\n");jTextArea.paintImmediately(jTextArea.getBounds());} catch (IOException e) {int index = scs.indexOf(sc);jTextArea.append(socket_name.get(index) + "disconnected...\n");scs.remove(index);socket_name.remove(index);if(socket_name.isEmpty()){socket_name.add("null");}break;}}}}

Server_main类
package Server;public class Server_main {public static void main(String[] args){//设置GUI界面S_MyGUI myGui = new S_MyGUI();//添加监视器,利用组合调用方法S_MySurveillanceForStart mySurveillanceForStart = new S_MySurveillanceForStart();S_MySurveillanceForSend mySurveillanceForSend = new S_MySurveillanceForSend();myGui.setMyCommandSurveillanceForStart(mySurveillanceForStart);myGui.setMyCommandSurveillanceForSend(mySurveillanceForSend);}
}

 至此,所有代码就完成了哈哈哈。

源代码和教程附上,说是教程其实主要是讲出构建整个代码的知识与思路,希望在完成作业的同时能够对你有帮助来学习思路。

如果觉得还不错的话...... :)

这篇关于Java实验三 基于GUI的网络通信程序设计【代码构建逻辑】【双向通信】【超多细节优化!!】的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/176442

相关文章

Oracle查询优化之高效实现仅查询前10条记录的方法与实践

《Oracle查询优化之高效实现仅查询前10条记录的方法与实践》:本文主要介绍Oracle查询优化之高效实现仅查询前10条记录的相关资料,包括使用ROWNUM、ROW_NUMBER()函数、FET... 目录1. 使用 ROWNUM 查询2. 使用 ROW_NUMBER() 函数3. 使用 FETCH FI

Java实现Excel与HTML互转

《Java实现Excel与HTML互转》Excel是一种电子表格格式,而HTM则是一种用于创建网页的标记语言,虽然两者在用途上存在差异,但有时我们需要将数据从一种格式转换为另一种格式,下面我们就来看看... Excel是一种电子表格格式,广泛用于数据处理和分析,而HTM则是一种用于创建网页的标记语言。虽然两

java图像识别工具类(ImageRecognitionUtils)使用实例详解

《java图像识别工具类(ImageRecognitionUtils)使用实例详解》:本文主要介绍如何在Java中使用OpenCV进行图像识别,包括图像加载、预处理、分类、人脸检测和特征提取等步骤... 目录前言1. 图像识别的背景与作用2. 设计目标3. 项目依赖4. 设计与实现 ImageRecogni

Java中Springboot集成Kafka实现消息发送和接收功能

《Java中Springboot集成Kafka实现消息发送和接收功能》Kafka是一个高吞吐量的分布式发布-订阅消息系统,主要用于处理大规模数据流,它由生产者、消费者、主题、分区和代理等组件构成,Ka... 目录一、Kafka 简介二、Kafka 功能三、POM依赖四、配置文件五、生产者六、消费者一、Kaf

Java访问修饰符public、private、protected及默认访问权限详解

《Java访问修饰符public、private、protected及默认访问权限详解》:本文主要介绍Java访问修饰符public、private、protected及默认访问权限的相关资料,每... 目录前言1. public 访问修饰符特点:示例:适用场景:2. private 访问修饰符特点:示例:

详解Java如何向http/https接口发出请求

《详解Java如何向http/https接口发出请求》这篇文章主要为大家详细介绍了Java如何实现向http/https接口发出请求,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 用Java发送web请求所用到的包都在java.net下,在具体使用时可以用如下代码,你可以把它封装成一

C#使用HttpClient进行Post请求出现超时问题的解决及优化

《C#使用HttpClient进行Post请求出现超时问题的解决及优化》最近我的控制台程序发现有时候总是出现请求超时等问题,通常好几分钟最多只有3-4个请求,在使用apipost发现并发10个5分钟也... 目录优化结论单例HttpClient连接池耗尽和并发并发异步最终优化后优化结论我直接上优化结论吧,

SpringBoot使用Apache Tika检测敏感信息

《SpringBoot使用ApacheTika检测敏感信息》ApacheTika是一个功能强大的内容分析工具,它能够从多种文件格式中提取文本、元数据以及其他结构化信息,下面我们来看看如何使用Ap... 目录Tika 主要特性1. 多格式支持2. 自动文件类型检测3. 文本和元数据提取4. 支持 OCR(光学

Java内存泄漏问题的排查、优化与最佳实践

《Java内存泄漏问题的排查、优化与最佳实践》在Java开发中,内存泄漏是一个常见且令人头疼的问题,内存泄漏指的是程序在运行过程中,已经不再使用的对象没有被及时释放,从而导致内存占用不断增加,最终... 目录引言1. 什么是内存泄漏?常见的内存泄漏情况2. 如何排查 Java 中的内存泄漏?2.1 使用 J

JAVA系统中Spring Boot应用程序的配置文件application.yml使用详解

《JAVA系统中SpringBoot应用程序的配置文件application.yml使用详解》:本文主要介绍JAVA系统中SpringBoot应用程序的配置文件application.yml的... 目录文件路径文件内容解释1. Server 配置2. Spring 配置3. Logging 配置4. Ma