Netty HTTP协议开发应用:
由于Netty的HTTP协议栈是基于Netty的NIO通信框架开发的,因此Netty的HTTP协议也是异步非阻塞的。
HTTP请求消息:
HTTP请求由三部分组成,具体如下:
- HTTP请求行
请求行以一个方法符开头,以空格分开,后面跟着请求的URI和协议的版本,格式为:Method Request-URI HTTP-Version CRLF。
其中Method表示请求方法,Request-URI是一个统一资源标识符,HTTP-Version表示请求的HTTP协议版本,CRLF表示回车和换行。请求方法有多种,各方法的作用如下:
-
HTTP消息头
-
HTTP请求正文
HTTP 响应消息:
处理完HTTP客户端的请求之后,HTTP服务端返回响应消息给客户端,HTTP响应也是有三个部分组成。分别是:
- 状态行
状态行的格式为:HTTP-Version Status-Code Reason-Phrase CRLF。
Status-Code表示服务器返回的响应状态代码。状态代码由三位数字组成,第一个数字定义了响应的类别,他有五种可能取值:
-
消息报头
-
响应正文
Netty5 示例:
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 1
2 System.out.println("HTTP 服务端启动,端口:"+port);
3 EventLoopGroup bossGroup = new NioEventLoopGroup();
4 EventLoopGroup workerGroup = new NioEventLoopGroup();
5 try {
6 ServerBootstrap b = new ServerBootstrap();
7 b.group(bossGroup, workerGroup)
8 .channel(NioServerSocketChannel.class)
9 .childHandler(new ChannelInitializer<SocketChannel>() {
10 @Override
11 protected void initChannel(SocketChannel ch)
12 throws Exception {
13 //HTTP 请求消息解码器
14 ch.pipeline().addLast("http-decoder",
15 new HttpRequestDecoder());
16 //HttpObjectAggregator解码器,将多个消息转换成单一的FullHttpRequest或者FullHTtpResponse,原因是HTTP解码器在每个HTTP消息中会生成多个消息对象(HttpRequst、HttpResponse、Httpontent/LastHttpContent)。
17 ch.pipeline().addLast("http-aggregator",
18 new HttpObjectAggregator(65536));
19 //HTTP响应结卖钱
20 ch.pipeline().addLast("http-encoder",
21 new HttpResponseEncoder());
22 //Chunked handler它的作用是支持异步发送大的码流但不占用过多的内存,防止发生java内存溢出错误。
23 ch.pipeline().addLast("http-chunked",
24 new ChunkedWriteHandler());
25 ch.pipeline().addLast("httpServerHandler",
26 new HttpReceiveHandler());
27 }
28 });
29 ChannelFuture future = b.bind( port).sync();
30 future.channel().closeFuture().sync();
31 } catch (InterruptedException e) {
32 // TODO Auto-generated catch block
33 e.printStackTrace();
34 } finally {
35 bossGroup.shutdownGracefully();
36 workerGroup.shutdownGracefully();
37 }
38
39
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
51
52
53
54
55
56
57
58
59
60
61
62
63
64 1package com.bh.service;
2
3import static io.netty.handler.codec.http.HttpHeaders.Names.CONTENT_TYPE;
4import static io.netty.handler.codec.http.HttpResponseStatus.OK;
5import static io.netty.handler.codec.http.HttpVersion.HTTP_1_1;
6import io.netty.buffer.ByteBuf;
7import io.netty.buffer.Unpooled;
8import io.netty.channel.ChannelFutureListener;
9import io.netty.channel.ChannelHandlerAdapter;
10import io.netty.channel.ChannelHandlerContext;
11import io.netty.handler.codec.http.DefaultFullHttpResponse;
12import io.netty.handler.codec.http.FullHttpResponse;
13import io.netty.handler.codec.http.HttpContent;
14import io.netty.util.CharsetUtil;
15
16import java.util.concurrent.atomic.AtomicInteger;
17
18import org.codehaus.jettison.json.JSONException;
19import org.codehaus.jettison.json.JSONObject;
20
21import com.bh.client.SendClient;
22
23/**
24 * @author cyq
25 *
26 */
27public class HttpReceiveHandler extends ChannelHandlerAdapter {
28
29 public static AtomicInteger httpReceiveTotal=new AtomicInteger();
30
31 @Override
32 public void channelRead(ChannelHandlerContext ctx, Object msg)
33 throws Exception {
34 if (msg instanceof HttpContent) {
35 HttpContent httpContent = (HttpContent) msg;
36 ByteBuf content = httpContent.content();
37 final StringBuilder buf = new StringBuilder();
38 buf.append(content.toString(CharsetUtil.UTF_8));
39 httpReceiveTotal.incrementAndGet();
40 //转发
41 String responseMessage="false";
42 try {
43 JSONObject jsonObj=new JSONObject(buf.toString());
44 String sendType=jsonObj.getString("sendType");
45 String sendUri= jsonObj.getString("url");
46 String message= jsonObj.getString("message");
47 responseMessage = SendClient.send(sendType, sendUri, message);
48 } catch (JSONException e) {
49 e.printStackTrace();
50 } catch (Exception e) {
51 // TODO Auto-generated catch block
52 e.printStackTrace();
53 }
54 FullHttpResponse response = new DefaultFullHttpResponse(HTTP_1_1, OK);
55 response.headers().set(CONTENT_TYPE, "text/html; charset=UTF-8");
56 ByteBuf buffer = Unpooled.copiedBuffer(responseMessage, CharsetUtil.UTF_8);
57 response.content().writeBytes(buffer);
58 buffer.release();
59 ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE);
60 }
61 }
62}
63
64