服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - Java教程 - 关于Netty--Http请求处理方式

关于Netty--Http请求处理方式

2023-02-15 14:50BtWangZhi Java教程

这篇文章主要介绍了关于Netty--Http请求处理方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

Netty--Http请求处理

1.这几天在看Netty权威指南,代码敲了一下,就当做个笔记吧。

?
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
30
31
32
33
34
35
36
37
38
39
/**
 * Http服务端
 * @author Tang
 * 2018年5月13日
 */
public class HttpServer {
    public void run(String url,Integer port) {
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        ServerBootstrap bootstrap = new ServerBootstrap();
        bootstrap.group(bossGroup, workerGroup);
        bootstrap.channel(NioServerSocketChannel.class);
        bootstrap.childHandler(new ChannelInitializer<Channel>() {
            @Override
            protected void initChannel(Channel ch) throws Exception {
                ch.pipeline().addLast("http-decoder", new HttpRequestDecoder());
                ch.pipeline().addLast("http-aggregator",
                        new HttpObjectAggregator(65536));
                ch.pipeline()
                        .addLast("http-encoder", new HttpResponseEncoder());
                ch.pipeline()
                        .addLast("http-chunked", new ChunkedWriteHandler());
                ch.pipeline().addLast("http-handler", new HttpServerHandler());
            }
        });
        try {
            ChannelFuture channelFuture = bootstrap.bind(url, port).sync();
            channelFuture.channel().closeFuture().sync();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }
    public static void main(String[] args) {
        new HttpServer().run("127.0.0.1",8001);
    }
}

业务处理逻辑

?
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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
public class HttpServerHandler extends
        SimpleChannelInboundHandler<FullHttpRequest> {
    @Override
    protected void messageReceived(ChannelHandlerContext ctx,
            FullHttpRequest fullHttpRequest) throws Exception {
        // 构造返回数据
        JSONObject jsonRootObj = new JSONObject();
        JSONObject jsonUserInfo = new JSONObject();
        jsonUserInfo.put("id", 1);
        jsonUserInfo.put("name", "张三");
        jsonUserInfo.put("password", "123");
        jsonRootObj.put("userInfo", jsonUserInfo);
        // 获取传递的数据
        Map<String, Object> params = getParamsFromChannel(ctx, fullHttpRequest);
        jsonRootObj.put("params", params);
        FullHttpResponse response = new DefaultFullHttpResponse(HTTP_1_1, OK);
        response.headers().set(CONTENT_TYPE, "application/json; charset=UTF-8");
        StringBuilder bufRespose = new StringBuilder();
        bufRespose.append(jsonRootObj.toJSONString());
        ByteBuf buffer = Unpooled.copiedBuffer(bufRespose, CharsetUtil.UTF_8);
        response.content().writeBytes(buffer);
        buffer.release();
        ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE);
    }
    /**
     * 获取传递的参数
     *
     * @param ctx
     * @param fullHttpRequest
     * @return
     * @throws UnsupportedEncodingException
     */
    private static Map<String, Object> getParamsFromChannel(
            ChannelHandlerContext ctx, FullHttpRequest fullHttpRequest)
            throws UnsupportedEncodingException {
        HttpHeaders headers = fullHttpRequest.headers();
        String strContentType = headers.get("Content-Type").trim();
        System.out.println("ContentType:" + strContentType);
        Map<String, Object> mapReturnData = new HashMap<String, Object>();
        if (fullHttpRequest.getMethod() == HttpMethod.GET) {
            // 处理get请求
            QueryStringDecoder decoder = new QueryStringDecoder(
                    fullHttpRequest.getUri());
            Map<String, List<String>> parame = decoder.parameters();
            for (Entry<String, List<String>> entry : parame.entrySet()) {
                mapReturnData.put(entry.getKey(), entry.getValue().get(0));
            }
            System.out.println("GET方式:" + parame.toString());
        } else if (fullHttpRequest.getMethod() == HttpMethod.POST) {
            // 处理POST请求
            if (strContentType.contains("x-www-form-urlencoded")) {
                HttpPostRequestDecoder decoder = new HttpPostRequestDecoder(
                        new DefaultHttpDataFactory(false), fullHttpRequest);
                List<InterfaceHttpData> postData = decoder.getBodyHttpDatas();
                for (InterfaceHttpData data : postData) {
                    if (data.getHttpDataType() == HttpDataType.Attribute) {
                        MemoryAttribute attribute = (MemoryAttribute) data;
                        mapReturnData.put(attribute.getName(),
                                attribute.getValue());
                    }
                }
            } else if (strContentType.contains("application/json")) {
                // 解析json数据
                ByteBuf content = fullHttpRequest.content();
                byte[] reqContent = new byte[content.readableBytes()];
                content.readBytes(reqContent);
                String strContent = new String(reqContent, "UTF-8");
                System.out.println("接收到的消息" + strContent);
                JSONObject jsonParamRoot = JSONObject.parseObject(strContent);
                for (String key : jsonParamRoot.keySet()) {
                    mapReturnData.put(key, jsonParamRoot.get(key));
                }
            } else {
                FullHttpResponse response = new DefaultFullHttpResponse(
                        HTTP_1_1, HttpResponseStatus.INTERNAL_SERVER_ERROR);
                ctx.writeAndFlush(response).addListener(
                        ChannelFutureListener.CLOSE);
            }
            System.out.println("POST方式:" + mapReturnData.toString());
        }
        return mapReturnData;
    }
}

