我遇到了意外的Apache CXF行为:当我从我的服务返回String
时,它没有正确转换为JSON - 而不是在字符串周围添加双引号,Apache CXF按原样返回。
我的服务:
@Path(ROOT_URL)
@Produces(MediaType.APPLICATION_JSON)
public class SomeRestService {
@GET
@Path(SERVICE_URL)
public Response getString() {
return Response.ok("OK").build();
}
}
Apache CXF配置的一部分:
<jaxrs:server id="RestService" address="/api">
<jaxrs:serviceBeans>
<bean class="org.example.project.ws.rest.SomeRestService" />
</jaxrs:serviceBeans>
<jaxrs:extensionMappings>
<entry key="json" value="application/json" />
</jaxrs:extensionMappings>
</jaxrs:server>
你能帮助我理解为什么这样工作以及如何告诉CXF返回字符串真的是JSON吗?
答案 0 :(得分:1)
JSON是一种序列化复杂对象的方法,Java的字符串(实际上)不是。这意味着无法直接将字符串序列化为JSON对象;序列化程序只是不知道将它映射到什么,因此挽救(或者说它不会为String
启用它自己)。对此有两种可能的解决方法。
字符串的自然映射是发送text/plain
类型的内容,而不是application/json
。这个映射是内置到CXF(以及任何其他JAX-RS实现)中,它很容易使它工作。 (我更喜欢将产品和消费注释放在个别方法而不是整体课程上,但这是个人选择。)
@Path(ROOT_URL)
public class SomeRestService {
@GET
@Path(SERVICE_URL)
@Produces("text/plain")
public Response getString() {
return Response.ok("OK").build();
}
}
如果您确实希望数据以JSON格式显示,则需要提供其他元数据。通过添加具有JAXB注释的包装类来实现此目的的绝大多数最简单的方法,然后允许Jettison(CXF使用的序列化库)将正确的东西吐出来。在下面的示例中,我使用的是静态内部类,因为它使(基本上无聊的)类靠近使用它的唯一位置,但是YMMV;它确实必须是一个带注释的公共“结构”(即,一个带有无参数构造函数的类以及公共字段或适当的微不足道的getter和setter)。
@Path(ROOT_URL)
public class SomeRestService {
@GET
@Path(SERVICE_URL)
@Produces("application/json")
public Response getServiceMessage() {
ServiceMessage result = new ServiceMessage();
result.message = "OK";
return Response.ok(result).build();
// Or: return Response.ok(result,"application/json").build();
// Or: return Response.ok(result).type("application/json").build();
}
@XmlRootElement // This annotation _is_ required, can be customized further
public static class ServiceMessage {
@XmlElement // This annotation isn't required, but documents intention
public String message;
}
}
我省略了为ServiceMessage
构建一整套构造函数,这使得使用它比它可能稍微不方便;代码(几乎)纯粹是简单的骨头。