1. 首先下載下傳gradle然後配置到環境變量中,gradle下載下傳位址:https://gradle.org/
2. 使用gradle下載下傳netty所需要的jar包(搜尋網址:http://search.maven.org/)
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIwczLcVmds92czlGZvwVP9EUTDZ0aRJkSwk0LcxGbpZ2LcBDM08CXlpXazRnbvZ2LcRlMMVDT2EWNvwFdu9mZvwVPJpXT6FERNhXQE10MrdlYohmMMBjVtJWd0ckW65UbM5WOHJWa5kHT20ESjBjUIF2LcRHelR3LcJzLctmch1mclRXY39DO0YTMzkzMxIzNxUDM4EDMy8CX0Vmbu4GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.jpg)
選擇all
在選擇最新的版本(ps最新的版本不是5.x,netty的5.x已經被廢棄掉了,原因是netty5做了大量的工作以後發現并沒有提高netty的便利和性能):
複制gradle位址
導入成功:
3. 編寫netty的伺服器端代碼
package com.baidu.netty.firstExample;
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 TestHttpServer {
public static void main(String[] args) throws Exception{
//1. 定義2個線程池 一個是boss 一個是worker, boss負責接收請求,然後傳遞給worker處理
EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
//2. 建立netty給我們提供的用來簡化伺服器端啟動的ServerBootstrap 對象
ServerBootstrap serverBootstrap = new ServerBootstrap();
//3. 設定組、通道、事件流
serverBootstrap.group(bossGroup,workerGroup).channel(NioServerSocketChannel.class).childHandler(new TestHttpServerInitializer());
//4. 綁定端口等資料
ChannelFuture future = serverBootstrap.bind(8899).sync();
future.channel().closeFuture().sync();
}finally {
// 5. 調用netty的優雅關閉
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
}
4. 編寫netty事件流對象(netty主要是使用事件回調的方式來工作的,是以事件對象在netty中是非常重要的,可以了解為struts2中的Interceptor)
package com.baidu.netty.firstExample;
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 TestHttpServerInitializer extends ChannelInitializer<SocketChannel> {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
//HttpServerCodec是netty中非常重要的一個類,用來設定http的編碼和解碼,
pipeline.addLast("httpServerCodec", new HttpServerCodec());
//添加自己的處理器
pipeline.addLast(new TestHttpHandler());
}
}
5. 編寫自己的處理器對象
package com.baidu.netty.firstExample;
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 TestHttpHandler extends SimpleChannelInboundHandler<HttpObject> {
/**
* 該方法在5.0中被命名為messageReceived,估計後期還是會對該方法進行重命名
* 該方法的主要作用是讀取用戶端的請求,并生産相應資料,我們在該處傳回一個helloworld
*/
@Override
protected void channelRead0(ChannelHandlerContext ctx, HttpObject msg) throws Exception {
//1.定義傳回對象
ByteBuf content = Unpooled.copiedBuffer("hello world", CharsetUtil.UTF_8);
//2. 定義response傳回對象,注意該處的response對象不是servlet中的HttpResponse,他是netty自己封裝的傳回資料,跟http沒有任何關系
FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1,HttpResponseStatus.OK, content);
//3. 設定傳回的資料頭資訊
response.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/plain");
response.headers().set(HttpHeaderNames.CONTENT_LENGTH, content.readableBytes());
//4. 調用ctx傳回response對象
ctx.writeAndFlush(response);
}
}
6. 啟動伺服器,完成測試
7. 在TestHttpHandler 的channelRead0中添加一行列印,然後使用浏覽器和crul再次通路會發現curl執行了2次,浏覽器執行了4次
為何會出現這種情況呢?
我們可以對我們的代碼在進行一次修改,然後在使用curl進行通路
我們發現其實有2個http請求,但是真正有意思的是第一個,第二個屬于空請求,參考Servlet的做法,我們可以對http請求進行過濾
package com.baidu.netty.firstExample;
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 TestHttpHandler extends SimpleChannelInboundHandler<HttpObject> {
/**
* 該方法在5.0中被命名為messageReceived,估計後期還是會對該方法進行重命名
* 該方法的主要作用是讀取用戶端的請求,并生産相應資料,我們在該處傳回一個helloworld
*/
@Override
protected void channelRead0(ChannelHandlerContext ctx, HttpObject msg) throws Exception {
System.out.println(msg);
if (msg instanceof HttpRequest) //過濾非HTTP的請求和垃圾請求
{
System.out.println("invoked....");
//1.定義傳回對象
ByteBuf content = Unpooled.copiedBuffer("hello world", CharsetUtil.UTF_8);
//2. 定義response傳回對象,注意該處的response對象不是servlet中的HttpResponse,他是netty自己封裝的傳回資料,跟http沒有任何關系
FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1,HttpResponseStatus.OK, content);
//3. 設定傳回的資料頭資訊
response.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/plain");
response.headers().set(HttpHeaderNames.CONTENT_LENGTH, content.readableBytes());
//4. 調用ctx傳回response對象
ctx.writeAndFlush(response);
}
}
}
那麼為何浏覽器是4次呢?我們打開浏覽器的F12看network發現其實請求了2次
其中有一次是圖示,是以我們應該把圖示這個請求也過濾掉,
package com.baidu.netty.firstExample;
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;
import java.net.URI;
public class TestHttpHandler extends SimpleChannelInboundHandler<HttpObject> {
/**
* 該方法在5.0中被命名為messageReceived,估計後期還是會對該方法進行重命名
* 該方法的主要作用是讀取用戶端的請求,并生産相應資料,我們在該處傳回一個helloworld
*/
@Override
protected void channelRead0(ChannelHandlerContext ctx, HttpObject msg) throws Exception {
if (msg instanceof HttpRequest) //過濾非HTTP的請求和垃圾請求
{
HttpRequest req = (HttpRequest)msg; //将對象強制類型轉換為HttpRequest的對象
URI uri = new URI(req.uri()); //注意不要引錯了包,是java.net下的
if ("/favicon.ico".equals(uri.getPath())) //過濾掉圖示請求
{
System.out.println("get favicon.icon");
return;
}
System.out.println("invoked....");
//1.定義傳回對象
ByteBuf content = Unpooled.copiedBuffer("hello world", CharsetUtil.UTF_8);
//2. 定義response傳回對象,注意該處的response對象不是servlet中的HttpResponse,他是netty自己封裝的傳回資料,跟http沒有任何關系
FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1,HttpResponseStatus.OK, content);
//3. 設定傳回的資料頭資訊
response.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/plain");
response.headers().set(HttpHeaderNames.CONTENT_LENGTH, content.readableBytes());
//4. 調用ctx傳回response對象
ctx.writeAndFlush(response);
}
}
}
結果就自己測試了
總結
作為netty的第一個程式而已,還是有很多的api不熟悉,耐心寫完第一個helloworld程式,發現netty程式基本都是這個套路來編寫了,而且千萬不要将HttpServerCodec寫成了HttpClientCodec,同時通路的時候需要使用netty綁定的端口來進行通路。