@FormDataParam vs. @FormParam in Jersey – 泽西岛的 @FormDataParam vs. @FormParam

最后修改: 2023年 10月 17日

中文/混合/英文(键盘快捷键:t)

 1. Introduction

1.导言

Jersey is a full-featured open-source framework for developing web services and clients using Java. By using Jersey, we can create robust web applications that support the full set of HTTP features.

泽西是一个功能齐全的开源框架,用于使用 Java 开发网络服务和客户端。通过使用 Jersey,我们可以创建支持全套 HTTP 功能的强大 Web 应用程序

In this article, we’ll look at two specific features of Jersey: the @FormDataParam and @FormParam annotations. While these two annotations are similar in nature, they have significant differences, as we’ll see below.

在本文中,我们将了解 Jersey 的两个特定功能:@FormDataParam@FormParam 注释。虽然这两个注解在性质上相似,但它们有很大的不同,我们将在下文中看到。

2. Background

2. 背景

There are many ways to exchange data between clients and servers. The two most popular are XML and JSON, but they aren’t the only options.

在客户端和服务器之间交换数据有很多方法。最流行的两种是 XML 和 JSON,但它们并不是唯一的选择。

Form encoded data is another way to format data when sending it between a client and server, particularly when the client is a web page. This is because HTML makes it easy to define forms with a variety of inputs (text, checkboxes, drop downs, etc) and send that data back to a remote server.

表单编码数据是在客户端和服务器之间发送数据时格式化数据的另一种方法,尤其是当客户端是一个网页时。这是因为 HTML 可以轻松定义带有各种输入(文本、复选框、下拉选项等)的表单,并将数据发回远程服务器。

This is where the @FormDataParam vs. @FormParam annotations come in. They are both used to handle form data in a Jersey server application but with some important differences.

这就是 @FormDataParam@FormParam 注解的区别所在。它们都用于在 Jersey 服务器应用程序中处理表单数据,但有一些重要区别。

Now that we know the background of both annotations, let’s take a look at how to use each one and some of their differences.

既然我们已经了解了这两种注释的背景,那么让我们来看看如何使用每一种注释以及它们之间的一些区别。

3. Using @FormParam

3.使用 @FormParam

In short, we use the @FormParam annotation whenever the API expects URL-encoded data. Let’s look at a simple HTML form with only text fields:

简而言之,只要 API 希望使用 URL 编码数据,我们就会使用 @FormParam 注解。让我们来看一个只有文本字段的简单 HTML 表单:

<form method="post" action="/example1">
    <input name="first_name" type="text">
    <input name="last_name" type="text">
    <input name="age" type="text">
    <input type="submit">
</form>

This form has three fields: first name, last name, and age. It also uses the HTTP POST method to send the form data to a URL located at /example1.

该表单有三个字段:名、姓和年龄。它还使用 HTTP POST 方法将表单数据发送到位于 /example1 的 URL。

To process this form using Jersey, we would define the following endpoint in our server application:

要使用 Jersey 处理该表单,我们需要在服务器应用程序中定义以下端点:

@POST
@Path("/example1")
public String example1(
  @FormParam("first_name") String firstName,
  @FormParam("last_name") String lastName,
  @FormParam("age") String age)
{
    // process form data
}

Notice that we use the annotation for each field in the HTML form. This works the same regardless of how many or what types of fields the form has. By using the @FormParam annotation, Jersey binds the value from each field into the corresponding method parameter.

请注意,我们对 HTML 表单中的每个字段都使用了注释。无论表单中有多少个字段,也无论字段的类型是什么,该注解的作用都是一样的。通过使用 @FormParam 注解,Jersey 将每个字段的值绑定到相应的方法参数中。

In practice, form-encoded data correlates to the MIME type application/x-www-form-urlencoded. Under the hood, the data sent between the web browser and our service looks like this:

实际上,表单编码数据与 MIME 类型 application/x-www-form-urlencoded 相关。在引擎盖下,网络浏览器和我们的服务之间发送的数据如下所示:

first_name=john&last_name=smith&age=42

The benefit of this approach is that the data is easy to process because it only involves text and no binary data. Additionally, this approach can work using the HTTP GET verb because the string can be passed as query parameters in the URL. However, we should be careful when passing form data via URL since it may contain sensitive data.

这种方法的优点是数据易于处理,因为它只涉及文本而不涉及二进制数据。此外,这种方法还可以使用 HTTP GET verb,因为字符串可以作为查询参数传递到 URL 中。不过,在通过 URL 传递表单数据时,我们应该小心谨慎,因为其中可能包含敏感数据。

4. Using @FormDataParam

4.使用 @FormDataParam

In contrast, the @FormDataParam annotation is more flexible and can handle any combination of text and binary data. In practical terms, this is useful for things like file uploads with HTML forms.

