1. Overview
1.概述
There are many web frameworks like Spring, Play, and Grails available in the Java ecosystem. However, none of them can claim to be completely immutable and object-oriented.
在Java生态系统中,有许多Web框架,如Spring、Play,以及Grails。然而,它们都不能声称是完全不可变的和面向对象的。
In this tutorial, we’ll explore the Takes framework and create a simple web application using its common features like routing, request/response handling, and unit testing.
在本教程中,我们将探索Takes框架,并利用其常见的功能如路由、请求/响应处理和单元测试创建一个简单的Web应用。
2. Takes
2.摄取
Takes is an immutable Java 8 web framework that neither uses null nor public static methods.
Takes是一个不可变的Java 8网络框架,既不使用null也不使用public static方法。
Also, the framework doesn’t support mutable classes, casting, or reflection. Hence, it is a true object-oriented framework.
此外,该框架不支持可变类、铸造或反射。因此,它是一个真正的面向对象的框架。
Takes don’t require configuration files for the setup. Besides that, it provides built-in features like JSON/XML response and templating.
Takes不需要配置文件的设置。除此之外,它还提供内置功能,如JSON/XML响应和模板化。
3. Setup
3.设置
First, we’ll add the latest takes Maven dependency to the pom.xml:
首先,我们要把最新的takesMaven依赖性添加到pom.xml。
<dependency>
<groupId>org.takes</groupId>
<artifactId>takes</artifactId>
<version>1.19</version>
</dependency>
Then, let’s create the TakesHelloWorld class that implements the Take interface:
然后,让我们创建TakesHelloWorld类,实现Take接口。
public class TakesHelloWorld implements Take {
@Override
public Response act(Request req) {
return new RsText("Hello, world!");
}
}
The Take interface provides the fundamental feature of the framework. Each Take serves as a request handler, returning the response through the act method.
Take接口提供了该框架的基本特征。每个Take作为一个请求处理程序,通过act方法返回响应。
Here, we’ve used the RsText class to render the plain text Hello, world! as a response, when a request is made to the TakesHelloWorld take.
在这里,我们使用RsText类来渲染纯文本Hello, world!作为响应,当一个请求被送到TakesHelloWorld取时。
Next, we’ll create the TakesApp class to start the web application:
接下来,我们将创建TakesApp类来启动网络应用。
public class TakesApp {
public static void main(String... args) {
new FtBasic(new TakesHelloWorld()).start(Exit.NEVER);
}
}
Here, we’ve used the FtBasic class that provides the basic implementation of the Front interface to start the webserver and forward the request to the TakesHelloWorld take.
在这里,我们使用了FtBasic类,它提供了Front接口的基本实现,以启动Webserver并将请求转发给TakesHelloWorld采取。
Takes implements its own stateless webserver by using the ServerSocket class. By default, it starts the server on port 80. However, we can define the port in the code:
Takes通过使用ServerSocket类来实现自己的无状态Webserver。默认情况下,它在80端口启动服务器。然而,我们可以在代码中定义端口。
new FtBasic(new TakesHelloWorld(), 6060).start(Exit.NEVER);
Or, we can pass the port number using the command-line parameter –port.
或者,我们可以使用命令行参数-port传递端口号。
Then, let’s compile the classes using the Maven command:
然后,让我们用Maven命令编译这些类:
mvn clean package
Now, we’re ready to run the TakesApp class as a simple Java application in an IDE.
现在,我们准备在IDE中把TakesApp类作为一个简单的Java应用程序运行。
4. Run
4.运行
We can also run our TakesApp class as a separate web server application.
我们也可以将我们的TakesApp类作为一个单独的Web服务器应用程序运行。
4.1. Java Command Line
4.1 Java命令行
First, let’s compile our classes:
首先,我们来编译我们的类。
javac -cp "takes.jar:." com.baeldung.takes.*
Then, we can run the application using the Java command line:
然后,我们可以使用Java命令行运行该应用程序。
java -cp "takes.jar:." com.baeldung.takes.TakesApp --port=6060
4.2. Maven
4.2. Maven
Or, we can use the exec-maven-plugin plugin to run it through Maven:
或者,我们可以使用exec-maven-plugin插件来通过Maven运行它。
<profiles>
<profile>
<id>reload</id>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<id>start-server</id>
<phase>pre-integration-test</phase>
<goals>
<goal>java</goal>
</goals>
</execution>
</executions>
<configuration>
<mainClass>com.baeldung.takes.TakesApp</mainClass>
<cleanupDaemonThreads>false</cleanupDaemonThreads>
<arguments>
<argument>--port=${port}</argument>
</arguments>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>
Now, we can run our app using the Maven command:
现在,我们可以使用Maven命令运行我们的应用程序。
mvn clean integration-test -Preload -Dport=6060
5. Routing
5.路由
The framework provides the TkFork class to route the requests to different takes.
该框架提供了TkFork类来将请求路由到不同的地方。
For instance, let’s add a few routes to our application:
例如,让我们向我们的应用程序添加一些路由。
public static void main(String... args) {
new FtBasic(
new TkFork(
new FkRegex("/", new TakesHelloWorld()),
new FkRegex("/contact", new TakesContact())
), 6060
).start(Exit.NEVER);
}
Here, we’ve used the FkRegex class to match the request path.
这里,我们使用了FkRegex类来匹配请求路径。
6. Request Handling
6.请求处理
The framework provides a few decorator classes in the org.takes.rq package to handle the HTTP request.
该框架在org.takes.rq包中提供了一些decorator类来处理HTTP请求。
For example, we can use the RqMethod interface to extract the HTTP method:
例如,我们可以使用RqMethod接口来提取HTTP方法。
public class TakesHelloWorld implements Take {
@Override
public Response act(Request req) throws IOException {
String requestMethod = new RqMethod.Base(req).method();
return new RsText("Hello, world!");
}
}
Similarly, the RqHeaders interface is available to fetch the request headers:
同样,RqHeaders接口也可用于获取请求头文件。
Iterable<String> requestHeaders = new RqHeaders.Base(req).head();
We can use the RqPrint class to get the body of the request:
我们可以使用RqPrint类来获取请求的主体。
String body = new RqPrint(req).printBody();
Likewise, we can use the RqFormSmart class to access the form parameter:
同样地,我们可以使用RqFormSmart类来访问表单参数。
String username = new RqFormSmart(req).single("username");
7. Response Handling
7. 响应处理
Takes also provides many useful decorators to handle the HTTP response in the org.takes.rs package.
Takes还提供了许多有用的装饰器来处理org.takes.rs包中的HTTP响应。
The response decorator implements the head and body methods of the Response interface.
响应装饰器实现了Response接口的head和body方法。
For instance, the RsWithStatus class renders the response with status code:
例如,RsWithStatus类渲染了带有状态代码的响应。
Response resp = new RsWithStatus(200);
The output of the response can be verified using the head method:
响应的输出可以使用head方法进行验证。
assertEquals("[HTTP/1.1 200 OK], ", resp.head().toString());
Similarly, the RsWithType class renders the response with content-type:
类似地,RsWithType类渲染了带有内容类型的响应。
Response resp = new RsWithType(new RsEmpty(), "text/html");
Here, the RsEmpty class renders the empty response.
这里,RsEmpty类渲染了空响应。
Likewise, we can use the RsWithBody class to render the response with the body.
同样地,我们可以使用RsWithBody类来渲染带有body的响应。
So, let’s create the TakesContact class and use the discussed decorators to render the response:
因此,让我们创建TakesContact类,并使用所讨论的装饰器来渲染响应。
public class TakesContact implements Take {
@Override
public Response act(Request req) throws IOException {
return new RsWithStatus(
new RsWithType(
new RsWithBody("Contact us at https://www.baeldung.com"),
"text/html"), 200);
}
}
Similarly, we can use the RsJson class to render the JSON response:
同样地,我们可以使用RsJson类来渲染JSON响应。
@Override
public Response act(Request req) {
JsonStructure json = Json.createObjectBuilder()
.add("id", rs.getInt("id"))
.add("user", rs.getString("user"))
.build();
return new RsJson(json);
}
8. Exception Handling
8.异常处理
The framework contains the Fallback interface to handle exceptional conditions. It also provides a few implementations to handle the fallback scenarios.
该框架包含Fallback接口,以处理特殊情况。它还提供了一些实现来处理回退场景。
For instance, let’s use the TkFallback class to handle the HTTP 404 and shows a message to the user:
例如,让我们使用TkFallback类来处理HTTP 404并向用户显示一条信息。
public static void main(String... args) throws IOException, SQLException {
new FtBasic(
new TkFallback(
new TkFork(
new FkRegex("/", new TakesHelloWorld()),
// ...
),
new FbStatus(404, new RsText("Page Not Found"))), 6060
).start(Exit.NEVER);
}
Here, we’ve used the FbStatus class to handle the fallback on the defined status code.
在这里,我们使用了FbStatus类来处理定义状态代码的回退。
Similarly, we can use the FbChain class to define a combination of fallbacks:
同样,我们可以使用FbChain类来定义一个回退的组合。
new TkFallback(
new TkFork(
// ...
),
new FbChain(
new FbStatus(404, new RsText("Page Not Found")),
new FbStatus(405, new RsText("Method Not Allowed"))
)
), 6060
).start(Exit.NEVER);
Also, we can implement the Fallback interface to handle the exceptions:
另外,我们可以实现Fallback接口来处理异常。
new FbChain(
new FbStatus(404, new RsText("Page Not Found")),
new FbStatus(405, new RsText("Method Not Allowed")),
new Fallback() {
@Override
public Opt<Response> route(RqFallback req) {
return new Opt.Single<Response>(new RsText(req.throwable().getMessage()));
}
}
)
9. Templates
9.模板
Let’s integrate Apache Velocity with our Takes web app to provide some templating functionality.
让我们将Apache Velocity与我们的Takes Web应用程序集成,以提供一些模板功能。
First, we’ll add the velocity-engine-core Maven dependency:
首先,我们要添加velocity-engine-core Maven依赖。
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-engine-core</artifactId>
<version>2.2</version>
</dependency>
Then, we’ll use the RsVelocity class to define the template string and the binding parameters in the act method:
然后,我们将使用RsVelocity类来定义模板字符串和act方法中的绑定参数。
public class TakesIndex implements Take {
@Override
public Response act(Request req) throws IOException {
return new RsHtml(
new RsVelocity("${username}", new RsVelocity.Pair("username", "Baeldung")));
);
}
}
Here, we’ve used the RsHtml class to render the HTML response.
在这里,我们使用了RsHtml类来渲染HTML响应。
Also, we can use a velocity template with the RsVelocity class:
此外,我们还可以使用速度模板与RsVelocity类。
new RsVelocity(this.getClass().getResource("/templates/index.vm"),
new RsVelocity.Pair("username", username))
);
10. Unit Testing
10.单元测试
The framework supports unit testing of any Take by providing the RqFake class that creates a fake request:
该框架通过提供创建假请求的RqFake类,支持对任何Take进行单元测试。
For example, let’s write a unit test for our TakesContact class using JUnit:
例如,让我们使用JUnit为我们的TakesContact类编写一个单元测试。
String resp = new RsPrint(new TakesContact().act(new RqFake())).printBody();
assertEquals("Contact us at https://www.baeldung.com", resp);
11. Integration Testing
11.集成测试
We can test the entire application using JUnit and any HTTP client.
我们可以使用JUnit和任何HTTP客户端测试整个应用程序。
The framework provides the FtRemote class that starts the server on the random port and provides remote control to the execution of the Take.
该框架提供了FtRemote类,它在随机端口上启动服务器,并为Take的执行提供远程控制。
For instance, let’s write an integration test and verify the response of the TakesContact class:
例如,让我们写一个集成测试,验证TakesContact类的响应。
new FtRemote(new TakesContact()).exec(
new FtRemote.Script() {
@Override
public void exec(URI home) throws IOException {
HttpClient client = HttpClientBuilder.create().build();
HttpResponse response = client.execute(new HttpGet(home));
int statusCode = response.getStatusLine().getStatusCode();
HttpEntity entity = response.getEntity();
String result = EntityUtils.toString(entity);
assertEquals(200, statusCode);
assertEquals("Contact us at https://www.baeldung.com", result);
}
});
Here, we’ve used Apache HttpClient to make the requests to the server and verify the response.
在这里,我们使用了Apache HttpClient来向服务器发出请求并验证响应。
12. Conclusion
12.结语
In this tutorial, we’ve explored the Takes framework by creating a simple web application.
在本教程中,我们通过创建一个简单的Web应用来探索Takes框架。
First, we’ve seen a quick way to set up the framework in our Maven project and run our application.
首先,我们已经看到了在Maven项目中设置框架并运行应用程序的快速方法。
Then, we examined a few common features like routing, request/response handling, and unit testing.
然后,我们研究了一些常见的功能,如路由、请求/响应处理和单元测试。
Lastly, we explored the support of unit and integration testing provided by the framework.
最后,我们探讨了该框架所提供的单元和集成测试的支持。
As usual, all the code implementations are available over on GitHub.
像往常一样,所有的代码实现都可以在GitHub上找到,。