作为 this question 的后续行动,对于如何正确使用 CXF-RS 组件,我仍然有些困惑。
我很困惑为什么我们需要 <cxf:rsServer>
当我可以使用 <jaxrs:server>
时,用于指定 CXF-RS 端点的标签(或者甚至有这样的概念?)标签非常好。
这是我的 Camel 和 CXF 配置 XML:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:jaxrs="http://cxf.apache.org/jaxrs"
xmlns:camel="http://camel.apache.org/schema/spring"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd
http://cxf.apache.org/transports/http/configuration http://cxf.apache.org/schemas/configuration/http-conf.xsd
http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd
http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd">
<jaxrs:server id="userService" address="/users">
<jaxrs:serviceBeans>
<bean class="com.example.UserServiceNoop" />
</jaxrs:serviceBeans>
<jaxrs:providers>
<bean class="org.codehaus.jackson.jaxrs.JacksonJaxbJsonProvider" />
</jaxrs:providers>
</jaxrs:server>
<bean id="user" class="org.apache.camel.component.direct.DirectComponent" />
<camel:camelContext id="someCamelContext">
<camel:route id="userServiceRoute">
<camel:from uri="cxfrs:bean:userService" />
<camel:routingSlip>
<camel:simple>user:${header.operationName}</camel:simple>
</camel:routingSlip>
</camel:route>
<camel:route id="userServiceRetrieveUser">
<from uri="user:retrieveUser" />
<!-- Assume this is going to a useful Processor -->
</camel:route>
</camel:camelContext>
</beans>
用户服务.java:
package com.example;
/* a bunch of imports... */
public interface UserService {
@GET
@Path(value="/{user.id}")
@Produces({MediaType.APPLICATION_JSON})
public User retrieveUser(
@PathParam("user.id") Integer id
);
}
用户服务Noop.java
package com.example;
/* a bunch of imports ... */
public class UserServiceNoop implements UserService
{
@Override
public User retrieveUser(Integer id) {
throw new RuntimeException();
}
}
在这个例子中,我没有使用任何 <cxf:rsServer>
标签,但它工作正常。我知道它通过 CXF-RS 组件,因为当我运行应用程序时,它不会抛出任何 RuntimeExceptions
,这是使用 CXF-RS 时的预期行为(不会调用服务类中的方法实现)。
我是否因为不使用这个标签而遗漏了什么?
最佳答案
正如另一个答案所说,cxf:rsServer
主要用于由 Camel 路由处理,因为在 jaxrs:server
中完成了请求的处理通过经典 Controller 。
例如:
- 经典 JAXRS 服务器:
您将声明一个经典的 Bean Rest( Controller )并在其中注入(inject)一个服务。
XML 配置示例(摘录):
<jaxrs:server id="deviceServiceSvcV1" address="/device/v1">
<jaxrs:serviceBeans>
<ref component-id="deviceServiceRest" />
</jaxrs:serviceBeans>
<!-- and other providers, interceptors, etc... here -->
</jaxrs:server>
<!-- Service bean -->
<bean id="deviceServiceRest" class="org.mycomp.device.rest.v1.ws.api.DeviceServiceRest">
<property name="deviceService" ref="deviceService" />
</bean>
Controller 类将以经典方式处理请求/响应(例如调用注入(inject)服务)。
- 使用
cxf:rsServer
的 Camel 路线
XML 配置示例(摘录):
<cxf:rsServer id="rsServer" address="/device/v1"
serviceClass="org.mycomp.device.rest.v1.ws.api.DeviceServiceRest">
<cxf:properties>
<!-- whatever here -->
</cxf:properties>
<!-- and other interceptors, etc... here -->
</cxf:rsServer>
在类里面:
@Produces({ MediaType.APPLICATION_XML })
@Path("/")
public class DeviceServiceRest {
@GET
public Response listDevicess(
@QueryParam("model") String model,
@QueryParam("sid") String sid,
) {
return null; // never used
}
@GET
@Path("{id}")
public Response getDeviceById(
@PathParam("id") String id,
@QueryParam("model") String model,
@QueryParam("sid") String sid
){
return null; // never used
}
}
REST Controller 有空方法(返回 null),但我认为最新的 camel-cxf
现在支持一个 Interface
,它比让方法返回 更优雅空
。
现在,请求处理可以通过这样的 Camel Route 实现:
from("cxfrs:bean:rsServer?synchronous=true")
.routeId("cxf-device-rest-v1")
.process( new CheckAuthenticationProcessor())
.choice()
.when(header("operationName").isEqualTo("listDevice"))
.setHeader("backenOperation").constant("list")
.setHeader("backendResource").constant("device")
.endChoice()
.when(header("operationName").isEqualTo("getDeviceById"))
.setHeader("backenOperation").constant("retrieve")
.setHeader("backendResource").constant("device")
.endChoice()
.end()
.bean("requestProcessor")
.to(InOut, backendEndpoint)
.process(checkResponseStatusCode())
.bean(new HttpResponseProcessor())
;
并且您还可以根据需要从路由中控制请求/响应处理。
这是实现 REST API(服务器端)的两种不同类型,但在我看来这有点老套,因为像 spring-boot 这样的现代框架不需要这些。
我发现第二种方法有点矫枉过正,因为我喜欢 Camel 用于集成目的,但将它用于 REST API 可能需要讨论。 我可以看到的一个用例是用于异步处理的 HTTP REST Web 服务,服务响应 202 Accepted 和 Camel Route 以异步模式集成请求,尤其是当可以轻松使用特定的 Camel 组件而不是复杂的组件时类(或 EIP 模式的任何需要)。
关于java - 为什么我们使用 <cxf :rsServer> as opposed to a plain <jaxrs:server> when using the CXF-RS component?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21441124/