前言
构建一个只有Server服务端的netty服务,不需要额外的编写client去访问,也就是说使用现在的软件去访问。
最简单的就是使用浏览器去访问,浏览是HTTP协议,所以服务必须是一个支持HTTP协议的应用。
实现使用:
IDEA + netty + gradle 构建一个简单的HTTP服务,用来学习netty。
主要角色
netty 构建一个服务,需要三个角色参与
- Server 运行服务
- Initializer 组装组件
- Handle 业秋处理
项目构建
可以创建一个gradle
的空项目,这下面的代码复制进到项目中。
build.gradle
复制内容
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| plugins { id 'java' }
group 'com.liukai.netty' version '1.0-SNAPSHOT'
sourceCompatibility = 1.8 targetCompatibility = 1.8
repositories { mavenCentral() }
dependencies { testCompile group: 'junit', name: 'junit', version: '4.12' testCompile( "junit:junit:4.12" ) compile( "io.netty:netty-all:4.1.10.Final" ) }
|
服务端 NettyServer
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| package com.liukai.netty.test01;
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 NettyServer {
public static void main(String[] args) { EventLoopGroup bossGroup = new NioEventLoopGroup(); EventLoopGroup workerGroup = new NioEventLoopGroup();
ServerBootstrap bootstrap = new ServerBootstrap(); bootstrap.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class) .childHandler(new NettyChannelInitializer()); try { ChannelFuture channelFuture = bootstrap.bind(8889).sync(); channelFuture.channel().closeFuture().sync(); } catch (InterruptedException e) { e.printStackTrace(); } finally { bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); } }
}
|
组装组件 NettyChannelInitializer
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| package com.liukai.netty.test01;
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 NettyChannelInitializer extends ChannelInitializer<SocketChannel> {
@Override protected void initChannel(SocketChannel ch) throws Exception { ChannelPipeline pipeline = ch.pipeline(); pipeline.addLast("httpServerCodec", new HttpServerCodec()); pipeline.addLast("testHttpServerHandler", new NettyServerHandle()); } }
|
Handle 业务处理器 NettyServerHandle
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
| package com.liukai.netty.test01;
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 NettyServerHandle extends SimpleChannelInboundHandler<HttpObject> {
@Override protected void channelRead0(ChannelHandlerContext ctx, HttpObject msg) throws Exception { if (msg instanceof HttpRequest) { System.out.println(msg.getClass()); System.out.println(ctx.channel().remoteAddress()); HttpRequest httpRequest = (HttpRequest) msg; URI uri = new URI(httpRequest.getUri()); ctx.channel().closeFuture();
if ("/favicon.ico".equals(uri.getPath())) { System.out.println("chrome 请求 favicon"); return; } System.out.println("请求方法名: " + httpRequest.getMethod().name()); ByteBuf content = Unpooled.copiedBuffer("Hello World", 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); } } }
|
验证
控制台输出
总结
netty是一个不错的网络通信框架,本身使用起来比较简单,但是越是使用简单的框架底层实现就会比较复杂。
就跟String一样,使用简单,原理复杂是一个样的,但是凡事都是先从会用开始学习。