1.  前言

现在互联网Open API流行,将您的Web应用也可以开放Open API给其他第三方使用。达到一种资源有效利用的目的。而Open API的暴露方式是多种多样的。有Web Service形式的,也有提供一个URI方式的,还有就是给客户端一个jar包,直接使用即可。个人认为,对于使用者来说,使用最简单的就是一个“jar包”+“一份使用文档了”,jar将具体的远程通讯细节、鉴权、握手、数据格式转换等等全部都屏蔽掉。不过这个方式仅仅针对于Java应用,如果用于其他技术,例如ASP.NET、PHP的客户端就不合适了。那么折中一下还是提供一个URI资源,客户端无论是什么技术,只要调用此URI资源就可以获取感兴趣的数据,数据格式和技术平台无关(比如JSON、XML)。REST是一种针对网络应用的设计和开发方式,可以降低开发的复杂性,提高系统的可伸缩性。Web应用暴露出来的是URI资源,客户端可以对资源进行操作(CRUD),REST最重要一点就是无状态,这点实际上感觉是特地针对EJB的会话Bean的重量级说的。所以REST轻量得很,轻量就意味着事务性、稳定性、安全性并没有传统JavaEE应用要求得那么高。主要集中于互联网应用对于不同终端的接口。具体的Rest介绍可以参考:

http://baike.baidu.com/view/1077487.htm

Apache的CXF不仅可以将您的Web系统暴露成为Web Service,还可以将您的应用暴露成REST资源供不同客户端调用。

2.  环境搭建

先从Apache站点下载CXF相关jar包。网址是:http://cxf.apache.org/download.html

我下载的是apache-cxf-2.3.2,这个版本算是比较老了,能用就行。

下载后将项目lib下面的jar拷贝到自己web项目的lib中。CXF的samples下面有很多例子,都是支持Ant构建和Maven构建的。建议还是先使用传统方式构建项目,之后再迁移为Maven项目。这样依赖哪些东西心理有数,CXF是强依赖于Spring框架的。

3.  暴露REST服务

