如何在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中创build一个Jersey客户端时,调用post方法的方法如下所示:

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

运行此testing时:

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

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

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

我需要改变什么,以便参数给出正确的值?

你的@POST方法应该接受一个JSON对象而不是一个string。 Jersey使用JAXB来支持编组和解组JSON对象(请参阅jersey文档了解详细信息 )。 创build一个类如下:

 @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消息的内容主体作为一个unannotated参数 – 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已经具有所需types的实现(例如,Java原语和JAXB包装类)以及JSON。 JAX-RS支持许多其他传递数据的方法。 这些不需要创build一个新的类,因为数据是通过简单的parameter passing来传递的。


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 

我不会使用这个方法进行广义的parameter passing。 如果你需要访问一个特定的HTTP头的值,那真的很方便。


HTTP查询参数

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

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

像以前的技术一样,通过查询string传递参数不需要消息体。 这里是HTTP消息:

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

你必须特别小心,在客户端正确编码查询参数 。 使用查询参数可能会有问题,因为某些代理实施的URL长度限制以及与编码相关的问题。


HTTPpath参数

path参数与查询参数类似,只不过它们embedded在HTTP资源path中。 这种方法似乎是有利于今天。 由于path是真正定义HTTP资源的,所以对HTTPcaching有影响。 该代码看起来有点不同于其他人,因为@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段的编码方式不同,所以您也必须小心。


正如你所看到的,每种方法都有优点和缺点。 select通常由您的客户决定。 如果您正在提供基于FORM的HTML页面,请使用@FormParam 。 如果您的客户端是基于JavaScript + HTML5的,那么您可能需要使用基于JAXB的序列化和JSON对象。 MessageBodyReader/Writer实现应该照顾必要的转义,这样可以减less错误的发生。 如果你的客户端是基于Java的,但没有一个好的XML处理器(例如,Android),那么我可能会使用FORM编码,因为内容体比URL更容易生成和编码。 希望这个迷你维基条目能够阐明JAX-RS支持的各种方法。

注意:为了充分披露,我还没有使用Jersey的这个function。 由于我们已经部署了大量JAXB + JAX-RS应用程序,并且正在进入移动客户端空间,所以我们对此进行了修改。 JSON更适合HTML5或基于jQuery的解决scheme。