欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

XFire 架构的 WebService 开发 XFireWebServicespring 

程序员文章站 2022-04-09 10:48:17
...

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 开发
            
    
    
        XFireWebServicespring 
 

 

1.1.1.   启动服务器端

浏览器中输入:

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

 

 
XFire 架构的 WebService 开发
            
    
    
        XFireWebServicespring 
 

 

完成后,我们就可以让别人调用我们的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();
		}

 

 

 效果:
XFire 架构的 WebService 开发
            
    
    
        XFireWebServicespring 
 

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吧!  

  • XFire 架构的 WebService 开发
            
    
    
        XFireWebServicespring 
  • 大小: 19.7 KB
  • XFire 架构的 WebService 开发
            
    
    
        XFireWebServicespring 
  • 大小: 31.1 KB
  • XFire 架构的 WebService 开发
            
    
    
        XFireWebServicespring 
  • 大小: 100 KB
  • XFire 架构的 WebService 开发
            
    
    
        XFireWebServicespring 
  • 大小: 19 KB
  • XFire 架构的 WebService 开发
            
    
    
        XFireWebServicespring 
  • 大小: 40.6 KB