我已经成功设置了一个快速测试,创建一个“类似REST”的服务,返回一个序列化为JSON的对象,这非常简单快捷(基于this article)。
但是虽然返回JSON-ified对象很容易像桃子一样,但我还没有看到任何处理非基本输入参数的例子。如何将复杂对象作为参数传递?我正在使用Apache CXF,但是也欢迎使用像Jackson这样的其他框架的示例:)
客户端可能类似于构建javascript对象,将其传递给JSON.stringify(complexObj),并将该字符串作为参数之一传递。
该服务可能看起来像这样
@Service("myService")
class RestService {
@GET
@Produces("application/json")
@Path("/fooBar")
public Result fooBar(@QueryParam("foo") double foo, @QueryParam("bar") double bar,
@QueryParam("object") MyComplex object) throws WebServiceException {
...
}
}
将序列化对象作为参数发送可能会快速触及Internet Explorer强加的2KB URL限制。您是否建议在这些情况下使用POST,我是否需要在函数定义中进行更改?
答案 0 :(得分:30)
挖了一下后我很快发现基本上有两种选择:
将包含所有其他参数的“包装器对象”传递给服务。您可能需要使用@XmlRootElement等JAXB注释来注释此包装类,以便与基于Jettison的提供程序一起使用,但如果您使用Jackson而不需要。只需将内容类型设置为正确的类型,即可调用正确的邮件正文阅读器。 这仅适用于POST类型的服务(AFAIK)。
这只是使用包装器对象将原始问题中提到的服务转换为一个的示例。
@Service("myService")
class RestService {
@POST
@Produces("application/json")
@Path("/fooBar")
public Result fooBar(
/**
* Using "" will inject all form params directly into a ParamsWrapper
* @see http://cxf.apache.org/docs/jax-rs-basics.html
*/
@FormParam("") FooBarParamsWrapper wrapper
) throws WebServiceException {
doSomething(wrapper.foo);
}
}
class ParamsWrapper {
double foo, bar;
MyComplexObject object;
}
您可以提供一些特殊的字符串格式,将对象打包到其中,然后实现一个构造函数,该构造函数接受一个字符串,一个静态valueOf(String s)或一个静态fromString(String s),该类将接受此字符串和从中创建一个对象。或者非常相似,创建一个完全相同的ParameterHandler。
AFAIK,只有第二个版本允许您使用JSONP从浏览器调用您的服务(因为JSONP是限制为GET的技巧)。我选择此路由以便能够在URI中传递复杂对象的数组。
作为其工作原理的示例,请使用以下域类和服务
@GET
@Path("myService")
public void myService(@QueryParam("a") MyClass [] myVals) {
//do something
}
class MyClass {
public int foo;
public int bar;
/** Deserializes an Object of class MyClass from its JSON representation */
public static MyClass fromString(String jsonRepresentation) {
ObjectMapper mapper = new ObjectMapper(); //Jackson's JSON marshaller
MyClass o= null;
try {
o = mapper.readValue(jsonRepresentation, MyClass.class );
} catch (IOException e) {
throw new WebApplicationException()
}
return o;
}
}
在这种情况下,URI http://my-server.com/myService?a={"foo":1, "bar":2}&a={"foo":100, "bar":200}
将被反序列化为由两个MyClass对象组成的数组。
答案 1 :(得分:3)
接受的答案缺少@BeanParam。看到 https://docs.jboss.org/resteasy/docs/3.0-rc-1/javadocs/javax/ws/rs/BeanParam.html 有关更多详细信息。它允许您在包装对象内定义查询参数。 例如
public class TestPOJO {
@QueryParam("someQueryParam")
private boolean someQueryParam;
public boolean isSomeQueryParam() {
return someQueryParam;
}
public boolean setSomeQueryParam(boolean value) {
this.someQueryParam = value;
}
}
... // inside the Resource class
@GET
@Path("test")
public Response getTest(@BeanParam TestPOJO testPOJO) {
...
}
答案 2 :(得分:1)
最好和最简单的解决方案是将您的对象作为json字符串发送,并在服务器端实现一个方法,该方法将解码该json并根据您的需要映射到指定的对象..是的,最好使用POST