XFire 架构的 WebService 开发

1.引言

1.1.  目的

Java 开发WebService 的开发有多种,而且没有特别是没有一个统一的标准实现,XFireAxis2,CXF等;本文档主要是讲使用XFire来实习WebService的开发。

1、为了避免在以后编写WebService时,研发人员的重复工作。

2、为了避免不必要的矛盾和冲突,减少研发、维护成本。

 

1.2.  范围

适合使用Web Services的情况

1、跨越防火墙;

2、应用程序集成;

3B2B集成;

4、软件重用

 

不适合使用Web服务的情况

1、单机应用程序;

2、局域网上的同构应用程序

 

1.3.  术语与缩写

序号

术语

说明

1

SOAP

简单对象访问协议(SOAP)提供了标准的RPC方法来调用Web service

2

WSDL

Web service描述语言(WSDL)就是这样一个基于XML(标准通用标记语言下的一个子集)的语言

3

XML

可扩展的标记语言(标准通用标记语言下的一个子集)是Web service平台中表示数据的基本格式

4

 

 

5

 

 

2.实现功能特点

A.   基于J2EE 平台的Web Service 服务

B.   开发方便,配置简单

l  设计接口

l  实现服务

l  配置暴露接口

l  XFire 将自动生成对应的wsdl

l  支持高级详细配置

C.   Spring 无缝集成

 

3.运行环境

JDK 1.5+

Tomcat 5.0+ / WebLogic 8.1 (需要特殊配置,见附录)未测试其他环境

其他包依赖参看 http://xfire.codehaus.org/Dependency+Guide

 

4.开发平台

Eclipse

Tomcat 6.0

XFire 1.2.6 - http://xfire.codehaus.org/Home

Maven3.0

 

5.开发步骤

Java 开发WebService 的开发有多种,而且没有特别是没有一个统一的标准实现,XFireAxis2,CXF等。下面我们选用 XFire来开发WebServiceXFire与其他WebService框架的不同,它最大的不同之处在于它需要一个接口,而且如果需要用XFire来调用相应的WebService必须知道接口的定义,这感觉这里有点限制但也符合。但这点也符合Jave的面向对象的特点。而且XFire调用WebService,那是相当的方便,就跟调用本地方法一样

我们先虚拟一个场景:

服务端:
1
、提供获取订单信息的方法;

2、提供添加订单信息的方法;

 

客户端:

1、根据订单ID获取服务端的订单信息;

2、向服务段添加一个订单信息;

 

以下是两种模式的实现方式:

1.1.  XFire简单模式

简单模式服务器端的4个步骤:

1.   提供一个接口,接口里面有两个方法,一个是获取订单信息的方法,一个是添加订单信息的方法。

2.   实现上面的接口。

3.   配置XFireservices.xml

4.   添加XFirejar包依赖,并在Web.XML 新增WebService 的请求拦截

下面我们开始编写代码:

1.1.1.   订单实体

代码:

 

 



 

package com.topinfo.xfire.bean;

import java.io.Serializable;

/**
 * @Description: 订单实体
 * @Author:杨攀
 * @Since:2014年3月24日下午3:09:45
 */
public class Order implements Serializable {

	/** 
	 *@Fields serialVersionUID : 序列化
	 */ 
	private static final long serialVersionUID = 3089238328535163124L;

	/**
	 * @Fields orderId : 订单号
	 */
	private String orderId;

	/**
	 * @Fields orderName : 订单名称
	 */
	private String orderName;

	public String getOrderId() {
		return orderId;
	}

	public void setOrderId(String orderId) {
		this.orderId = orderId;
	}

	public String getOrderName() {
		return orderName;
	}

	public void setOrderName(String orderName) {
		this.orderName = orderName;
	}

	@Override
	public String toString() {
		return "订单号为:" + orderId + ",订单名称:" + orderName;
	}

}

 

注意:我们这里的Order类实现了Serializable接口,Java在互联网上传递对象,需要序列化。

 

 

1.1.1.   服务器提供接口

接口代码:

 

 

package com.topinfo.xfire.service;

