欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java框架解說之BIO NIO AIO不同IO模型演進(jìn)之路

 更新時(shí)間:2021年10月11日 09:50:00   作者:慕楓技術(shù)筆記  
網(wǎng)上很多IO資料,對(duì)新手來說,越看越暈。根據(jù)自己的理解,總結(jié)對(duì)比了一下BIO、NIO、AIO,對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下

引言

Netty作為高性能的網(wǎng)絡(luò)通信框架,它是IO模型演變過程中的產(chǎn)物。NettyJava NIO為基礎(chǔ),是一種基于異步事件驅(qū)動(dòng)的網(wǎng)絡(luò)通信應(yīng)用框架,Netty用以快速開發(fā)高性能、高可靠的網(wǎng)絡(luò)服務(wù)器和客戶端程序,很多開源框架都選擇Netty作為其網(wǎng)絡(luò)通信模塊。本文主要通過分析IO模型的優(yōu)化演進(jìn)之路,比較不同IO模型的異同,讓大家對(duì)于Java IO模型有著更加深刻的理解,我想這也是Netty如何實(shí)現(xiàn)高性能網(wǎng)絡(luò)通信理解的重要基礎(chǔ)。話不多說,我們趕緊發(fā)車了。

PS:文末有是彩蛋哦!

在這里插入圖片描述

IO模型

1、什么是IO

在闡述BIO、NIOAIO之前,我們先來看下到底什么是IO模型。我們都知道無(wú)論是程序還是平臺(tái),它們的功能高度抽象之后其實(shí)可以描述為這樣一個(gè)過程,即為通過外部條件以及數(shù)據(jù)的輸入,經(jīng)過程序或者平臺(tái)的處理產(chǎn)生了新的輸出,IO模型實(shí)際上就是描述了計(jì)算機(jī)世界中的輸入和輸出過程的模式。

對(duì)于計(jì)算機(jī)來說,其鍵盤以及鼠標(biāo)等就是輸入設(shè)備,顯示器以及磁盤等就是輸出設(shè)備。舉個(gè)栗子,如果我們?cè)谟?jì)算機(jī)上寫一篇設(shè)計(jì)文檔并進(jìn)行保存,實(shí)際就是通過鍵盤對(duì)計(jì)算機(jī)進(jìn)行了數(shù)據(jù)輸入,完成設(shè)計(jì)文檔后將其保存輸出到了計(jì)算機(jī)的磁盤上。

在這里插入圖片描述


上圖中的IO描述,即為著名的計(jì)算機(jī)馮諾依曼體系,它大致描述了外部設(shè)備與計(jì)算機(jī)的IO交互過程。

2、應(yīng)用程序IO交互

上文中我們介紹了計(jì)算機(jī)與外部設(shè)備交互的大致過程,那么我們的應(yīng)用程序是如何進(jìn)行IO交互的呢?我們平時(shí)編寫的代碼不會(huì)獨(dú)立的存在,它總是被部署在linux服務(wù)器或者各種容器中,應(yīng)用程序在服務(wù)器或者容器中啟動(dòng)后再對(duì)外提供服務(wù)。因此網(wǎng)絡(luò)請(qǐng)求數(shù)據(jù)首先需要和計(jì)算機(jī)進(jìn)行交互,才會(huì)被交由到對(duì)應(yīng)的程序去進(jìn)行后續(xù)的業(yè)務(wù)處理。

Linux的世界中,文件是用來描述Linux世界的,目錄文件、套接字等都是文件。那文件又是什么鬼呢?文件實(shí)際就是二進(jìn)制流,二進(jìn)制流就是人類世界與計(jì)算機(jī)世界進(jìn)行交互的數(shù)據(jù)媒介。應(yīng)用從流中讀取數(shù)據(jù)即為read操作,當(dāng)把流中的數(shù)據(jù)進(jìn)行寫入的時(shí)候就是write操作。但是linux系統(tǒng)又是如何區(qū)分不同類型的文件呢?實(shí)際是通過文件描述符(File Descriptor)來進(jìn)行區(qū)分,文件描述符其實(shí)就是個(gè)整數(shù),這個(gè)整數(shù)實(shí)際是一個(gè)索引值,指向內(nèi)核為每一個(gè)進(jìn)程所維護(hù)的該進(jìn)程打開文件的記錄表。所以對(duì)這個(gè)整數(shù)的操作、就是對(duì)這個(gè)文件(流)的操作。

