JAVA socket FTPserver HTTPserver chatting RMI(Remote Method Invocation)

本文主要是介绍JAVA socket FTPserver HTTPserver chatting RMI(Remote Method Invocation),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录(?)[-]

  1. github-httpserverftpserverchattingRoomRMI
  2. RMI Remote Method Invocation
  3. httpserver
    1. 遇到的问题
  4. FTP
    1. 客户端连接到服务器端 c语言伪码Java版见github
    2. 客户端连接到 FTP 服务器接收欢迎信息
    3. 客户端发送用户名和密码登入 FTP 服务器
    4. 让服务器进入被动模式在数据端口监听
    5. 客户端通过被动模式下载文件
      1. 遇到的问题
  5. Chatting功能
    1. 服务器和客户端通信协议
    2. 客户端发送请求数据格式
    3. 服务器响应数据格式
      1. 基于socket的一个简单的android聊天工具
    4. 遇到的问题

  • github-httpserverftpserverchattingRoomRMI
  • RMI Remote Method Invocation
  • httpserver
      • 遇到的问题
  • FTP
    • 客户端连接到服务器端 c语言伪码Java版见github
    • 客户端连接到 FTP 服务器接收欢迎信息
    • 客户端发送用户名和密码登入 FTP 服务器
    • 让服务器进入被动模式在数据端口监听
    • 客户端通过被动模式下载文件
      • 遇到的问题
  • Chatting功能
    • 服务器和客户端通信协议
    • 客户端发送请求数据格式
    • 服务器响应数据格式
        • 基于socket的一个简单的android聊天工具
      • 遇到的问题

github-httpserver/ftpserver/chattingRoom/RMI

RMI Remote Method Invocation

调用不同JVM上的方法

httpserver

这里并不需要解析xml/html, 根据request请求,返回html让浏览器解析

遇到的问题

  • 第一个问题,之前在创建文件的时候程序一直报错,说文件路径不对或者不存在,之后发现在写路径的时候’/’这些元字符是需要转义的。

  • 第二个问题,是服务器运行后,无法在网页上查看图片等信息,同时服务端抛出异常,但是html网页可以正常显示。这个问题最后通过询问同学和查资料,得知我所使用的发送和接收消息的流不对,不能够使用datainputstream和dataoutputstream,并且wirteUTF方法不能用于http服务器中因为这个方法一开始会写入两个字节,即为将要写入的字节数(不是字符串的长度)。后来改成了printstream和bufferedreader就成功了。

  • 第三个问题,是没有意识到浏览器解析html时,对于html内嵌的图片和视频等资源会在解析之后再次送一个get请求。所以通过浏览器访问服务端网页时,服务端不用进行标签解析。

  • 第四个问题,在服务器发送响应体的时候,我发现出现一个奇怪的现象,就是程序运行的时候,总是无法下载完成,打开对应的客户端文件夹发现文件没有下载完成(即为0字节),但是在关闭客户端运行之后,那个文件夹里的文件就下载好了。最后发现,是服务器在发送响应体的时候,最后忘记关闭了文件发送流,所以导致客户端一直在读取服务器的信息,导致失败。后来添加了close,判断-1才能成功,接受所有信息并关闭文件

FTP:

Resume file upload/download after lost connection 
使用 Socket 通信实现 FTP 客户端程序

客户端连接到服务器端 c语言伪码(Java版见github)

客户端连接到服务器端

客户端连接到 FTP 服务器,接收欢迎信息