支持Get和PostContentType为application/json、x-www-form-urlencoded的处理。

用Postman亲测无问题。

Netty处理简单Http请求的例子

废话不多说 上代码

HttpHelloWorldServerInitializer.java

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import io.netty.channel.ChannelInitializer;
  import io.netty.channel.ChannelPipeline;
  import io.netty.channel.socket.SocketChannel;
  import io.netty.handler.codec.http.HttpServerCodec;
  import io.netty.handler.ssl.SslContext;
  public class HttpHelloWorldServerInitializer extends ChannelInitializer<SocketChannel> {
      private final SslContext sslCtx;
      public HttpHelloWorldServerInitializer(SslContext sslCtx) {
         this.sslCtx = sslCtx;
      }
      @Override
      public void initChannel(SocketChannel ch) {
          ChannelPipeline p = ch.pipeline();
          if (sslCtx != null) {
              p.addLast(sslCtx.newHandler(ch.alloc()));
          }
          p.addLast(new HttpServerCodec());
          p.addLast(new HttpHelloWorldServerHandler());
      }
  }

HttpHelloWorldServerHandler.java

?
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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerAdapter;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.http.DefaultFullHttpResponse;
import io.netty.handler.codec.http.FullHttpResponse;
import io.netty.handler.codec.http.HttpHeaderUtil;
import io.netty.handler.codec.http.HttpHeaderValues;
import io.netty.handler.codec.http.HttpRequest;
import static io.netty.handler.codec.http.HttpHeaderNames.*;
import static io.netty.handler.codec.http.HttpResponseStatus.*;
import static io.netty.handler.codec.http.HttpVersion.*;
  public class HttpHelloWorldServerHandler extends ChannelHandlerAdapter {
      private static final byte[] CONTENT = { 'H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd' };
      @Override
      public void channelReadComplete(ChannelHandlerContext ctx) {
          ctx.flush();
      }
      @Override
      public void channelRead(ChannelHandlerContext ctx, Object msg) {
          if (msg instanceof HttpRequest) {
              HttpRequest req = (HttpRequest) msg;
              if (HttpHeaderUtil.is100ContinueExpected(req)) {
                  ctx.write(new DefaultFullHttpResponse(HTTP_1_1, CONTINUE));
              }
              boolean keepAlive = HttpHeaderUtil.isKeepAlive(req);
              FullHttpResponse response = new DefaultFullHttpResponse(HTTP_1_1, OK, Unpooled.wrappedBuffer(CONTENT));
              response.headers().set(CONTENT_TYPE, "text/plain");
              response.headers().setInt(CONTENT_LENGTH, response.content().readableBytes());
              if (!keepAlive) {
                  ctx.write(response).addListener(ChannelFutureListener.CLOSE);
              } else {
                  response.headers().set(CONNECTION, HttpHeaderValues.KEEP_ALIVE);
                  ctx.write(response);
              }
          }
      }
      @Override
      public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
          cause.printStackTrace();
          ctx.close();
      }
  }

HttpHelloWorldServer.java