就拿網(wǎng)絡(luò)連接來說,我們創(chuàng)建一個(gè)網(wǎng)絡(luò)socket,通過系統(tǒng)調(diào)用(socket調(diào)用)會(huì)返回一個(gè)文件描述符(某個(gè)整數(shù)),那么后續(xù)對(duì)socket的操作就會(huì)轉(zhuǎn)化為對(duì)這個(gè)描述符的操作,主要涉及的操作包括accept調(diào)用、read調(diào)用以及 write調(diào)用。這里所說的各種調(diào)用就是程序通過Linux內(nèi)核與計(jì)算機(jī)進(jìn)行交互。那么問題又來了,這個(gè)計(jì)算機(jī)內(nèi)核又是什么鬼。(PS:關(guān)于內(nèi)核不是本文的重點(diǎn),這里就簡(jiǎn)單和大家說明下)

//socket函數(shù)
socket(PF_INET6,SOCK_STREAM,IPPROTO_IP)

但是實(shí)際上應(yīng)用程序并不是直接從計(jì)算機(jī)中的網(wǎng)卡中獲取數(shù)據(jù),也就是說大家編寫的程序并不是直接操作計(jì)算機(jī)的底層硬件。

在這里插入圖片描述

如上圖所示,在Linux的結(jié)構(gòu)體系中,用戶的應(yīng)用程序都是通過Linux Kernel內(nèi)核來操作計(jì)算機(jī)硬件。那么為什么應(yīng)用程序不能直接與底層硬件進(jìn)行交互還需要在中間再加一層內(nèi)核呢?主要有以下幾點(diǎn)考慮。

(1)計(jì)算機(jī)資源統(tǒng)一管理

Linux內(nèi)核的作用就是進(jìn)程調(diào)度管理,同時(shí)對(duì)cpu、內(nèi)存等系統(tǒng)資源進(jìn)行統(tǒng)一管理。因此內(nèi)核管理的都是系統(tǒng)極其敏感的資源,采用內(nèi)核制是為了實(shí)現(xiàn)系統(tǒng)的網(wǎng)絡(luò)通信,用戶管理,文件系統(tǒng)等安全穩(wěn)定的進(jìn)程管理,避免用戶應(yīng)用程序破壞系統(tǒng)數(shù)據(jù)。

(2)底層硬件調(diào)用統(tǒng)一封裝

試想一下,如果沒有內(nèi)核這層系統(tǒng)進(jìn)程,那么每個(gè)用戶應(yīng)用程序和硬件交互的時(shí)候都需要自己實(shí)現(xiàn)對(duì)應(yīng)的硬件驅(qū)動(dòng)。這樣的設(shè)計(jì)很難讓人接受,按照面向?qū)ο蟮脑O(shè)計(jì)思想,硬件的管理統(tǒng)一由Kernel內(nèi)核負(fù)責(zé),Kernel向下管理所有的硬件設(shè)備,向上提供給用戶進(jìn)程統(tǒng)一的系統(tǒng)調(diào)用,方便應(yīng)用程序可以像程序調(diào)用一樣進(jìn)行系統(tǒng)硬件交互。

在這里插入圖片描述

3、5種IO模型

(1)阻塞型IO

當(dāng)用戶應(yīng)用進(jìn)程發(fā)起系統(tǒng)調(diào)用之后,在內(nèi)核數(shù)據(jù)沒有準(zhǔn)備好的情況下,調(diào)用一直處于阻塞狀態(tài),直到內(nèi)核準(zhǔn)備好數(shù)據(jù)后,將數(shù)據(jù)從內(nèi)核態(tài)拷貝到用戶態(tài),用戶應(yīng)用進(jìn)程獲取到數(shù)據(jù)后,本次調(diào)用才算完成。就好比你是外賣小哥,你到商家去取餐,商家的外賣還沒有準(zhǔn)備好,所以你只能在取餐的地方一直等待著,直到商家將做好的外賣準(zhǔn)備好,你才能拿了外賣去送餐。

在這里插入圖片描述

(2)非阻塞型IO

