CXF系列之JAX-WS规范的java实现方式

Web服务分为Server,Client两部分,Server公开Web服务,Client调用Web服务,JAX-WS的服务端、客户端双方使用HTTP协议进行数据的传输,SOAP消息格式进行数据的封装(其实SOAP信封内包装的也就是一段XML代码)。

1、服务端

(1)、公开Web服务的接口IHelloService
package com.test.inter.service;

import javax.jws.WebService;

import com.test.bean.Customer;

@WebService
public interface IHelloService {

	public Customer selectMaxAgeCustomer(Customer c1,Customer c2);
	public Customer selectLongNameCustomer(Customer c1,Customer c2);
}
我们看到的这个接口很简单,仅仅是使用类级别的注解@WebService就标注了这个接口的方法将公开为Web服务,使用了这个注解的接口的所有的方法都将公开为Web服务,如果你想屏蔽某个方法,可以使用方法注解@Method的exclude=true。我们通常把公开为Web服务的接口叫做SEI(Service EndPoint Interface)服务端点接口。
(2)、实现类HelloServiceImpl
package com.test.impl.service;

import com.test.bean.Customer;
import com.test.inter.service.IHelloService;

public class HelloServiceImpl implements IHelloService{

	@Override
	public Customer selectMaxAgeCustomer(Customer c1, Customer c2) {
		if(c1 == null || c2 == null){
			return null;
		}
		if(c1.getBirthday().getTime() > c2.getBirthday().getTime()){
			return c2;
		}else{
			return c1;
		}
	}

	@Override
	public Customer selectLongNameCustomer(Customer c1, Customer c2) {
		if(c1 == null || c2 == null){
			return null;
		}
		if(c1.getName().length() < c2.getName().length()){
			return c2;
		}else{
			return c1;
		}
	}

}
这个实现类没有任何特殊之处,但是如果你的实现类还实现了其他的接口,那么你需要在实现类上,使用@WebService注解的endpointInterface属性指定哪个接口是SEI(全类名)
@WebService(endpointInterface="com.test.inter.IHelloService")
(3)、实体类:Customer
package com.test.bean;

import java.util.Date;

import javax.xml.bind.annotation.XmlRootElement;

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

	private long id;
	private String name;
	private Date birthday;
	public long getId() {
		return id;
	}
	public void setId(long id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public Date getBirthday() {
		return birthday;
	}
	public void setBirthday(Date birthday) {
		this.birthday = birthday;
	}
	
	
}
这个类是公开为Web服务的接口中的参数类型和返回值,因此你需要使用JAXB注解告诉CXF如何在XML和Java Object之间处理,因为之前说过SOAP消息格式包装的是一段XML代码,那么无论是服务端还是客户端在接受到SOAP消息时都需要将XML转化为Java Object,在发送SOAP消息时需要将Java Object转化为XML。
(4)、发布Web服务
package com.test.server;

import javax.xml.ws.Endpoint;

import com.test.impl.service.HelloServiceImpl;

public class SoapServer {

	public static void main(String[] args) {
		Endpoint.publish("http://localhost:8080/helloService", new HelloServiceImpl());
	}
}
注意,我们发布Web服务使用的是javax.xml.ws.*包中的EndPoint的静态方法publish()。该方法最少需要两个参数,第一个参数表示该Web服务发布的地址,第二个参数表示需要发布的Web服务的具体实现类。在本例中,我们没有借助于Tomcat服务器,直接运行main方法发布Web服务,其实是使用了CXF内置的Jetty(servlet容器)。
(5)、查看WSDL
访问在publish方法中设置的发布地址后面加上"?wsdl"(比如:http://localhost:8080/helloService?wsdl),就会看到一个XML文件,该文件就是WSDL(WebService Definition Language),Web服务能够被各种编程语言书写的程序访问就是通过WSDL这种通用的契约来完成的。

2、客户端

(1)、通过WSDL生成客户端
由于Web服务只向客户端暴露WSDL,因此客户端必须要将WSDL转化为自己的编程语言编写的代码,JAX-WS的各种实现都提供相应的工具进行WSDL与Java之间的转换,在CXF运行包中的bin目录下,其中的wsdl2java.bat可以将WSDL转化为JAVA类。
打开dos窗口,将目录切换到CXF的bin目录下(如果将CXF加入到了环境变量中,可以不用切换目录),常用的生成客户端的命令格式:wsdl2java -p 生成的客户端的包路径 -d 目标文件夹 wsdl的url地址
生成本例客户端:wsdl2java -p com.test.client -d E:\ http://localhost:8080/helloService?wsdl
在E盘根目录下将会生成客户端代码,然后将其复制到eclipse中即可使用。
生成的客户端的相关类如下:

其中package-info.java、ObjectFactory.java是JAXB需要的文件,HelloServiceImplService.java继承自javax.xml.ws.Service类,用于提供WSDL客户端视图,里面使用的是大量的javax.xml.ws.*包中的注解,剩下的类是Web服务的接口、方法参数、响应值的类。
(2)、使用JaxWsProxyFactoryBean客户端代理工厂类调用Web服务
package com.test.client;

import java.text.ParseException;
import java.text.SimpleDateFormat;

import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;

import com.test.bean.Customer;
import com.test.inter.service.IHelloService;

public class SoapClient {

	public static void main(String[] args) throws ParseException {
		JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
		factory.setAddress("http://localhost:8080/helloService");
		factory.setServiceClass(IHelloService.class);
		Object o = factory.create();
		IHelloService service = (IHelloService)o;
		
		Customer c1 = new Customer();
		c1.setId(1L);
		c1.setName("A");
		c1.setBirthday(new SimpleDateFormat("yyyy-MM-dd").parse("1993-03-06"));
		
		Customer c2 = new Customer();
		c2.setId(2L);
		c2.setName("B");
		c2.setBirthday(new SimpleDateFormat("yyyy-MM-dd").parse("1993-04-06"));
		
		Customer c3 = service.selectMaxAgeCustomer(c1, c2);
		System.out.println(c3.getName());
	}
}
这里运行结果为A,在Web服务调用过程中,可能经常出现超时的问题,但你切不可以为只要WSDL可以访问,就代表Web服务一定可以访问,因为是否可以访问与SEI的实现类有关,而WSDL仅是SEI的一种XML表示。






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值