Netty在IDEA中搭建HelloWorld服務端並對Netty執行流程與重要組件進行介紹


場景

什么是Netty

Netty 是一個利用 Java 的高級網絡的能力,隱藏其背后的復雜性而提供一個易於使用的 API 的客戶端/服務器框架。

Netty 是基於 Java NIO 的異步事件驅動的網絡應用框架,使用 Netty 可以快速開發網絡應用,Netty 提供了高層次的抽象來簡化 TCP 和 UDP 服務器的編程,但是你仍然可以使用底層的 API。

Netty 的內部實現是很復雜的,但是 Netty 提供了簡單易用的API從網絡處理代碼中解耦業務邏輯。Netty 是完全基於 NIO 實現的,所以整個 Netty 都是異步的。

Netty 是最流行的 NIO 框架,它已經得到成百上千的商業、商用項目驗證,許多框架和開源組件的底層 rpc 都是使用的 Netty,如 Dubbo、Elasticsearch 等等。

這里使用IDEA和Gradle,也可以使用Maven作為依賴管理工具。

在Windows中下載配置以及在IDEA中配置Gradle參照如下

https://mp.csdn.net/console/editor/html/108578033

注:

博客:
https://blog.csdn.net/badao_liumang_qizhi
關注公眾號
霸道的程序猿
獲取編程相關電子書、教程推送與免費下載。

實現

IDEA新建一個Gradle項目

 

 

配置使用Java並設置JDK

新建之后的項目目錄

 

 

 

 

此時會自動在build.gradle類似於Maven的pom.xml中引入了junit的依賴。

這里需要引入Netty的依賴。

瀏覽器打開Maven中央倉庫地址

https://mvnrepository.com/

搜索netty-all

 

 

 

 

 

 

選擇穩定版本這里是4.1.52

 

 

選擇Gradle的依賴

 

 

將其復制進IDEA下的build.gradle中

dependencies {
    // https://mvnrepository.com/artifact/io.netty/netty-all
    compile group: 'io.netty', name: 'netty-all', version: '4.1.52.Final'
}

 

 

 

因為上面已經設置了自動導入依賴。

所以保存后就能實現自動導入。

 

 

同樣在上面的gradle的配置的博客中設置了jar包的存儲位置。

來到配置的jar包的存儲位置就可以看到jar包所在的位置。

 

 

在項目中引入Netty后,在src下新建包,包下新建HelloWorldServer類作為服務端的啟動類

在啟動類中新建main方法

package com.badao.netty;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;

public class HelloWorldServer {
    public static void main(String[] args) throws  Exception
    {
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        try{
            //服務端啟動類-Netty提供的啟動服務端的類
            ServerBootstrap serverBootstrap = new ServerBootstrap();
            //參數為兩個事件組 前面的用來接收請求 后面的用來處理
            //childHandler 設置請求到了之后進行處理的處理器
            serverBootstrap.group(bossGroup,workerGroup).channel(NioServerSocketChannel.class)
            .childHandler(new HelloWorldServerInitializer());
            //綁定端口
            ChannelFuture channelFuture = serverBootstrap.bind(70).sync();
            channelFuture.channel().closeFuture().sync();
        }finally {
            //關閉事件組
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }
}

注意這里的都是引入的netty的包,不要引入nio的包。

首先EventLoopGroup是事件循環組,可以認為是一個死循環,一直監聽是否有連接然后處理。

這里使用兩個是Netty官方推薦,一個bossGroup只用來監聽連接,然后交由后面的workerGroup進行處理。

ServerBootstrap是Netty的啟動服務端的類。

分別設置兩個group並設置通道為NioServerSocketChannel

然后childHandler是設置對請求具體處理的處理器。這里新建了一個HelloWorldInititalizer類作為服務端初始化的類。

下面綁定了70端口。

所以在包下再新建類HelloWorldServerInitializer作為服務端初始化器,並使其繼承ChannelInitializer

然后重寫initChannel方法,連接一旦被創建后就會執行此方法。

package com.badao.netty;

import io.netty.channel.Channel;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.http.HttpServerCodec;

//服務端初始化器
public class HelloWorldServerInitializer extends ChannelInitializer<SocketChannel> {


    @Override
    protected void initChannel(SocketChannel ch) throws Exception {
        //連接一旦被創建后就會執行此方法
        ChannelPipeline channelPipeline = ch.pipeline();
        //在最后添加由Netty提供的處理器
        channelPipeline.addLast("httpServerCodec",new HttpServerCodec());
        channelPipeline.addLast("helloWorldServerHandler",new HelloWorldServerHandler());
    }
}

 

注意這里的繼承的泛型里面的SocketChannel是在netty包下的。

在方法中在處理的最后添加處理器,第一個添加的是Netty自帶的處理器。

后面再創建一個自定的處理器HelloWorldServerHandler

前面的name可以自己定義。

所以需要在包下再新建HelloWorldServerHandler處理器類並使其繼承SimpleChannelInboundHandler

然后重寫其方法channelRead0

此方法就是讀取客戶端發送過來的請求並返回響應。

package com.badao.netty;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.*;
import io.netty.util.CharsetUtil;

//自定義的處理器
public class HelloWorldServerHandler extends SimpleChannelInboundHandler<HttpObject> {
    //此方法就是讀取客戶端發送過來的請求並返回響應
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, HttpObject msg) throws Exception {
        if(msg instanceof HttpRequest)
        {
            //構造返回內容
            ByteBuf content = Unpooled.copiedBuffer("公眾號:霸道的程序猿", CharsetUtil.UTF_8);
            //構造響應
            FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK,content);
            //設置響應頭類型
            response.headers().set(HttpHeaderNames.CONTENT_TYPE,"text/plain");
            //設置響應頭長度
            response.headers().set(HttpHeaderNames.CONTENT_LENGTH,content.readableBytes());
            //返回響應
            ctx.writeAndFlush(response);
        }

    }
}

在方法中構造返回的內容和響應頭,然后將其返回響應。

這樣一個客戶端,功能是接受到請求時返回字符串"公眾號:霸道的程序猿",就搭建完成了。

找到項目下的.idea下的gradle.xml,將下面的

<option name="delegatedBuild" value="false" />

改為false,如果沒有則將這行加上

 

 

這樣就能使用java運行main方法,gradle就不會認為其是task了。

運行最上面的服務端的main方法。

如果沒有輸出任何報錯則是運行成功。

 

 

怎樣去驗證服務端搭建成功?

這里可以使用curl去進行請求驗證

cURL是一個利用URL語法在命令行下工作的文件傳輸工具,1997年首次發行。
它支持文件上傳和下載,所以是綜合傳輸工具,但按傳統,習慣稱cURL為下載工具。
cURL還包含了用於程序開發的libcurl。

cURL支持的通信協議有FTP、FTPS、HTTP、HTTPS、TFTP、SFTP、Gopher、SCP、Telnet、DICT、FILE、LDAP、LDAPS、IMAP、POP3、SMTP和RTSP。

curl還支持SSL認證、HTTP POST、HTTP PUT、FTP上傳, HTTP form based upload、proxies、HTTP/2、cookies、用戶名+密碼認證(Basic, Plain, Digest, CRAM-MD5, NTLM, Negotiate and Kerberos)、file transfer resume、proxy tunneling。

這里因為是在Windows下,所以需要下載curl

下載地址:

https://curl.haxx.se/windows/

 

 

這里下載64位的,將其解壓到磁盤上的某目錄。

 

 

找到其目錄下的bin目錄,即curl.exe所在的目錄。

在此處打開cmd

curl http://localhost:70

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM