Веб-фреймворк своими руками на основе Netty

Java задняя часть MVC Netty
Веб-фреймворк своими руками на основе Netty

На последнем занятии мы сами сделали RPC-фреймворк, а на этом уроке мы поставили перед собой чуть более сложную задачу — вручную сделать веб-фреймворк. Я неохотно называю это фреймворком MVC, потому что я не думал о том, что это за MVC, когда делал этот небольшой проект, и все было направлено на простоту использования.

Сначала давайте посмотрим, насколько легко использовать этот веб-фреймворк.

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Это основной объект веб-сервера.Помимо IP-порта, HttpServer также должен предоставлять три ключевых параметра, а именно количество потоков ввода-вывода, количество бизнес-потоков и объект диспетчера запросов. Потоки ввода-вывода используются для обработки чтения и записи слов набора и управляются внутри 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. Например, изображение ниже широко распространено.

Итак, здесь я собираюсь показать стек вызовов httpkids, давайте посмотрим, насколько он глубок.

код проекта

HttpKids Web Framework based on Netty for Kids of You

RpcKids RPC Framework based on Netty for Kids of You

большой взрыв

Обратите внимание на общественный номер»дворовая дыра", давайте узнаем о дизайне и реализации этого фреймворка.