一、简介
1、用netty作为通信框架
2、集成spring mvc来处理http请求
二、Server端
1、server接收端
正常启动netty server即可。netty的启动会阻塞后续的执行,所以单独建一个SingleThreadExecutor来执行start,这样不会阻塞主线程,也可以直接对线程池进行控制。
netty接受到请求后转发给HttpServerHandler处理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
30private void startBootstrap() throws Exception {
EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
ServerBootstrap bootstrap = new ServerBootstrap();
bootstrap.group(bossGroup, workerGroup);
bootstrap.channel(NioServerSocketChannel.class);
bootstrap.childHandler(new ServletChannelInitializer());
bootstrap.option(ChannelOption.SO_BACKLOG, 128);
bootstrap.childOption(ChannelOption.SO_KEEPALIVE, true);
String[] addressArray = StringUtil.split(httpAddress, ":");
String ip = addressArray[0];
int port = Integer.parseInt(addressArray[1]);
ChannelFuture future = bootstrap.bind(ip, port).sync();
LOGGER.info("HTTP srver started on ip:" + ip + ", port :" + port);
future.channel().closeFuture().sync();
} finally {
workerGroup.shutdownGracefully();
bossGroup.shutdownGracefully();
}
}
public void initChannel(SocketChannel ch) {
ch.pipeline().addLast("decoder", new HttpRequestDecoder());
ch.pipeline().addLast("aggregator", new HttpObjectAggregator(65536));
ch.pipeline().addLast("encoder", new HttpResponseEncoder());
ch.pipeline().addLast("chunkedWriter", new ChunkedWriteHandler());
ch.pipeline().addLast("httpServerHandler", new HttpServerHandler(dispatcherServlet));
}
HttpServerHandler收到FullHttpRequest后,转换成spring的MockHttpServletRequest(必须是ServletRequest,才可以做后续的解析和转发)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16MockHttpServletRequest servletRequest = createServletRequest(request);
MockHttpServletResponse servletResponse = new MockHttpServletResponse();
this.servlet.service(servletRequest, servletResponse); //自定义servlet处理request和response
HttpResponseStatus status = HttpResponseStatus.valueOf(servletResponse.getStatus());
DefaultFullHttpResponse response = new DefaultFullHttpResponse(HTTP_1_1, status,
Unpooled.wrappedBuffer(servletResponse.getContentAsByteArray()));
for (String name : servletResponse.getHeaderNames()) {
for (Object value : servletResponse.getHeaderValues(name)) {
response.headers().add(name, value);
}
}
ChannelFuture writeFuture = ctx.write(response);
writeFuture.addListener(ChannelFutureListener.CLOSE);
Spring配置好扫描路径,在Controller的类和方法中加入SpringMVC的相应注解,
通过this.servlet.service(servletRequest, servletResponse)将request转发至自定义的dispatcher,处理request后,便能正常转发至Controller中执行。