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

Kla*_*aak 118 java rest web-services jax-rs jersey

我的POST方法如下所示:

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

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

public void create(Object requestEntity){
    webResource.path("create").type(MediaType.APPLICATION_JSON).post(requestEntity);
}
Run Code Online (Sandbox Code Playgroud)

运行此测试时:

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

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

INFO: param1 = {param1="hello",param2="hello2"}
INFO: param2 = 
Run Code Online (Sandbox Code Playgroud)

我需要更改什么才能使参数给出正确的值?

D.S*_*ley 345

您的@POST方法应该接受JSON对象而不是字符串.Jersey使用JAXB来支持编组和解组JSON对象(有关详细信息,请参阅jersey文档).创建一个类,如:

@XmlRootElement
public class MyJaxBean {
    @XmlElement public String param1;
    @XmlElement public String param2;
}
Run Code Online (Sandbox Code Playgroud)

然后你的@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);
}
Run Code Online (Sandbox Code Playgroud)

此方法希望接收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"}
Run Code Online (Sandbox Code Playgroud)

出于显而易见的原因,以这种方式使用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) {
    ...
}
Run Code Online (Sandbox Code Playgroud)

浏览器将使用"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
Run Code Online (Sandbox Code Playgroud)

在这种情况下,内容是URL编码的.

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

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

HTTP标头

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

@POST
@Path("/create")
public void create(@HeaderParam("param1") String param1,
                   @HeaderParam("param2") String param2) {
    ...
}
Run Code Online (Sandbox Code Playgroud)

这是HTTP消息的样子.请注意,此POST没有正文.

POST /create HTTP/1.1
Content-Length: 0
Host: www.example.com
param1: hello
param2: world
Run Code Online (Sandbox Code Playgroud)

我不会将此方法用于通用参数传递.如果您需要访问特定HTTP标头的值,这非常方便.


HTTP查询参数

此方法主要用于HTTP GET,但它同样适用于POST.它使用@QueryParam注释.

@POST
@Path("/create")
public void create(@QueryParam("param1") String param1,
                   @QueryParam("param2") String param2) {
    ...
}
Run Code Online (Sandbox Code Playgroud)

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

POST /create?param1=hello&param2=world HTTP/1.1
Content-Length: 0
Host: www.example.com
Run Code Online (Sandbox Code Playgroud)

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


HTTP路径参数

路径参数与查询参数类似,只是它们嵌入在HTTP资源路径中.这种方法今天似乎有利于此.由于路径是真正定义HTTP资源的,因此对HTTP缓存有影响.代码看起来与其他代码略有不同,因为@Path注释被修改并且它使用@PathParam:

@POST
@Path("/create/{param1}/{param2}")
public void create(@PathParam("param1") String param1,
                   @PathParam("param2") String param2) {
    ...
}
Run Code Online (Sandbox Code Playgroud)

该消息类似于查询参数版本,但参数的名称不包含在消息中的任何位置.

POST /create/hello/world HTTP/1.1
Content-Length: 0
Host: www.example.com
Run Code Online (Sandbox Code Playgroud)

此方法与查询参数版本共享相同的编码问题. 路径段的编码方式不同,因此您也必须小心.


如您所见,每种方法都有利弊.选择通常由您的客户决定.如果您正在提供FORM基于HTML的页面,请使用@FormParam.如果您的客户端是基于JavaScript + HTML5的,那么您可能希望使用基于JAXB的序列化和JSON对象.该MessageBodyReader/Writer实现应该照顾必要逃避对你的所以这是一个可以去错更少的东西.如果您的客户端是基于Java的,但没有良好的XML处理器(例如,Android),那么我可能会使用FORM编码,因为内容正文比URL更容易生成和编码.希望这个迷你wiki条目能够揭示JAX-RS支持的各种方法.

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

  • 我昨天测试了这个功能,不需要@XmlElement注释 (4认同)
  • 非常感谢你做的这些!这真的是我想要的.你做了我的一天;)我现在正在使用FormParams,它的工作原理! (2认同)