非阻塞IO式基于輪詢機(jī)制的IO模型,應(yīng)用進(jìn)程不斷輪詢檢查內(nèi)核數(shù)據(jù)是否準(zhǔn)備好,如果沒有則返回EWOULDBLOCK,進(jìn)程繼續(xù)發(fā)起recvfrom調(diào)用,此時(shí)應(yīng)用可以去處理其他業(yè)務(wù)。當(dāng)內(nèi)核數(shù)據(jù)準(zhǔn)備好后,將內(nèi)核數(shù)據(jù)拷貝至用戶空間。這個(gè)過程就好比外賣小哥在等待取餐的時(shí)候不斷問商家外賣做好了沒(這個(gè)外賣小哥比較著急,送餐時(shí)間比較臨近了),每隔30s問一次,直到外賣做好送到。

在這里插入圖片描述

(3)多路復(fù)用IO

Linux主要提供了select、poll以及epoll等多路復(fù)用I/O的實(shí)現(xiàn)方式,為什么會(huì)有三個(gè)實(shí)現(xiàn)呢?實(shí)際上他們的出現(xiàn)都是有時(shí)間順序的,后者的出現(xiàn)都是為了解決前者在使用中出現(xiàn)的問題。
在實(shí)際場(chǎng)景中,后端服務(wù)器接收大量的socket連接,IO多路復(fù)用是實(shí)際是使用了內(nèi)核提供的實(shí)現(xiàn)函數(shù),在實(shí)現(xiàn)函數(shù)中有一個(gè)參數(shù)是文件描述符集合,對(duì)這些文件描述符(FD)進(jìn)行循環(huán)監(jiān)聽,當(dāng)某個(gè)文件描述符(FD)就緒時(shí),就對(duì)這個(gè)文件描述符進(jìn)行處理。

下面我們分別看下select、poll以及epoll這三個(gè)實(shí)現(xiàn)函數(shù)的實(shí)現(xiàn)原理:

select:
select是操作系統(tǒng)的提供的內(nèi)核系統(tǒng)調(diào)用函數(shù),通過它可以將一組FD傳給操作系統(tǒng),操作系統(tǒng)對(duì)這組FD進(jìn)行遍歷,當(dāng)存在FD處于數(shù)據(jù)就緒狀態(tài)后,將其全部返回給調(diào)用方,這樣應(yīng)用程序就可以對(duì)已經(jīng)就緒的IO流進(jìn)行處理了。

在這里插入圖片描述

select在使用過程中存在一些問題:
(1)select最多只能監(jiān)聽1024個(gè)連接,支持的連接數(shù)較少;
(2)select并不會(huì)只返回就緒的FD,而是需要用戶進(jìn)程自己一個(gè)一個(gè)進(jìn)行遍歷找到就緒的FD
(3)用戶進(jìn)程在調(diào)用select時(shí),都需要將FD集合從用戶態(tài)拷貝到內(nèi)核態(tài),當(dāng)FD較多時(shí)資源開銷相對(duì)較大。

poll:
poll機(jī)制實(shí)際與select機(jī)制區(qū)別不大,只是poll機(jī)制去除掉了監(jiān)聽連接數(shù)1024的限制。

epoll:
epoll解決了select以及poll機(jī)制的大部分問題,主要體現(xiàn)在以下幾個(gè)方面:
(1)FD發(fā)現(xiàn)的變化:內(nèi)核不再通過輪詢遍歷的方式找到就緒的FD,而是通過異步IO事件喚醒的方式,當(dāng)socket有事件發(fā)生時(shí),通過回調(diào)函數(shù)將就緒的FD加入到就緒事件鏈表中,從而避免了輪詢掃描FD集合;
(2)FD返回的變化:內(nèi)核將已經(jīng)就緒的FD返回給用戶,用戶應(yīng)用程序不需要自己再遍歷找到就緒的FD;
(3)FD拷貝的變化:epoll和內(nèi)核共享同一塊內(nèi)存,這塊內(nèi)存中保存的就是那些已經(jīng)可讀或者可寫的的文件描述符集合,這樣就減少了內(nèi)核和程序的內(nèi)存拷貝開銷。

在這里插入圖片描述

(該圖片來自于網(wǎng)絡(luò))

(4)信號(hào)驅(qū)動(dòng)IO

