本文源码地址meethigher/jooby-example: 基于Netty的轻量级Web框架Jooby使用示例
一、搭建项目 创建原生maven空项目,引入依赖
1 2 3 4 5 6 7 8 9 10 <dependency > <groupId > io.jooby</groupId > <artifactId > jooby-netty</artifactId > <version > 2.16.1</version > </dependency > <dependency > <groupId > ch.qos.logback</groupId > <artifactId > logback-classic</artifactId > <version > 1.2.12</version > </dependency >
创建启动类
1 2 3 4 5 6 7 8 9 10 11 12 13 import io.jooby.Jooby;public class Application extends Jooby { { get("/" , ctx -> "Hello World" ); } public static void main (String[] args) { runApp(args, Application.class ) ; } }
二、配置文件 Jooby同样支持解析多种类型的配置文件,只记录常用的application.conf
Jooby读取配置文件优先级顺序
优先应用根目录下。即System.getProperty("user.dir")
其次类路径下,即resources下或者jar包内的。 resources添加application.conf
1 2 3 server.port = 8080 app.name = "内部" database.url = "jdbc:mysql://localhost:3306/mydb"
示例接口
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 import io.jooby.Jooby;import io.jooby.MediaType;import java.nio.charset.StandardCharsets;public class Application extends Jooby { { decorator(next -> ctx -> { final MediaType responseType = ctx.getResponseType(); if (responseType.isTextual()) ctx.setResponseType(responseType, StandardCharsets.UTF_8); return next.apply(ctx); }); get("/" , ctx -> { String appName = getConfig().getString("app.name" ); return "Welcome to " + appName; }); get("/database" , ctx -> { String dbUrl = getConfig().getString("database.url" ); return "Database URL: " + dbUrl; }); } public static void main (String[] args) { runApp(args, Application.class ) ; } }
三、开发接口 3.1 Script API-仅支持简单路由 Script API 通常用于编写小型的、单一用途的路由处理器。
支持占位符路由规则,但是像拼参形式的就不支持。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 import static io.jooby.Jooby.runApp;public class ScriptAPIApplication { public static void main (String[] args) { runApp(args, app -> { app.get("/param/{id}" , ctx -> { String id = ctx.path("id" ).value(); return id; }); app.post("/param/{id}" , ctx -> { return ctx.path("id" ).value(); }); }); } }
3.2 MVC API-支持复杂路由/静态资源/全局请求拦截/全局异常拦截 添加依赖
1 2 3 4 5 6 7 8 9 10 11 12 <dependency > <groupId > io.jooby</groupId > <artifactId > jooby-apt</artifactId > <version > 2.16.1</version > </dependency > <dependency > <groupId > io.jooby</groupId > <artifactId > jooby-gson</artifactId > <version > 2.16.1</version > </dependency >
创建controller
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 package top.meethigher.mvc.controller;import io.jooby.MediaType;import io.jooby.Multipart;import io.jooby.annotations.*;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStream;@Path ("/mvc" )public class Controller { @GET ("/get" ) public String get () { return "Hello World" ; } @GET ("/pathParam/{id}" ) public String pathParam (@PathParam String id) { return id; } @GET ("/pathParam/{id:^[a-zA-Z0-9]{5}$}" ) public String pathParamRegex (@PathParam String id) { return id; } @GET ("/queryParam" ) public String queryParam (@QueryParam String id, @QueryParam String name) { return name + "--->" + id; } @POST ("/formParam" ) public String formParam (@FormParam String name, @FormParam String age, @FormParam Multipart file) { if (file != null ) { try (InputStream is = file.file("file" ).stream(); FileOutputStream fos = new FileOutputStream("test.txt" )) { int b; while ((b = is.read()) != -1 ) { fos.write(b); } fos.flush(); } catch (IOException e) { } } return name + "--->" + age; } @POST ("/bodyParam" ) @Consumes (MediaType.JSON) @Produces (MediaType.JSON) public Object bodyParam (Object body) { return body; } @POST ("/pageQuery" ) public String pageQuery (PageRequest req) { return req.toString(); } @GET ("/failure" ) public String failure () { throw new RuntimeException("测试失败" ); } @GET ("/error" ) public String error () { int i = 1 / 0 ; return null ; } } class PageRequest { private Integer pageIndex; private Integer pageSize; public Integer getPageIndex () { return pageIndex; } public void setPageIndex (Integer pageIndex) { this .pageIndex = pageIndex; } public Integer getPageSize () { return pageSize; } public void setPageSize (Integer pageSize) { this .pageSize = pageSize; } }
注册controller
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 import io.jooby.*;import io.jooby.json.GsonModule;import top.meethigher.mvc.controller.Controller;import top.meethigher.mvc.utils.Resp;import javax.annotation.Nonnull;import java.nio.charset.StandardCharsets;import static io.jooby.Jooby.runApp;public class MVCApplication { public static void main (String[] args) { runApp(args, app -> { app.assets("/**" , "/static" ); app.decorator(new GlobalDecorator()); app.error(new GlobalErrorHandler()); app.install(new GsonModule()); app.mvc(new Controller()); }); } } class GlobalDecorator implements Route .Decorator { @Nonnull @Override public Route.Handler apply (@Nonnull Route.Handler next) { return ctx -> { final MediaType responseType = ctx.getResponseType(); if (responseType.isTextual()) { ctx.setResponseType(responseType, StandardCharsets.UTF_8); } return next.apply(ctx); }; } } class GlobalErrorHandler extends DefaultErrorHandler { @Override public void apply (@Nonnull Context ctx, @Nonnull Throwable cause, @Nonnull StatusCode code) { if (cause.getClass().equals(RuntimeException.class )) { ctx.setResponseType(MediaType.json, StandardCharsets.UTF_8); ctx.send(Resp.getFailureResp(cause.getMessage()).toString()); } else { super .apply(ctx, cause, code); } } }
四、参考致谢 jooby:做更多! 更容易!