探秘Netty6:基于Netty自己动手实现Web框架
大厨小鲜——基于Netty自己动手实现Web框架
上节课我们自己动手制作了一个RPC框架,本节课我们挑战一个稍有难度的一点的任务,手动制作一个Web框架。
我不太愿意叫什么MVC框架,因为我在制作这个小项目的时候可没想过它要怎么怎么的MVC,一切皆以易于使用为目标。
首先我们看看这个Web框架使用起来如何简单
Hello World
import httpkids.server.KidsRequestDispatcher;
import httpkids.server.Router;
import httpkids.server.internal.HttpServer;
public class HelloWorld {
public static void main(String[] args) {
var rd = new KidsRequestDispatcher("/kids", new Router((ctx, req) -> {
ctx.html("Hello, World");
}));
new HttpServer("localhost", 8080, 2, 16, rd).start();
}
}
http://localhost:8080/kids
KidsRequestDispatcher
是请求派发器,用于将收到的HTTP请求对象扔给响应的RequestHandler
进行处理。Router
用于构建路由,它负责的是将URL规则和RequestHandler
挂接起来,形成一个复杂的映射表。
Router
为了简化实现细节,所以没有支持复杂的URL规则,例如像RESTFUL
这种将参数写在URL里面的这种形式是不支持的。
HttpServer
是Web服务器的核心对象,构建HttpServer除了IP端口之外,还需要提供3个关键参数,分别是IO线程数、业务线程数和请求派发器对象。IO线程用于处理套件字读写,由Netty内部管理。业务线程专门用于处理HTTP请求,由httpkids框架来管理。
一个全面的例子
import java.util.HashMap;
import httpkids.server.KidsRequestDispatcher;
import httpkids.server.Router;
import httpkids.server.internal.HttpServer;
public class HelloWorld {
public static void main(String[] args) {
var router = new Router((ctx, req) -> {
ctx.html("Hello, World"); // 纯文本html
})
.handler("/hello.json", (ctx, req) -> {
ctx.json(new String[] { "Hello", "World" }); // JSON API
})
.handler("/hello", (ctx, req) -> {
var res = new HashMap<String, Object>();
res.put("req", req);
ctx.render("playground.ftl", res); // 模版渲染
})
.handler("/world", (ctx, req) -> {
ctx.redirect("/hello"); // 302跳转
})
.handler("/error", (ctx, req) -> {
ctx.abort(500, "wtf"); // 异常
})
.resource("/pub", "/static") // 静态资源
.child("/user", () -> { // 路由嵌套
return new Router((ctx, req) -> {
ctx.html("Hello, World");
})
.handler("/hello.json", (ctx, req) -> {
ctx.json(new String[] { "Hello", "World" });
})
.filter((ctx, req, before) -> { // 过滤器、拦截器
if (before) {
System.out.printf("before %s\n", req.path());
} else {
System.out.printf("after %s\n", req.path());
}
return true;
});
});
var rd = new KidsRequestDispatcher("/kids", router); // 请求派发器
rd.templateRoot("/tpl"); // 模版classpath根目录
rd.exception(500, (ctx, e) -> { // 异常处理
ctx.html("what the fuck it is", 500);
})
.exception((ctx, e) -> { // 通用异常处理
ctx.html("mother fucker!", e.getStatus().code());
});
var server = new HttpServer("localhost", 8080, 2, 16, rd);
server.start();
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
server.stop(); // 优雅停机
}
});
}
}
http://localhost:8080/kids
http://localhost:8080/kids/hello
http://localhost:8080/kids/hello.json
http://localhost:8080/kids/world
http://localhost:8080/kids/error
http://localhost:8080/kids/pub/bootstrap.min.css
http://localhost:8080/kids/user
http://localhost:8080/kids/user/hello
堆栈深度
非Java程序员总是抱怨Java的框架过于复杂,特别爱拿Java恐怖的调用栈说事。比如下面这张图是SpringBoot的HelloWorld程序的调用栈。
这里我要亮出httpkids的调用栈,我们来看看它到底有多深
项目代码
HttpKids
Web Framework based on Netty for Kids of You
RpcKids
RPC Framework based on Netty for Kids of You
大爆炸
关注公众号「码洞」,让我们来一起学习一下这个框架的设计与实现。

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
-
上一篇
13个开发者技能必知必会!
本文翻译自dZone,英文原文链接:https://dzone.com/articles/the-13-developer-skills-that-will-get-you-hired 为了找到今年最受欢迎的开发者技能,原作者接触了一系列HR、CTO、CEO及其他管理人员,他们提供了面试中的一些必须技能,战略考虑和所需掌握的软技能。 一、JavaScript 最近熟练掌握JavaScript的开发者不会没有饭碗。精通JavaScript是目前为止被管理者和HR提到的最频繁的技能。目前市面上JavaScript已经被证明是高可移植性和高价值的技能。 二、Big Data 去年大数据项目持续增长,预计未来一年发展态势依然不会减慢。开发者应当深入理解商业智能、数据分析、机器学习,及其他转换存储聚合大量数据的解决方案。只有这样,开发者才能够帮助公司处理大数据,制定更好的商业决定。 三、Full Stack 很多顶尖公司正在寻找全栈工程师,他们可以轻松地穿梭于大量的技术和平台之间。 四、DevOps 在简历中考虑添加开发运维技能不仅能提高热门工作的竞争胜出概率;DevOps实践轻易地打造更加优秀...
-
下一篇
guava快速入门(二)
Guava工程包含了若干被Google的 Java项目广泛依赖 的核心库,例如:集合 [collections] 、缓存 [caching] 、原生类型支持 [primitives support] 、并发库 [concurrency libraries] 、通用注解 [common annotations] 、字符串处理 [string processing] 、I/O 等等。 guava类似Apache Commons工具集 Collection 不可变集合 不可变对象有很多优点,包括: 当对象被不可信的库调用时,不可变形式是安全的; 不可变对象被多个线程调用时,不存在竞态条件问题 不可变集合不需要考虑变化,因此可以节省时间和空间。所有不可变的集合都比它们的可变形式有更好的内存利用率(分析和测试细节); 不可变对象因为有固定不变,可以作为常量来安全使用。 JDK也提供了Collections.unmodifiableXXX方法把集合包装为不可变形式,但: 笨重而且累赘:不能舒适地用在所有想做防御性拷贝的场景; 不安全:要保证没人通过原集合的引用进行修改,返回的集合才是事实上不可变的...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- CentOS6,CentOS7官方镜像安装Oracle11G
- CentOS7,8上快速安装Gitea,搭建Git服务器
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- CentOS7编译安装Gcc9.2.0,解决mysql等软件编译问题
- MySQL8.0.19开启GTID主从同步CentOS8
- SpringBoot2初体验,简单认识spring boot2并且搭建基础工程
- 面试大杂烩
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- CentOS7设置SWAP分区,小内存服务器的救世主
- Docker使用Oracle官方镜像安装(12C,18C,19C)