`
mj4d
  • 浏览: 302480 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

JAX-RS:CXF的实现与集成

阅读更多

 

依赖
本文基于cxf2.7.0,需要在前面的例子中加入对jaxrs的依赖:

<dependency>  
    <groupId>org.apache.cxf</groupId>  
    <artifactId>cxf-rt-frontend-jaxrs</artifactId>  
    <version>2.7.0</version>  
</dependency>  

 由于2.7.0是采用jax-rs2.0版本,即JSR339,默认会引入:

<dependency>  
    <groupId>javax.ws.rs</groupId>  
    <artifactId>javax.ws.rs-api</artifactId>  
    <version>2.0-m10</version>  
</dependency>  

 当然对于之前的版本,基于jsr311。需要在pom中手动加入:1.0或1.1版本

 

<dependency>   
    <groupId>javax.ws.rs</groupId>   
    <artifactId>jsr311-api</artifactId>   
    <version>1.1.1</version>   
</dependency>  

 整合
这里主要考虑一下几种整合方式,更多见这里

 

  • 编程式发布server

在CXF中与JAX-WS一样,提供了JAXRSServerFactoryBean作为工厂服务类来编程式发布资源类

JAXRSServerFactoryBean sf = new JAXRSServerFactoryBean();  
//Bind one or more resources  
sf.setResourceClasses(CustomerService.class, AnotherService.class);  
// JAX-RS默认是每个请求会实例,这样修改为单例  
sf.setResourceProvider(CustomerService.class, new SingletonResourceProvider(new CustomerService()));  
sf.setAddress("http://localhost:9000/");  
BindingFactoryManager manager = sf.getBus().getExtension(BindingFactoryManager.class);  
JAXRSBindingFactory factory = new JAXRSBindingFactory();  
factory.setBus(sf.getBus());  
manager.registerBindingFactory(JAXRSBindingFactory.JAXRS_BINDING_ID, factory);  
sf.create();  
  •  spring

当然这里说的与spring整合少不了与web容器的整合,首先需要在web.xml中添加CXF的servlet监听请求路径:

<servlet>  
    <servlet-name>CXFServlet</servlet-name>  
    <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>  
    <load-on-startup>5</load-on-startup>  
</servlet>  
<servlet-mapping>  
    <servlet-name>CXFServlet</servlet-name>  
    <url-pattern>/*</url-pattern>  
</servlet-mapping>  

 下面介绍两种spring的配置,这也是通用的

  • jaxrs命名空间

这是一个最简单的配置:

<?xml version="1.0" encoding="UTF-8"?>  
<beans xmlns="http://www.springframework.org/schema/beans"  
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
    xmlns:jaxrs="http://cxf.apache.org/jaxrs"  
    xsi:schemaLocation="  
    http://www.springframework.org/schema/beans  
    http://www.springframework.org/schema/beans/spring-beans.xsd  
    http://cxf.apache.org/jaxrs  
    http://cxf.apache.org/schemas/jaxrs.xsd">  
  
    <import resource="classpath:META-INF/cxf/cxf.xml" />  
    <import resource="classpath:META-INF/cxf/cxf-servlet.xml" />  
  
    <jaxrs:server id="customerService" address="/jaxrs">  
        <jaxrs:serviceBeans>  
            <ref bean="restPathService1"/>  
        </jaxrs:serviceBeans>  
  
    </jaxrs:server>  
  
    <bean id="restPathService1" class="org.ws.server.cxf.chap3.cxf.server.CustomerService"/>  
</beans>  

 当然在jaxrs:server中可以加入其他节点,具体可参考http://cxf.apache.org/schemas/jaxrs.xsd

 

  • spring bean

也可以使用普通的bean配置,只是需要作为JAXRSServerFactoryBean实例的属性:

<?xml version="1.0" encoding="UTF-8"?>  
<beans xmlns="http://www.springframework.org/schema/beans"  
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
    xsi:schemaLocation="  
    http://www.springframework.org/schema/beans  
    http://www.springframework.org/schema/beans/spring-beans.xsd">  
  
    <import resource="classpath:META-INF/cxf/cxf.xml" />  
    <import resource="classpath:META-INF/cxf/cxf-servlet.xml" />  
  
    <bean class="org.apache.cxf.jaxrs.JAXRSServerFactoryBean" init-method="create">  
        <property name="address" value="/jaxrs"/>  
        <property:serviceBeans>  
            <ref bean="restPathService1" />  
        </property:serviceBeans>  
    </bean>  
  
    <bean id="restPathService2" class="org.ws.server.cxf.chap3.cxf.server.AnotherService"/>  
</beans>  

 
数据绑定(Data Bindings)
CXF对JAX-RS的数据绑定与之前的一样,需要选择相应的绑定类型,如需要加入JAXB对XML的处理:

<dependency>  
        <groupId>org.apache.cxf</groupId>  
        <artifactId>cxf-rt-databinding-jaxb</artifactId>  
        <version>${cxf.version}</version>  
</dependency>  

 这也是CXF对JAX-RS的默认编码类型,因此我们在采用XML作为传输时只需要做简单的处理:
资源类中的一个方法:

@GET  
@Path("/meth1")  
@Produces({ MediaType.APPLICATION_XML })  
public User meth1() {  
    return new User(1, "robin", "123");  
}  

 其中User作为返回需要以XML的格式传输,最简单的处理只需要在: 

@XmlRootElement(name = "user")  
public class User {  
  
    private Integer id;  
    private String  username;  
    private String  password;   

 当然更多操作需要了解

 

再介绍对JSON格式的处理,由于CXF默认支持是依赖Jettison通常我们更喜欢Jackson。所以,首先需要加入其依赖:

<dependency>  
  <groupId>org.codehaus.jackson</groupId>  
  <artifactId>jackson-jaxrs</artifactId>  
  <version>1.9.0</version>  
</dependency>  

 需要更换默认的JSON providers为Jackson:

<jaxrs:providers>  
   <bean class="org.codehaus.jackson.jaxrs.JacksonJsonProvider"/>  
</jaxrs:providers>  

 

<jaxrs:providers>  
   <bean class="org.codehaus.jackson.jaxrs.JacksonJaxbJsonProvider"/>  
</jaxrs:providers>

 一个完整的例子:
资源类的方法声明:

@GET  
@Path("/meth2")  
@Produces({ MediaType.APPLICATION_JSON })  
public User meth2() {  
    return new User(1, "robin", "123");  
}  

 spring配置文件:

<jaxrs:server id="customerService" address="/jaxrs">
    <jaxrs:serviceBeans>
        <ref bean="restPathService3"/>
    </jaxrs:serviceBeans>

    <jaxrs:providers>
        <bean class="org.codehaus.jackson.jaxrs.JacksonJsonProvider"/>
    </jaxrs:providers>
</jaxrs:server>

<bean id="restPathService3" class="org.ws.server.cxf.chap3.cxf.data.RESTDataBindService"/>

  更多信息见这里


URI路径选择算法
当一个请求URI匹配了多个resource类,进行下面的算法:
1、优先匹配resource类@Path中更多的文字

@Path("/bar/{id}")  
public class Test1 {}  
@Path("/bar/{id}/baz")  
public class Test2 {}  
@Path("/foo")  
public class Test3 {}  
@Path("/foo/")  
public class Test4 {}  

 对请求URI: /bar/1/baz 同时匹配上了Test1和Test2,但Test2中有9个文字而Test1只有5个,同样对请求/foo/将匹配Test4

 

2、优先匹配resource类@Path中更多组类

@Path("/bar/{id}/")  
public class Test1 {}  
@Path("/bar/{id}/{id2}")  
public class Test2 {}  

 对请求URI:/bar/1/2同时匹配Test1和Test2,但Test2中有3个分组将优先匹配

 

3、优先匹配resource类@Path中捕获更多的正则组

@Path("/bar/{id:.+}/baz/{id2}")  
public class Test1 {}  
@Path("/bar/{id}/bar/{id2}")  
public class Test2 {}  

 对请求URI:/bar/1/baz/2同时匹配Test1和Test2,且文字长度和组都一样,但Test1中匹配为1而Test2匹配中0

 

在多个resource方法中选择
根据上面的规则,我们已经选择了resource类。接下来对类中方法的选择也遵循这个原则,其中只有一点额外需要注意:

如果同时包含sub-resource优先选择非sub-resource

@Path("/rest")  
public class Test1 {  
  
 @Path("/bar")  
 @GET  
 public Order getOrder() {...}  
  
 @Path("/bar")  
 public Order getOrderFromSubresource() {...}  
}  
  
public class Order {  
  
 @Path("/")  
 @GET  
 public Order getOrder() { return this; }  
  
}  

 对请求URI: /rest/bar将匹配方法getOrder()因为另外一个是sub-resource

 

 

方法与MediaType的选择
考虑这样的情况如果方法都匹配,但是MediaType不一样:

@Path("/rest")  
public class Test1 {  
  
     @Path("/bar")  
     @POST   
     @Consumes("application/json")  
     @Produces("application/json")  
     public Order addOrderJSON(OrderDetails details) {...}  
  
     @Path("/bar")  
     @POST  
     @Consumes("application/xml")  
     @Produces("application/xml")  
     public Order getOrderXML(OrderDetails details) {...}  
  
}  

 对请求URI: /rest/bar以上两个都匹配,当然如果请求的Content-Type和Accept都有设置相应的类型,那么就好判断,如application/json指向addOrderJSON,如果是application/xml则指向方法getOrderXML当然,如果客户端并没明显指定而是直接在浏览器请求,可能会选择的是getOrderXML因为默认的可能是:

Content-Type:   text/html  
Accept:         text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8  

 当然其实可以更好的方式处理这种情况:

@Path("/")  
public class Test1 {  
  
 @Path("/bar")  
 @POST   
 @Consumes({"application/json", "application/xml"})  
 @Produces({"application/json", "application/xml"})  
 public Order addOrder(OrderDetails details) {...}  
  
} 

 
 自定义URI选择算法
CXF 2.2.5以后提供了自定义的URI选择器,需要实现ResourceComparator接口

public class QueryResourceInfoComperator extends OperationResourceInfoComparator implements ResourceComparator {  
  
    public QueryResourceInfoComperator() {  
        super(null, null);  
    }  
  
    @Override  
    public int compare(ClassResourceInfo cri1, ClassResourceInfo cri2, Message message) {  
        return 0;  
    }  
  
    @Override  
    public int compare(OperationResourceInfo oper1, OperationResourceInfo oper2, Message message) {  
  
        int cxfResult = super.compare(oper1, oper2);  
        if (cxfResult != 0)  
            return cxfResult;  
        //OperationResourceInfo获取resource方法请求路径相关信息  
        int op1Counter = getMatchingRate(oper1, message);  
        int op2Counter = getMatchingRate(oper2, message);  
        //通过两两比较权重选择具体的方法  
        return op1Counter == op2Counter ? 0 : op1Counter < op2Counter ? 1 : -1;  
    }  
  
    protected int getMatchingRate(OperationResourceInfo operation, Message message) {  
  
        List<Parameter> params = operation.getParameters();  
        if (params == null || params.size() == 0)  
            return 0;  
  
        Set<String> qParams = getParams((String) message.get(Message.QUERY_STRING));  
  
        //匹配更多的参数获得更多的权限  
        int rate = 0;  
        for (Parameter p : params) {  
            switch (p.getType()) {  
                case QUERY:  
                    if (qParams.contains(p.getName()))  
                        rate += 2;  
                    else if (p.getDefaultValue() == null)  
                        rate -= 1;  
                    break;  
                default:  
                    break;  
            }  
        }  
        return rate;  
    }  
  
    /** 
     * @param query URL Query Example: 'key=value&key2=value2' 
     * @return A Set of all keys, contained within query. 
     */  
    protected Set<String> getParams(String query) {  
        Set<String> params = new HashSet<String>();  
        if (query == null || query.length() == 0)  
            return params;  
  
        MultivaluedMap<String, String> allQueries = JAXRSUtils.getStructuredParams(query, "&", false, false);  
        return allQueries.keySet();  
    }  
}  

 注册相应的服务:

<jaxrs:server id="customerService" address="/jaxrs">
    <jaxrs:serviceBeans>
        <ref bean="restPathService6"/>
    </jaxrs:serviceBeans>

    <jaxrs:resourceComparator>
        <bean class="org.ws.server.cxf.chap3.cxf.uri.QueryResourceInfoComperator"/>
    </jaxrs:resourceComparator>
</jaxrs:server>

<bean id="restPathService6" class="org.ws.server.cxf.chap3.cxf.uri.CustomURITemplateService"/>  

 其中resource类的声明:

@Path("/rest")  
public class CustomURITemplateService {  
  
    @GET  
    @Path("/meth")  
    public Response meth1(@QueryParam("name") String name) {  
        return Response.status(200).entity("/rest/meth1 called[name=" + name + "]").build();  
    }  
  
    @GET  
    @Path("/meth")  
    public Response meth2(@QueryParam("name") String name, @QueryParam("age") Integer age) {  
        return Response.status(200).entity("/rest/meth2 called[name=" + name + ", age=" + age + "]").build();  
    }  
  
    @GET  
    @Path("/meth")  
    public Response meth3(@QueryParam("name") String name, @QueryParam("age") Integer age,  
                          @QueryParam("password") String password) {  
        return Response.status(200)  
                .entity("/rest/meth3 called[name=" + name + ", age=" + age + ",password=" + password + "]").build();  
    }  
  
}  

 对请求遵循以下规则:

/jaxrs/rest/meth?name=abd&age=123&password=aaa   --> meth3  
/jaxrs/rest/meth?name=abd&age=123                --> meth2  
/jaxrs/rest/meth?name=abd                        --> meth1  

 更多信息见这里

分享到:
评论

相关推荐

    jax-rs jax-ws所需包,亲测可用

    - `provider.jar`: 这可能是一个JAX-RS或JAX-WS的具体实现,如Jersey或Apache CXF,提供了服务的运行时环境。 **使用步骤:** 1. 下载并解压压缩包。 2. 将解压后的四个jar文件导入到IDE的项目构建路径中。 3. ...

    java_webservice_JAX-RS.zip_cxf_jax_jax-rs_spring cxf

    Java Web服务,特别是JAX-RS(Java API for RESTful Web Services)和Apache CXF,是企业级应用程序中实现服务接口的重要技术。本教程将深入探讨如何在SSH(Spring、Struts、Hibernate)架构中集成Web服务,以及如何...

    Jax-RS所需要的依赖jar

    Jetty可以轻松地与JAX-RS实现(如Jersey或RESTEasy)集成,提供REST服务。 3. **Jersey**:Jersey是Sun Microsystems(现Oracle)开发的一个开源JAX-RS实现,它是许多项目首选的JAX-RS框架。它提供了丰富的功能,...

    JAX-RS cxf web服务 rest简单增删改查 集成spring webService

    通过以上步骤,你可以构建一个基于JAX-RS CXF的RESTful Web服务,并与Spring框架集成,实现简单的CRUD操作。这个服务可以方便地与其他系统交互,提供数据访问接口,同时结合Spring的强大功能,使得服务更易于维护和...

    mybatis+cxf,jax-rs

    它结合了MyBatis的数据库操作能力,CXF的JAX-RS实现,以及Spring的依赖管理和事务控制,使得开发RESTful服务变得更加高效和便捷。通过深入理解并实践这个框架,开发者可以构建出高质量、易于维护的企业级应用程序。

    JAX-RS+spring

    4. **提供者与容器**: JAX-RS不强制使用特定的服务器或容器,它定义了一个API,服务器和容器如Jersey、RestEasy、Apache CXF等实现这个API来提供具体服务。 5. **拦截器与过滤器**: 通过`@Provider`注解,可以...

    spring-boot-cxf-jaxrs:Spring Boot CXF 集成

    &lt;artifactId&gt;spring-boot-cxf-jaxrs &lt;version&gt;1.1 所有用@Path标记的 bean 将自动添加为 JAX-RS 服务。 所有标记为@Provider bean 都将添加为 JAX-RS 提供者。 依赖关系 您必须将 Spring、Spring Boot 和 CXF ...

    jee8-jax-rs:JAX-RS测试

    在"JEE8-JAX-RS: JAX-RS测试"项目中,我们关注的是如何在Java Enterprise Edition 8(JEE8)环境中有效地测试JAX-RS接口和实现。JEE8是Java企业版的一个版本,提供了多种服务器端技术和框架,包括JAX-RS,以支持大型...

    cxf jax-rs 配置演示程序

    &lt;artifactId&gt;cxf-rt-frontend-jaxrs &lt;version&gt;3.x.x &lt;groupId&gt;org.apache.cxf &lt;artifactId&gt;cxf-rt-transports-http&lt;/artifactId&gt; &lt;version&gt;3.x.x ``` (请将3.x.x替换为最新的CXF版本) 3. **配置...

    cxf.apache.org/schemas/(jaxrs.xsd、jaxrs.xsd、core.xsd)文件下载

    在本文中,我们将深入探讨与标题和描述相关的知识点,主要关注JAX-RS和CXF的集成,以及如何利用xsd文件来增强IDE的配置提示。 JAX-RS(Java API for RESTful Web Services)是Java平台上的一个标准,用于创建...

    apache-cxf-2.4.6.zip

    7. **集成其他Apache项目**:CXF与Apache Axis2、Tomcat、Jetty等项目有良好的集成,可以方便地嵌入到现有的应用服务器中。 8. **多种数据绑定技术**:CXF支持JAXB、XMLBeans、Aegis等多种数据绑定技术,使XML到...

    jax-rs-api:JAX-RS API源代码

    这些实现提供了JAX-RS规范的具体实现和扩展功能,比如Jersey支持CDI集成、JSON绑定等。 在给定的压缩包文件`jax-rs-api-master`中,很可能是JAX-RS API的源代码仓库。由于该项目已被迁移到Eclipse Foundation,这...

    apache cxf -jax rs + swagger+mybatis整合

    Apache CXF是一个开源服务框架,它支持多种Web服务标准,包括Java API for RESTful Web Services (JAX-RS)。JAX-RS是Java平台上的一个标准,用于创建RESTful Web服务,它允许开发者通过简单的注解来定义资源类和方法...

    cxf-bundle-jaxrs-2.4.7.zip

    【标题】"CXF-BUNDLE-JAXRS-2.4.7.zip" 是一个与Apache CXF相关的开源项目,它包含了一个JAX-RS(Java API for RESTful Web Services)的OSGi捆绑包。JAX-RS是Java平台上的标准,用于创建RESTful服务,而CXF是一个...

    jaxrs导致的错误

    在探讨“jaxrs导致的错误”这一主题时,我们深入分析了由JAX-RS(Java API for RESTful Web Services)引发的特定异常情况。这一问题不仅涉及JAX-RS框架本身,还牵扯到Spring框架与Apache CXF库之间的交互,其中包含...

    cxf-jax-rs-template:开始使用 gradle 作为依赖管理器的 jax rs 项目的基本项目

    例如,对于JAX-RS项目,可能需要Apache CXF或其他JAX-RS实现的依赖。 6. **项目结构**:`cxf-jax-rs-template-master`可能是项目的源代码仓库主分支名,暗示项目可能来源于Git,遵循一定的目录结构,包括源代码、...

    apache-cxf-2.7.5所有jar都在

    - **cxf-rt-frontend-jaxrs**: 提供JAX-RS(Java API for RESTful Web Services)的支持。 - **cxf-rt-transports-http**和**cxf-rt-transports-http-jetty**: HTTP和Jetty传输实现。 - **cxf-rt-bindings-soap**和*...

    apache-cxf-2.5.2

    1. **Web服务实现**:CXF允许开发者使用JAX-WS和JAX-RS标准来创建和部署Web服务。JAX-WS是用于构建SOAP服务的,而JAX-RS则用于构建RESTful服务。 2. **多种协议支持**:CXF支持多种通信协议,如HTTP、HTTPS、JMS等...

    jaxrs-api.jar

    使用 JAX-RS 创建 RESTful Web 服务时,通常会结合 CDI(Contexts and Dependency Injection)或 EJB 进行依赖注入,以及与服务器平台(如 Jersey, RESTEasy, Apache CXF 等)集成,以实现更复杂的功能和扩展。...

    webservice实例 CXF的JAXWS和JAXRS实现 及JAXB标准接口实现带jar包

    CXF集成了JAXB,使得在处理XML消息时,无需编写大量的转换代码。 在提供的压缩包“ws_test”中,很可能包含了使用CXF实现的Web服务示例,包括JAX-WS和JAX-RS的服务端点,以及使用JAXB进行数据交换的类。这个实例...

Global site tag (gtag.js) - Google Analytics