netty实现 nsf文件系统_Netty学习笔记(五) 使用Netty构建静态网页服务器

👆关注微信公众号,获取更多编程内容

昨天在继续完善基于Netty构建的聊天室系统的过程中,发现了一个有意思的知识点,特此拿来做一个简单的静态网页服务器,好好的玩一玩Netty。

但是不管怎么说利用netty实现各种功能的流程都是类似的

配置ServerHandle

(可选)实现自定义的编码器

完成ServerBootStarp的配置

启动服务

连接到该服务

好的,那么我们基于此来实现一个简单静态网页需求,要求实现能够通过地址访问html,js,css,以及图片等资源文件,那么开始吧

静态网页资源服务器

HttpServerHandleAdapter

这里是最为复杂的步骤,具体代码可以看注释。

package com.zhoutao123.simpleChat.html;

import io.netty.channel.*;

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

import io.netty.handler.ssl.SslHandler;

import io.netty.handler.stream.ChunkedNioFile;

import java.io.File;

import java.io.RandomAccessFile;

public class HttpServerHandleAdapter extends SimpleChannelInboundHandler {

// 资源所在路径

private static final String location;

// 404文件页面地址

private static final File NOT_FOUND;

static {

// 构建资源所在路径,此处参数可优化为使用配置文件传入

location = "/home/tao/code/resource";

// 构建404页面

String path = location + "/404.html";

NOT_FOUND = new File(path);

}

@Override

protected void channelRead0(ChannelHandlerContext ctx, FullHttpRequest request) throws Exception {

// 获取URI

String uri = request.getUri();

// 设置不支持favicon.ico文件

if ("favicon.ico".equals(uri)) {

return;

}

// 根据路径地址构建文件

String path = location + uri;

File html = new File(path);

// 状态为1xx的话,继续请求

if (HttpHeaders.is100ContinueExpected(request)) {

send100Continue(ctx);

}

// 当文件不存在的时候,将资源指向NOT_FOUND

if (!html.exists()) {

html = NOT_FOUND;

}

RandomAccessFile file = new RandomAccessFile(html, "r");

HttpResponse response = new DefaultHttpResponse(request.getProtocolVersion(), HttpResponseStatus.OK);

// 文件没有发现设置状态为404

if (html == NOT_FOUND) {

response.setStatus(HttpResponseStatus.NOT_FOUND);

}

// 设置文件格式内容

if (path.endsWith(".html")){

response.headers().set(HttpHeaders.Names.CONTENT_TYPE, "text/html; charset=UTF-8");

}else if(path.endsWith(".js")){

response.headers().set(HttpHeaders.Names.CONTENT_TYPE, "application/x-javascript");

}else if(path.endsWith(".css")){

response.headers().set(HttpHeaders.Names.CONTENT_TYPE, "text/css; charset=UTF-8");

}

boolean keepAlive = HttpHeaders.isKeepAlive(request);

if (keepAlive) {

response.headers().set(HttpHeaders.Names.CONTENT_LENGTH, file.length());

response.headers().set(HttpHeaders.Names.CONNECTION, HttpHeaders.Values.KEEP_ALIVE);

}

ctx.write(response);

if (ctx.pipeline().get(SslHandler.class) == null) {

ctx.write(new DefaultFileRegion(file.getChannel(), 0, file.length()));

} else {

ctx.write(new ChunkedNioFile(file.getChannel()));

}

// 写入文件尾部

ChannelFuture future = ctx.writeAndFlush(LastHttpContent.EMPTY_LAST_CONTENT);

if (!keepAlive) {

future.addListener(ChannelFutureListener.CLOSE);

}

file.close();

}

private static void send100Continue(ChannelHandlerContext ctx) {

FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.CONTINUE);

ctx.writeAndFlush(response);

}

}

HttpServerInitializer

添加我们刚刚完成的HttpServerHandleAdapter

package com.zhoutao123.simpleChat.html;

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.stream.ChunkedWriteHandler;

public class HttpServerInitializer extends ChannelInitializer {

@Override

public void initChannel(SocketChannel ch) throws Exception {

ChannelPipeline pipeline = ch.pipeline();

//将请求和应答消息编码或解码为HTTP消息

pipeline.addLast(new HttpServerCodec());

//将HTTP消息的多个部分组合成一条完整的HTTP消息

pipeline.addLast(new HttpObjectAggregator(64 * 1024));

pipeline.addLast(new ChunkedWriteHandler());

pipeline.addLast(new HttpServerHandleAdapter());

}

}

服务启动

public class Server {

private final static int port = 8080;

public static void main(String[] args) throws InterruptedException {

NioEventLoopGroup boss = new NioEventLoopGroup();

NioEventLoopGroup work = new NioEventLoopGroup();

try {

ServerBootstrap serverBootstrap = new ServerBootstrap();

serverBootstrap.group(boss, work)

.channel(NioServerSocketChannel.class)

.childHandler(new HttpServerInitializer())

.option(ChannelOption.SO_BACKLOG, 128)

.childOption(ChannelOption.SO_KEEPALIVE, true);

ChannelFuture future = serverBootstrap.bind(port).sync();

// 等待服务器 socket 关闭 。

// 在这个例子中,这不会发生,但你可以优雅地关闭你的服务器。

future.channel().closeFuture().sync();

} finally {

work.shutdownGracefully();

boss.shutdownGracefully();

}

}

}

静态资源文件

静态资源文件这里主要测试html以及js和css文件,这里写了3个html文件(404.html用于当输入路径不存在的时候,跳转到的文件),一个js文件,一个css文件,一个logo图片,测试js和css在index.html文件中测试

需要注意的是这些资源文件需要放在上面代码中的location指定的位置,否则可能会出现访问不到的异常情况具体的代码如下:

index.html

Netty静态资源服务器

你好,欢迎来到基于Netty构建的静态资源服务器主页

当前位置Index.html

关于Netty和作者

about.html

WebSocket Chat

这是关于界面

点击我,返回主页

404.html

WebSocket Chat

没有发现此页面

js文件

function sayHello() {

alert("你好,欢迎使用Netty服务器")

}

css文件

#title{

color: red;

text-underline: darkcyan;

}

input{

background-color: darkcyan;

}

文件整体结构

.

├── index.html

├── 404.html

├── about.html

├── logo.jpg

├── css

│   └── style.css

└── js

└── message.js

2 directories, 5 files

测试效果

浏览器输入URL即可访问

主页

可以看到访问成功,地址是localhost:8080/index.html ,开发者工具中展示状态均为200

调用JS效果

点击启动问候语会执行js脚本弹出窗口

跳转效果

点击超链接 ,即可跳转到about.html界面,这里引用了一个jpg图片

404页面

当输入一个不存在的文件的时候,可以看到状态为404.

总结

基于Netty实现的一个简单的静态资源服务器,可以说实现了基本的功能,但是还有其他很多idea可以实现,如负载均衡,设置配置文件(如资源所在路径以及端口等信息),

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值