1. HttpServer
HttpServer作为http服务器的server端:
public final class HttpServer {
private static final String IP = "127.0.0.1";
private static final int PORT = 9000;
private static final int BIZ_THREAD_SIZE = 100;
private static final Logger logger = LoggerFactory.getLogger(HttpServer.class);
public static void main(String[] args) throws Exception {
System.out.println("启动Server...");
HttpServer.start();
}
public static void start() throws Exception {
initServerConfig();
// new NioEventLoopGroup()默认线程数为CPU核心数的两倍(Runtime.getRuntime().availableProcessors() * 2),所以这里不用额外指定。
EventLoopGroup bossGroup = new NioEventLoopGroup();
// 这里worker不能使用默认,如果并发大的话需要增加线程数量
EventLoopGroup workerGroup = new NioEventLoopGroup(BIZ_THREAD_SIZE);
try {
ServerBootstrap bootstrap = new ServerBootstrap();
bootstrap.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
// ChannelOption.SO_BACKLOG对应的是tcp/ip协议listen函数中的backlog参数。函数listen(int socketfd, int backlog)用来初始化服务端可连接队列。
// 服务端处理客户端连接请求是顺序处理的,所以同一时间只能处理一个客户端连接,多个客户端来的时候,服务端将不能处理的客户端连接请求放在队列中等待处理,backlog参数指定了队列的大小。
.option(ChannelOption.SO_BACKLOG, 1024)
.handler(new LoggingHandler(LogLevel.INFO))
.childOption(ChannelOption.SO_KEEPALIVE, true) // 子channel配置,保持长连接
.childHandler(new HttpServerInitializer());
// sync追踪代码可以得到:this.await(),实现阻塞
ChannelFuture channelFuture = bootstrap.bind(IP, PORT).sync();
// 启动失败则关闭线程组
if (!channelFuture.isSuccess()) {
shutdown(bossGroup, workerGroup);
throw new RuntimeException(channelFuture.cause());
}
channelFuture.channel().closeFuture().sync();
logger.info("bootstrap channel closed...");
} finally {
shutdown(bossGroup, workerGroup);
}
}
// 添加路径映射和过滤器映射
private static void initServerConfig() {
ServerContext.setFilter(ServerContext.MAPPING_ALL, BaseFilter.class);
ServerContext.setFilter("/template", TemplateFilter.class);
ServerContext.setAction(ServerContext.MAPPING_ALL, DefaultIndexAction.class);
ServerContext.setAction("/template", TemplateAction.class);
ServerContext.setAction("/files", FileAction.class);
ServerContext.setROOT("root");
ServerContext.setPORT(8090);
}
private static void shutdown(EventLoopGroup bossGroup, EventLoopGroup workerGroup) {
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
HttpServerInitializer设置http编解码器,以及请求aggregator等:
public class HttpServerInitializer extends ChannelInitializer<SocketChannel> {
@Override
public void initChannel(SocketChannel socketChannel) {
ChannelPipeline pipeline = socketChannel.pipeline();
pipeline
//或者使用HttpRequestDecoder & HttpResponseEncoder
.addLast(new HttpServerCodec())
//把HttpObjectAggregator放入管道里。HttpObjectAggregator会把多个消息转换为一个单一的FullHttpRequest或是FullHttpResponse
.addLast(new HttpObjectAggregator(1024 * 1024))
//压缩Http消息
// .addLast(new HttpChunkContentCompressor())
//大文件支持,文件上传时使用
// .addLast(new ChunkedWriteHandler())
.addLast(new HttpServerExpectContinueHandler())
.addLast(new HttpServerDispatcherHandler());
}
}
入栈处理器,用于转发http请求,类似于DispatcherServlet:
public class HttpServerDispatcherHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) {
if (!(msg instanceof FullHttpRequest)) {
return;
}
FullHttpRequest fullHttpRequest = (FullHttpRequest) msg;
final Request customerRequest = Request.build(ctx, fullHttpRequest);
final Response customerResponse = Response.build(ctx, customerRequest);
if (customerRequest.getRequestUrl().equals(HttpHelper.FAVICON_ICO)) {
return;
}
// 过滤器放行之后,执行action,实际处理业务逻辑
boolean passFilter = doFilter(customerRequest, customerResponse);
if (passFilter) {
doAction(customerRequest, customerResponse);
}
//如果发送请求未被触发,则触发之,否则跳过。
if(false == customerResponse.isSent()) {
customerResponse.response();
}
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
cause.printStackTrace();
ctx.close();
}
@Override
public void channelReadComplete(ChannelHandlerContext ctx) {
ctx.flush();
}
/**
* 过滤器
* @param request
* @param response
* @return
*/
private boolean doFilter(Request request, Response response) {
//全局过滤器
Filter filter = ServerContext.getFilter(ServerContext.MAPPING_ALL);
if(null != filter) {
if(false == filter.doFilter(request, response)) {
return false;
}
}
//自定义过滤器
filter = ServerContext.getFilter(request.getRequestUrl());
if(null != filter) {
if(false == filter.doFilter(request, response)) {
return false;
}
}
return true;
}
/**
* 请求处理器
* 相当于servlet
* @param request
* @param response
*/
private void doAction(Request request, Response response) {
Action action = ServerContext.getAction(request.getRequestUrl());
if (null == action) {
//查找匹配所有路径的Action
action = ServerContext.getAction(ServerContext.MAPPING_ALL);
if(null == action) {
// 非Action方法,调用静态文件读取
action = Singleton.get(FileAction.class);
}
}
action.doAction(request, response);
}
}
过滤器
public interface Filter {
/**
* 执行过滤
* @param request 请求对象
* @param response 响应对象
* @return 如果返回true,则继续执行下一步内容,否则中断
*/
boolean doFilter(Request request, Response response);
}
过滤器示例:
public class TemplateFilter implements Filter {
@Override
public boolean doFilter(Request request, Response response) {
System.out.println("welcome in template filter...");
return true;
}
}
action
action用于实际处理业务,顶层接口:
public interface Action {
void doAction(Request request, Response response);
}
抽象Adapter:
public abstract class AbstractAction implements Action {
@Override
public void doAction(Request request, Response response) {
String method = request.getMethod();
if (HttpHelper.METHOD_GET.equals(method)) {
doGet(request, response);
} else if (HttpHelper.METHOD_POST.equals(method)) {
doPost(request, response);
} else if (HttpHelper.METHOD_PUT.equals(method)) {
doPut(request, response);
} else if (HttpHelper.METHOD_DELETE.equals(method)) {
doDelete(request, response);
} else if (HttpHelper.METHOD_HEAD.equals(method)) {
doHead(request, response);
} else if (HttpHelper.METHOD_OPTIONS.equals(method)) {
doOptions(request, response);
} else if (HttpHelper.METHOD_TRACE.equals(method)) {
doTrace(request, response);
}
}
protected void doGet(Request request, Response response) {}
protected void doPost(Request request, Response response) {}
protected void doPut(Request request, Response response) {}
protected void doDelete(Request request, Response response) {}
protected void doOptions(Request request, Response response) {}
protected void doHead(Request request, Response response) {}
protected void doTrace(Request request, Response response) {}
}
action示例:
public class TemplateAction extends AbstractAction {
@Override
protected void doGet(Request request, Response response) {
response.setContentType(HttpHelper.CONTENT_TYPE_JSON);
response.setContent("welcome in template action, do get...");
}
@Override
protected void doPost(Request request, Response response) {
response.setContent("welcome in template action, do post...");
}
}
。。。