基于 Netty + Spring 实现一个 HTTP REST 服务器(三)Gevlet 源码分享之网络请求处理

Gevlet 源码分享之网络请求处理

网络服务相关代码主要在connector 下,统一抽象为一个 BackendServer 对象,后续其他的网络协议可以实现此接口进行扩展

import io.netty.channel.socket.SocketChannel;

/** 
BackendServer  有两个方法
1.start 用于启动某个网络服务,可以指定端口
2.setSocketChannel 用于指定处理该协议请求的处理类 
*/
public interface BackendServer {

    void start(int port) throws Exception;

    void setSocketChannel(SocketChannel channel);
}

目前 BackendServer 只有一个实现类 HttpBackendServer 用于处理 HTTP 协议的请求

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
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.HttpRequestDecoder;
import io.netty.handler.codec.http.HttpResponseEncoder;
import java.net.InetSocketAddress;


public class HttpBackendServer implements BackendServer {


    @Override
    public void start(int port) throws InterruptedException {
        ServerBootstrap serverBootstrap = new ServerBootstrap();
        EventLoopGroup group = new NioEventLoopGroup();
        try {
            serverBootstrap.group(group);
            serverBootstrap.channel(NioServerSocketChannel.class);
            serverBootstrap.localAddress(new InetSocketAddress(port));
            serverBootstrap.childHandler(new ChannelInitializer<SocketChannel>() {//有连接到达时会创建一个channel
                protected void initChannel(SocketChannel channel) throws Exception {
                    setSocketChannel(channel);
                }
            }).childOption(ChannelOption.SO_KEEPALIVE, true);
            ChannelFuture f = serverBootstrap.bind().sync();
            f.channel().closeFuture().sync();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            group.shutdownGracefully().sync();
        }
    }


    @Override
    public void setSocketChannel(SocketChannel channel) {
        channel.pipeline().addLast(new HttpResponseEncoder());
        channel.pipeline().addLast(new HttpRequestDecoder());
        channel.pipeline().addLast(new HttpRequestHandlerAdapter());
    }
}

HttpRequestHandlerAdapter 是具体的HTTP 请求处理类

import com.gevlet.coop.Utils.Strings;
import com.gevlet.coop.connector.protocol.ByteBufferReader;
import com.gevlet.coop.connector.protocol.NetMessagetProtocol;
import com.gevlet.coop.core.ServerRequestHolder;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.EmptyByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.http.*;
import java.util.HashMap;



public class HttpRequestHandlerAdapter extends AbstractHandlerAdapter {


    private NetMessagetProtocol protocol;

    private ByteBufferReader bufferReader;


    @Override
    protected void doRequest(ChannelHandlerContext context, Object message) throws Exception {
        //处理请求头
        buildHttpRequest(message);
        //处理请求参数
        buildHttpContentAndProcess(context, message);
    }

    /**
     * 处理请求头
     *
     * @param message
     */
    private void buildHttpRequest(Object message) {
        if (message instanceof HttpRequest) {
            initialize();
            HttpRequest request = (HttpRequest) message;
            buildUrl(request.uri());
            if (HttpUtil.isContentLengthSet(request)) {
                bufferReader = new ByteBufferReader(
                        (int) HttpUtil.getContentLength(request));
            }
        }
    }

    /**
     * 处理请求参数
     *
     * @param context
     * @param message
     */
    private void buildHttpContentAndProcess(ChannelHandlerContext context, Object message) {
        if (message instanceof HttpContent) {
            HttpContent httpContent = (HttpContent) message;
            ByteBuf content = httpContent.content();
            if (content instanceof EmptyByteBuf) {
                //处理业务请求
                ServerRequestHolder.newInstance().holdRequest(protocol);
                destroy();
                return;
            } else {

                bufferReader.reading(content);
                content.release();
                if (bufferReader.isEnd()) {
                    HashMap<String, String> contentData = getContentData(content);
                    protocol.setBody(contentData);
                    protocol.setHandlerContext(context);
                    //处理业务请求
                    ServerRequestHolder.newInstance().holdRequest(protocol);
                    //销毁请求参数
                    destroy();
                }
            }

        }
    }

    private void destroy() {
        protocol = null;
        bufferReader = null;
    }

    private HashMap<String, String> getContentData(ByteBuf content) {
        HashMap<String, String> dataMap = new HashMap<>();
        String resultStr = new String(bufferReader.readFull());
        if (!Strings.isEmpty(resultStr)) {
            String[] splitedResult = resultStr.split("\n");
            int roudNum = splitedResult.length / 4;
            for (int i = 0; i < roudNum; i++) {
                String key = splitedResult[i * 4 + 1].
                        replace("\r", "").
                        replace("Content-Disposition: form-data; name=\"", "");
                String keyResult = key.substring(0, key.length() - 1);
                String value = splitedResult[i * 4 + 3].replace("\r", "");
                //设置值
                dataMap.put(keyResult, value);
            }
        }
        return dataMap;
    }


    private void buildUrl(String url) {
        if (Strings.isEmpty(url)) {
            protocol.setThrowable(new NullPointerException("URL 不能为空"));
        }
        if ("/".equals(url)) {
            protocol.setApplication("/");
        } else {
            String[] splitedUrl = url.split("/");
            protocol.setApplication(splitedUrl[1]);
            protocol.setPathUrl(splitedUrl[2]);
            protocol.setHandlerUrl(splitedUrl[3]);
            protocol.setProtocolType("HTTP");
        }
    }


    private void initialize() {
        this.protocol = new NetMessagetProtocol();
        this.bufferReader = null;
    }
}

猜你喜欢

转载自blog.csdn.net/qq_38692223/article/details/80269672