<code class="language-c hljs  has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">SOCKET control_sock;
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">struct</span> hostent *hp;
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">struct</span> sockaddr_in server;
<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">memset</span>(&server, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">sizeof</span>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">struct</span> sockaddr_in));<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">/* 初始化socket */</span>
control_sock = socket(AF_INET, SOCK_STREAM, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>);
hp = gethostbyname(server_name);
<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">memcpy</span>(&server.sin_addr, hp->h_addr, hp->h_length);
server.sin_family = AF_INET;
server.sin_port = htons(port);<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">/* 连接到服务器端 */</span>
connect(control_sock,(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">struct</span> sockaddr *)&server, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">sizeof</span>(server));
<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">/* 客户端接收服务器端的一些欢迎信息 */</span>
read(control_sock, read_buf, read_len);</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li></ul>

客户端发送用户名和密码,登入 FTP 服务器

<code class="language-c hljs  has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">/* 命令 ”USER username\r\n” */</span>
<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">sprintf</span>(send_buf,<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"USER %s\r\n"</span>,username);
<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">/*客户端发送用户名到服务器端 */</span>
write(control_sock, send_buf, <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">strlen</span>(send_buf));
<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">/* 客户端接收服务器的响应码和信息,正常为 ”331 User name okay, need password.” */</span>
read(control_sock, read_buf, read_len);<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">/* 命令 ”PASS password\r\n” */</span>
<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">sprintf</span>(send_buf,<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"PASS %s\r\n"</span>,password);
<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">/* 客户端发送密码到服务器端 */</span>
write(control_sock, send_buf, <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">strlen</span>(send_buf));
<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">/* 客户端接收服务器的响应码和信息,正常为 ”230 User logged in, proceed.” */</span>
read(control_sock, read_buf, read_len);</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li></ul>

让服务器进入被动模式,在数据端口监听

<code class="language-c hljs  has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">/* 命令 ”PASV\r\n” */</span>
<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">sprintf</span>(send_buf,<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"PASV\r\n"</span>);
<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">/* 客户端告诉服务器用被动模式 */</span>
write(control_sock, send_buf, <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">strlen</span>(send_buf));
<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">/*客户端接收服务器的响应码和新开的端口号,
* 正常为 ”227 Entering passive mode (<h1,h2,h3,h4,p1,p2>)” */</span>
read(control_sock, read_buf, read_len);</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li></ul>

客户端通过被动模式下载文件

<code class="language-c hljs  has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">/* 连接服务器新开的数据端口 */</span>
connect(data_sock,(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">struct</span> sockaddr *)&server, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">sizeof</span>(server));
<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">/* 命令 ”CWD dirname\r\n” */</span>
<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">sprintf</span>(send_buf,<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"CWD %s\r\n"</span>, dirname);
<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">/* 客户端发送命令改变工作目录 */</span>
write(control_sock, send_buf, <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">strlen</span>(send_buf));
<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">/* 客户端接收服务器的响应码和信息,正常为 ”250 Command okay.” */</span>
read(control_sock, read_buf, read_len);<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">/* 命令 ”SIZE filename\r\n” */</span>
<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">sprintf</span>(send_buf,<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"SIZE %s\r\n"</span>,filename);
<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">/* 客户端发送命令从服务器端得到下载文件的大小 */</span>
write(control_sock, send_buf, <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">strlen</span>(send_buf));
<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">/* 客户端接收服务器的响应码和信息,正常为 ”213 <size>” */</span>
read(control_sock, read_buf, read_len);<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">/* 命令 ”RETR filename\r\n” */</span>
<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">sprintf</span>(send_buf,<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"RETR %s\r\n"</span>,filename);
<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">/* 客户端发送命令从服务器端下载文件 */</span>
write(control_sock, send_buf, <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">strlen</span>(send_buf));
<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">/* 客户端接收服务器的响应码和信息,正常为 ”150 Opening data connection.” */</span>
read(control_sock, read_buf, read_len);<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">/* 客户端创建文件 */</span>
file_handle = open(disk_name, CRFLAGS, RWXALL);
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span>( ; ; ) {
... ...
<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">/* 客户端通过数据连接 从服务器接收文件内容 */</span>
read(data_sock, read_buf, read_len);
<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">/* 客户端写文件 */</span>
write(file_handle, read_buf, read_len);
... ... 
}
<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">/* 客户端关闭文件 */</span>
rc = close(file_handle);</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li><li style="box-sizing: border-box; padding: 0px 5px;">35</li></ul>

遇到的问题

  • 第一个问题是很迷茫,应为是第一个做的实验,不知道如何进行文件上传和下载。后来在网上查询,明白了可以分成两部分,第一部分把文件从硬盘里读取到内存中,再把数据从内存中发送到另一端,由另一端读取到内存,再从内存写入到文件。其中使用了一个字节数组当做一个缓冲,就像一辆运输车一样,一趟一趟的运送货物,直到最后read()==-1就读完了。

  • 第二个问题是下载文件夹。逻辑较为复杂,首先要使用isDirectory方法判断是否是文件夹,然后在本地判断是否存在同名文件夹,通过file.list方法获得文件列表,进而得到文件个数,然后对每个文件进行下载即可,此处隐含了list,cwd,retr等指令,较为复杂,并且dos dis使用后要及时flush和关闭。

  • 第三个问题是阻塞方法的调用。多线程间的协作和socket通信容易混淆,了解到相关原则是尽量少开线程,并时刻注意线程同步异步问题,如上传文件时,服务端使用线程同步(synchronized)的方法,即一个线程访问该方法时,他就获得了该object的对象锁,另一个线程对该object的访问将被暂时阻塞, 保证只存在一个同名文件且后上传的不会覆盖之前的。由于实验末尾才稍微了解了java并发的锁机制,所以所有实验都可以用线程锁等java并发编程知识进行优化,这也是下一步的改进方向

Chatting功能:

登录
发送文件、表情、信息
多人同时聊天
离线发送消息(上线后就能看到)

服务器和客户端通信协议

客户端登录,客户端取得用户列表,以及客户端和客户端的通信都必须跟服务器交互,我们约定客户端和服务器端的通信协议如下: 
请求数据格式

客户端发送请求数据格式:

请求码 请求数据

请求码: 
101 用户登录 
102 取得用户列表 
103 发送消息

如登录请求,客户端向服务器发送的请求数据为: 
101|用户名,密码

如取得用户列表,客户端向服务器发送的请求数据为: 
102|

如发送消息,客户端向服务器发送的请求数据为: 
103|消息发送方,消息接收方,消息内容 
响应数据格式

服务器响应数据格式:

响应码 响应数据

响应码: 
1 响应成功 
0 响应失败

如登录请求,服务器端的响应数据为: 
1| 或者 0|

如取得用户列表,服务器端的响应数据为: 
1|消息类型(102)@消息发送方(Server)@用户1,用户2,用户3@消息发送时间

如服务器给客户端发送消息 
1|消息类型(103)@消息发送方@消息内容@消息发送时间 
服务器消息队列格式

服务器端接收到客户的请求后(取得用户列表和用户信息)将请求结果放在消息队列中,发送消息的线程用队列中取消息,发送给客户端,

我们约定消息队列中消息的格式如下: 
消息发送方 消息接收方 内容 发送时间 消息类别 
Server tom Tom,jack,luly,lily 2016-1-29 11:11:11 102 
Jack tom How are you doing? 2016-1-29 12:12:12 103

基于socket的一个简单的android聊天工具

socket采用TCP/IP时,应有可自由分配的IP(内外网)。对于蓝牙协议,上层接口无法得到IP,所以与wifi组成网络时比较困难,需修改底层框架结构。

遇到的问题

  • 第一个问题是对该设计模式的理解。这个模型类似于生产-消费者模型,将该模型的订阅模式和p2p模式结合,就实现了即能群聊,又能单独聊天的功能。一开始看通信流程图,认为是每个用户一个消息信道,直到想明白生产-消费者模型,才开始正确的实验过程。网上相关资料实现了jms接口进行开发,这也是可以进一步改进的方向

  • 第二个问题是初始化用户列表的时机,后来发现了问题,添加了构造函数,初始化了用户列表。但是主线程里并没有初始化任何一个用户包对象,仅仅是调用了一个静态方法,所以我在服务器建立伊始就初始化了一个用户包对象,虽然这个对象没有被使用,但是成功初始化了用户列表。同样的,消息列表类(MessageDAO)我也使用了此种方法,只不过不在建立服务器时,是在用户登录成功过后。

这篇关于JAVA socket FTPserver HTTPserver chatting RMI(Remote Method Invocation)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

Java编译生成多个.class文件的原理和作用

《Java编译生成多个.class文件的原理和作用》作为一名经验丰富的开发者,在Java项目中执行编译后,可能会发现一个.java源文件有时会产生多个.class文件,从技术实现层面详细剖析这一现象... 目录一、内部类机制与.class文件生成成员内部类(常规内部类)局部内部类(方法内部类)匿名内部类二、

SpringBoot实现数据库读写分离的3种方法小结

《SpringBoot实现数据库读写分离的3种方法小结》为了提高系统的读写性能和可用性,读写分离是一种经典的数据库架构模式,在SpringBoot应用中,有多种方式可以实现数据库读写分离,本文将介绍三... 目录一、数据库读写分离概述二、方案一:基于AbstractRoutingDataSource实现动态

揭秘Python Socket网络编程的7种硬核用法

《揭秘PythonSocket网络编程的7种硬核用法》Socket不仅能做聊天室,还能干一大堆硬核操作,这篇文章就带大家看看Python网络编程的7种超实用玩法,感兴趣的小伙伴可以跟随小编一起... 目录1.端口扫描器:探测开放端口2.简易 HTTP 服务器:10 秒搭个网页3.局域网游戏:多人联机对战4.

Springboot @Autowired和@Resource的区别解析

《Springboot@Autowired和@Resource的区别解析》@Resource是JDK提供的注解,只是Spring在实现上提供了这个注解的功能支持,本文给大家介绍Springboot@... 目录【一】定义【1】@Autowired【2】@Resource【二】区别【1】包含的属性不同【2】@

springboot循环依赖问题案例代码及解决办法

《springboot循环依赖问题案例代码及解决办法》在SpringBoot中,如果两个或多个Bean之间存在循环依赖(即BeanA依赖BeanB,而BeanB又依赖BeanA),会导致Spring的... 目录1. 什么是循环依赖?2. 循环依赖的场景案例3. 解决循环依赖的常见方法方法 1:使用 @La

Java枚举类实现Key-Value映射的多种实现方式

《Java枚举类实现Key-Value映射的多种实现方式》在Java开发中,枚举(Enum)是一种特殊的类,本文将详细介绍Java枚举类实现key-value映射的多种方式,有需要的小伙伴可以根据需要... 目录前言一、基础实现方式1.1 为枚举添加属性和构造方法二、http://www.cppcns.co

Elasticsearch 在 Java 中的使用教程

《Elasticsearch在Java中的使用教程》Elasticsearch是一个分布式搜索和分析引擎,基于ApacheLucene构建,能够实现实时数据的存储、搜索、和分析,它广泛应用于全文... 目录1. Elasticsearch 简介2. 环境准备2.1 安装 Elasticsearch2.2 J

Java中的String.valueOf()和toString()方法区别小结

《Java中的String.valueOf()和toString()方法区别小结》字符串操作是开发者日常编程任务中不可或缺的一部分,转换为字符串是一种常见需求,其中最常见的就是String.value... 目录String.valueOf()方法方法定义方法实现使用示例使用场景toString()方法方法

Java中List的contains()方法的使用小结

《Java中List的contains()方法的使用小结》List的contains()方法用于检查列表中是否包含指定的元素,借助equals()方法进行判断,下面就来介绍Java中List的c... 目录详细展开1. 方法签名2. 工作原理3. 使用示例4. 注意事项总结结论:List 的 contain

Java实现文件图片的预览和下载功能

《Java实现文件图片的预览和下载功能》这篇文章主要为大家详细介绍了如何使用Java实现文件图片的预览和下载功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... Java实现文件(图片)的预览和下载 @ApiOperation("访问文件") @GetMapping("