下面我们开始暴露自己的Web资源成为REST服务。我们先来看看web.xml的内容

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <web-app>
  3. <!-- 配置Spring的配置文件 -->
  4. <context-param>
  5. <param-name>contextConfigLocation</param-name>
  6. <param-value>WEB-INF/beans.xml</param-value>
  7. </context-param>
  8. <!-- 配置Spring的web Context监听器,将Spring与web工程集成在一起 -->
  9. <listener>
  10. <listener-class>
  11. org.springframework.web.context.ContextLoaderListener
  12. </listener-class>
  13. </listener>
  14. <!-- 配置CXF -->
  15. <servlet>
  16. <servlet-name>CXFServlet</servlet-name>
  17. <display-name>CXF Servlet</display-name>
  18. <servlet-class>
  19. org.apache.cxf.transport.servlet.CXFServlet
  20. </servlet-class>
  21. <load-on-startup>1</load-on-startup>
  22. </servlet>
  23. <servlet-mapping>
  24. <servlet-name>CXFServlet</servlet-name>
  25. <url-pattern>/service/*</url-pattern>
  26. </servlet-mapping>
  27. <welcome-file-list>
  28. <welcome-file>index.jsp</welcome-file>
  29. </welcome-file-list>
  30. </web-app>

bean.xml内容

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jaxrs="http://cxf.apache.org/jaxrs"
  4. xmlns:context="http://www.springframework.org/schema/context"
  5. xsi:schemaLocation="
  6. http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
  7. http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd
  8. http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
  9. <!-- 引入CXF下面的配置文件 -->
  10. <import resource="classpath:META-INF/cxf/cxf.xml" />
  11. <import resource="classpath:META-INF/cxf/cxf-extension-soap.xml" />
  12. <import resource="classpath:META-INF/cxf/cxf-servlet.xml" />
  13. <!-- 将Bean托管给Spring -->
  14. <bean id="roomService" class="com.platform.restful.demo.RoomService">
  15. </bean>
  16. <bean id="userService" class="com.platform.restful.demo.UserService">
  17. </bean>
  18. <!-- 配置需要暴露的BeanService -->
  19. <jaxrs:server id="restContainer" address="/">
  20. <jaxrs:serviceBeans>
  21. <ref bean="roomService" />
  22. <ref bean="userService" />
  23. </jaxrs:serviceBeans>
  24. </jaxrs:server>
  25. </beans>

此配置文件需要注意几点,一个就是xml的beans声明,需要支持jaxrs:server标签,还有一个就是需要引入CXF自己的一些Spring配置项。该配置项全部在cxf-2.3.2.jar下面的META-INF下面。最后就是注意要暴露的Service类需要配置在jaxrs:server标签中,这样REST资源才能生效。我们就看一个服务吧,在看之前先说明一点,代码有问题,先这么写,根据爆出的问题,咱们再修改代码。

先建立值对象

  1. package com.platform.restful.demo;
  2. import javax.xml.bind.annotation.XmlRootElement;
  3. @XmlRootElement(name = "UserVO")
  4. public class UserVO {
  5. private int id;
  6. private String name;
  7. //省去setter和getter
  8. }

下面是DAO

  1. package com.platform.restful.demo;
  2. import java.util.HashMap;
  3. import java.util.Map;
  4. public class UserDAO {
  5. private static Map<String, UserVO> userVOs;
  6. static {
  7. userVOs = new HashMap<String, UserVO>();
  8. UserVO u1=new UserVO();
  9. u1.setId(1);
  10. u1.setName("liuyan");
  11. UserVO u2=new UserVO();
  12. u2.setId(2);
  13. u2.setName("yexiaochai");
  14. userVOs.put("1", u1);
  15. userVOs.put("2", u2);
  16. }
  17. public static Map<String,UserVO> getPersons(){
  18. return userVOs;
  19. }
  20. public static UserVO getPerson(){
  21. return userVOs.get("1");
  22. }
  23. }

下面就是爆出来的门面服务类了

  1. package com.platform.restful.demo;
  2. import java.util.Map;
  3. import javax.ws.rs.Consumes;
  4. import javax.ws.rs.GET;
  5. import javax.ws.rs.Path;
  6. import javax.ws.rs.Produces;
  7. @Path("/userservice")
  8. @Produces("application/json")
  9. public class UserService {
  10. @GET
  11. @Path("/getUsers")
  12. @Consumes("application/xml")
  13. public Map<String, UserVO> getUsers() {
  14. System.out.println("get users ");
  15. Map<String, UserVO> userVOs = UserDAO.getPersons();
  16. return userVOs;
  17. }
  18. @GET
  19. @Path("/getUser")
  20. @Consumes("application/xml")
  21. public UserVO getUser() {
  22. System.out.println("get user ");
  23. UserVO userVO = UserDAO.getPerson();
  24. return userVO;
  25. }
  26. }

我们将项目部署到Tomcat上,打开浏览器,输入URL

http://127.0.0.1:8080/cxfdemo/service/userservice/getUser

则输出了一段Json信息

  1. {"UserVO":{"id":1,"name":"liuyan"}}

那我们输入URL:

http://127.0.0.1:8080/cxfdemo/service/userservice/getUsers

会是什么效果呢,控制台报出如下错误

  1. 2011-6-15 13:52:47 org.apache.cxf.jaxrs.interceptor.JAXRSOutInterceptor writeResponseErrorMessage
  2. 警告: No message body writer has been found for response class HashMap.

错误信息很明确了public Map<String, UserVO> getUsers()返回的是Map,ok,比较简单的办法就是再写一个复合值对象。具体可参考

http://blog.sina.com.cn/s/blog_4051f5dc0100ju0a.html

复合对象

  1. package com.platform.restful.demo;
  2. import java.util.Map;
  3. import javax.xml.bind.annotation.XmlRootElement;
  4. @XmlRootElement(name = "UserVOMap")
  5. public class UserVOMap {
  6. private Map<String, UserVO> userVOs;
  7. public Map<String, UserVO> getUserVOs() {
  8. return userVOs;
  9. }
  10. public void setUserVOs(Map<String, UserVO> userVOs) {
  11. this.userVOs = userVOs;
  12. }
  13. }

Service服务类修改如下

  1. @GET
  2. @Path("/getUsers")
  3. @Consumes("application/xml")
  4. public UserVOMap getUsers() {
  5. System.out.println("get users ");
  6. Map<String, UserVO> userVOs = UserDAO.getPersons();
  7. UserVOMap userVOMap = new UserVOMap();
  8. userVOMap.setUserVOs(userVOs);
  9. return userVOMap;
  10. }

之后再次访问http://127.0.0.1:8080/cxfdemo/service/userservice/getUsers

获得Json数据如下

  1. {"UserVOMap":{"userVOs":{"entry":[{"key":2,"value":{"id":2,"name":"yexiaochai"}},{"key":1,"value":{"id":1,"name":"liuyan"}}]}}}

另外共享一篇8366的文章和demo

http://8366.iteye.com/blog/952887

本文转自:http://suhuanzheng7784877.iteye.com/blog/1090370

使用CXF暴露您的REST服务的更多相关文章

  1. 使用CXF框架,发布webservice服务,并使用客户端远程访问webservice

    使用CXF框架,发布webservice服务,并使用客户端远程访问webservice  1. CXF介绍 :soa的框架    * cxf 是 Celtrix (ESB框架)和 XFire(webs ...

  2. 怎样让 Web 项目暴露在外的服务坚不可摧?

    Web 项目一般给特定人群使用,有些是局域网用户量不足1K的内部系统,也有些广域网用户上万的中型项目,当然还有用户上亿的大型项目. 这些大大小小的 Web 项目都会有用户登录的存在,登录后有特定的权限 ...

  3. 使用CXF和spring搭建webService服务

    虽然下一个项目需要使用xfire,但是在查资料的过程中还是看到有不少地方都说cxf比xfire更好,cxf继承了xfire,但是不仅仅包含xfire,因此便也一起来尝试尝试.大概是有了xfire的经验 ...

  4. Apache cxf暴露接口以及客户端调用之WebService初步理解

    在我们真实的项目中,经常会调用别人提供给我们的接口,或者在自己的团队中, restful风格的前后端分离也经常会提供一个后端接口暴露出去供app,或者.net/C/C++程序员去调用,此时就需要使用到 ...

  5. CXF创建webservice客户端和服务端

    转 一.CXF的介绍 Apache CXF是一个开源的WebService框架,CXF大大简化了Webservice的创建,同时它继承了XFire的传统,一样可以和spring天然的进行无缝的集成.C ...

  6. cxf 生成客户端代码调用服务

    cxf是另一种发布webservice的方式,与jdk提供的相比 jdk提供的是wsimport cxf 提供的是 wsdl2java- d 地址 根据http://www.cnblogs.com/f ...

  7. cxf整合spring发布rest服务 httpclient访问服务

    1.创建maven web项目并添加依赖 pom.xml <properties> <webVersion>3.0</webVersion> <cxf.ver ...

  8. 使用CXF开发RESTFul服务

    相信大家在阅读CXF官方文档(http://cxf.apache.org/docs/index.html)时,总是一知半解.这里向大家推荐一本PacktPub.Apache.CXF.Web.Servi ...

  9. WebService学习总结(四)--基于CXF的服务端开发

    本节将实践目前最流行的第二种web service 发布和调试框架  CXF Apache CXF 是一个开放源代码框架,提供了用于方便地构建和开发 Web 服务的可靠基础架构.它允许创建高性能和可扩 ...

随机推荐

  1. Highcharts条形与柱形同时显示

    var chart; $(function() { chart = new Highcharts.Chart({ chart: { renderTo: 'chart_combo' //关联页面元素di ...

  2. 小课堂Week11 会说话的代码

    小课堂Week11 会说话的代码 今天主要讨论下,在编码过程中和"命名"相关的问题.因为命名方法比较自由,如果要提高可读性,我们需要尽量使其符合正规的英文语法习惯. 变量/属性 通 ...

  3. Ubuntu12.10编译openwrt遇到的错误

    由于Openwrt有很多工具是要先编译的,在Ubuntu12.10平台下编译openwrt时就遇到了下面这样的错误:elf.cpp: In static member function 'static ...

  4. android架构介绍

    Android其本质就是在标准的Linux系统上增加了Java虚拟机Dalvik,并在Dalvik虚拟机上搭建了一个JAVA的application framework,所有的应用程序都是基于JAVA ...

  5. class_create(),device_create()使用

    开始写Linux设备驱动程序的时候,很多时候都是利用mknod命令手动创建设备节点(包括ldd3中不少例子也是这样),实际上现在Linux内核为我们提供了一组函数,可以用来在模块加载的时候自动在/de ...

  6. 0x04 高级语法

    while-endw .while(条件) 循环体(条件满足时执行) .endw repeat-until .repeat 循环体(条件不满足时执行) .until(条件) if-elseif-end ...

  7. cocos2dx中的定时器及其分类

    cocos2dx中的定时器分三大类: 1.帧循环定时器 2.一次性定时器 3.自定义定时器 一.帧循环定时器,顾名思义,每一帧都会执行一次,用于实时性要求比较高的场合,如碰撞检测 void sched ...

  8. Ado.Net实现简易(省、市、县)三级联动查询,还附加Access数据

    小弟在博客园驻园不久,初来咋到:将最近写的小程序附上,希望各位大牛们吐槽:激发对程序员围观的童鞋们,赶紧加入IT行业,如果你在上海那简称就是SHIT,哈哈题外话,以下开始切入正题: 坐公交车是旁边偶遇 ...

  9. 导致Asp.Net站点重启的10个原因 ,记录重启原因

    Asp.Net站点有时候会莫名其妙的重启,什么原因导致的却不得而知,经过一番折腾后,我总结了导致Asp.Net站点重启的10个原因 1. 回收应用程序池会导致站点重启,记录的原因是: HostingE ...

  10. uva 10859

    刘书例题  树形dp #include <cstdio> #include <cstdlib> #include <cmath> #include <map& ...