依赖
本文基于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
更多信息见这里
相关推荐
- `provider.jar`: 这可能是一个JAX-RS或JAX-WS的具体实现,如Jersey或Apache CXF,提供了服务的运行时环境。 **使用步骤:** 1. 下载并解压压缩包。 2. 将解压后的四个jar文件导入到IDE的项目构建路径中。 3. ...
Java Web服务,特别是JAX-RS(Java API for RESTful Web Services)和Apache CXF,是企业级应用程序中实现服务接口的重要技术。本教程将深入探讨如何在SSH(Spring、Struts、Hibernate)架构中集成Web服务,以及如何...
Jetty可以轻松地与JAX-RS实现(如Jersey或RESTEasy)集成,提供REST服务。 3. **Jersey**:Jersey是Sun Microsystems(现Oracle)开发的一个开源JAX-RS实现,它是许多项目首选的JAX-RS框架。它提供了丰富的功能,...
通过以上步骤,你可以构建一个基于JAX-RS CXF的RESTful Web服务,并与Spring框架集成,实现简单的CRUD操作。这个服务可以方便地与其他系统交互,提供数据访问接口,同时结合Spring的强大功能,使得服务更易于维护和...
它结合了MyBatis的数据库操作能力,CXF的JAX-RS实现,以及Spring的依赖管理和事务控制,使得开发RESTful服务变得更加高效和便捷。通过深入理解并实践这个框架,开发者可以构建出高质量、易于维护的企业级应用程序。
4. **提供者与容器**: JAX-RS不强制使用特定的服务器或容器,它定义了一个API,服务器和容器如Jersey、RestEasy、Apache CXF等实现这个API来提供具体服务。 5. **拦截器与过滤器**: 通过`@Provider`注解,可以...
<artifactId>spring-boot-cxf-jaxrs <version>1.1 所有用@Path标记的 bean 将自动添加为 JAX-RS 服务。 所有标记为@Provider bean 都将添加为 JAX-RS 提供者。 依赖关系 您必须将 Spring、Spring Boot 和 CXF ...
在"JEE8-JAX-RS: JAX-RS测试"项目中,我们关注的是如何在Java Enterprise Edition 8(JEE8)环境中有效地测试JAX-RS接口和实现。JEE8是Java企业版的一个版本,提供了多种服务器端技术和框架,包括JAX-RS,以支持大型...
<artifactId>cxf-rt-frontend-jaxrs <version>3.x.x <groupId>org.apache.cxf <artifactId>cxf-rt-transports-http</artifactId> <version>3.x.x ``` (请将3.x.x替换为最新的CXF版本) 3. **配置...
在本文中,我们将深入探讨与标题和描述相关的知识点,主要关注JAX-RS和CXF的集成,以及如何利用xsd文件来增强IDE的配置提示。 JAX-RS(Java API for RESTful Web Services)是Java平台上的一个标准,用于创建...
7. **集成其他Apache项目**:CXF与Apache Axis2、Tomcat、Jetty等项目有良好的集成,可以方便地嵌入到现有的应用服务器中。 8. **多种数据绑定技术**:CXF支持JAXB、XMLBeans、Aegis等多种数据绑定技术,使XML到...
这些实现提供了JAX-RS规范的具体实现和扩展功能,比如Jersey支持CDI集成、JSON绑定等。 在给定的压缩包文件`jax-rs-api-master`中,很可能是JAX-RS API的源代码仓库。由于该项目已被迁移到Eclipse Foundation,这...
Apache CXF是一个开源服务框架,它支持多种Web服务标准,包括Java API for RESTful Web Services (JAX-RS)。JAX-RS是Java平台上的一个标准,用于创建RESTful Web服务,它允许开发者通过简单的注解来定义资源类和方法...
【标题】"CXF-BUNDLE-JAXRS-2.4.7.zip" 是一个与Apache CXF相关的开源项目,它包含了一个JAX-RS(Java API for RESTful Web Services)的OSGi捆绑包。JAX-RS是Java平台上的标准,用于创建RESTful服务,而CXF是一个...
在探讨“jaxrs导致的错误”这一主题时,我们深入分析了由JAX-RS(Java API for RESTful Web Services)引发的特定异常情况。这一问题不仅涉及JAX-RS框架本身,还牵扯到Spring框架与Apache CXF库之间的交互,其中包含...
例如,对于JAX-RS项目,可能需要Apache CXF或其他JAX-RS实现的依赖。 6. **项目结构**:`cxf-jax-rs-template-master`可能是项目的源代码仓库主分支名,暗示项目可能来源于Git,遵循一定的目录结构,包括源代码、...
- **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**和*...
1. **Web服务实现**:CXF允许开发者使用JAX-WS和JAX-RS标准来创建和部署Web服务。JAX-WS是用于构建SOAP服务的,而JAX-RS则用于构建RESTful服务。 2. **多种协议支持**:CXF支持多种通信协议,如HTTP、HTTPS、JMS等...
使用 JAX-RS 创建 RESTful Web 服务时,通常会结合 CDI(Contexts and Dependency Injection)或 EJB 进行依赖注入,以及与服务器平台(如 Jersey, RESTEasy, Apache CXF 等)集成,以实现更复杂的功能和扩展。...
CXF集成了JAXB,使得在处理XML消息时,无需编写大量的转换代码。 在提供的压缩包“ws_test”中,很可能包含了使用CXF实现的Web服务示例,包括JAX-WS和JAX-RS的服务端点,以及使用JAXB进行数据交换的类。这个实例...