系統(tǒng)存在一個(gè)信號(hào)捕捉函數(shù),該信號(hào)捕捉函數(shù)與socket存在關(guān)聯(lián)關(guān)系,在用戶進(jìn)程發(fā)起sigaction調(diào)用之后,用戶進(jìn)程可以去處理其他的業(yè)務(wù)流程。當(dāng)內(nèi)核將數(shù)據(jù)準(zhǔn)備好之后,用戶進(jìn)程會(huì)接收到一個(gè)SIGIO信號(hào),然后用戶進(jìn)程中斷當(dāng)前的任務(wù)發(fā)起recvfrom調(diào)用從內(nèi)核讀取數(shù)據(jù)到用戶空間再進(jìn)行數(shù)據(jù)處理。

在這里插入圖片描述

(5)異步IO

所謂異步IO模型,就是用戶進(jìn)程發(fā)起系統(tǒng)調(diào)用之后,不管內(nèi)核對(duì)應(yīng)的請(qǐng)求數(shù)據(jù)是否準(zhǔn)備好,都不會(huì)阻塞當(dāng)前進(jìn)程,立即返回后進(jìn)程可以繼續(xù)處理其他的業(yè)務(wù)。當(dāng)內(nèi)核準(zhǔn)備好數(shù)據(jù)之后,系統(tǒng)會(huì)從內(nèi)核復(fù)制數(shù)據(jù)到用戶空間,然后通過信號(hào)通知用戶進(jìn)程進(jìn)行數(shù)據(jù)讀取處理。

在這里插入圖片描述

Java中的IO模型

上文中我們闡述了Linux本身存在的幾種IO模型,那么對(duì)應(yīng)到Java程序世界中,Java也有對(duì)應(yīng)的IO模型,分別是BIO、NIO以及AIO三種IO模型。它們都提供了和IO有關(guān)的API,這些API實(shí)際也是依賴系統(tǒng)層面的IO完成數(shù)據(jù)處理的,因此JavaIO模型,實(shí)際就是對(duì)系統(tǒng)層面IO模型的封裝。接下來我們來一起看下Java的這幾種IO模型。

BIO

BIO即為Blocking IO,顧名思義就是阻塞型IO模型,當(dāng)用戶進(jìn)程向服務(wù)端發(fā)起請(qǐng)求后,一定等到服務(wù)端處理完成有數(shù)據(jù)返回給用戶,用戶進(jìn)程才完成一次IO操作,否則就會(huì)阻塞住,像個(gè)癡心漢傻傻的一直等待數(shù)據(jù)返回,當(dāng)數(shù)據(jù)完成返回后用戶線程才會(huì)解除block狀態(tài),因此在整個(gè)數(shù)據(jù)讀取過程中會(huì)發(fā)生阻塞。

另外從下圖我們可以看出來,每一個(gè)客戶端連接,服務(wù)端都有對(duì)應(yīng)的處理線程來處理對(duì)應(yīng)的請(qǐng)求。還是以餐廳吃飯的例子,你到餐廳去吃飯,假如每來一個(gè)消費(fèi)者,餐廳都用一個(gè)服務(wù)員來接待直到消費(fèi)者吃飽喝足走出餐廳,那么這個(gè)餐廳得配置多少個(gè)服務(wù)員才合適?這么多服務(wù)員,餐廳的老板估計(jì)得賠的內(nèi)褲都沒了。

因此在網(wǎng)絡(luò)連接不多的情況下,BIO還能發(fā)回作用。但是當(dāng)連接數(shù)上來后,比如幾十萬(wàn)甚至上百萬(wàn)連接,BIO模型的IO交互就顯得心有余而力不足了。當(dāng)連接數(shù)不斷攀高時(shí),BIO模型的IO交互方式存在以下幾種弊端。
(1)頻繁創(chuàng)建和銷毀大量的線程會(huì)消耗系統(tǒng)資源給服務(wù)器造成巨大的壓力;
(2)另外大量的處理線程會(huì)占用過多的JVM內(nèi)存,你的程序不要干其他事情了,都被大量連接線程給占滿了;
(3)實(shí)際上線程的上下文切換成本也是很高的。

基于BIO模型在處理大量連接時(shí)存在上述的問題,因此我們需要一種更加高效的線程模型來應(yīng)對(duì)幾十萬(wàn)甚至上百萬(wàn)的客戶端連接。

