Netty实现HTTP服务器(含:请求处理控制器)

Netty实现HTTP服务器(含:请求处理控制器)

本文将使用Netty框架实现HTTP服务器,然后进行请求处理。

创建Http Server

public class HttpServer {
    /**
     * 服务开始
     */
    public static void start() {
        ServerBootstrap bootstrap = new ServerBootstrap();
        EventLoopGroup boss = new NioEventLoopGroup();
        EventLoopGroup work = new NioEventLoopGroup();
        bootstrap.group(boss, work)
                .handler(new LoggingHandler(LogLevel.DEBUG))
                .channel(NioServerSocketChannel.class)
                .childHandler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    protected void initChannel(SocketChannel channel) throws Exception {
                        ChannelPipeline pipeline = channel.pipeline();
                        pipeline.addLast(new HttpServerCodec());// http 编解码
                        pipeline.addLast("httpAggregator", new HttpObjectAggregator(100 * 1024 * 1024)); // http 消息聚合器                                                                     512*1024为接收的最大contentlength
                        pipeline.addLast(new HttpServerExpectContinueHandler());
                        pipeline.addLast(new HttpServerHandler());
                    }
                }).childOption(ChannelOption.SO_KEEPALIVE, true);
        //获取配置文件的端口        
        String port = PropertiesUtil.readByKey("http.port");
        try {
            //绑定端口,同步等待成功
            ChannelFuture future = bootstrap.bind(Integer.valueOf(port)).sync();
            StaticLog.info("http server start up on port : " + port);
            //关闭监听端口,同步等待
            future.channel().closeFuture().sync();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            // 退出
            boss.shutdownGracefully();
            work.shutdownGracefully();
        }
    }
}

创建Http Server Handler

这里的示例支持POST请求的API,form-data格式参数和body格式(JSON对象字符串)参数;

支持一次响应(写入一次response)和请求多次响应(多次写入response流);

设计思路:

参数中必传属性:sign, 对应springboot框架的controller handler。这个字段对应HttpRequestHandler的方法名。
可选属性:responseType,如果需要多次响应需要传递,需要自己关闭连接(channel)。
请求处理方法名格式:
XXXXXX String sign(JSONObject obj);
XXXXXX String sign(HashMap<String, Object> map);

public class HttpServerHandler extends SimpleChannelInboundHandler<FullHttpRequest> {
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, FullHttpRequest request) throws InterruptedException {
        String url = request.uri();
        if (url.endsWith("/api")){  //接口相关
            apiHandler(ctx, request);
        } else if (url.endsWith("/ping")) { //ping
            responseOK(ctx, "OK");
        } else {
            responseError(ctx, "url error");
        }
    }

    private void apiHandler(ChannelHandlerContext ctx, FullHttpRequest request){
		// 获取通道
        Channel channel = ctx.channel(); 
        //请求内容
        String body = request.content().toString(CharsetUtil.UTF_8);
        //请求Type
        String method = request.method().name();
        //---------
        //记录接口日志....省略
        //---------
        try {
        	//判断请求Type 这里仅仅支持POST请求
            if (!"POST".equals(method.toUpperCase())) {
                String msgData = "unsupported request type: " + method;
                responseError(ctx, msgData);
                return;
            }
            //调用方法
            String methodSign = "";
            Object content = null; //调用方法参数内容
            Class  clazz = null; //参数类型
            String responseType; //响应类型
            
            if (JSONUtil.isJsonObj(body)) {
                JSONObject bodyJson = JSONUtil.parseObj(body);
                methodSign = bodyJson.getStr("sign");
                responseType = bodyJson.getStr("responseType");
                content = bodyJson;
                clazz = JSONObject.class;
            } else {
                //不是json 数据--另外解析
                HashMap<String,Object> map = getRequestParameters(request);
                methodSign = String.valueOf(map.get("sign"));
                responseType = String.valueOf(map.get("responseType"));
                content = map;
                clazz = HashMap.class;
            }
            try {
                if (responseType != null && responseType.equals("custom")) {
                    //自定义响应用于特殊情况,需要自己关闭channel,需要自己保存日志
                    Method methodFunc = HttpRequestHandler.class.getDeclaredMethod(methodSign, clazz, ChannelHandlerContext.class, SysOperLog.class);
                    methodFunc.setAccessible(true);
                    methodFunc.invoke(HttpRequestHandler.getInstance(), content, ctx, sysOperLog);
                    return;
                } else {
                    Method methodFunc = HttpRequestHandler.class.getDeclaredMethod(methodSign, clazz);
                    methodFunc.setAccessible(true);
                    String invokeResult = (String) methodFunc.invoke(HttpRequestHandler.getInstance(),content);
                    responseOK(ctx, invokeResult);
                }

            } catch (NoSuchMethodException e) {
                Static.info(String.format("sign 参数错误, %s 不属于可选值", methodSign))
            }
        } catch (Exception e){
            String msg = "";
            if (e instanceof InvocationTargetException) {
                msg = ((InvocationTargetException)e).getTargetException().getMessage();
            } else {
                msg = e.getMessage();
            }
            responseError(ctx, Optional.ofNullable(msg).orElse("handler deal failed!"))
        }
    }

    private HashMap<String, Object> getRequestParameters(FullHttpRequest request) throws IOException {
        HashMap<String,Object> map = new HashMap<>();

        HttpDataFactory factory = new DefaultHttpDataFactory(DefaultHttpDataFactory.MINSIZE);
        HttpPostRequestDecoder decoder = new HttpPostRequestDecoder(factory, request);
        List<InterfaceHttpData> dataList = decoder.getBodyHttpDatas();
        for (InterfaceHttpData data : dataList) {
            if (data.getHttpDataType() == InterfaceHttpData.HttpDataType.FileUpload) {
                MixedFileUpload fileUpload = (MixedFileUpload) data;
                map.put(fileUpload.getName(),fileUpload.getFile());
            } else if (data.getHttpDataType() == InterfaceHttpData.HttpDataType.Attribute) {
                MixedAttribute attribute = (MixedAttribute) data;
                map.put(data.getName(),attribute.getString(Charset.forName("utf-8")));
            }
        }
        return map;

    }
   /**
     * 返回处理结果
     * @param apiResult 数据
     * @return 返回数据
     */
    private ApiResult response(ChannelHandlerContext ctx, ApiResult apiResult){
        FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK, Unpooled.wrappedBuffer(apiResult.toJSONStr().getBytes()));
        response.headers().set("Content-Type", "application/json; charset=UTF-8");
        ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE);
        return apiResult;
    }
    private ApiResult responseOK(ChannelHandlerContext ctx, String data) {
        return response(ctx, ApiResult.OK(data));
    }
    private ApiResult responseError(ChannelHandlerContext ctx, String data) {
        return response(ctx, ApiResult.ERROR(data));
    }
}

