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

Posted

技术标签:

【中文标题】如何访问 RESTful POST 方法中的参数【英文标题】:How to access parameters in a RESTful POST method 【发布时间】:2012-01-01 22:11:29 【问题描述】:

我的 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 客户端时,调用 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 = 

我需要更改哪些参数才能给出正确的值?

【问题讨论】:

你是否在安卓应用上使用这个? 我终于想在一个安卓应用中调用这个post方法。不知何故,网络服务不知道如何对参数的值进行签名。我想知道怎么做。 【参考方案1】:

您的 @POST 方法应该接受 JSON 对象而不是字符串。 Jersey 使用 JAXB 支持编组和解组 JSON 对象(请参阅the jersey docs for details)。创建一个类:

@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 对象作为 HTTP POST 的正文。 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 中,您将使用 MessageBodyReader 和 MessageBodyWriter 来实现这一点。我相信 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-urlencoded" 对表单进行编码。 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

本例中内容为URL encoded

如果您不知道 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 查询参数

此方法主要用于 HTTP GET,但同样适用于 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

您必须特别小心在客户端正确encode query parameters。由于某些代理强制执行 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

此方法与查询参数版本具有相同的编码问题。 Path segments are encoded differently 所以你也必须小心。


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

注意:为了全面披露,我还没有真正使用 Jersey 的这个功能。我们正在修改它,因为我们部署了许多 JAXB+JAX-RS 应用程序并且正在进入移动客户端空间。 JSON 比 XML 更适合 HTML5 或基于 jQuery 的解决方案。

【讨论】:

我昨天测试了这个功能,不需要@XmlElement 注释 谢谢。如果我仍然想发送 2 个字符串,那么 restfull 需要能够使用什么?还是多个参数仅适用于@PathParm? @Klaasvaak - 您需要指定每个参数的提取位置。正如您现在所拥有的那样,Jersey/NetBeans 正在假设一个表单发布并提取作为 FormParm 发送的数据。用您想要数据的位置(PathParam、FormParam、CookieParam 等)注释您的每个方法扩充 @Klaasvaak - 我使用各种注释添加了一堆示例 非常感谢您!这真的是我一直在寻找的。你成就了我的一天;)我现在正在使用 FormParams,它可以工作了!

以上是关于如何访问 RESTful POST 方法中的参数的主要内容,如果未能解决你的问题,请参考以下文章

如何通过类对象作为方法参数的RESTful服务吗

Android - 将参数传递给 Android 应用程序中的 RESTful URL

如何将两个不同的对象传递给邮递员中的 POST 请求以测试 RESTful API?

使用 HTTP RESTful 方法 GET/POST/等。它们是多余的吗?

python用post访问restful服务接口

Jersey写Restful接口获取参数的问题