netty实现http协议服务

前面了解了netty的启动流程,实现http协议服务在pipeline里添加对应的http协议报文处理器即可。

server端:

EventLoopGroup bossGroup = new NioEventLoopGroup(1);
EventLoopGroup workGroup = new NioEventLoopGroup(4);

ServerBootstrap bootstrap = new ServerBootstrap().group(bossGroup,workGroup)
        .channel(NioServerSocketChannel.class)
        .option(ChannelOption.SO_BACKLOG, 1024)
        .childHandler(new ChannelInitializer<SocketChannel>() {
            @Override
            protected void initChannel(SocketChannel ch) throws Exception {
                ChannelPipeline p = ch.pipeline();
                p.addLast(new HttpServerCodec());
                p.addLast(new HttpObjectAggregator(65536));
                p.addLast(new CustomHttpServerHandler());
            }
        });
bootstrap.bind(8080).sync();

这里添加了三个编解码处理handler。HttpServerCodec这个是http协议格式处理器,其相当于HttpRequestDecoder和HttpResponseEncoder一对编解码处理器。HttpObjectAggregator是用来报文数据聚合,合并请求数据成一个报文。CustomHttpServerHandler这个是我们自定义的报文处理器,

public class CustomHttpServerHandler extends SimpleChannelInboundHandler<FullHttpRequest> {

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, FullHttpRequest msg) throws Exception {
        String content = "Hello";
        FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK,
                Unpooled.wrappedBuffer(content.getBytes()));
        response.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/plain");
        response.headers().set(HttpHeaderNames.CONTENT_LENGTH, response.content().readableBytes());
        ctx.writeAndFlush(response);
    }
}

这里收到消息经过前面两个handler处理后类型是FullHttpRequest,在channelRead0方法里构造了一个简单的FullHttpResponse对象,返回数据给客户端。

这样访问http://localhost:8080就会看到服务端返回的hello。

上面例子只是做了一个简单的请求响应。没有对请求数据进行解析,也没有根据资源uri进行转发不同处理。

请求地址可以从入参FullHttpRequest msg中获取

HttpMethod method = msg.method();
System.out.println("接收请求:"+msg.uri()+"请求方法:"+msg.method().name());

这里uri的dispatch就不处理了,主要是了解报文数据处理。下面来看不同报文格式数据如何处理。同样的这里也只考虑POST请求。

我们平时web开发知道,POST传送数据有好几种方式,其报文数据格式是不一样的。不同数据格式可以从请求报文头的Content-type获取。

1、form表单形式(application/x-www-form-urlencoded)

这种方式参数还是key=value&key=value形式放到请求body中传过来的,可以使用HttpPostRequestDecoder来进行解析.

            HttpPostRequestDecoder decoder = new HttpPostRequestDecoder(new DefaultHttpDataFactory(false), msg);
            List<InterfaceHttpData> postData = decoder.getBodyHttpDatas();

            for (InterfaceHttpData data : postData) {
                if (data.getHttpDataType() == InterfaceHttpData.HttpDataType.Attribute) {
                    // 处理表单字段
                    Attribute attribute = (Attribute) data;
                    String fieldName = attribute.getName();
                    String fieldValue = null;
                    try {
                        fieldValue = attribute.getValue();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    System.out.println(fieldName + ": " + fieldValue);
                }
            }

2、包含文件(multipart/form-data)

这种方式有一个boundary来区分不同的表单项。可以用HttpPostMultipartRequestDecoder来解析

HttpPostMultipartRequestDecoder decoder = new HttpPostMultipartRequestDecoder(new DefaultHttpDataFactory(false), msg);
List<InterfaceHttpData> postData = decoder.getBodyHttpDatas();

for (InterfaceHttpData data : postData) {
    if (data.getHttpDataType() == InterfaceHttpData.HttpDataType.Attribute) {
        // 处理表单字段
        Attribute attribute = (Attribute) data;
        String fieldName = attribute.getName();
        String fieldValue = null;
        try {
            fieldValue = attribute.getValue();
        } catch (IOException e) {
            e.printStackTrace();
        }
        System.out.println(fieldName + ": " + fieldValue);
    } else if (data.getHttpDataType() == InterfaceHttpData.HttpDataType.FileUpload) {
        // 处理文件上传字段
        FileUpload fileUpload = (FileUpload) data;
        String fieldName = fileUpload.getName();
        String fileName = fileUpload.getFilename();
        String fileType = fileUpload.getContentType();
        long fileSize = fileUpload.length();
        System.out.println("文件上传属性: " + fieldName + ", 文件名: " + fileName + ", 文件类型: " + fileType + ", 文件大小: " + fileSize + " bytes");
    }
}

这里要注意文件的大小,还记得最开始添加的报文聚合handler:HttpObjectAggregator,如果超过了这个指定的大小会直接返回414错误。

另外像其它如json、xml这种格式,直接获取报文体进行处理即可,不需要特殊的处理

ByteBuf content = msg.content();
String requestBody = content.toString(StandardCharsets.UTF_8);
System.out.println("请求内容:"+requestBody);

请求报文处理完了之后还是最后要构建一个FullHttpResponse对象将响应数据返回给客户端。这里整个处理下来搭建一个完整的http服务还是有许多东西要考虑的,不如直接使用现有的web容器,这里仅仅是为了演示,也为下一篇说websocket做准备。

  • 9
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Netty是一个基于Java的网络编程框架,它提供了一种简单且高性能的方式来实现WebSocket协议。 要使用Netty实现WebSocket,可以按照以下步骤进行操作: 1. 创建一个新的Netty项目,并添加Netty的依赖。 2. 创建一个WebSocket服务器类,该类需要继承自`io.netty.channel.SimpleChannelInboundHandler`。 3. 在服务器类中,重写`channelRead0`方法,处理接收到的WebSocket消息。 4. 在服务器类中,重写`channelActive`和`channelInactive`方法,处理WebSocket连接的打开和关闭事件。 5. 在服务器类中,重写`exceptionCaught`方法,处理异常情况。 6. 创建一个启动类,在其中创建并配置一个`io.netty.bootstrap.ServerBootstrap`实例。 7. 在启动类中,绑定服务器端口并启动服务器。 下面是一个简单的示例代码,演示了如何使用Netty实现WebSocket服务器: ```java import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelInitializer; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioServerSocketChannel; import io.netty.handler.codec.http.HttpObjectAggregator; import io.netty.handler.codec.http.HttpServerCodec; import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler; public class WebSocketServer { public static void main(String[] args) throws Exception { EventLoopGroup bossGroup = new NioEventLoopGroup(); EventLoopGroup workerGroup = new NioEventLoopGroup(); try { ServerBootstrap bootstrap = new ServerBootstrap(); bootstrap.group(bossGroup, workerGroup) .channel(NioServerSocketChannel.class) .childHandler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel ch) throws Exception { ch.pipeline().addLast(new HttpServerCodec()); ch.pipeline().addLast(new HttpObjectAggregator(65536)); ch.pipeline().addLast(new WebSocketServerProtocolHandler("/websocket")); ch.pipeline().addLast(new WebSocketServerHandler()); } }); ChannelFuture future = bootstrap.bind(8080).sync(); future.channel().closeFuture().sync(); } finally { bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); } } } ``` 在上面的代码中,`WebSocketServerHandler`是自定义的处理器,用于处理WebSocket消息。你可以根据自己的需求来实现该处理器。 请注意,这只是一个简单的示例,实际的WebSocket服务器可能需要更复杂的处理逻辑。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值