美文网首页
(三)使用netty做一个简陋的web容器

(三)使用netty做一个简陋的web容器

作者: guessguess | 来源:发表于2021-02-20 15:34 被阅读0次

为了可持续发展的学习,还是决定利用netty做一个简陋的web容器。

先贴一下依赖

<project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.gee</groupId>
    <artifactId>my-webservice-netty</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <dependencies>
        <dependency>
            <groupId>io.netty</groupId>
            <artifactId>netty-all</artifactId>
            <version>4.1.16.Final</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <scope>provided</scope>
            <version>1.18.8</version>
        </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.41</version>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <!-- 指定maven编译的jdk的版本 -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <configuration>
                    <skip>true</skip>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

1.服务端代码

这里其实没有什么特殊的地方,只是需要使用特定的解码编码器。
HttpRequestDecoder 因为服务端是接受请求,从通道获取到的数据必然是序列化过的,所以需要进行反序列化,因此是解码。
HttpResponseEncoder 因为服务端响应最后要将响应数据写入到通道中,所以是编码器,将数据进行序列化。
HttpObjectAggregator 则是将请求,响应,或者是相关的数据,整合为一个对象。方便获取请求头,响应头等数据。
HttpHandler则是自定义的一个结构体。用于处理业务

package web.server;

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.HttpRequestDecoder;
import io.netty.handler.codec.http.HttpResponseEncoder;
import web.handler.HttpHandler;

public class WebService {
    private static final int port = 9527;
    public static void main(String args[]) {
        start();
    }

    private static void start() {
        EventLoopGroup boss = new NioEventLoopGroup();
        EventLoopGroup work = new NioEventLoopGroup();
        
        ServerBootstrap sb = new ServerBootstrap();
        sb.group(boss, work).channel(NioServerSocketChannel.class)
                .childHandler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    protected void initChannel(SocketChannel ch) throws Exception {
                        ch.pipeline().addLast(new HttpRequestDecoder());
                        ch.pipeline().addLast(new HttpResponseEncoder());
                        ch.pipeline().addLast(new HttpObjectAggregator(65536));
                        ch.pipeline().addLast(new HttpHandler());
                    }
                });
        ChannelFuture cf = null;
        try {
            cf = sb.bind(port).sync();
            cf.channel().closeFuture().sync();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            boss.shutdownGracefully();
            work.shutdownGracefully();
        }
    }
}

2.自定义处理器

package web.handler;

import java.util.Arrays;
import java.util.List;

import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.HttpMethod;
import web.service.UriHandlerService;

public class HttpHandler extends SimpleChannelInboundHandler<FullHttpRequest>{
    private static final List<String> methods = Arrays.asList(HttpMethod.GET.name(), HttpMethod.POST.name());
    private static final String get_url = "/get/userInfo";
    private static final String post_url = "/update/userInfo";
    private static final UriHandlerService service = new UriHandlerService();
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, FullHttpRequest msg) throws Exception {
        if(!methods.contains(msg.method().name())) {
            return;
        }
        String uri = msg.uri();
        if (HttpMethod.GET.name().equals(msg.method().name())) {
            if (!uri.equals(get_url)) {
                return;
            }
            service.handleGet(ctx, msg);
        }
        if (HttpMethod.POST.name().equals(msg.method().name())) {
            if (!uri.equals(post_url)) {
                return;
            }
            service.handlePost(ctx, msg);
        }
    }

}

package web.service;

import com.alibaba.fastjson.JSONObject;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.http.DefaultFullHttpResponse;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.FullHttpResponse;
import io.netty.handler.codec.http.HttpHeaderNames;
import io.netty.handler.codec.http.HttpResponseStatus;
import io.netty.handler.codec.http.HttpVersion;
import io.netty.util.CharsetUtil;
import web.entity.UserInfo;

public class UriHandlerService {
    public void handleGet(ChannelHandlerContext ctx, FullHttpRequest msg) {
        UserInfo userInfo = new UserInfo();
        userInfo.setId(1);
        userInfo.setName("peter");
        FullHttpResponse rsp = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK,
                Unpooled.copiedBuffer(JSONObject.toJSON(userInfo).toString().getBytes()));
        rsp.headers().set(HttpHeaderNames.CONTENT_TYPE, "application/json; charset=UTF-8");
        ctx.writeAndFlush(rsp).addListener(ChannelFutureListener.CLOSE);
    }

    public void handlePost(ChannelHandlerContext ctx, FullHttpRequest msg) {
        ByteBuf contentbb = msg.content();
        byte info[] = new byte[contentbb.readableBytes()];
        contentbb.readBytes(info);
        String infostr = new String(info);
        FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK,
                Unpooled.copiedBuffer(infostr, CharsetUtil.UTF_8));
        // 设置头信息
        response.headers().set(HttpHeaderNames.CONTENT_TYPE, "application/json; charset=UTF-8");
       // 响应写回给客户端,并在写入后会断开这个连接
        ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE);
    }
}

写的比较简单,只是一个简单的demo.
只是模拟get跟post请求。


模拟一下post

相关文章

网友评论

      本文标题:(三)使用netty做一个简陋的web容器

      本文链接:https://www.haomeiwen.com/subject/iitxfltx.html