import java.util.List;

import com.topinfo.xfire.bean.Order;




/**
 *@Description:订单接口服务器
 *@Author:杨攀
 *@Since:2014年3月24日下午3:06:59  
 */
public interface OrderService {
	
	/**
	 *@Description: 根据订单号获取订单信息
	 *@Author: 杨攀
	 *@Since: 2014年3月24日下午3:08:07
	 *@param orderId 订单号
	 *@return
	 */
	public Order queryOrder(String orderId);
	
	/**
	 *@Description: 保存订单信息
	 *@Author: 杨攀
	 *@Since: 2014年3月24日下午3:09:04
	 *@param order
	 *@return
	 */
	public String saveOrder(Order order);

	
	/**
	 *@Description: 返回List
	 *@Author: 杨攀
	 *@Since: 2014年3月25日上午10:14:06
	 *@param num
	 *@return
	 */
	public List<Order>  queryOrderList(int num);
	
}

 

1.1.1.   服务器接口的实现

实现类代码:

 

 

 

 

package com.topinfo.xfire.serviceImpl;



import java.util.ArrayList;
import java.util.List;

import com.topinfo.xfire.bean.Order;
import com.topinfo.xfire.service.OrderService;


/**
 *@Description:订单接口服务器的实现
 *@Author:杨攀
 *@Since:2014年3月24日下午3:18:13  
 */
public class OrderServiceImpl implements OrderService {

	
	public Order queryOrder(String orderId) {
		
		Order bean = null;
		
		if(null != orderId && !"".equals(orderId)){
			bean = new Order();
			bean.setOrderId(orderId);
			bean.setOrderName("ZJTX-"+orderId);
		}
		
		return bean;
	}

	
	public String saveOrder(Order order) {
		return order.toString();
	}


	public List<Order> queryOrderList(int num) {
		
		List<Order> list = new ArrayList<Order>();
		for (int i = 0; i < num; i++) {
			Order order = new Order();
			order.setOrderId("ZJTX-"+i);
			order.setOrderName("订单名称"+i);
			list.add(order);
		}
		
		return list;
	}

}

 

 

1.1.1.   创建XFireservices.xml文件

src目录下新建一个META-INF文件夹,再在它下面新建一个xfire的文件夹,里面新建一个services.xml的文件。我们这么建的目的是想让eclipse帮我们直接部署到tomcat容器中。其实我们只要保证在部署后的\WEB-INF\classes下面有META-INF\xfire\services.xml目录格式就行。

注意:这个文件所在文件夹层次是固定的,不可以修改。

 

代码如下:

 

 

 

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://xfire.codehaus.org/config/1.0">
	<service>
		<!-- webservice 名称,调用时需要指定这个 -->
		<name>OrderService</name>
		<!-- 这个一般是自己公司的网址,意义不大 -->
		<namespace>http://com.topinfp/OrderService</namespace>
		<!-- 接口类 -->
		<serviceClass>com.topinfo.xfire.service.OrderService</serviceClass>
		<!-- 实现类 -->
		<implementationClass>com.topinfo.xfire.serviceImpl.OrderServiceImpl</implementationClass>
		
		<!--注册监听处理器  
        <inHandlers>  
            <handler handlerClass="com.topinfo.xfire.listener.HandlerMappingListener"></handler>  
        </inHandlers>
       -->		
	</service>
</beans>

 

 

1.1.1.   添加Jar的依赖并添加请求拦截

添加Jar包的依赖

<!-- xfire  -->
		<dependency>
			<groupId>javax.mail</groupId>
			<artifactId>mail</artifactId>
			<version>1.4</version>
		</dependency>
		
		<dependency>
			<groupId>org.codehaus.xfire</groupId>
			<artifactId>xfire-aegis</artifactId>
			<version>1.2.6</version>
		</dependency>
		<dependency>
			<groupId>org.codehaus.xfire</groupId>
			<artifactId>xfire-spring</artifactId>
			<version>1.2.6</version>
		</dependency>
		<dependency>
			<groupId>xalan</groupId>
			<artifactId>xalan</artifactId>
			<version>2.7.0</version>
		</dependency>

 

 

 

