使用 CXF-RS 组件时,为什么我们使用 而不是普通的

2024-06-20

作为后续这个问题 https://stackoverflow.com/questions/20598199,对于如何正确使用CXF-RS组件我还是有点困惑。

我很困惑为什么我们需要<cxf:rsServer>用于指定 CXF-RS 端点的标签(或者是否有这样的概念?),当我可以使用<jaxrs:server>标签完全没问题。

这是我的 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
    );
}

UserServiceNoop.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请求的处理是由经典控制器完成的。

例如:

  1. 经典 JAXRS 服务器:

您将声明一个经典的 Bean Rest(控制器)并在其中注入一个 Service。

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 类将以经典方式处理请求/响应(例如调用注入的服务)。

  1. 骆驼路线cxf:rsServer

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 控制器有空方法(返回 null),但我认为最新的camel-cxf现在支持Interface这比让方法返回更优雅null。 现在,请求处理可以通过 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 模式的任何需要)。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 CXF-RS 组件时,为什么我们使用 而不是普通的 ? 的相关文章

随机推荐