相比之下,@FormDataParam注解更加灵活,可以处理文本和二进制数据的任意组合。在实际应用中,这对于使用 HTML 表单上传文件等操作非常有用。

Let’s look at an example form using the @FormDataParam annotation. To start, we must first import the jersey-media-multipart module from Maven Central into our project:

让我们来看一个使用 @FormDataParam 注解的表单示例。首先,我们必须从 Maven Centraljersey-media-multipart 模块导入我们的项目:

<dependency>
    <groupId>org.glassfish.jersey.media</groupId>
    <artifactId>jersey-media-multipart</artifactId>
    <version>3.1.3</version>
</dependency>

Now, let’s add a file upload field to the HTML form we created above:

现在,让我们在上面创建的 HTML 表单中添加一个文件上传字段:

<form method="post" action="/example2" enctype="multipart/form-data >
    <input name="first_name" type="text">
    <input name="last_name" type="text">
    <input name="age" type="text">
    <input name="photo" type="file">
    <input type="submit">
</form>

Notice that we’re now specifying the encoding type of multipart/form-data in the form element. This is necessary so the web browser sends the data in a format that our service is expecting.

请注意,我们现在在表单元素中指定了 multipart/form-data 的编码类型。这是必要的,这样网络浏览器才能以我们的服务所期望的格式发送数据。

Next, in our application, we would create the following endpoint to handle the data from this form:

接下来,我们将在应用程序中创建以下端点来处理来自该表单的数据:

@POST
@Path("/example2")
public String example2(
  @FormDataParam("first_name") String firstName,
  @FormDataParam("last_name") String lastName,
  @FormDataParam("age") String age,
  @FormDataParam("photo") InputStream photo)
{
    // handle form data
}

Notice that each form field now uses the @FormDataParam annotation. We also use an InputStream as the parameter type that handles the binary data.

请注意,现在每个表单字段都使用了 @FormDataParam 注解。我们还使用 InputStream 作为处理二进制数据的参数类型。

Unlike the previous example, where each field and its value were combined into a string, this example combines the fields into parts. Each part is separated by a unique token, allowing Jersey to easily identify each parameter and bind each part into the corresponding method parameter.

在上一个示例中,每个字段及其值都被组合成一个字符串,而本示例则不同,它将字段组合成多个部分。每个部分都由一个唯一的标记分隔,这样 Jersey 就能轻松识别每个参数,并将每个部分绑定到相应的方法参数中。

For example, the raw message sent from this form into our service might look like this:

例如,从该表单发送到我们服务的原始信息可能如下所示:

------WebKitFormBoundarytCyB57mkvJedAHFx
Content-Disposition: form-data; name="first_name"

John
------WebKitFormBoundarytCyB57mkvJedAHFx
Content-Disposition: form-data; name="last_name"

Smith
------WebKitFormBoundarytCyB57mkvJedAHFx
Content-Disposition: form-data; name="age"

42
------WebKitFormBoundarytCyB57mkvJedAHFx
Content-Disposition: form-data; name="photo"; filename="john-smith-profile.jpeg"
Content-Type: image/jpeg


------WebKitFormBoundarytCyB57mkvJedAHFx--

The main benefit of this approach is that we can send text and binary data together. However, there are some downsides when compared to using traditional form-encoded data.

这种方法的主要优点是我们可以同时发送文本和二进制数据。不过,与使用传统的表单编码数据相比,这种方法也有一些缺点。

First, we can only use the HTTP POST verb with this type. This is because the binary data cannot be encoded and passed along the URL string. Second, the payload sizes are much larger in size. As we can see in the example above, the additional text required to define separators and headers adds quite a bit of size above normal form-encoded data.

首先,我们只能使用 HTTP POST verb 该类型。这是因为二进制数据无法编码,也无法沿 URL 字符串传递。其次,有效负载的大小要大得多。正如我们在上面的示例中看到的,定义分隔符和标题所需的额外文本比正常的表单编码数据要大得多。

5. Conclusion

5.结论

In this article, we have looked at two different annotations in the Jersey library: @FormParam and @FormDataParam. Both of these annotations process form data in an application, but as we saw, they have very different purposes.

在本文中,我们研究了 Jersey 库中的两种不同注解:@FormParam@FormDataParam.这两个注解都在应用程序中处理表单数据,但正如我们所见,它们的目的截然不同

The @FormParam is better when sending form-encoded data. This can use either GET or POST verbs but can only include text fields. On the other hand, the @FormDataParam annotation processes multi-part data. This can include text and binary data but only works with the POST verb.

在发送表单编码数据时,使用 @FormParam 效果更好。它可以使用 GETPOST 动词,但只能包含文本字段。另一方面,@FormDataParam 注解可处理多部分数据。这可以包括文本和二进制数据,但只能与 POST 动词一起使用。

Finally, all of the code examples in this article are located over on GitHub.

最后,本文中的所有代码示例都位于 GitHub 上。