Java 我们为什么使用<;cxf:rsServer>;与平原相对<;jaxrs:server>;使用CXF-RS组件时?

Java 我们为什么使用<;cxf:rsServer>;与平原相对<;jaxrs:server>;使用CXF-RS组件时?,java,spring,web-services,apache-camel,cxfrs,Java,Spring,Web Services,Apache Camel,Cxfrs,作为后续工作,我仍然对如何正确使用CXF-RS组件感到困惑 我不明白为什么我们需要标记来指定CXF-RS端点(或者甚至有这样的概念吗?),而我可以很好地使用标记 以下是我针对Camel和CXF的配置XML: <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" x

作为后续工作,我仍然对如何正确使用CXF-RS组件感到困惑

我不明白为什么我们需要
标记来指定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>
userservicenop.java

package com.example;

/* a bunch of imports ... */

public class UserServiceNoop implements UserService 
{
    @Override
    public User retrieveUser(Integer id) {
        throw new RuntimeException();
    }
}
在本例中,我没有使用任何
标记,但它工作正常。我知道它是通过CXF-RS组件实现的,因为当我运行应用程序时,它不会抛出任何
运行时异常
,这是使用CXF-RS时的预期行为(不会调用服务类中的方法实现)


如果不使用此标记,是否丢失了某些内容?

如果要使用cxf endpoint作为某些内容的使用者,请使用cxf:reserver标记。例如,在复杂的apachecamel路由或Spring集成中。当您是端点服务请求的提供者时使用。

正如另一个答案所说,
cxf:rsServer
主要用于通过驼峰路由进行处理,就像在
jaxrs:server
中一样,请求的处理由经典控制器完成

例如:

  • 经典JAXRS服务器:
  • 您将声明一个经典的Bean Rest(控制器),并在其中注入一个服务

    XML配置(提取)示例:

    在课堂上:

    @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控制器有空方法(返回null),但我认为最新的
    camel cxf
    现在支持
    接口
    ,它比返回
    null
    的方法更优雅。 现在,请求处理可以通过驼峰路由实现,如下所示:

    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())
    ;
    
    您还可以根据需要从路由控制请求/响应处理

    这是两种实现RESTAPI(服务器端)的不同类型,但在我看来,这有点老派,因为像SpringBoot这样的现代框架不需要这些

    我发现第二种方法有点过分,因为出于集成目的我喜欢Camel,但将其用于restapi可能会引起讨论。 我可以看到的一个用例是用于异步处理的HTTP REST Web服务,服务响应202被接受,驼峰路由以异步模式集成请求,特别是当可以轻松使用特定的驼峰组件而不是复杂类(或任何EIP模式的需要)时

    <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
        }
    }
    
    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())
    ;