netty实现静态资源服务器

package com.example.netty;

import cn.hutool.core.util.ObjectUtil;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.http.*;
import io.netty.handler.ssl.SslHandler;
import io.netty.handler.stream.ChunkedNioFile;
import io.netty.handler.stream.ChunkedWriteHandler;
import io.netty.util.CharsetUtil;
import org.springframework.lang.NonNull;

import java.io.*;

import static io.netty.handler.codec.http.HttpHeaderNames.*;

/**
 * @author gl
 * @date 2023年06月04日
 */
public class ResourceServer {
    private ChannelFuture channelFuture;
    private NioEventLoopGroup nioEventLoopGroup;
    private ServerBootstrap serverBootstrap;
    private Boolean isStart = Boolean.FALSE;
    private Integer port;

    public ResourceServer(Integer port) {
        this.port = port;
        nioEventLoopGroup = new NioEventLoopGroup(3);
        serverBootstrap = new ServerBootstrap()
                .group(nioEventLoopGroup)
                .channel(NioServerSocketChannel.class)
                .childHandler(new ChannelInitializer<NioSocketChannel>() {
                    @Override
                    protected void initChannel(NioSocketChannel ch) throws Exception {
                        ch.pipeline()
//                                .addLast(new HttpRequestDecoder())
//                                .addLast(new HttpResponseEncoder())
                                .addLast(new HttpServerCodec())
//                                .addLast(new ChunkedWriteHandler())
                                .addLast(new SimpleChannelInboundHandler<HttpRequest>() {

                                    @Override
                                    protected void channelRead0(ChannelHandlerContext ctx, HttpRequest request) throws Exception {
                                        String fileName = request.getUri().replace("/", "");
                                        String path = this.getClass().getClassLoader().getResource(fileName).getPath();
                                        File file = new File(path);
                                        DefaultFullHttpResponse response = new DefaultFullHttpResponse(request.protocolVersion(), HttpResponseStatus.OK);
                                        response.headers().set(ACCESS_CONTROL_ALLOW_ORIGIN,"*");
                                        response.headers().set(ACCESS_CONTROL_ALLOW_HEADERS,"*");//允许headers自定义
                                        response.headers().set(ACCESS_CONTROL_ALLOW_METHODS,"GET, POST, PUT,DELETE");
                                        response.headers().set(ACCESS_CONTROL_ALLOW_CREDENTIALS,"true");
                                        //设置文件格式内容
                                        response.headers().set(HttpHeaderNames.CONTENT_TYPE, "application/octet-stream");
                                        response.headers().set(HttpHeaderNames.CONTENT_LENGTH, file.length());
                                        if (HttpUtil.isKeepAlive(request)) {
                                            response.headers().set(HttpHeaderNames.CONNECTION, HttpHeaderValues.KEEP_ALIVE);
                                        }

                                        try(InputStream inputStream = new FileInputStream(file);
                                            BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream)) {
                                            byte[] bytes = new byte[1024];
                                            int flat = 0;
                                            while((flat = bufferedInputStream.read(bytes))!= -1){
                                                response.content().writeBytes(bytes, 0, flat);
                                            }
                                        }catch (Throwable e){

                                        }
                                         ChannelFuture channelFuture = ctx.writeAndFlush(response);
                                        if (!HttpUtil.isKeepAlive(request)) {
                                            channelFuture.addListener(ChannelFutureListener.CLOSE);
                                        }
                                    }
                                });
                    }
                });
    }


    /*
     * <p>启动服务器</p>
     * @author gl
     * @date 2023/6/4 00:43
     * @param
     * @return
     *
     */
    public void start() {
        if(ObjectUtil.isNull(serverBootstrap) || isStart){
            return;
        }
        isStart = Boolean.TRUE;
        channelFuture = serverBootstrap.bind(this.port);
    }


    /*
     * <p>关闭服务器</p>
     * @author gl
     * @date 2023/6/4 00:47
     * @param null
     * @return null
     *
     */
    public void stop() {
        if (ObjectUtil.isNull(channelFuture)) {
            return;
        }

        Channel channel = channelFuture.channel();
        channel.closeFuture().addListener(new ChannelFutureListener() {
            @Override
            public void operationComplete(@NonNull ChannelFuture future) throws Exception {
                if(!nioEventLoopGroup.isShutdown()){
                    nioEventLoopGroup.shutdownGracefully();
                }
            }
        });
        channel.close();
    }

    public static void main(String[] args) throws InterruptedException {
        ResourceServer server =  new ResourceServer(8888);
        server.start();
//        TimeUnit.SECONDS.sleep(20);
//        server.stop();
    }
}

猜你喜欢

转载自blog.csdn.net/sunboylife/article/details/131035366