1. Introduction
1.介绍
Javalin is a lightweight web framework written for Java and Kotlin. It’s written on top of the Jetty web server, which makes it highly performant. Javalin is modeled closely off of koa.js, which means it’s written from the ground up to be simple to understand and build on.
Javalin是一个为Java和Kotlin编写的轻量级Web框架。它是在Jetty网络服务器的基础上编写的,这使得它具有很高的性能。Javalin是以koa.js为蓝本编写的,这意味着它从头到尾都很容易理解和构建。
In this tutorial, we’ll walk through steps of building a basic REST microservice using this light framework.
在本教程中,我们将通过使用这个轻型框架构建一个基本的REST微服务的步骤。
2. Adding Dependencies
2.添加依赖性
To create a basic application, we only need one dependency – Javalin itself:
要创建一个基本的应用程序,我们只需要一个依赖项–Javalin本身。
<dependency>
<groupId>io.javalin</groupId>
<artifactId>javalin</artifactId>
<version>1.6.1</version>
</dependency>
The current version can be found here.
目前的版本可以在这里找到。
3. Setting up Javalin
3.设置Javalin
Javalin makes setting up a basic application easy. We’re going to start by defining our main class and setting up a simple “Hello World” application.
Javalin使设置一个基本的应用程序变得简单。我们将从定义我们的主类开始,设置一个简单的 “Hello World “应用程序。
Let’s create a new file in our base package called JavalinApp.java.
让我们在我们的基础包中创建一个新文件,名为JavalinApp.java。
Inside this file, we create a main method and add the following to set up a basic application:
在这个文件中,我们创建一个main方法,并添加以下内容来设置一个基本的应用程序。
Javalin app = Javalin.create()
.port(7000)
.start();
app.get("/hello", ctx -> ctx.html("Hello, Javalin!"));
We’re creating a new instance of Javalin, making it listen on port 7000, and then starting the application.
我们正在创建一个新的Javalin实例,让它监听7000端口,然后启动应用程序。
We’re also setting up our first endpoint listening for a GET request at the /hello endpoint.
我们还设置了第一个端点,在/hello端点监听GET请求。
Let’s run this application and visit http://localhost:7000/hello to see the results.
让我们运行这个应用程序并访问http://localhost:7000/hello以查看结果。
4. Creating a UserController
4.创建一个UserController
A “Hello World” example is great for introducing a topic, but it isn’t beneficial for a real application. Let’s look into a more realistic use case for Javalin now.
一个 “Hello World “的例子对于介绍一个主题来说是很好的,但是对于一个真正的应用来说,它并没有好处。现在让我们来看看Javalin的一个更现实的用例。
First, we need to create a model of the object we’re working with. We start by creating a package called user under the root project.
首先,我们需要创建一个我们正在处理的对象的模型。我们首先在根项目下创建一个名为user的包。
Then, we add a new User class:
然后,我们添加一个新的User类。
public class User {
public final int id;
public final String name;
// constructors
}
Also, we need to set up our data access object (DAO). We’ll use an in-memory object to store our users in this example.
另外,我们需要设置我们的数据访问对象(DAO)。在这个例子中,我们将使用一个内存对象来存储我们的用户。
We create a new class in the user packaged called UserDao.java:
我们在用户包中创建一个新的类,名为UserDao.java:。
class UserDao {
private List<User> users = Arrays.asList(
new User(0, "Steve Rogers"),
new User(1, "Tony Stark"),
new User(2, "Carol Danvers")
);
private static UserDao userDao = null;
private UserDao() {
}
static UserDao instance() {
if (userDao == null) {
userDao = new UserDao();
}
return userDao;
}
Optional<User> getUserById(int id) {
return users.stream()
.filter(u -> u.id == id)
.findAny();
}
Iterable<String> getAllUsernames() {
return users.stream()
.map(user -> user.name)
.collect(Collectors.toList());
}
}
Implementing our DAO as a singleton makes it easier to use in the example. We could also declare it as a static member of our main class or use dependency injection from a library like Guice if we wanted to.
将我们的DAO实现为一个单子,使得它在这个例子中更容易使用。我们也可以把它声明为主类的一个静态成员,或者如果我们想的话,从Guice这样的库中使用依赖注入。
Finally, we want to create our controller class. Javalin allows us to be very flexible when we declare our route handlers, so this is only one way of defining them.
最后,我们要创建我们的控制器类。Javalin允许我们在声明我们的路由处理程序时非常灵活,所以这只是定义它们的一种方式。
We create a new class called UserController.java in the user package:
我们在user包中创建一个名为UserController.java的新类。
public class UserController {
public static Handler fetchAllUsernames = ctx -> {
UserDao dao = UserDao.instance();
Iterable<String> allUsers = dao.getAllUsernames();
ctx.json(allUsers);
};
public static Handler fetchById = ctx -> {
int id = Integer.parseInt(Objects.requireNonNull(ctx.param("id")));
UserDao dao = UserDao.instance();
Optional<User> user = dao.getUserById(id);
if (user.isPresent()) {
ctx.json(user);
} else {
ctx.html("Not Found");
}
};
}
By declaring the handlers as static, we ensure that the controller itself holds no state. But, in more complex applications, we may want to store state between requests, in which case we’d need to remove the static modifier.
通过将处理程序声明为静态,我们确保控制器本身不持有任何状态。但是,在更复杂的应用中,我们可能希望在不同的请求之间存储状态,在这种情况下,我们需要删除静态修改器。
Also note that unit testing is harder with static methods, so if we want that level of testing we will need to use non-static methods.
还要注意的是,静态方法的单元测试比较困难,所以如果我们想获得这种水平的测试,我们需要使用非静态方法。
5. Adding Routes
5.添加路线
We now have multiple ways of fetching data from our model. The last step is to expose this data via REST endpoints. We need to register two new routes in our main application.
我们现在有多种方式从我们的模型中获取数据。最后一步是通过REST端点公开这些数据。我们需要在我们的主程序中注册两个新的路由。
Let’s add them to our main application class:
让我们把它们添加到我们的主应用程序类中。
app.get("/users", UserController.fetchAllUsernames);
app.get("/users/:id", UserController.fetchById);
After compiling and running the application, we can make a request to each of these new endpoints. Calling http://localhost:7000/users will list all users and calling http://localhost:7000/users/0 will get the single User JSON object with the id 0. We now have a microservice that allows us to retrieve User data.
在编译和运行该应用程序后,我们可以向这些新的端点中的每一个提出请求。调用http://localhost:7000/users将列出所有用户,而调用http://localhost:7000/users/0将获得id为0的单一用户JSON对象。我们现在有一个微服务,允许我们检索User数据。
6. Extending Routes
6.扩展路线
Retrieving data is a vital task of most microservices.
检索数据是大多数微服务的一项重要任务。
However, we also need to be able to store data in our datastore. Javalin provides the full set of path handlers that are required to build services.
然而,我们还需要能够在我们的数据存储中存储数据。Javalin提供了构建服务所需的全套路径处理程序。
We saw an example of GET above, but PATCH, POST, DELETE, and PUT are possible as well.
我们在上面看到了GET的例子,但PATCH、POST、DELETE和PUT也是可能的。
Also, if we include Jackson as a dependency, we can parse JSON request bodies automatically into our model classes. For instance:
另外,如果我们把Jackson作为一个依赖项,我们可以自动解析JSON请求体到我们的模型类中。比如说。
app.post("/") { ctx ->
User user = ctx.bodyAsClass(User.class);
}
would allow us to grab the JSON User object from the request body and translate it into the User model object.
将允许我们从请求体中抓取JSON User 对象,并将其转换为User 模型对象。
7. Conclusion
7.结论
We can combine all of these techniques to make our microservice.
我们可以结合所有这些技术来制作我们的微服务。
In this article, we saw how to set up Javalin and build a simple application. We also talked about how to use the different HTTP method types to let clients interact with our service.
在这篇文章中,我们看到了如何设置Javalin并建立一个简单的应用程序。我们还谈到了如何使用不同的HTTP方法类型来让客户与我们的服务进行交互。
For more advanced examples of how to use Javalin, be sure to check out the documentation.
关于如何使用Javalin的更多高级示例,请务必查看文档。
Also, as always, the code can be found over on GitHub.
此外,像往常一样,可以在GitHub上找到代码。