首页 > 其他分享 >netty实现http服务器

netty实现http服务器

时间:2023-07-21 10:13:42浏览次数:24  
标签:netty http java 服务器 io new import

pom.xml

 <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>io.netty</groupId>
            <artifactId>netty-all</artifactId>
            <version>4.1.94.Final</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba.fastjson2</groupId>
            <artifactId>fastjson2</artifactId>
            <version>2.0.35</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.8.16</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

HttpServer.java netty服务类

package com.example.springfileupload3.netty.http;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel;
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;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import lombok.extern.slf4j.Slf4j;

/**
 * httpServer
 *
 * @Description
 * @Author wzq
 **/
@Slf4j
public class HttpServer {

    static final int PORT = 8888;

    public void run() throws Exception {
        // Configure the server.
        EventLoopGroup bossGroup = new NioEventLoopGroup(1);
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        try {
            ServerBootstrap b = new ServerBootstrap();
            b.option(ChannelOption.SO_BACKLOG, 1024);
            b.childOption(ChannelOption.TCP_NODELAY, true);
            b.childOption(ChannelOption.SO_KEEPALIVE, true);
            b.group(bossGroup, workerGroup)
                    .channel(NioServerSocketChannel.class)
                    .handler(new LoggingHandler(LogLevel.INFO))
                    .childHandler(new HttpServerInitializer());

            ChannelFuture cf = b.bind(PORT).sync();
            cf.addListener(future -> {
                if (future.isSuccess()) {
                    log.info("netty服务器绑定端口成功:" + PORT);
                } else {
                    log.error("netty服务器绑定端口失败:" + PORT);
                }
            });
            log.info("netty启动完成!");
            //等待netty完成,会堵塞主线程
            //cf.channel().closeFuture().sync();
        } catch (Exception e){
            log.info("netty启动异常了!");
            e.printStackTrace();
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }
}

HttpServerInitializer.java netty初始化配置类

package com.example.springfileupload3.netty.http;

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;

/**
 * HttpServerInitializer
 *
 * @Description
 * @Author wzq
 **/
public class HttpServerInitializer extends ChannelInitializer<SocketChannel> {


    @Override
    protected void initChannel(SocketChannel ch) throws Exception {
        ChannelPipeline p = ch.pipeline();
        /**
         * 或者使用HttpRequestDecoder & HttpResponseEncoder
         */
        p.addLast(new HttpServerCodec());
        /**
         * 在处理Post消息时需要加上
         */
        p.addLast(new HttpObjectAggregator(1024*1024));
        p.addLast(new HttpServerExpectContinueHandler());
        p.addLast(new HttpServerHandler());
    }
}

HttpServerInitializer.java 处理类

package com.example.springfileupload3.netty.http;

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
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.internal.StringUtil;
import lombok.extern.slf4j.Slf4j;
import io.netty.util.AsciiString;

import java.nio.charset.CharsetEncoder;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * HttpServerHandler
 *
 * @Description
 * @Author wzq
 **/
@Slf4j
public class HttpServerHandler extends SimpleChannelInboundHandler<HttpObject> {

    private static final String FAVICON_ICO = "/favicon.ico";
    private HttpRequest request;
    private HttpHeaders headers;
    private FullHttpRequest fullRequest;


    @Override
    protected void channelRead0(ChannelHandlerContext ctx, HttpObject httpObject) throws Exception {
        User user = new User();
        user.setUserName("GoslingWu");
        user.setDate(new Date());

        if (httpObject instanceof HttpRequest) {
            request = (HttpRequest) httpObject;
            headers = request.headers();
            String uri = request.uri();
            log.info("http uri:" + uri);
            if (FAVICON_ICO.equals(uri)) {
                return;
            }
            HttpMethod method = request.method();
            if (method.equals(HttpMethod.GET)) {
                log.info("http method GET");
                QueryStringDecoder queryDecoder = new QueryStringDecoder(uri, StandardCharsets.UTF_8);
                Map<String, List<String>> uriParameters = queryDecoder.parameters();
                // 打印
                uriParameters.forEach((key, value) -> {
                    log.info("key:{} , value:{}", key, value);
                });
                user.setMethod("get");
            } else if (method.equals(HttpMethod.POST)) {
                log.info("http method POST");
                fullRequest = (FullHttpRequest) httpObject;
                //根据不同的Content_Type处理body数据
                dealWithContentType();
                user.setMethod("post");
            }
        }

        JSONSerializer jsonSerializer = new JSONSerializer();
        byte[] content = jsonSerializer.serialize(user);

        FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK, Unpooled.wrappedBuffer(content));
        response.headers().set("Content-Type", "text/plain");
        response.headers().setInt("Content-Length", response.content().readableBytes());


        boolean keepAlive = HttpUtil.isKeepAlive(request);
        if (!keepAlive) {
            ctx.write(response).addListener(ChannelFutureListener.CLOSE);
        } else {
            response.headers().set("Connection","keep-alive");
            ctx.write(response);
        }
    }


    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        log.info("exceptionCaught...");
        cause.printStackTrace();
        ctx.close();
    }

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        log.info("channelReadComplete...");
        ctx.flush();
    }

    /**
     * 解析ContentType
     *
     * @throws Exception
     */
    private void dealWithContentType() throws Exception {
        String contentType = getContentType();
        // 可以使用HttpJsonDecoder
        if ("application/json".equals(contentType)) {
            String jsonStr = fullRequest.content().toString(StandardCharsets.UTF_8);
            JSONObject jsonObject = JSON.parseObject(jsonStr);
            jsonObject.forEach((key, value) -> {
                log.info("key:{} , value:{}", key, value);
            });
        } else if ("application/x-www-form-urlencoded".equals(contentType)) {
            //方式一:使用 QueryStringDecoder
            String jsonStr = fullRequest.content().toString(StandardCharsets.UTF_8);
            QueryStringDecoder queryDecoder = new QueryStringDecoder(jsonStr, false);
            Map<String, List<String>> uriAttributes = queryDecoder.parameters();
            for (Map.Entry<String, List<String>> attr : uriAttributes.entrySet()) {
                for (String attrVal : attr.getValue()) {
                    log.info(attr.getKey() + "=" + attrVal);
                }
            }
        } else if ("multipart/form-data".equals(contentType)) {
            //TODO 用于文件上传
        } else {
            //do nothing...
        }

    }

    /**
     * 从请求头中获取 Content-Type
     *
     * @return
     */
    private String getContentType() {
        String typeStr = headers.get("Content-Type").toString();
        String[] list = typeStr.split(";");
        return list[0];
    }


}

序列化接口

package com.example.springfileupload3.netty.http;

/**
 * 序列化接口类
 *
 * @Description
 * @Author wzq
 **/
public interface Serializer {

    /**
     * java 对象转换成二进制
     * @param object
     * @return
     */
    byte[] serialize(Object object);

    /**
     * 二进制转换成 java 对象
     * @param clazz
     * @param bytes
     * @return
     * @param <T>
     */
    <T> T deserialize(Class<T> clazz, byte[] bytes);

}

JSONSerializer.java 序列化类

package com.example.springfileupload3.netty.http;

import com.alibaba.fastjson2.JSON;

import java.util.Date;

/**
 * JSON序列化
 *
 * @Description
 * @Author wzq
 **/
public class JSONSerializer implements Serializer {

    @Override
    public byte[] serialize(Object object) {
        return JSON.toJSONBytes(object);
    }

    @Override
    public <T> T deserialize(Class<T> clazz, byte[] bytes) {
        return JSON.parseObject(bytes, clazz);
    }

}

User.java response返回类

package com.example.springfileupload3.netty.http;

import lombok.Data;

import java.util.Date;

/**
 * User
 *
 * @Description
 * @Author wzq
 **/
@Data
public class User {

    private String userName;

    private String method;

    private Date date;

}

ProjectCommandLineRunner.java 项目启动时启动类

package com.example.springfileupload3.config;

import com.example.springfileupload3.netty.http.HttpServer;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.CommandLineRunner;
import org.springframework.context.annotation.Configuration;

/**
 * ProjectCommandLineRunner
 *
 * @Description
 * @Author wzq
 * @Date 2023/7/20 11:47
 **/
@Configuration
@Slf4j
public class ProjectCommandLineRunner implements CommandLineRunner {

    @Override
    public void run(String... args) throws Exception {
        log.info("ProjectCommandLineRunner run...");
        HttpServer httpServer = new HttpServer();
        httpServer.run();
    }

}

