一、簡(jiǎn)介
Java的底層API逐漸復(fù)雜,而開(kāi)發(fā)者面對(duì)的開(kāi)發(fā)場(chǎng)景需求也在逐漸增大。如果直接針對(duì)底層API進(jìn)行編程,無(wú)疑是耗時(shí)耗力的。這時(shí)就催生了極多的編程框架,這些框架隱藏了API實(shí)現(xiàn)的復(fù)雜細(xì)節(jié),以最簡(jiǎn)潔的方式給開(kāi)發(fā)人員提供功能的實(shí)現(xiàn)接口。Netty就是一款針對(duì)于網(wǎng)絡(luò)鏈接的框架,他的出現(xiàn)讓服務(wù)器開(kāi)發(fā)人員更加的集中關(guān)注于更多邏輯的實(shí)現(xiàn),而不為了實(shí)現(xiàn)更好更多更穩(wěn)定的鏈接而頭疼。Netty的核心功能基于NIO 實(shí)現(xiàn)。
二、Netty的應(yīng)用場(chǎng)景
幾乎適用于所有的長(zhǎng)短鏈接場(chǎng)景,由于Java應(yīng)用的廣泛性,幾乎所有的互聯(lián)網(wǎng)公司或多或少的都會(huì)使用到。博主從事游戲開(kāi)發(fā),可以說(shuō)幾乎所有短鏈接游戲服務(wù)器都是使用Netty開(kāi)發(fā),實(shí)效性要求比較高也有熱修復(fù)需求的服務(wù)器一般不會(huì)使用Java,目前采用更多的是C+Lua的組合方式。Java不可以熱修復(fù)是很多長(zhǎng)鏈服務(wù)器不考慮java 的一個(gè)重要原因。
三、異步和事件驅(qū)動(dòng)性
NIO 文章中強(qiáng)調(diào)了,這種模型的主要特地拿就是異步和事件驅(qū)動(dòng)性,異步是服務(wù)器不需要一直等待鏈接輸入直到鏈接關(guān)閉。而是可以在某個(gè)特定的時(shí)候去相應(yīng)鏈接的輸入,而特定的時(shí)候就是另一個(gè)事件驅(qū)動(dòng)性,鏈接發(fā)生變化時(shí),會(huì)產(chǎn)生一個(gè)事件,而NIO模型檢測(cè)到這個(gè)事件之后,會(huì)去相應(yīng)這個(gè)事件的處理事件。
四、Netty核心組件
1.Channel:
Channel時(shí)Java-NIO的一個(gè)基本構(gòu)造,它代表到一個(gè)實(shí)體的開(kāi)放鏈接,如讀操作和寫(xiě)操作,在NIO模型中也可以被理解成一個(gè)入站或者出站的數(shù)據(jù)載體,可以被關(guān)閉或者關(guān)閉。
2.回調(diào) ChannelHandler:
一個(gè)回調(diào)就是一個(gè)方法,Netty提供了兩個(gè)子類(lèi),ChannelInboundHandlerAdapter 以及 ChannelOutboundHandlerAdapter ,這兩個(gè)子類(lèi)分別可以應(yīng)用于數(shù)據(jù)進(jìn)站和出站時(shí)期,各種階段的回調(diào),比如入站時(shí)Active方法,表明鏈接剛剛被建立起,代碼如下:
public class ConnectHandler extend ChannelInboundHandlerAdapter{
@override
public void ChannelActive(ChannelHandlerContext ctx){
//數(shù)據(jù)入站回調(diào)子類(lèi)被建立時(shí)調(diào)用,也就是鏈接建立時(shí)調(diào)用
System.out.println("遠(yuǎn)程客戶(hù)端 : "+ ctx.channel().remoteAddress() + '建立鏈接');
}
}
不了解Netty的讀者看到這里可能會(huì)有點(diǎn)疑惑,這個(gè)類(lèi)應(yīng)該怎么用。這里簡(jiǎn)單的解釋一下:這種類(lèi)會(huì)在Netty創(chuàng)建的時(shí)候注冊(cè)進(jìn)服務(wù)中,然后在數(shù)據(jù)進(jìn)站、出站的不同階段,調(diào)用這個(gè)類(lèi)中不同的回調(diào)函數(shù),以處理不同的開(kāi)發(fā)需求。可以關(guān)注一下讀者其他的文章
3.Future:
jdk-Future:Java中提供了Future的實(shí)現(xiàn),這種Futrue可以看作是一個(gè)異步操作結(jié)果的占位符。我們可以通過(guò)這個(gè)Future查詢(xún)到這個(gè)異步操作的結(jié)果,并進(jìn)行一些處理。比如在操作失敗的時(shí)候拋出異常。但是jdk內(nèi)置的Future的查詢(xún)只能在某個(gè)時(shí)刻手動(dòng)去查詢(xún)結(jié)果,或者直接阻塞這個(gè)異步操作,直到異步完成操作之后可以查詢(xún)Future的成功或者失敗。
ChannelFuture:Netty內(nèi)部提供的Future實(shí)現(xiàn)類(lèi),很多異步操作在執(zhí)行的時(shí)候都會(huì)返回一個(gè)ChannelFuture對(duì)象,我們可以針對(duì)這個(gè)ChannelFuture對(duì)象設(shè)置一些回調(diào)函數(shù),比如重寫(xiě)operationComplete()方法,這樣這個(gè)異步事件在完成的時(shí)候會(huì)自動(dòng)調(diào)用這個(gè)方法,并且執(zhí)行我們自己的處理邏輯。
接下來(lái)可以看一下ChannelFuture的應(yīng)用實(shí)例,檢測(cè)Netty服務(wù)器鏈接遠(yuǎn)程地址是否成功:
Channel channel = "";
//鏈接地址192.168.100.113 的7000端口
InetSocketAddress socketAddress = new InetSocketAddress("192.168.100.113",7000);
//管道綁定地址并返回一個(gè)ChannelFuture
ChannelFuture channelFuture = channel.connect(socketAddress);
//給ChannelFuture設(shè)置完成回調(diào),判斷這個(gè)操作是否完成
channelFuture.addListener(new ChannelFutureListener(){
@override
public void operationComplete(ChannelFuture future){
if(future.isSucess()){
//創(chuàng)建一個(gè)字符串,并指定所使用的字符集,下面這種寫(xiě)法是Netty中經(jīng)常遇到的
ByteBuf buffer = Unpooled.copiedBuffer("Hello",Charset.defaultCharset());
//發(fā)送信息并且返回一個(gè)新的writeFuture,依舊可以根據(jù)這個(gè)writeFuture處理一些邏輯
ChannelFuture writeFuture = future.channel().writeAndFlush(buffer);
}else{
//鏈接失敗則答應(yīng)出失敗的消息
Throwable cause = future.cause();
cause.printStackTrace();
}
}
})
五、總結(jié)
Netty以一種異步事件驅(qū)動(dòng)以及回調(diào)的方式,能幫我們快速完善服務(wù)器處理數(shù)據(jù)的進(jìn)出,以及各個(gè)流程細(xì)節(jié)中的處理邏輯。極大的精簡(jiǎn)了服務(wù)器開(kāi)發(fā)人員在,鏈接處理,數(shù)據(jù)出入方面的開(kāi)發(fā)工作。是一個(gè)及其易用且穩(wěn)定的網(wǎng)絡(luò)開(kāi)發(fā)框架。
到此這篇關(guān)于 Java 中一款易于使用API的 C/S 框架 Netty 相關(guān)知識(shí)的文章就介紹到這了,想要了解更多相關(guān)Java Netty內(nèi)容請(qǐng)搜索W3Cschool以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持!