本文目录导读:

我来为您展示一个完整的Netty实现HTTP服务器的案例,包含代码和详细说明。
Maven依赖配置
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.1.100.Final</version>
</dependency>
服务器主类
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
public class HttpServer {
private static final int PORT = 8080;
public static void main(String[] args) throws InterruptedException {
// 创建boss线程组:接收连接
EventLoopGroup bossGroup = new NioEventLoopGroup(1);
// 创建worker线程组:处理I/O
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
ServerBootstrap bootstrap = new ServerBootstrap();
bootstrap.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.option(ChannelOption.SO_BACKLOG, 128)
.childOption(ChannelOption.SO_KEEPALIVE, true)
.childHandler(new ServerInitializer());
// 绑定端口并启动服务
ChannelFuture channelFuture = bootstrap.bind(PORT).sync();
System.out.println("HTTP Server started on port " + PORT);
// 关闭服务器
channelFuture.channel().closeFuture().sync();
} finally {
// 优雅关闭
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
}
服务器初始化器
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.codec.http.HttpServerExpectContinueHandler;
public class ServerInitializer extends ChannelInitializer<SocketChannel> {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
// HTTP编解码器
pipeline.addLast("httpCodec", new HttpServerCodec());
// HTTP聚合器:将HTTP消息聚合成完整的请求
pipeline.addLast("aggregator", new HttpObjectAggregator(65536));
// HTTP应答处理
pipeline.addLast("httpServerHandler", new HttpServerHandler());
// 添加压缩支持(可选)
// pipeline.addLast("compressor", new HttpContentCompressor());
}
}
HTTP请求处理器
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.*;
import io.netty.util.CharsetUtil;
import java.util.HashMap;
import java.util.Map;
public class HttpServerHandler extends SimpleChannelInboundHandler<HttpObject> {
@Override
protected void channelRead0(ChannelHandlerContext ctx, HttpObject msg) throws Exception {
if (msg instanceof HttpRequest) {
HttpRequest request = (HttpRequest) msg;
// 处理HTTP请求
handleRequest(ctx, request);
} else if (msg instanceof HttpContent) {
// 处理请求内容(如POST body)
HttpContent content = (HttpContent) msg;
handleContent(ctx, content);
}
}
private void handleRequest(ChannelHandlerContext ctx, HttpRequest request) {
// 获取请求方法
HttpMethod method = request.method();
// 获取请求URI
String uri = request.uri();
System.out.println("Received " + method + " request for: " + uri);
// 获取请求头
HttpHeaders headers = request.headers();
// 处理不同路径的请求
String responseContent;
if ("/".equals(uri)) {
responseContent = generateHomePage();
} else if ("/api/user".equals(uri) && method == HttpMethod.GET) {
responseContent = handleUserApi();
} else if ("/api/test".equals(uri)) {
responseContent = handleTestApi(request);
} else {
responseContent = "404 - Not Found";
sendResponse(ctx, responseContent, HttpResponseStatus.NOT_FOUND);
return;
}
sendResponse(ctx, responseContent, HttpResponseStatus.OK);
}
private void handleContent(ChannelHandlerContext ctx, HttpContent content) {
// 读取POST请求的内容
ByteBuf buf = content.content();
if (buf.isReadable()) {
String requestBody = buf.toString(CharsetUtil.UTF_8);
System.out.println("Request body: " + requestBody);
// 在这里处理请求体
if (content instanceof LastHttpContent) {
System.out.println("Request content received completely");
}
}
}
private void sendResponse(ChannelHandlerContext ctx, String content, HttpResponseStatus status) {
// 创建响应内容
ByteBuf responseBuf = Unpooled.copiedBuffer(content, CharsetUtil.UTF_8);
// 创建FullHttpResponse
FullHttpResponse response = new DefaultFullHttpResponse(
HttpVersion.HTTP_1_1,
status,
responseBuf);
// 设置响应头
response.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/plain; charset=UTF-8");
response.headers().set(HttpHeaderNames.CONTENT_LENGTH, responseBuf.readableBytes());
// 添加CORS支持(可选)
response.headers().set(HttpHeaderNames.ACCESS_CONTROL_ALLOW_ORIGIN, "*");
// 发送响应并关闭连接
ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE);
}
private String generateHomePage() {
StringBuilder html = new StringBuilder();
html.append("<!DOCTYPE html>")
.append("<html>")
.append("<head>")
.append("<title>Netty HTTP Server</title>")
.append("<style>")
.append("body { font-family: Arial; text-align: center; padding-top: 50px; }")
.append("h1 { color: #333; }")
.append("</style>")
.append("</head>")
.append("<body>")
.append("<h1>Welcome to Netty HTTP Server</h1>")
.append("<p>This is a simple HTTP server implemented with Netty</p>")
.append("<p>Time: " + new java.util.Date() + "</p>")
.append("<p>Test APIs:</p>")
.append("<ul>")
.append("<li><a href='/api/user'>API Test</a></li>")
.append("<li><a href='/api/test?param=value'>Parameter Test</a></li>")
.append("</ul>")
.append("</body>")
.append("</html>");
return html.toString();
}
private String handleUserApi() {
Map<String, Object> user = new HashMap<>();
user.put("id", 1);
user.put("name", "张三");
user.put("age", 25);
user.put("email", "zhangsan@example.com");
return "JSON Response: " + user.toString();
}
private String handleTestApi(HttpRequest request) {
// 解析查询参数
QueryStringDecoder decoder = new QueryStringDecoder(request.uri());
Map<String, java.util.List<String>> params = decoder.parameters();
StringBuilder result = new StringBuilder();
result.append("Query Parameters:\n");
for (Map.Entry<String, java.util.List<String>> entry : params.entrySet()) {
result.append(entry.getKey()).append("=").append(entry.getValue()).append("\n");
}
return result.toString();
}
@Override
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
ctx.flush();
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
System.err.println("Error: " + cause.getMessage());
ctx.close();
}
}
完整示例:支持RESTful API的服务器
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.*;
import io.netty.util.CharsetUtil;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
public class RestfulApiServer extends SimpleChannelInboundHandler<FullHttpRequest> {
private final Gson gson = new Gson();
@Override
protected void channelRead0(ChannelHandlerContext ctx, FullHttpRequest request) throws Exception {
String uri = request.uri();
HttpMethod method = request.method();
// 路由处理
if ("/api/hello".equals(uri) && method == HttpMethod.GET) {
handleHello(ctx);
} else if ("/api/posts".equals(uri) && method == HttpMethod.GET) {
handleGetPosts(ctx);
} else if ("/api/posts".equals(uri) && method == HttpMethod.POST) {
// 读取POST请求体的JSON数据
String content = request.content().toString(CharsetUtil.UTF_8);
handleCreatePost(ctx, content);
} else if (uri.startsWith("/api/posts/") && method == HttpMethod.GET) {
String id = uri.substring("/api/posts/".length());
handleGetPostById(ctx, id);
} else {
sendJsonResponse(ctx, "{\"error\":\"Not Found\"}", HttpResponseStatus.NOT_FOUND);
}
}
private void handleHello(ChannelHandlerContext ctx) {
JsonObject response = new JsonObject();
response.addProperty("message", "Hello from Netty REST API");
sendJsonResponse(ctx, response.toString(), HttpResponseStatus.OK);
}
private void handleGetPosts(ChannelHandlerContext ctx) {
// 模拟帖子数据
String mockData = "[{\"id\":1, \"title\":\"Post 1\"}, {\"id\":2, \"title\":\"Post 2\"}]";
sendJsonResponse(ctx, mockData, HttpResponseStatus.OK);
}
private void handleCreatePost(ChannelHandlerContext ctx, String content) {
// 解析JSON并创建帖子
JsonObject request = gson.fromJson(content, JsonObject.class);
String title = request.get("title").getAsString();
JsonObject response = new JsonObject();
response.addProperty("success", true);
response.addProperty("title", title);
response.addProperty("message", "Post created successfully");
sendJsonResponse(ctx, response.toString(), HttpResponseStatus.CREATED);
}
private void handleGetPostById(ChannelHandlerContext ctx, String id) {
JsonObject response = new JsonObject();
response.addProperty("id", id);
response.addProperty("title", "Post " + id);
sendJsonResponse(ctx, response.toString(), HttpResponseStatus.OK);
}
private void sendJsonResponse(ChannelHandlerContext ctx, String json, HttpResponseStatus status) {
ByteBuf content = Unpooled.copiedBuffer(json, CharsetUtil.UTF_8);
FullHttpResponse response = new DefaultFullHttpResponse(
HttpVersion.HTTP_1_1,
status,
content);
response.headers().set(HttpHeaderNames.CONTENT_TYPE, "application/json; charset=UTF-8");
response.headers().set(HttpHeaderNames.CONTENT_LENGTH, content.readableBytes());
response.headers().set(HttpHeaderNames.ACCESS_CONTROL_ALLOW_ORIGIN, "*");
ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE);
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
cause.printStackTrace();
ctx.close();
}
}
测试方法
命令行测试
# GET请求
curl -X GET http://localhost:8080/
# 带参数的GET请求
curl -X GET "http://localhost:8080/api/test?param1=value1¶m2=value2"
# POST请求
curl -X POST http://localhost:8080/api/posts \
-H "Content-Type: application/json" \
-d '{"title":"My First Post"}'
浏览器访问
打开浏览器访问 http://localhost:8080/ 查看HTML页面
高级特性扩展
// 添加HTTPS支持
import io.netty.handler.ssl.SslContext;
import io.netty.handler.ssl.SslContextBuilder;
import io.netty.handler.ssl.util.SelfSignedCertificate;
// 在ServerInitializer中添加SSL支持
public class SecureServerInitializer extends ChannelInitializer<SocketChannel> {
private final SslContext sslContext;
public SecureServerInitializer(SslContext sslContext) {
this.sslContext = sslContext;
}
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
// 添加SSL处理器
pipeline.addLast("ssl", sslContext.newHandler(ch.alloc()));
// 添加HTTP处理器
pipeline.addLast("httpCodec", new HttpServerCodec());
pipeline.addLast("aggregator", new HttpObjectAggregator(65536));
pipeline.addLast("handler", new HttpServerHandler());
}
}
测试工具类
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
public class TestClient {
public static void main(String[] args) throws Exception {
// 测试GET请求
URL url = new URL("http://localhost:8080/api/user");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
int responseCode = conn.getResponseCode();
System.out.println("Response Code: " + responseCode);
BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
System.out.println("Response Body: " + response.toString());
}
}
-
核心组件:
HttpServerCodec:处理HTTP编解码HttpObjectAggregator:聚合HTTP消息SimpleChannelInboundHandler:处理具体请求
-
线程模型:
- Boss线程:接受连接
- Worker线程:处理I/O
-
异步处理:
- 使用
ChannelFuture进行异步操作 - 通过
addListener监听完成状态
- 使用
-
性能优化:
- 使用零拷贝特性
- 减少内存复制
- 支持长连接和连接池
这个案例提供了一个完整的Netty HTTP服务器实现,可以直接运行并测试,您可以根据自己的需求修改处理器逻辑来扩展功能。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播