JAX-RS 和 JAX-RS CXF 将请求映射到基于 XML 的方法
希望我的标题是正确的,但我正在尝试使用 JAX-RS @Path
注释将请求映射到基于实体参数的不同方法。
我认为示例代码会让事情变得更容易:
超级类:
public class Geothing {
private int thingId;
private String status;
// Ctor, getters and setters
}
PolygonGeothing 扩展 Geothing:
@XmlRootElement
public class PolygonGeothing extends Geothing {
private Coordinates coordinates;
// Ctor, getters and setters
}
CircleGeothing 扩展 Geothing:
@XmlRootElement
public class CircleGeothing extends Geothing {
private Coordinate center;
private int radius;
// Ctor, getters and setters
}
服务接口:
@Path("/geothing/{id}")
public interface GeothingService extends CoService {
@POST
Response createGeothing(@PathParam("{id}") Long id, PolygonGeothing geothing);
@POST
Response createGeothing(@PathParam("{id}") Long id, CircleGeothing geothing);
}
我的期望是,如果我发布 PolygonGeothing 或 CircleGeothing 的 XML,那么它就会起作用。但是,只有当我发布 PolygonGeothing XML 并且发布 CircleGeothing XML 时,它才有效,然后我会得到一个 JAXBException:发生 JAXBException:意外元素(uri:“”,本地:“circleGeothing”)。预期元素为 <{}polygonGeothing>。
是否可以正确映射此元素,而无需为 CircleGeothing 和 PolygonGeothing 指定单独的 URI 路径?此外,是否可以有一个如下所示的接口,我可以在其中使用超类作为参数?我测试了返回类型 Geothing,如果我创建一个 PolygonGeothing 或 CircleGeothing 并返回它,那么它工作正常......但如果我尝试将 PolygonGeothing 或 CircleGeothing 作为参数传递,其中参数类型为 Geothing,则不会。
@Path("/geothing/{id}")
public interface GeothingService extends CoService {
@POST
Response createGeothing(@PathParam("{id}") Long id, Geothing geothing);
}
Hopefully I got the title right, but I'm trying to map requests using JAX-RS @Path
annotations to different methods based on the entity parameter.
I think example code will make it easier:
Super class:
public class Geothing {
private int thingId;
private String status;
// Ctor, getters and setters
}
PolygonGeothing extends Geothing:
@XmlRootElement
public class PolygonGeothing extends Geothing {
private Coordinates coordinates;
// Ctor, getters and setters
}
CircleGeothing extends Geothing:
@XmlRootElement
public class CircleGeothing extends Geothing {
private Coordinate center;
private int radius;
// Ctor, getters and setters
}
Service interface:
@Path("/geothing/{id}")
public interface GeothingService extends CoService {
@POST
Response createGeothing(@PathParam("{id}") Long id, PolygonGeothing geothing);
@POST
Response createGeothing(@PathParam("{id}") Long id, CircleGeothing geothing);
}
My expectation was that if I POSTed XML for a PolygonGeothing or CircleGeothing then it would work. However, it only works if I POST PolygonGeothing XML and if I POST CircleGeothing XML then I get a JAXBException:JAXBException occurred : unexpected element (uri:"", local:"circleGeothing"). Expected elements are <{}polygonGeothing>.
Is it possible to have this mapped correctly without having to specify a separate URI path for CircleGeothing and PolygonGeothing? Furthermore, is it possible to have an interface such as the following, where I can use the super-class as the parameter? I tested returning type Geothing and if I create a PolygonGeothing or CircleGeothing and return it then it works fine... but not if I try to pass PolygonGeothing or CircleGeothing as a parameter where the param type is Geothing.
@Path("/geothing/{id}")
public interface GeothingService extends CoService {
@POST
Response createGeothing(@PathParam("{id}") Long id, Geothing geothing);
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这样做是不可能的。原因很简单:CXF(与任何其他 JAX-RS 框架一样)基于 REST 定义而不是基于面向对象的原则来路由响应。
我的意思是,它根据 URL、生成的内容类型和消耗的内容类型来选择方法。 (这是简化的描述,请参阅 JSR311 了解确切的算法)。但它与你期望的对象无关。仅在选择方法后对象才会被序列化。这就是您收到异常的原因:选择了
createGeothing(@PathParam("{id}") Long id, PolygonGeothing geothing)
,因此它尝试序列化错误的类。您可以执行以下操作:
然后进行强制转换并调用相关方法。
当然,您需要确保 JAXB 上下文已知 Geothing。
It's impossible to do it this way. The reason is simple: CXF (as any other JAX-RS framework) routs the responses based on REST definitions and not based on object oriented principals.
I mean that it selects the method based on URL, produced content type and consumed content type. (This is simplified description, see the JSR311 for exact algorithm). But it has nothing to do with objects you expect. Objects are getting serialized only after the method is already selected. This is the reason you are getting the exception:
createGeothing(@PathParam("{id}") Long id, PolygonGeothing geothing)
is selected, so it tries to serialize the wrong class.You can do the following:
and than cast and call the relevant method.
Of course you need to make sure that Geothing is known to JAXB context.