在這里插入圖片描述

NIO

通過上文的分析,由于在BIO模型下,Java中在進(jìn)行IO操作時(shí)候是沒辦法知道什么時(shí)候可以讀數(shù)據(jù)或者什么時(shí)候可以寫數(shù)據(jù),BIO又是一個(gè)實(shí)在孩子因此沒有什么好的辦法只能在哪里傻等著。由于socket的讀寫操作不能進(jìn)行中斷,因此當(dāng)有新的連接到來時(shí),只能不斷創(chuàng)建新的線程來處理,從而導(dǎo)致存在性能問題。

那么如何解決這個(gè)問題呢?我們都知道問題的根源就是BIO模型中我們不知道數(shù)據(jù)的讀取與寫入的時(shí)機(jī),才導(dǎo)致的阻塞等待,那么如果我們能夠知道數(shù)據(jù)讀寫的時(shí)機(jī),是不是就不用傻傻的等著響應(yīng),也不用再創(chuàng)建新的線程來處理連接了。

在這里插入圖片描述

為了提升IO交互效率,避免阻塞傻等的情況發(fā)生。Java 1.4中引入了NIO,對(duì)于NIO來說,有人稱之為Non-blocking IO,但是我更愿意稱之為New IO。因?yàn)樗且环N基于IO多路復(fù)用的IO模型,而不是簡(jiǎn)單的同步非阻塞的IO模型。所謂IO多路復(fù)用指的就是用同一個(gè)線程處理大量連接,多路指的就是大量連接,復(fù)用指的就是使用一個(gè)線程來進(jìn)行處理。

在這里插入圖片描述

那我們先來看看同步非阻塞模型有什么問題,NIO 的讀寫以及接受方法在等待數(shù)據(jù)就緒階段都是非阻塞的。如上文中的描述,同步非阻塞模式下應(yīng)用進(jìn)程不斷向內(nèi)核發(fā)起調(diào)用,詢問內(nèi)核數(shù)據(jù)完成準(zhǔn)備。相對(duì)于同步阻塞模型有了一定的優(yōu)化,通過不斷輪詢數(shù)據(jù)是否準(zhǔn)備好,避免了調(diào)用阻塞。但是由于應(yīng)用不斷進(jìn)行系統(tǒng)IO調(diào)用,在此過程中十分消耗CPU,因此還有進(jìn)一步優(yōu)化的空間。此時(shí)就該IO多路復(fù)用模型上場(chǎng)一展拳腳了,而JavaNIO正是借助于此實(shí)現(xiàn)了IO性能的提升。(這里以epoll機(jī)制來進(jìn)行說明)

Java NIO基于通道和緩沖區(qū)的形式來處理流數(shù)據(jù),借助于Linux操作系統(tǒng)的epoll機(jī)制,多路復(fù)用器selector就會(huì)不斷進(jìn)行輪詢,當(dāng)某個(gè)channel的事件(讀事件,寫事件,連接事件等等)準(zhǔn)備就緒的時(shí)候,就是會(huì)找到這個(gè)channel對(duì)應(yīng)的SelectionKey,去做相應(yīng)的操作,進(jìn)行數(shù)據(jù)的讀寫操作。

在這里插入圖片描述

AIO

所謂AIO(Asynchronous IO)就是NIO第二代,它是在Java 7中引入的,是一種異步IO模型。異步IO模型是基于事件和回調(diào)機(jī)制實(shí)現(xiàn)的,當(dāng)應(yīng)用發(fā)起調(diào)用請(qǐng)求之后會(huì)直接返回不會(huì)阻塞在那里,當(dāng)后臺(tái)進(jìn)行數(shù)據(jù)處理完成后,操作系統(tǒng)便會(huì)通知對(duì)應(yīng)的線程來進(jìn)行后續(xù)的數(shù)據(jù)處理。
從效率上來看,AIO 無(wú)疑是最高的,然而,美中不足的是目前作為廣大服務(wù)器使用的系統(tǒng) linux 對(duì) AIO 的支持還不完善,導(dǎo)致我們還不能愉快的使用 AIO 這項(xiàng)技術(shù),Netty實(shí)際也是使用過AIO技術(shù),但是實(shí)際并沒有帶來很大的性能提升,目前還是基于Java NIO實(shí)現(xiàn)的。

