Mình đã giới thiệu với các bạn về Javalin, trong bài viết này chúng ta sẽ tìm hiểu rõ hơn về cách chúng ta sẽ handle request trong Javalin framework các bạn nhé!
Mình cũng tạo một Maven project để làm ví dụ:
Javalin và SLF4J Simple dependency như sau:
1 2 3 4 5 6 7 8 9 10 |
<dependency> <groupId>io.javalin</groupId> <artifactId>javalin</artifactId> <version>2.8.0</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-simple</artifactId> <version>1.7.26</version> </dependency> |
Mình cũng tạo một class với phương thức main() khởi tạo một web server với đối tượng Javalin như sau:
1 2 3 4 5 6 7 8 9 10 |
package com.huongdanjava.javalin; import io.javalin.Javalin; public class JavalinExample { public static void main(String[] args) { Javalin javalin = Javalin.create().start(8080); } } |
Như mình đã nói, để handle request trong Javalin chúng ta sẽ sử dụng Functional Interface Handler của nó. Class Handler chỉ có một phương thức handle() với tham số là một đối tượng Context, và đối tượng Context này sẽ giữ tất cả các thông tin của request và response cho một request.
Mình implement đối tượng Handler cho GET request “/example” như sau:
1 2 3 4 5 6 7 |
javalin.get("/example", new Handler() { @Override public void handle(Context ctx) throws Exception { } }); |
Chúng ta sẽ sử dụng các phương thức queryParam() để lấy thông tin về các request parameter từ người dùng, ví dụ:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
package com.huongdanjava.javalin; import io.javalin.Context; import io.javalin.Handler; import io.javalin.Javalin; public class JavalinExample { public static void main(String[] args) { Javalin javalin = Javalin.create().start(8080); javalin.get("/example", new Handler() { @Override public void handle(Context ctx) throws Exception { String name = ctx.queryParam("name"); ctx.result(name); } }); } } |
Kết quả:
Một trong các phương thức overload của phương thức queryParam() còn cho phép chúng ta validate data mà chúng ta truyền vào. Tham số của phương thức này gồm key là request parameter và class là kiểu dữ liệu của giá trị của parameter đó. Ví dụ nếu giờ mình sửa lại đoạn code trên như sau:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
package com.huongdanjava.javalin; import io.javalin.Context; import io.javalin.Handler; import io.javalin.Javalin; import io.javalin.validation.TypedValidator; public class JavalinExample { public static void main(String[] args) { Javalin javalin = Javalin.create().start(8080); javalin.get("/example", new Handler() { @Override public void handle(Context ctx) throws Exception { TypedValidator<Integer> id = ctx.queryParam("id", Integer.class); ctx.result(id.get() + ""); } }); } } |
thì khi request với URL http://localhost:8080/example?id=Khanh, các bạn sẽ thấy lỗi sau:
Chúng ta có thể định nghĩa request với path parameter như sau:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
package com.huongdanjava.javalin; import io.javalin.Context; import io.javalin.Handler; import io.javalin.Javalin; public class JavalinExample { public static void main(String[] args) { Javalin javalin = Javalin.create().start(8080); javalin.get("/example/:name", new Handler() { @Override public void handle(Context ctx) throws Exception { String name = ctx.pathParam("name"); ctx.result(name); } }); } } |
Ở đoạn code trên thì mình đã định nghĩa một path parameter name, để lấy giá trị này thì chúng ta sẽ sử dụng phương thức pathParam() của đối tượng Context.
Kết quả:
Tương tự như phương thức queryParam(), chúng ta cũng có thể validate dữ liệu request của người dùng sử dụng phương thức overload của pathParam().
Nếu request của các bạn có phần body thì các bạn có thể sử dụng phương thức body() hoặc bodyAsClass() để lấy được dữ liệu trong phần body này. Ví dụ như sau:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
package com.huongdanjava.javalin; import io.javalin.Context; import io.javalin.Handler; import io.javalin.Javalin; public class JavalinExample { public static void main(String[] args) { Javalin javalin = Javalin.create().start(8080); javalin.post("/example", new Handler() { @Override public void handle(Context ctx) throws Exception { String name = ctx.body(); ctx.result(name); } }); } } |
Kết quả:
Với phần body thì chúng ta có thể validate data sử dụng phương thức bodyValidator() các bạn nhé!
Sau khi validate với các phương thức queryParam(), pathParam() hay bodyValidator() xong, các bạn cũng có thể add thêm điều kiện để check data của người dùng gửi tới sử dụng phương thức check() của đối tượng TypedValidator như sau:
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 |
package com.huongdanjava.javalin; import io.javalin.Context; import io.javalin.Handler; import io.javalin.Javalin; import io.javalin.validation.TypedValidator; public class JavalinExample { public static void main(String[] args) { Javalin javalin = Javalin.create().start(8080); javalin.get("/example", new Handler() { @Override public void handle(Context ctx) throws Exception { TypedValidator<Integer> id = ctx.queryParam("id", Integer.class); id.check(i -> i > 10); ctx.result(id.get() + ""); } }); } } |
Kết quả:
Thông thường, khi hiện thực các ứng dụng RESTful Web Service, chúng ta thường hiện thực các API CRUD (Create, Read, Update, Delete) và những API này thường bắt đầu với cùng context path, ví dụ “/user” chẳng hạn.
1 2 3 4 |
javalin.post("/user/", ctx -> ctx.result("")); javalin.get("/user/:id", ctx -> ctx.result("")); javalin.patch("/user/:id", ctx -> ctx.result("")); javalin.delete("/user/:id", ctx -> ctx.result("")); |
Để đơn giản và tăng khả năng readable, Javalin hỗ trợ groups handler giúp chúng ta có thể gom nhóm để handle request như sau:
1 2 3 4 5 6 7 8 9 10 |
javalin.routes(() -> { path("user", () -> { post(UserService::createUser); path(":id", () -> { get(UserService::getUser); patch(UserService::updateUser); delete(UserService::deleteUser); }); }); }); |
Để sử dụng được đoạn code như trên, các bạn sẽ cần phải implement interface Handler cho các phương thức post(), get(), delete(), patch() ở một class khác và thêm nữa là các bạn cần import static các phương thức này từ class io.javalin.apibuilder.ApiBuilder các bạn nhé!
Một điểm của Javalin trong phần handle request nữa mà các bạn cần biết là chúng ta có thể sử dụng các phương thức before() và after() của đối tượng Javalin để thêm phần xử lý trước khi handle request và trước khi return response cho một request bất kỳ hoặc tất cả các request.
Ví dụ, mình muốn trước khi handle một request bất kỳ cho ví dụ trên thì ứng dụng sẽ in ra dòng chữ “Start processing…” thì mình sẽ sửa code lại như sau:
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 |
package com.huongdanjava.javalin; import io.javalin.Context; import io.javalin.Handler; import io.javalin.Javalin; import io.javalin.validation.TypedValidator; public class JavalinExample { public static void main(String[] args) { Javalin javalin = Javalin.create().start(8080); javalin.before(ctx -> { System.out.println("Start processing..."); }); javalin.get("/example", new Handler() { @Override public void handle(Context ctx) throws Exception { TypedValidator<Integer> id = ctx.queryParam("id", Integer.class); id.check(i -> i > 10); ctx.result(id.get() + ""); } }); } } |
Kết quả: