如何访问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客户端时,调用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方法应该接受JSON对象而不是字符串。Jersey使用JAXB支持封送和反封送JSON对象(请参阅Jersey文档了解详细信息)。创建如下的类:

@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编码的

如果你不知道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 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

您必须特别小心地在客户端正确编码查询参数。由于某些代理强制的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支持的各种方法提供一些启发。

注意:为了充分披露,我还没有实际使用Jersey的这个功能。由于我们已经部署了许多JAXB+JAX-RS应用程序,并且正在进入移动客户端领域,因此我们一直在对它进行修补。JSON比XML更适合HTML5或基于jquery的解决方案。

相关内容

最新更新