總結(jié)

本文主要從計(jì)算機(jī)IO交互出發(fā),分別給大家介紹了什么是IO模型以及常見的五種IO模型,介紹了這幾種IO模型的優(yōu)缺點(diǎn),從系統(tǒng)優(yōu)化演進(jìn)的角度分析了Java BIO、NIO以及AIO演化之路。從設(shè)計(jì)者的角度分析Java BIO存在的不足。我們?cè)賮砘仡櫹抡麄€(gè)演進(jìn)過程的脈絡(luò)。

在這里插入圖片描述

在后續(xù)的文章中,筆者將繼續(xù)帶大家深入研究的Netty作為高性能網(wǎng)絡(luò)通信框架的奇妙之處,敬請(qǐng)期待哦。

真正的大師永遠(yuǎn)懷著一顆學(xué)徒的心

到此這篇關(guān)于Java框架解說之BIO NIO AIO不同IO模型演進(jìn)之路的文章就介紹到這了,更多相關(guān)Java IO模型內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • java冒泡排序簡(jiǎn)單實(shí)例

    java冒泡排序簡(jiǎn)單實(shí)例

    本文主要介紹了JSONjava冒泡排序?qū)嵗c思路分析。具有一定的參考價(jià)值,下面跟著小編一起來看下吧
    2017-01-01
  • Java9新特性Java.util.Optional優(yōu)化與增強(qiáng)解析

    Java9新特性Java.util.Optional優(yōu)化與增強(qiáng)解析

    這篇文章主要為大家介紹了Java9新特性Java.util.Optional優(yōu)化與增強(qiáng)使用說明解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步
    2022-03-03
  • 接口簽名怎么用Java實(shí)現(xiàn)

    接口簽名怎么用Java實(shí)現(xiàn)

    今天帶大家學(xué)習(xí)java的相關(guān)知識(shí),文章圍繞怎么用Java實(shí)現(xiàn)接口簽名展開,文中有非常詳細(xì)的代碼示例及介紹,需要的朋友可以參考下
    2021-06-06
  • java連接MySQL數(shù)據(jù)庫(kù)實(shí)現(xiàn)代碼

    java連接MySQL數(shù)據(jù)庫(kù)實(shí)現(xiàn)代碼

    這篇文章主要為大家詳細(xì)介紹了java連接MySQL數(shù)據(jù)庫(kù)實(shí)現(xiàn)代碼,感興趣的小伙伴們可以參考一下
    2016-06-06
  • Java 替換空格

    Java 替換空格

    本文主要介紹了Java中替換空格的方法。具有很好的參考價(jià)值,下面跟著小編一起來看下吧
    2017-01-01
  • Java 在PDF中繪制形狀的兩種方法

    Java 在PDF中繪制形狀的兩種方法

    這篇文章主要介紹了Java 在 PDF 中繪制形狀的兩種實(shí)現(xiàn)方法,文中講解非常細(xì)致,代碼幫助大家更好的理解和學(xué)習(xí),感興趣的朋友可以了解下
    2020-07-07
  • C# TreeNode案例詳解

    C# TreeNode案例詳解

    這篇文章主要介紹了C# TreeNode案例詳解,本篇文章通過簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-08-08
  • 詳解RabbitMQ中死信隊(duì)列和延遲隊(duì)列的使用詳解

    詳解RabbitMQ中死信隊(duì)列和延遲隊(duì)列的使用詳解

    這篇文章主要為大家介紹了RabbitMQ中死信隊(duì)列和延遲隊(duì)列的原理與使用,這也是Java后端面試中常見的問題,感興趣的小伙伴可以了解一下
    2022-05-05
  • JAVA獲取當(dāng)前項(xiàng)目和文件所在路徑的實(shí)例代碼

    JAVA獲取當(dāng)前項(xiàng)目和文件所在路徑的實(shí)例代碼

    這篇文章主要介紹了JAVA獲取當(dāng)前項(xiàng)目和文件所在路徑的實(shí)例代碼,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-03-03
  • Spring boot redis cache的key的使用方法

    Spring boot redis cache的key的使用方法

    這篇文章主要介紹了Spring boot redis cache的key的使用方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-05-05

最新評(píng)論