标签:netty,http,java,服务器,io,new,import
From: https://www.cnblogs.com/GoslingWu/p/17570504.html

相关文章

  • netty 分享
    讲解步骤Linux网络编程什么是Socket网络事件模型连接事件优化—多路复用epollI/OBIO/OIO:食堂排队打饭模式:排队在窗口,打好才走;NIO:点单、等待被叫模式:等待被叫,好了自己去端;AIO:包厢模式:点单后菜直接被端上桌。NIO核心组件Selector选择器Channel管道buffer缓冲区核心原......
  • HTTP | 服务器防盗链
    什么是防盗链防盗链其实就是采用服务器端编程,通过url过滤技术实现的防止盗链的软件。比如file.abc.com/test.rar这个下载地址,如果没有装防盗链,别人就能轻而易举的在他的网站上引用这个地址。如果对file.abc.com这个站的服务器端编程,比如通过file.abc.com/test.rar?authcode=xx......
  • [GPT] 如何配置抓包工具以解密HTTPS流量才能看到明文的域名地址
     要配置抓包工具以解密HTTPS流量,您需要执行以下步骤: 1.安装抓包工具:首先,确保您已经安装了支持HTTPS解密的抓包工具,例如Wireshark。 2.获取SSL证书:抓包工具需要使用目标网站的SSL证书来解密HTTPS流量。您可以通过以下两种方式之一获取SSL证书:a.从目标网站获取......
  • 本机搭建一个简单的HTTP服务器
    ①http-server是一个简单的零配置的命令行http服务器(基于nodejs),它足够强大便于生产和使用,用于本地测试和开发。②http-server是一个超轻量级web服务器。③当我们想要在服务器运行一些代码,但是又不会配置服务器的时候,就可以使用http-server就可以搞定。安装方法①使用Deepin/Ubuntu......
  • 云服务器韩国
    云服务器韩国云服务器(CloudServer)是一种基于云计算技术的虚拟计算资源,它能够提供可扩展的计算能力和存储空间,为用户提供强大的计算和存储能力。云服务器的运行环境和硬件资源都由云服务提供商进行管理和维护,用户只需要通过网络访问云服务器,无需关心硬件设备和系统管理。韩国作为......
  • Java Netty简介
    Netty和Mina是Java世界非常知名的通讯框架。它们都出自同一个作者,Mina诞生略早,属于Apache基金会,而Netty开始在Jboss名下,后来出来自立门户netty.io(http://netty.io/)。Netty是一个基于JAVANIO类库的异步通信框架,它的架构特点是:异步非阻塞、基于事件驱动、高性能、高可靠性和高可定......
  • NoSuchMethodError: javax.servlet.http.HttpServletRequest.getHttpServletMappi
    NoSuchMethodError:javax.servlet.http.HttpServletRequest.getHttpServletMapping1.介绍在Java应用程序中,可能会遇到javax.servlet.http.HttpServletRequest.getHttpServletMapping方法引发的NoSuchMethodError异常。这个异常通常是由于servletAPI版本不兼容导致的。本文将详......
  • java “HttpServletRequest”中删除“授权”标头
    JavaHttpServletRequest中删除授权标头在Java的Web开发中,我们经常使用HttpServletRequest对象来处理HTTP请求。HttpServletRequest对象提供了许多方法来获取请求的信息,包括请求头信息。有时候我们需要从请求头中删除某些特定的标头,本文将介绍如何在HttpServletRequest中删除授权......
  • Android程序调用接口http请求不到
    经过查询,安卓9.0之后,不允许采用http这种非安全模式,具体参考(48条消息)关于打包安卓Apk在安卓平板和手机不请求接口问题(underfined/netWorkError)问题解决_app打包后访问不了网络_It_渣渣宇的博客-CSDN博客如果还不行,则把相关防火墙在关掉......
  • Docker自建DNS服务器
    www.yuansredevsecops.top1.搭建搭建依然使⽤docker,安装前请安装好docker的运⾏时环境。 #创建⼀个持久化存放⽂件的⽬录 mkdir-p/opt/docker/bind #使⽤容器创建应⽤ dockerrun--namebind-d--restart=always\ --publish53:53/tcp--publish53:53/udp--publ......