创建HttpRequestHandler

用于request请求的处理器

public class HttpRequestHandler {
    private static class SingletonHolder {
        private static HttpRequestHandler instance = new HttpRequestHandler();
    }
    public static HttpRequestHandler getInstance() {
        return SingletonHolder.instance;
    }

    private HttpRequestHandler() {
    }
    //其他处理方法
    private String test(JSONObject obj){ return "OK"};
    private String test2(HashMap<String,Object> obj){ return "OK"};
}

以上就是Netty 创建HTTP服务器以及处理Http请求以及响应的主要代码实现,可供参考;

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
是的,Netty可以创建HTTP请求服务器Netty是一个网络编程框架,可以处理各种协议,包括HTTP协议。使用Netty创建HTTP服务器非常简单,你只需要编写一个HTTP请求处理器并将其注册到Netty服务器的ChannelPipeline中即可。 下面是一个使用Netty创建HTTP服务器的简单示例: ```java public class HttpServer { public static void main(String[] args) throws Exception { EventLoopGroup bossGroup = new NioEventLoopGroup(1); EventLoopGroup workerGroup = new NioEventLoopGroup(); try { ServerBootstrap b = new ServerBootstrap(); b.group(bossGroup, workerGroup) .channel(NioServerSocketChannel.class) .childHandler(new ChannelInitializer<SocketChannel>() { @Override public void initChannel(SocketChannel ch) throws Exception { ChannelPipeline p = ch.pipeline(); p.addLast(new HttpServerCodec()); p.addLast(new HttpObjectAggregator(65536)); p.addLast(new HttpHandler()); } }) .option(ChannelOption.SO_BACKLOG, 128) .childOption(ChannelOption.SO_KEEPALIVE, true); ChannelFuture f = b.bind(8080).sync(); f.channel().closeFuture().sync(); } finally { workerGroup.shutdownGracefully(); bossGroup.shutdownGracefully(); } } private static class HttpHandler extends SimpleChannelInboundHandler<FullHttpRequest> { @Override protected void channelRead0(ChannelHandlerContext ctx, FullHttpRequest msg) throws Exception { // 处理HTTP请求 String content = "Hello, World!"; FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK, Unpooled.wrappedBuffer(content.getBytes())); response.headers().set(HttpHeaders.Names.CONTENT_TYPE, "text/plain"); response.headers().set(HttpHeaders.Names.CONTENT_LENGTH, response.content().readableBytes()); response.headers().set(HttpHeaders.Names.CONNECTION, HttpHeaders.Values.KEEP_ALIVE); ctx.write(response); ctx.flush(); } } } ``` 在上面的示例中,我们创建了一个HTTP服务器,并将其绑定到8080端口。当有HTTP请求到达时,Netty会将其转发给我们编写的HttpHandler处理器进行处理HttpHandler处理器会返回一个"Hello, World!"的响应。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

雨中漫步t2

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值