`
suhuanzheng7784877
  • 浏览: 691659 次
  • 性别: Icon_minigender_1
  • 来自: 北京
博客专栏
Ff8d036b-05a9-33b5-828a-2633bb68b7e6
读金庸故事,品程序人生
浏览量:47234
社区版块
存档分类
最新评论

使用CXF暴露您的REST服务

阅读更多

1.  前言

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

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

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

2.  环境搭建

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

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

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

3.  暴露REST服务

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

<?xml version="1.0" encoding="UTF-8"?>
<web-app>
	<!-- 配置Spring的配置文件 -->
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>WEB-INF/beans.xml</param-value>
	</context-param>
	
	<!-- 配置Spring的web Context监听器,将Spring与web工程集成在一起 -->
	<listener>
		<listener-class>
			org.springframework.web.context.ContextLoaderListener
        </listener-class>
	</listener>
	
	<!-- 配置CXF -->
	<servlet>
		<servlet-name>CXFServlet</servlet-name>
		<display-name>CXF Servlet</display-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>/service/*</url-pattern>
	</servlet-mapping>
	<welcome-file-list>
		<welcome-file>index.jsp</welcome-file>
	</welcome-file-list>
</web-app>

 bean.xml内容

 

<?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"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation=" 
       http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd 
       http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd 
       http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
	
	<!-- 引入CXF下面的配置文件 -->
	<import resource="classpath:META-INF/cxf/cxf.xml" />
	<import resource="classpath:META-INF/cxf/cxf-extension-soap.xml" />
	<import resource="classpath:META-INF/cxf/cxf-servlet.xml" />

	<!-- 将Bean托管给Spring -->
	<bean id="roomService" class="com.platform.restful.demo.RoomService">
	</bean>

	<bean id="userService" class="com.platform.restful.demo.UserService">
	</bean>
	
	<!-- 配置需要暴露的BeanService -->
	<jaxrs:server id="restContainer" address="/">
		<jaxrs:serviceBeans>
			<ref bean="roomService" />
			<ref bean="userService" />
		</jaxrs:serviceBeans>
	</jaxrs:server>
</beans>

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

先建立值对象

package com.platform.restful.demo;

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement(name = "UserVO")
public class UserVO {

	private int id;
	private String name;

//省去setter和getter
}

 下面是DAO

package com.platform.restful.demo;

import java.util.HashMap;
import java.util.Map;

public class UserDAO {
	
	private static Map<String, UserVO> userVOs;
	
	static {
		userVOs = new HashMap<String, UserVO>();
	
		UserVO u1=new UserVO();
		u1.setId(1);
		u1.setName("liuyan");
		
		UserVO u2=new UserVO();
		u2.setId(2);
		u2.setName("yexiaochai");
		
		userVOs.put("1", u1);
		userVOs.put("2", u2);
	}
	
	public static Map<String,UserVO> getPersons(){
		return userVOs;
	}
	
	public static UserVO getPerson(){
		return userVOs.get("1");
	}

}

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

 

package com.platform.restful.demo;

import java.util.Map;

import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;

@Path("/userservice")
@Produces("application/json")
public class UserService {
	
	@GET
	@Path("/getUsers")
	@Consumes("application/xml")
	public Map<String, UserVO> getUsers() {
		System.out.println("get users ");
		Map<String, UserVO> userVOs = UserDAO.getPersons();
		return userVOs;
	}
	
	@GET
	@Path("/getUser")
	@Consumes("application/xml")
	public UserVO getUser() {
		System.out.println("get user ");
		UserVO userVO = UserDAO.getPerson();
		return userVO;
	}

}

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

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

则输出了一段Json信息

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

 那我们输入URL

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

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

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

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

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

复合对象

package com.platform.restful.demo;

import java.util.Map;
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement(name = "UserVOMap")
public class UserVOMap {

	private Map<String, UserVO> userVOs;

	public Map<String, UserVO> getUserVOs() {
		return userVOs;
	}

	public void setUserVOs(Map<String, UserVO> userVOs) {
		this.userVOs = userVOs;
	}

}

 Service服务类修改如下

	@GET
	@Path("/getUsers")
	@Consumes("application/xml")
	public UserVOMap getUsers() {
		System.out.println("get users ");
		Map<String, UserVO> userVOs = UserDAO.getPersons();
		UserVOMap userVOMap = new UserVOMap();
		userVOMap.setUserVOs(userVOs);
		return userVOMap;
	}

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

获得Json数据如下

{"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

12
0
分享到:
评论
5 楼 hty881008 2018-07-18  
LZ,你的json返回是怎么出来的,我的怎么是No message body writer has been found for response class UserVO.
4 楼 wangyudong 2018-03-12  
新版本的Wisdom RESTClient地址
https://github.com/Wisdom-Projects/rest-client
3 楼 wangyudong 2017-11-27  
由CXF实现的微服务需要有比较好的工具去测试RESTful API,很多REST Client是不支持自动化测试RESTful API,也不支持自动生成API文档.
之前习惯用一款名字为 WisdomTool REST Client,支持自动化测试RESTful API,输出精美的测试报告,并且自动生成精美的RESTful API文档。
轻量级的工具,功能却很精悍哦!

https://github.com/wisdomtool/rest-client

Most of REST Client tools do not support automated testing.

Once used a tool called WisdomTool REST Client supports automated testing, output exquisite report, and automatically generating RESTful API document.

Lightweight tool with very powerful features!

https://github.com/wisdomtool/rest-client
2 楼 zjc198805 2012-04-27  
LZ,如何上传文件呢?求指教!644952013@qq.com
1 楼 itcyt 2011-12-26  
这里怎么加入安全认证呢?

相关推荐

Global site tag (gtag.js) - Google Analytics