如何访问 RESTful POST 方法中的参数

我的 POST 方法如下:

@POST
@Consumes({"application/json"})
@Path("create/")
public void create(String param1, String param2){
System.out.println("param1 = " + param1);
System.out.println("param2 = " + param2);
}

当我在 Netbeans 中创建 Jersey Client 时,调用 post 方法的方法如下所示:

public void create(Object requestEntity){
webResource.path("create").type(MediaType.APPLICATION_JSON).post(requestEntity);
}

运行此测试时:

@Test
public void hello(){
String json = "{param1=\"hello\",param2=\"hello2\"}";
this.client.create(json);
}

它在服务器中提供以下输出:

INFO: param1 = {param1="hello",param2="hello2"}
INFO: param2 =

What do I need to change so that the parameters are giving the correct value?

319303 次浏览

您的 @POST方法应该接受 JSON 对象而不是字符串。Jersey 使用 JAXB 来支持编组和解组 JSON 对象(请参见 新泽西州文件的细节)。创建一个类:

@XmlRootElement
public class MyJaxBean {
@XmlElement public String param1;
@XmlElement public String param2;
}

那么你的 @POST方法看起来如下:

@POST @Consumes("application/json")
@Path("/create")
public void create(final MyJaxBean input) {
System.out.println("param1 = " + input.param1);
System.out.println("param2 = " + input.param2);
}

这个方法期望接收 JSON 对象作为 HTTPPOST 的主体。JAX-RS 将 HTTP 消息的内容体作为未注释的参数传递——在本例中为 input。实际的信息应该是这样的:

POST /create HTTP/1.1
Content-Type: application/json
Content-Length: 35
Host: www.example.com


{"param1":"hello","param2":"world"}

由于显而易见的原因,以这种方式使用 JSON 非常普遍。但是,如果您使用 JavaScript 以外的其他工具生成或使用它,那么您必须小心地正确转义数据。在 JAX-RS 中,可以使用 MessageBodyReaderMessageBodyWriter来实现这一点。我相信 Jersey 已经实现了所需类型(例如,Java 原语和 JAXB 包装类)以及 JSON。JAX-RS 支持许多其他传递数据的方法。这些不需要创建新类,因为数据是通过简单的参数传递传递的。


HTML <FORM>

参数将使用 @ FormParam进行注释:

@POST
@Path("/create")
public void create(@FormParam("param1") String param1,
@FormParam("param2") String param2) {
...
}

浏览器将使用 “ application/x-www-form-urlencode”对表单进行编码。JAX-RS 运行时将负责解码主体并将其传递给方法。这是你应该在电线上看到的:

POST /create HTTP/1.1
Host: www.example.com
Content-Type: application/x-www-form-urlencoded;charset=UTF-8
Content-Length: 25


param1=hello&param2=world

本例中的内容是 < em > 已编码的 URL

如果您不知道 FormParam 的名称,您可以执行以下操作:

@POST @Consumes("application/x-www-form-urlencoded")
@Path("/create")
public void create(final MultivaluedMap<String, String> formParams) {
...
}

HTTP 头

如果希望通过 HTTP 头传递参数,可以使用 @ HeaderParam注释:

@POST
@Path("/create")
public void create(@HeaderParam("param1") String param1,
@HeaderParam("param2") String param2) {
...
}

下面是 HTTP 消息的样子。请注意,这个 POST 没有主体。

POST /create HTTP/1.1
Content-Length: 0
Host: www.example.com
param1: hello
param2: world

对于广义参数传递,我不会使用这种方法。但是,如果您需要访问特定 HTTP 头的值,那么它确实非常方便。


HTTP 查询参数

此方法主要用于 HTTPGET,但也同样适用于 POST。它使用 @QueryParam注释。

@POST
@Path("/create")
public void create(@QueryParam("param1") String param1,
@QueryParam("param2") String param2) {
...
}

与前面的技术一样,通过查询字符串传递参数不需要消息体。下面是 HTTP 消息:

POST /create?param1=hello&param2=world HTTP/1.1
Content-Length: 0
Host: www.example.com

您必须特别小心才能在客户端正确地使用 编码查询参数。由于某些代理强制执行的 URL 长度限制以及与编码它们相关的问题,使用查询参数可能会带来问题。


HTTP 路径参数

路径参数与查询参数类似,只不过它们嵌入在 HTTP 资源路径中。这种方法今天似乎受到欢迎。由于路径才是真正定义 HTTP 资源的东西,因此对 HTTP 缓存有一些影响。由于修改了 @ Path注释并使用了 @ PathParam,因此这段代码看起来与其他代码略有不同:

@POST
@Path("/create/{param1}/{param2}")
public void create(@PathParam("param1") String param1,
@PathParam("param2") String param2) {
...
}

该消息类似于查询参数版本,只是参数的名称不包括在消息中的任何位置。

POST /create/hello/world HTTP/1.1
Content-Length: 0
Host: www.example.com

此方法与查询参数版本共享相同的编码问题。所以你在那里也要小心。


正如您所看到的,每种方法都有利有弊。选择通常是由你的客户决定的。如果您提供的是基于 FORM的 HTML 页面,那么使用 @FormParam。如果您的客户端是基于 JavaScript + HTML5的,那么您可能希望使用基于 JAXB 的序列化和 JSON 对象。MessageBodyReader/Writer实现应该为您处理必要的转义,这样就少了一个可能出错的地方。如果您的客户端是基于 Java 的,但是没有一个好的 XML 处理器(例如,Android) ,那么我可能会使用 FORM编码,因为内容主体比 URL 更容易生成和正确编码。希望这个迷你 wiki 条目能够对 JAX-RS 支持的各种方法有所帮助。

Note: in the interest of full disclosure, I haven't actually used this feature of Jersey yet. We were tinkering with it since we have a number of JAXB+JAX-RS applications deployed and are moving into the mobile client space. JSON is a much better fit that XML on HTML5 or jQuery-based solutions.