web.xml中新增代码:

 

 

 

	<servlet>
		<servlet-name>XFireServlet</servlet-name>
		<servlet-class>org.codehaus.xfire.transport.http.XFireConfigurableServlet</servlet-class>
		<load-on-startup>1</load-on-startup>
	</servlet>

	<servlet-mapping>
		<servlet-name>XFireServlet</servlet-name>
		<url-pattern>/webservice/*</url-pattern>
	</servlet-mapping>

 

 

1.1.1.   订单服务端的目录结构

 

结构下:

 

 

 
XFire 架构的 WebService 开发_第1张图片
 

 

1.1.1.   启动服务器端

浏览器中输入:

http://localhost:8080/OrderService/webservice/OrderService?wsdl

 

 
XFire 架构的 WebService 开发_第2张图片
 

 

完成后,我们就可以让别人调用我们的WebService了,下面我模拟客户端来调用WebService

 

注意:目前接口中有返回 List的 方法去掉才能正常启动的啊,原因看后面的扩展

 

 

 

1.1.1.   客户端测试

客户端测试需要把服务器端的接口和实体打成jar包给客户端引用,或者根据wsdl 生产客户端,网上有很多小工具或者通过 eclipse 生产也许,手写也行,代码如下:

 

 

 

// 这里是创建一个service,需要传入一个接口类,因为我们后面必须调用相应的接口方法
		Service srcModel = new ObjectServiceFactory().create(OrderService.class);

		// 代理工厂,这里是为了后面创建相应的接口类
		// XFireProxyFactory factory = new XFireProxyFactory(XFireFactory.newInstance().getXFire());
		XFireProxyFactory factory = new XFireProxyFactory();

		String readerServiceUrl = "http://localhost:8080/OrderService/webservice/OrderService";

		try {
			// 利用工厂返回相应的接口类
			OrderService orderService = (OrderService) factory.create(srcModel,
					readerServiceUrl);

			List<Order> orderList = orderService.queryOrderList(5);

			for (int i = 0; i < orderList.size(); i++) {
				System.out.println(orderList.get(i));
			}
		} catch (MalformedURLException e) {
			e.printStackTrace();
		}

 

 

 效果:

 

1.1.1.   总结

当我们需要提供一个WebService接口的时候,我们需要4步:

1、提供接口和实现类

2、创建XFireservices.xml 文件

3、添加Jar的依赖

4、web.xmlWebService的请求Maping

 

这样 WebService 就完成了!

 

1.1.2.   扩展

1、当返回对象的复杂对象时,处理方式

如返回List

因为我们用到了List等集合类型,所以需要定义Mapping关系,文件名为:接口名称.aegis.xml,存放到接口的同一包下。代码如下:

 

  

<?xml version="1.0" encoding="UTF-8" ?>
<!-- 该文件用来描述IUsersService接口中getUsers()方法返回值的类型 该文件必须与IUsersService位于同一目录中,且该文件遵循如下命名规则 
	webservice接口名.aegis.xml 如本文件IUsersService.aegis.xml -->
<mappings>
	<!-- 映射方法返回值类型 -->
	<mapping>
		 
		<method name="queryOrder">
			<return-type componentType="com.topinfo.xfire.bean.Order" />
		</method>
		
		<method name="queryOrderList">
			<return-type componentType="com.topinfo.xfire.bean.Order" />
		</method>
		 
	</mapping>
</mappings> 

 

 

 

2、请求的校验(基于Xfire SOAP HeaderWebService安全验证)

共以下 4 步骤:

1、服务器段添加安全验证的监听类

 

 

package com.topinfo.xfire.listener;

import org.codehaus.xfire.MessageContext;
import org.codehaus.xfire.handler.AbstractHandler;
import org.jdom.Element;

/**
 * @Description: 监听处理器
 * @Author:杨攀
 * @Since:2014年3月25日上午11:19:55
 */
public class HandlerMappingListener extends AbstractHandler {
 
