言成言成啊 | Kit Chen's Blog

基于Netty的轻量级Web框架Jooby

2023-06-17 04:07:37 转载随意,文章会持续修订,请注明来源地址:https://meethigher.top/blog

本文源码地址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读取配置文件优先级顺序

  1. 优先应用根目录下。即System.getProperty("user.dir")
  2. 其次类路径下,即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 {

//构造函数快
{
// use Decorator.
decorator(next -> ctx -> {
// get response content-type.
final MediaType responseType = ctx.getResponseType();
// if content-type is text-specific
if(responseType.isTextual())
// override response type with current media type and always use UTF-8 charset!
ctx.setResponseType(responseType, StandardCharsets.UTF_8);
// pipe next response procedure.
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) {
//consumer函数式接口简写
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
<!-- MVC API 核心模块 -->
<dependency>
<groupId>io.jooby</groupId>
<artifactId>jooby-apt</artifactId>
<version>2.16.1</version>
</dependency>
<!-- json模块 -->
<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
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;

/**
* @author chenchuancheng github.com/meethigher
* @since 2023/6/17 23:30
*/
public class MVCApplication {
public static void main(String[] args) {
runApp(args, app -> {
// 配置静态资源,优先应用路径下static,其次类路径下static
app.assets("/**", "/static");
// 设置全局装饰器
app.decorator(new GlobalDecorator());
// 设置全局异常处理
app.error(new GlobalErrorHandler());
// 设置 JSON 支持
app.install(new GsonModule());
// 注册控制器
app.mvc(new Controller());
});
}
}

/**
* 全局装饰器
*
* @author chenchuancheng github.com/meethigher
* @since 2023/6/18 17:38
*/
class GlobalDecorator implements Route.Decorator {
@Nonnull
@Override
public Route.Handler apply(@Nonnull Route.Handler next) {
return ctx -> {
final MediaType responseType = ctx.getResponseType();
//设置编码为utf-8
if (responseType.isTextual()) {
ctx.setResponseType(responseType, StandardCharsets.UTF_8);
}
return next.apply(ctx);
};
}
}

/**
* 全局异常处理器
*
* @author chenchuancheng github.com/meethigher
* @since 2023/6/18 17:36
*/
class GlobalErrorHandler extends DefaultErrorHandler {
@Override
public void apply(@Nonnull Context ctx, @Nonnull Throwable cause, @Nonnull StatusCode code) {
// 处理异常并返回适当的响应
// if (cause instanceof RuntimeException) {//会存在多态问题,如继承。而我需要的是严格相等
if (cause.getClass().equals(RuntimeException.class)) {
// 处理自定义异常
ctx.setResponseType(MediaType.json, StandardCharsets.UTF_8);
ctx.send(Resp.getFailureResp(cause.getMessage()).toString());
} else {
// // 处理自定义异常
// ctx.setResponseType(MediaType.json, StandardCharsets.UTF_8);
// ctx.send(Resp.getErrorResp().toString());
super.apply(ctx, cause, code);
}
}
}

注册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
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;

/**
* @author chenchuancheng github.com/meethigher
* @since 2023/6/17 23:30
*/
public class MVCApplication {
public static void main(String[] args) {
runApp(args, app -> {
// 设置全局装饰器
app.decorator(new GlobalDecorator());
// 设置全局异常处理
app.error(new GlobalErrorHandler());
// 设置 JSON 支持
app.install(new GsonModule());
// 注册控制器
app.mvc(new Controller());
});
}
}

/**
* 全局装饰器
*
* @author chenchuancheng github.com/meethigher
* @since 2023/6/18 17:38
*/
class GlobalDecorator implements Route.Decorator {
@Nonnull
@Override
public Route.Handler apply(@Nonnull Route.Handler next) {
return ctx -> {
final MediaType responseType = ctx.getResponseType();
//设置编码为utf-8
if (responseType.isTextual()) {
ctx.setResponseType(responseType, StandardCharsets.UTF_8);
}
return next.apply(ctx);
};
}
}

/**
* 全局异常处理器
*
* @author chenchuancheng github.com/meethigher
* @since 2023/6/18 17:36
*/
class GlobalErrorHandler extends DefaultErrorHandler {
@Override
public void apply(@Nonnull Context ctx, @Nonnull Throwable cause, @Nonnull StatusCode code) {
// 处理异常并返回适当的响应
// if (cause instanceof RuntimeException) {//会存在多态问题,如继承。而我需要的是严格相等
if (cause.getClass().equals(RuntimeException.class)) {
// 处理自定义异常
ctx.setResponseType(MediaType.json, StandardCharsets.UTF_8);
ctx.send(Resp.getFailureResp(cause.getMessage()).toString());
} else {
// // 处理自定义异常
// ctx.setResponseType(MediaType.json, StandardCharsets.UTF_8);
// ctx.send(Resp.getErrorResp().toString());
super.apply(ctx, cause, code);
}
}
}

四、参考致谢

jooby:做更多! 更容易!

发布:2023-06-17 04:07:37
修改:2023-06-18 23:19:16
链接:https://meethigher.top/blog/2023/jooby/
标签:java 
付款码 打赏 分享
shift+ctrl+1可控制目录显示