【Apache CXF】CXF对JAX-RS的支持
用CXF构建RESTful services有两种方式: 首先列举一下JAX-RS的一些常用注解。 相关dependency: <dependency> ????<groupId>org.apache.cxf</groupId> ????<artifactId>cxf-bundle-jaxrs</artifactId> ????<version>${cxf.version}</version> </dependency> 现在我打算定义一个服务用来返回一组用户信息。 当以get method访问users资源时将以XML表述: package?pac.king.webservice; import?javax.ws.rs.GET; import?javax.ws.rs.Path; import?javax.ws.rs.Produces; import?javax.ws.rs.core.MediaType; import?pac.king.pojo.User; @Path("/") public?interface?MyRestService?{ ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? ????@GET ????@Path("users") ????@Produces({?MediaType.APPLICATION_XML?}) ????public?User[]?userInfos(); } 接口实现我就简单写一下: public?class?MyRestServiceImpl?implements?MyRestService{ ????@WebMethod ????public?User[]?userInfos()?{ ????????User[]?myInfos?=?new?User[4]; ????????myInfos[0]?=?new?User("0001","Kim","t;stmdtkg"); ????????myInfos[1]?=?new?User("0002","King.","t;stmdtkg"); ????????myInfos[2]?=?new?User("0003","sweet_dreams","t;stmdtkg"); ????????myInfos[3]?=?new?User("0004","show_time","t;stmdtkg"); ????????return?myInfos; ????} } 定义User时需要注意加上无参的constructor和@XmlRootElement package?pac.king.pojo; import?javax.xml.bind.annotation.XmlRootElement; @XmlRootElement public?class?User?{ ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? ????private?String?id; ????private?String?name; ????private?String?password; ????public?String?getPassword()?{ ????????return?password; ????} ????public?void?setPassword(String?password)?{ ????????this.password?=?password; ????} ????public?String?getId()?{ ????????return?id; ????} ????public?void?setId(String?id)?{ ????????this.id?=?id; ????} ????public?String?getName()?{ ????????return?name; ????} ????public?void?setName(String?name)?{ ????????this.name?=?name; ????} ????public?User()?{} ????public?User(String?id,?String?name,?String?password)?{ ????????super(); ????????this.id?=?id; ????????this.name?=?name; ????????this.password?=?password; ????} } 使用org.apache.cxf.jaxrs.JAXRSServerFactoryBean启动服务: JAXRSServerFactoryBean?rsFactory?=?new?JAXRSServerFactoryBean(); rsFactory.setAddress("http://localhost:8888/myRest"); rsFactory.setResourceClasses(MyRestServiceImpl.class); rsFactory.create(); 访问http://localhost:8888/myRest/users,输出: 用CXF+Spring方式构建RESTful service也非常方便,虽然也会带来一些问题。 <?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:context="http://www.springframework.org/schema/context" ????xmlns:util="http://www.springframework.org/schema/util" ????xmlns:p="http://www.springframework.org/schema/p" ????xmlns:jaxws="http://cxf.apache.org/jaxws" ????xmlns:jaxrs="http://cxf.apache.org/jaxrs" ????xmlns:cxf="http://cxf.apache.org/core" ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? ????xsi:schemaLocation=" ????????http://www.springframework.org/schema/beans?http://www.springframework.org/schema/beans/spring-beans-4.0.xsd ????????http://www.springframework.org/schema/context?http://www.springframework.org/schema/context/spring-context-4.0.xsd ????????http://www.springframework.org/schema/util?http://www.springframework.org/schema/util/spring-util-4.0.xsd ????????http://cxf.apache.org/jaxws?http://cxf.apache.org/schemas/jaxws.xsd ????????http://cxf.apache.org/core?http://cxf.apache.org/schemas/core.xsd ????????http://cxf.apache.org/jaxrs?http://cxf.apache.org/schemas/jaxrs.xsd ????????" ????????default-autowire="byName"> <import?resource="classpath:META-INF/cxf/cxf.xml"/> ????<import?resource="classpath:META-INF/cxf/cxf-servlet.xml"/> ????<import?resource="classpath:META-INF/cxf/osgi/cxf-extension-osgi.xml"?/> ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? ????<jaxrs:server?id="customerService"?address="/rest"?> ????????<jaxrs:serviceBeans> ????????????<ref??bean="myRestService"/> ????????</jaxrs:serviceBeans> ????</jaxrs:server> ????<bean?id="myRestService"?class="pac.king.webservice.impl.MyRestServiceImpl"/> ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? </beans> 在web.xml中加入CXFServlet,注意我写的url pattern是/services/*: <servlet> ????<servlet-name>CXFServlet</servlet-name> ????<servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class> ????<load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> ????<servlet-name>CXFServlet</servlet-name> ????<url-pattern>/services/*</url-pattern> </servlet-mapping> <servlet> 访问http://localhost:8080/runtrain/services,效果如下(还有一个是上一篇的JAX-WS服务): 访问http://localhost:8080/runtrain/services/rest/users,效果如下: 最后说一下lifecycle的问题。 jaxrs:server下还有一个子标签叫jaxrs:serviceFactories,里面可以存放org.apache.cxf.jaxrs.spring.SpringResourceFactory类型的Bean,SpringResourceFactory将会把服务的声明周期委派给ApplicationContext来管理。 <bean?id="myRestService"?class="pac.king.webservice.impl.MyRestServiceImpl"?scope="prototype"/> <jaxrs:server?id="customerService"?address="/rest"?> ????<jaxrs:serviceFactories> ????????<ref?bean="resourceFactory"?/> ????</jaxrs:serviceFactories> </jaxrs:server> <bean?id="resourceFactory"?class="org.apache.cxf.jaxrs.spring.SpringResourceFactory"> ????<property?name="beanId"?value="myRestService"?/> </bean> 但这种方式有些麻烦,难道我就为了让scope生效定义bean又定义SpringResourceFactory又设置serviceFactoris? <beans> ????<jaxrs:server?id="customerService"?address="/rest" ????????beanNames="myRestService"?/> ????<bean?id="myRestService"?class="pac.king.webservice.impl.MyRestServiceImpl"?scope="prototype"/> </beans> 需要注意的是beanNames属性中写多个值时以space分隔。 别人辛苦构建了RESTful Service,总不能只用浏览器调用。 继续使用上面的例子,这次加个参数,如下: package?pac.king.webservice; import?javax.ws.rs.GET; import?javax.ws.rs.Path; import?javax.ws.rs.PathParam; import?javax.ws.rs.Produces; import?javax.ws.rs.core.MediaType; import?pac.king.pojo.User; @Path("/") public?interface?MyRestService?{ ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? ????@GET ????@Path("limitUsers/{count}") ????@Produces({?MediaType.APPLICATION_XML?}) ????public?User[]?userInfos(@PathParam("count")int?cnt); } 实现: public?User[]?userInfos(int?count)?{ ????System.out.println("count="+count); ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? ????User[]?myInfos?=?new?User[count]; ????for?(int?i?=?0;?i?<?count;?i++)?{ ????????myInfos[i]?=?new?User(i+1+"","King."+UUID.randomUUID(),"t;stmdtkg"); ????} ????return?myInfos; } User类: package?pac.king.pojo; import?javax.xml.bind.annotation.XmlRootElement; @XmlRootElement public?class?User?{ ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? ????private?String?id; ????private?String?name; ????private?String?password; ????public?String?getPassword()?{ ????????return?password; ????} ????public?void?setPassword(String?password)?{ ????????this.password?=?password; ????} ????public?String?getId()?{ ????????return?id; ????} ????public?void?setId(String?id)?{ ????????this.id?=?id; ????} ????public?String?getName()?{ ????????return?name; ????} ????public?void?setName(String?name)?{ ????????this.name?=?name; ????} ????public?User()?{} ????public?User(String?id,?String?password)?{ ????????super(); ????????this.id?=?id; ????????this.name?=?name; ????????this.password?=?password; ????} } 当然,某种程度上org.apache.commons.httpclient.HttpClient也可以调用。 JAXRSClientFactoryBean?bean?=?new?JAXRSClientFactoryBean(); bean.setAddress("http://localhost:8080/runtrain/services/rest"); bean.setResourceClass(MyRestServiceImpl.class); ????????MyRestServiceImpl?proxy?=?(MyRestServiceImpl)bean.create();
比如可以这样使用: MyRestServiceImpl?client?=?JAXRSClientFactory.create("http://localhost:8080/runtrain/services/rest",?MyRestServiceImpl.class); User[]?users?=?client.userInfos(10); 让人感觉很奇怪,提供了一个工厂类却可以直接使用Bean,官网上没找到答案,我也不纠结了吧。 上面代码中使用的MyRestServiceImpl和Server端可以是没有任何关系的,让远程调用变得透明也正是proxy的意义。 除了JAXRSClientFactoryBean,还有Http-centric web client:
WebClient?webClient?=?WebClient.create("http://localhost:8080/runtrain/services/rest"); ????????webClient?.path("limitUsers").path(new?Integer(10)); ????????webClient?.type(MediaType.APPLICATION_XML).accept(MediaType.APPLICATION_XML); ????????User[]?res?=?webClient.get(User[].class); ????????System.out.println(res.length); (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |