文章目录
HttpServer
java
复制代码
public class HttpServer {
public static void main(String[] args) {
EventLoopGroup bossGroup = new NioEventLoopGroup(1);
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
ServerBootstrap serverBootstrap = new ServerBootstrap()
.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new ChannelInitializer<NioSocketChannel>() {
@Override
protected void initChannel(NioSocketChannel ch) throws Exception {
ch.pipeline().addLast(new HttpRequestDecoder());
ch.pipeline().addLast(new HttpResponseEncoder());
ch.pipeline().addLast(new HttpServerHandler());
}
});
ChannelFuture bindFuture = serverBootstrap.bind(8080);
Channel channel = bindFuture.sync().channel();
System.out.println("---启动http服务成功---");
channel.closeFuture().sync();
} catch (Exception e) {
System.out.println("---启动http服务失败---");
e.printStackTrace();
} finally {
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
System.out.println("---http服务已关闭---");
}
}
HttpServerHandler
java
复制代码
public class HttpServerHandler extends SimpleChannelInboundHandler<HttpObject> {
HttpPostRequestDecoder decoder;
HttpDataFactory factory;
HttpRequest request;
@Override
protected void channelRead0(ChannelHandlerContext ctx, HttpObject httpObject) throws Exception {
System.out.println("[============> channelRead0]: " + httpObject);
if (httpObject instanceof HttpRequest) {
if (decoder != null) {
decoder.destroy();
}
request = (HttpRequest) httpObject;
factory = new DefaultHttpDataFactory(DefaultHttpDataFactory.MINSIZE);
decoder = new HttpPostRequestDecoder(factory, request);
} else if (httpObject instanceof HttpContent) {
decoder.offer(((HttpContent) httpObject));
if (httpObject instanceof LastHttpContent) {
for (InterfaceHttpData bodyHttpData : decoder.getBodyHttpDatas()) {
if (bodyHttpData.refCnt() > 0) {
handleHttpData(((HttpData) bodyHttpData));
}
}
decoder.destroy();
decoder = null;
sendResponse(ctx, request);
} else {
InterfaceHttpData next = null;
while ((next = decoder.next()) != null) {
try {
handleHttpData(((HttpData) next));
} finally {
next.release();
decoder.removeHttpDataFromClean(next);
}
}
}
} else {
System.out.println("never reach here");
ctx.fireChannelRead(httpObject);
}
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
System.out.println("异常了...");
cause.printStackTrace();
ctx.close();
}
private void sendResponse(ChannelHandlerContext ctx, HttpRequest request) {
DefaultFullHttpResponse response = new DefaultFullHttpResponse(
HttpVersion.HTTP_1_1,
HttpResponseStatus.OK,
Unpooled.wrappedBuffer("请求处理完成".getBytes(CharsetUtil.UTF_8))
);
response.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/plain; charset=UTF-8");
response.headers().set(HttpHeaderNames.CONTENT_LENGTH, response.content().readableBytes());
ChannelFuture channelFuture = ctx.writeAndFlush(response);
// 客户端让我关, 我才关
if (request.headers().contains(HttpHeaderNames.CONNECTION, HttpHeaderValues.CLOSE, true)) {
System.out.println("添加关闭");
channelFuture.addListener(future -> {
ctx.channel().close();
});
}
}
private void handleHttpData(HttpData httpData) {
if (httpData instanceof Attribute) {
Attribute attribute = (Attribute) httpData;
System.out.println("received attribute: " + attribute);
} else if (httpData instanceof FileUpload) {
FileUpload fileUpload = (FileUpload) httpData;
System.out.println("received fileUpload: " + fileUpload);
String filename = fileUpload.getFilename();
String userDir = System.getProperty("user.dir");
File file = new File(userDir + File.separator + "file" + File.separator + filename);
if (file.exists() && file.isFile()) {
file.delete();
}
try {
fileUpload.renameTo(file);
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
HttpClient
java
复制代码
public class HttpClient {
public static void main(String[] args) {
EventLoopGroup group = new NioEventLoopGroup(1);
try {
Bootstrap bootstrap = new Bootstrap()
.group(group)
.channel(NioSocketChannel.class)
.handler(new ChannelInitializer<NioSocketChannel>() {
@Override
protected void initChannel(NioSocketChannel ch) throws Exception {
ch.pipeline().addLast(new HttpResponseDecoder());
ch.pipeline().addLast(new HttpRequestEncoder());
ch.pipeline().addLast(new ChunkedWriteHandler());
ch.pipeline().addLast(new HttpClientHandler());
}
});
ChannelFuture connectFuture = bootstrap.connect("127.0.0.1", 8080);
Channel channel = connectFuture.sync().channel();
System.out.println("---客户端连接http服务成功---");
// 发送单个请求
// sendSingleRequest(channel);
// 发送多次请求
// sendManyRequests(channel);
// 发送文件上传请求
sendPostData(channel);
channel.closeFuture().sync();
} catch (Exception e) {
System.out.println("---客户端发生错误---");
e.printStackTrace();
} finally {
group.shutdownGracefully();
}
}
private static void sendPostData(Channel channel) throws HttpPostRequestEncoder.ErrorDataEncoderException {
DefaultHttpRequest request = new DefaultHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, "/testEncoder");
HttpPostRequestEncoder encoder = new HttpPostRequestEncoder(request, true);
encoder.addBodyAttribute("name", "zzhua");
encoder.addBodyAttribute("age", "18");
encoder.addBodyFileUpload("mfile", new File("D:\\Projects\\practice\\demo-netty\\logs\\app.log"), null, false);
HttpRequest httpRequest = encoder.finalizeRequest();
channel.writeAndFlush(httpRequest);
if (encoder.isChunked()) {
channel.writeAndFlush(encoder);
}
}
private static void sendManyRequests(Channel channel) {
System.out.println("发第1个请求");
sendSimplePost(channel);
// try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {}
System.out.println("发第2个请求");
sendSimplePost(channel, true);
}
private static void sendSingleRequest(Channel channel, boolean... needClose) {
System.out.println("发1个请求");
sendSimplePost(channel, needClose);
}
private static ChannelFuture sendSimplePost(Channel channel, boolean... needClose) {
DefaultFullHttpRequest request = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.POST, "/test");
if (needClose != null && needClose.length > 0 && needClose[0]) {
request.headers().set(HttpHeaderNames.CONNECTION, HttpHeaderValues.CLOSE);
}
return channel.writeAndFlush(request);
}
}
HttpClientHandler
java
复制代码
public class HttpClientHandler extends SimpleChannelInboundHandler<HttpObject> {
@Override
protected void channelRead0(ChannelHandlerContext ctx, HttpObject msg) throws Exception {
System.out.println("[客户端received]: " + msg);
if (msg instanceof HttpResponse) {
HttpResponse response = (HttpResponse) msg;
System.out.println("响应状态码: " + response.status());
System.out.println("响应头: " + response.headers());
} else if (msg instanceof HttpContent) {
HttpContent httpContent = (HttpContent) msg;
System.out.println("响应内容: " + httpContent.content().toString(CharsetUtil.UTF_8));
if (httpContent instanceof LastHttpContent) {
System.out.println("响应结束");
}
}
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
System.out.println("客户端异常");
cause.printStackTrace();
}
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
System.out.println("客户端inactive");
}
}
SimpleHttpClient
java
复制代码
public class SimpleHttpClient {
private final EventLoopGroup workerGroup;
private final Bootstrap bootstrap;
public SimpleHttpClient() {
workerGroup = new NioEventLoopGroup();
bootstrap = new Bootstrap();
bootstrap.group(workerGroup)
.channel(NioSocketChannel.class)
.option(ChannelOption.SO_KEEPALIVE, true)
.handler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) {
ch.pipeline().addLast(new HttpClientCodec());
ch.pipeline().addLast(new HttpObjectAggregator(65536));
}
});
}
/**
* 发送HTTP请求
* @param url 请求URL
* @param method 请求方法
* @param body 请求体内容
* @param timeout 超时时间(秒)
* @return 响应内容
*/
public CompletableFuture<String> sendRequest(String url, HttpMethod method,
String body, int timeout) {
CompletableFuture<String> future = new CompletableFuture<>();
try {
URI uri = new URI(url);
String host = uri.getHost();
int port = uri.getPort() != -1 ? uri.getPort() :
(uri.getScheme().equals("https") ? 443 : 80);
String path = uri.getRawPath() + (uri.getRawQuery() != null ? "?" + uri.getRawQuery() : "");
// 创建HTTP请求
FullHttpRequest request;
if (body != null && !body.isEmpty()) {
request = new DefaultFullHttpRequest(
HttpVersion.HTTP_1_1,
method,
path,
Unpooled.copiedBuffer(body, CharsetUtil.UTF_8)
);
request.headers().set(HttpHeaderNames.CONTENT_LENGTH, body.length());
} else {
request = new DefaultFullHttpRequest(
HttpVersion.HTTP_1_1,
method,
path
);
}
// 设置请求头
request.headers()
.set(HttpHeaderNames.HOST, host)
.set(HttpHeaderNames.CONNECTION, HttpHeaderValues.CLOSE)
.set(HttpHeaderNames.ACCEPT_ENCODING, HttpHeaderValues.GZIP)
.set(HttpHeaderNames.USER_AGENT, "SimpleNettyClient/1.0");
if (body != null && !body.isEmpty()) {
request.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/plain; charset=UTF-8");
}
// 连接服务器
ChannelFuture channelFuture = bootstrap.connect(host, port);
channelFuture.addListener((ChannelFutureListener) f -> {
if (f.isSuccess()) {
Channel channel = f.channel();
// 添加响应处理器
channel.pipeline().addLast(new SimpleChannelInboundHandler<FullHttpResponse>() {
@Override
protected void channelRead0(ChannelHandlerContext ctx, FullHttpResponse response) {
try {
String content = response.content().toString(CharsetUtil.UTF_8);
future.complete("Status: " + response.status() +
"\nHeaders: " + response.headers() +
"\nBody: " + content);
} finally {
ctx.close();
}
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
future.completeExceptionally(cause);
ctx.close();
}
});
// 发送请求
channel.writeAndFlush(request);
} else {
future.completeExceptionally(f.cause());
}
});
} catch (URISyntaxException e) {
future.completeExceptionally(e);
}
// 设置超时
workerGroup.schedule(() -> {
if (!future.isDone()) {
future.completeExceptionally(new RuntimeException("Request timeout"));
}
}, timeout, TimeUnit.SECONDS);
return future;
}
/**
* 发送GET请求(简化方法)
*/
public CompletableFuture<String> get(String url) {
return sendRequest(url, HttpMethod.GET, null, 10);
}
/**
* 发送POST请求(简化方法)
*/
public CompletableFuture<String> post(String url, String body) {
return sendRequest(url, HttpMethod.POST, body, 10);
}
/**
* 关闭客户端
*/
public void shutdown() {
workerGroup.shutdownGracefully();
}
public static void main(String[] args) throws Exception {
SimpleHttpClient client = new SimpleHttpClient();
try {
// 示例1:发送GET请求
System.out.println("=== Sending GET request ===");
String getResponse = client.get("http://127.0.0.1:8080/abc").get(15, TimeUnit.SECONDS);
System.out.println(getResponse);
Thread.sleep(1000); // 等待一下
// 示例2:发送POST请求
System.out.println("\n=== Sending POST request ===");
String postResponse = client.post("http://127.0.0.1:8080/abc",
"Hello from Netty!").get(15, TimeUnit.SECONDS);
System.out.println(postResponse);
} finally {
client.shutdown();
}
}
}