	public void invoke(MessageContext context) throws Exception {
		// 为SOAP Header构造验证信息
		if (context.getInMessage().getHeader() == null) {
			throw new org.codehaus.xfire.fault.XFireFault("请求必须包含验证信息", org.codehaus.xfire.fault.XFireFault.SENDER);
		}

		Element token = context.getInMessage().getHeader().getChild("AuthenticationToken");
		if (token == null) {
			throw new org.codehaus.xfire.fault.XFireFault("请求必须包含身份验证信息", org.codehaus.xfire.fault.XFireFault.SENDER);
		}

		String username = token.getChild("Username").getValue();
		String password = token.getChild("Password").getValue();

		try {
			// 进行身份验证 ,只有admin/admin 的用户为授权用户
			if ("admin".equals(username) && "admin".equals(password)) {
				System.out.println("身份验证通过");
			} else {
				throw new Exception();
			}
		} catch (Exception e) {
			throw new org.codehaus.xfire.fault.XFireFault("非法的用户名和密码", org.codehaus.xfire.fault.XFireFault.SENDER);
		}
	}
}

 

 

 

1、把监听类注册到XFireservices.xml 文件中

<!--注册监听处理器-->  
        <inHandlers>  
            <handler handlerClass="com.topinfo.xfire.listener.HandlerMappingListener"></handler>  
        </inHandlers>

 

1、 2、客户端构造授权信息

package com.topinfo.xfire.listener;

import org.codehaus.xfire.MessageContext;
import org.codehaus.xfire.handler.AbstractHandler;
import org.jdom.Element;

/**
 *@Description: 监听处理器
 *@Author:杨攀
 *@Since:2014年3月25日上午11:19:55
 */
public class ClientHandler extends AbstractHandler {

	private String username = null;

	private String password = null;

	public ClientHandler() {
	} 
	public ClientHandler(String username, String password) {
		this.username = username;
		this.password = password;
	}
 
	public void invoke(MessageContext context) throws Exception {
		// 为SOAP Header构造验证信息
		Element el = new Element("header");
		context.getOutMessage().setHeader(el);
		//添加一个 AuthenticationToken 的元素
		Element auth = new Element("AuthenticationToken");
		
		Element username_el = new Element("Username");
		username_el.addContent(username);
		
		Element password_el = new Element("Password");
		password_el.addContent(password);
		
		auth.addContent(username_el);
		auth.addContent(password_el);
		
		el.addContent(auth);
	}

}

 

 

 

 

 

1、发送授权信息

 

package com.topinfo.xfire.client;

import java.lang.reflect.Proxy;
import java.net.MalformedURLException;
import java.util.List;

import org.codehaus.xfire.client.Client;
import org.codehaus.xfire.client.XFireProxy;
import org.codehaus.xfire.client.XFireProxyFactory;
import org.codehaus.xfire.service.Service;
import org.codehaus.xfire.service.binding.ObjectServiceFactory;

import com.topinfo.xfire.bean.Order;
import com.topinfo.xfire.listener.ClientHandler;
import com.topinfo.xfire.service.OrderService;

public class ListenerTest {
	
	public static void main(String[] args) {
		
				// 这里是创建一个service,需要传入一个接口类,因为我们后面必须调用相应的接口方法
				Service srcModel = new ObjectServiceFactory().create(OrderService.class);

				// 代理工厂,这里是为了后面创建相应的接口类
				// XFireProxyFactory factory = new XFireProxyFactory(XFireFactory.newInstance().getXFire());
				XFireProxyFactory factory = new XFireProxyFactory();

				String readerServiceUrl = "http://localhost:8080/OrderService/webservice/OrderService";

				try {
					// 利用工厂返回相应的接口类
					OrderService orderService = (OrderService) factory.create(srcModel,readerServiceUrl);
					
					//在报头加入信息,供安全校验
					XFireProxy proxy = (XFireProxy) Proxy.getInvocationHandler(orderService); 
					Client client = proxy.getClient();
					// 发送授权信息  
		            client.addOutHandler(new ClientHandler("admin","admin1")); 
					
					List<Order> orderList = orderService.queryOrderList(5);

					for (int i = 0; i < orderList.size(); i++) {
						System.out.println(orderList.get(i));
					}
				} catch (MalformedURLException e) {
					e.printStackTrace();
				}
		
	}

}

 