?
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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.handler.ssl.SslContext;
import io.netty.handler.ssl.util.SelfSignedCertificate;
/**
 * An HTTP server that sends back the content of the received HTTP request
 * in a pretty plaintext form.
 */
public final class HttpHelloWorldServer {
      static final boolean SSL = System.getProperty("ssl") != null;
      static final int PORT = Integer.parseInt(System.getProperty("port", SSL? "8443" : "8080"));
      public static void main(String[] args) throws Exception {
          // Configure SSL.
          final SslContext sslCtx;
          if (SSL) {
              SelfSignedCertificate ssc = new SelfSignedCertificate();
              sslCtx = SslContext.newServerContext(ssc.certificate(), ssc.privateKey());
          } else {
              sslCtx = null;
          }
          // Configure the server.
          EventLoopGroup bossGroup = new NioEventLoopGroup(1);
          EventLoopGroup workerGroup = new NioEventLoopGroup();
          try {
              ServerBootstrap b = new ServerBootstrap();
              b.option(ChannelOption.SO_BACKLOG, 1024);
              b.group(bossGroup, workerGroup)
               .channel(NioServerSocketChannel.class)
               .handler(new LoggingHandler(LogLevel.INFO))
               .childHandler(new HttpHelloWorldServerInitializer(sslCtx));
              Channel ch = b.bind(PORT).sync().channel();
              System.err.println("Open your web browser and navigate to " +
                      (SSL? "https" : "http") + "://127.0.0.1:" + PORT + '/');
              ch.closeFuture().sync();
          } finally {
              bossGroup.shutdownGracefully();
              workerGroup.shutdownGracefully();
          }
      }
}

以上为个人经验,希望能给大家一个参考,也希望大家多多支持服务器之家。

原文链接:https://blog.csdn.net/BtWangZhi/article/details/80303577

延伸 · 阅读

精彩推荐
  • Java教程spring MVC搭建及配置详解

    spring MVC搭建及配置详解

    本篇文章主要介绍了spring MVC配置方法,要想灵活运用Spring MVC来应对大多数的Web开发,就必须要掌握它的配置及原理,有兴趣的可以了解一下。...

    牧涛3352020-07-23
  • Java教程Java线程在什么情况下可以终止

    Java线程在什么情况下可以终止

    Thread线程类自带的stop方法,但是jdk不建议使用,因为stop方法终止线程只是强行终止,内存中部分值可能已发生变化,并未保证数据的一致性,将会导致线...

    淡沫初夏Zz11482022-11-23
  • Java教程SpringBoot2.0实现多图片上传加回显

    SpringBoot2.0实现多图片上传加回显

    这两天公司有需求让做一个商户注册的后台功能,其中需要商户上传多张图片并回显,本文就使用SpringBoot2.0实现,具有一定的参考价值,感兴趣的可以了解...

    不学无数的程序员5302021-10-26
  • Java教程Java中return和finally到底哪个先执行

    Java中return和finally到底哪个先执行

    本章节我们从字节码的角度来探究下return和finally到底哪个先执行。下面先来看一段简单地源码。...

    今日头条5502020-10-28
  • Java教程java抛出异常的几种情况小结

    java抛出异常的几种情况小结

    这篇文章主要介绍了java抛出异常的几种情况小结,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教...

    微微一笑满城空7402022-01-25
  • Java教程解析Mybatis判断表达式源码分析

    解析Mybatis判断表达式源码分析

    这篇文章主要介绍了Mybatis判断表达式源码分析,本文通过实例代码给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下...

    Enjoyjava4482021-06-04
  • Java教程Java Fluent Mybatis实战之构建项目与代码生成篇上

    Java Fluent Mybatis实战之构建项目与代码生成篇上

    Java中常用的ORM框架主要是mybatis, hibernate, JPA等框架。国内又以Mybatis用的多,基于mybatis上的增强框架,又有mybatis plus和TK mybatis等。今天我们介绍一个新的...

    剑客阿良_ALiang10942022-03-03
  • Java教程如何基于js及java分析并封装排序算法

    如何基于js及java分析并封装排序算法

    这篇文章主要介绍了如何基于js及java分析并封装排序算法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友...

    Tom最好的朋友是Jerry2072020-07-23