OK  校验添加完成!

 

 

 

1.1.  XFireSpring无缝集成模式

步骤:

1、  添加jar依赖

2、  修改web.xml

3、  修改applicationContext.xml

4、  编写接口和实现

 

spring 整合的时候,就不需要在配置 XFire service.xml文件,其他地方和原来的简单模式一样

 

 

1.1.1.   添加依赖

添加Jar依赖:注意包冲突的问题

<!-- xfire 依赖包 -->
			<dependency>
				<groupId>javax.mail</groupId>
				<artifactId>mail</artifactId>
				<version>1.4</version>
			</dependency>
			<dependency>
				<groupId>org.codehaus.xfire</groupId>
				<artifactId>xfire-aegis</artifactId>
				<version>1.2.6</version>
			</dependency>
			<dependency>
				<groupId>org.codehaus.xfire</groupId>
				<artifactId>xfire-spring</artifactId>
				<version>1.2.6</version>
				<exclusions>
	                <exclusion>
	                    <artifactId>spring</artifactId>
	                    <groupId>org.springframework</groupId>
	                </exclusion>
	            </exclusions>
			</dependency>
			<dependency>
				<groupId>xalan</groupId>
				<artifactId>xalan</artifactId>
				<version>2.7.0</version>
			</dependency>

 

 

1.1.1.   修改Web.XML 文件

 

1、添加 xfire的配置文件,

<context-param>
		<param-name>contextConfigLocation</param-name>
		<!-- 引入 classpath:org/codehaus/xfire/spring/xfire.xml -->
		<param-value>classpath:org/codehaus/xfire/spring/xfire.xml,classpath:applicationContext.xml</param-value>
	</context-param>

 

 

2、添加WebService Mapping 配置

 

<!-- begin XFire 配置 -->
	 
	<servlet>
		<servlet-name>XFireServlet</servlet-name>
		<!-- 不整合spring 时使用org.codehaus.xfire.transport.http.XFireConfigurableServlet -->  
		<servlet-class>org.codehaus.xfire.spring.XFireSpringServlet</servlet-class>
		<load-on-startup>1</load-on-startup>
	</servlet>

	<servlet-mapping>
		<servlet-name>XFireServlet</servlet-name>
		<url-pattern>/webservice/*</url-pattern>
	</servlet-mapping>
	
	<!-- end XFire 配置 -->

 

 

 

 

 

1.1.1.   修改applicationContext.xml

 

 

 

	<!-- =================== 通知公告 =================== -->
	<bean id="iTSMEStandardService" class="com.topinfo.xfire.webserviceImpl.ITSMEStandardServiceImpl">
		<property name="slNoticeServiceImpl" ref="slNoticeServiceImpl"></property>
	</bean>
	
	<bean name="WebService" class="org.codehaus.xfire.spring.ServiceBean">
		<!-- 业务接口实现类 -->
		<property name="serviceBean" ref="iTSMEStandardService"/>
		<!-- 业务接口 -->
		<property name="serviceClass" value="com.topinfo.xfire.webservice.ITSMEStandardService"/>
		<property name="inHandlers">
			<list>
				<ref bean="addressingHandler"/>
				<ref bean="handlerMappingListener"/><!--普通的用户名密码的方式进行WebService的验证-->
			</list>
		</property>
	</bean>
	<bean id="handlerMappingListener" class="com.topinfo.xfire.webservice.listener.HandlerMappingListener"/>	
	<bean id="addressingHandler" class="org.codehaus.xfire.addressing.AddressingInHandler"/>

 

 

1.1.1.   编写接口和实现类

这里就是普通的接口实现类,省略:

 

 

 

   

 

这样。。webservice 就完美搞定了,,篇幅有点大。可能有看不清楚的地方,大伙可以下载我的word吧!  

你可能感兴趣的:(spring,webservice,xfire)