`
wuhongyu
  • 浏览: 407342 次
  • 性别: Icon_minigender_1
  • 来自: 哈尔滨
社区版块
存档分类
最新评论

JAVA6开发WebService (二)——JAX-WS例子

阅读更多

    上一篇写了个最简单的小例子,只是为了说明JAVA6开发Web Service很方便,这一篇稍微深入一点,写个稍微有点代表性的小例子。

 

    依然使用 JAX-WS(jdk自带的实现)方式,这次要在服务中使用一个复杂类型Customer,并实现附件传输的功能,这里使用MTOM的附件传输方式。MTOM(SOAP Message Transmission Optimization Mechanism)是SOAP 消息传输优化机制,MTOM可以在SOAP 消息中发送二进制数据。

 

先来看Customer类:

 

package com.why.server;

import java.util.Date;

import javax.activation.DataHandler;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlMimeType;
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement(name = "Customer")
@XmlAccessorType(XmlAccessType.FIELD)
public class Customer {
	private long id;
	private String name;
	private Date birthday;
	@XmlMimeType("application/octet-stream")
	private DataHandler imageData;
	
        //getter and setter
        ......
}

     MTOM 方式中要传输的附件必须使用javax.activation.DataHandler 类,还要注意必须在类上使用@XmlAccessorType(FIELD)注解,标注JAXB 在进行JAVA 对象与XML 之间进行转换时只关注字段,而不关注属性(getXXX()方法),否则发布Web 服务时会报出现了两个imageData 属性的错误,原因未知,可能是BUG。

    然后使用@XmlMimeType 注解标注这是一个附件类型的数据,这里我们标注imageData 是一个二进制文件,当然你也可以使用具体的MIME类型,譬如:image/jpg、image/gif 等,但要考虑到客户端是否支持。

 

接口类:

package com.why.server;

import javax.jws.WebParam;
import javax.jws.WebService;
import javax.xml.ws.soap.MTOM;

/**
 * 
 * @author why
 *
 */
@WebService(name="Hello")
@SOAPBinding(style = SOAPBinding.Style.RPC)
@MTOM
public interface Hello {
	public void printContext();
	public Customer selectCustomerByName(@WebParam(name = "customer")Customer customer);
	public Customer selectMaxAgeCustomer(Customer c1, Customer c2);
}

    @MTOM注解用于开启MTOM功能。

    @WebService注解中的name属性标注在接口类上,可以指定wsdl中接口名称,也就是生成的客户端代码中接口类的名字。

    @SOAPBinding(style = SOAPBinding.Style.RPC)指定SOAP消息样式,有两个枚举值:SOAPBinding.Style.DOCUMENT(默认)和SOAPBinding.Style.RPC,可以对比这两种方式生成的wsdl会有所不同,而且生成的客户端代码也会有所不同。

 

实现类:

package com.why.server;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Set;
import javax.activation.DataHandler;
import javax.activation.FileDataSource;
import javax.annotation.Resource;
import javax.jws.WebService;
import javax.xml.ws.WebServiceContext;
import javax.xml.ws.handler.MessageContext;

/**
 * 
 * @author why
 *
 */
@WebService(serviceName="HelloService",portName="HelloServicePort",targetNamespace="http://service.why.com/",endpointInterface="com.why.server.Hello")
public class HelloImpl implements Hello {
	
	@Resource
	private WebServiceContext context;
	
	@Override
	public void printContext(){
		MessageContext ctx = context.getMessageContext();
		Set<String> set = ctx.keySet();
		for (String key : set) {
			System.out.println("{" + key + "," + ctx.get(key) +"}");
			try {
				System.out.println("key.scope=" + ctx.getScope(key));
			} catch (Exception e) {
				System.out.println(key + " is not exits");
			}
		}
	}
	
	@Override
	public Customer selectCustomerByName(Customer customer) {
		if("why".equals(customer.getName())){
			customer.setId(1);
			try {
				customer.setBirthday(new SimpleDateFormat("yyyy-MM-dd").parse("1985-10-07"));
			} catch (ParseException e) {
				e.printStackTrace();
			}
			customer.setImageData(new DataHandler(new FileDataSource(new File("c:"+ File.separator + "why.jpg"))));
		}else{
			customer.setId(2);
			customer.setBirthday(new Date());
			customer.setImageData(new DataHandler(new FileDataSource(new File("c:"+ File.separator + "origin.jpg"))));
		}
		return customer;
	}
	
	@Override
	public Customer selectMaxAgeCustomer(Customer c1, Customer c2) {
		try {
			// 输出接收到的附件
			System.out.println("c1.getImageData().getContentType()=" + c1.getImageData().getContentType());
			InputStream is = c2.getImageData().getInputStream();
			OutputStream os = new FileOutputStream("c:\\temp1.jpg");
			byte[] bytes = new byte[1024];
			int c;
			while ((c = is.read(bytes)) != -1) {
				os.write(bytes, 0, c);
			}
			os.close();
			
			System.out.println("c2.getImageData().getContentType()=" + c2.getImageData().getContentType());
			is = c2.getImageData().getInputStream();
			os = new FileOutputStream("c:\\temp2.jpg");
			bytes = new byte[1024];
			while ((c = is.read(bytes)) != -1) {
				os.write(bytes, 0, c);
			}
			os.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		if (c1.getBirthday().getTime() > c2.getBirthday().getTime()){
			return c2;
		}
		else{
			return c1;
		}
	}
}
 

    @WebService注解的serviceName属性指定wsdl中service节点的name属性值。portName属性指定wsdl中service节点下port节点name属性值。targetNamespace属性指定wsdl根节点definitions的targetNamespace属性值。endpointInterface属性指定要发布的WebService接口的全路径名,当实现类实现了多个接口时,需要通过此属性标注哪个类是WebService的服务端点接口(SEI)。

    在这个类中,通过@Resource注解注入了一个WebServiceContext对象,这个对象即是WebService的上下文环境。

 

发布这个服务:

package com.why.server;

import javax.xml.ws.Endpoint;

/**
 * 
 * @author why
 *
 */
public class SoapServer {
	public static void main(String[] args) {
		Endpoint.publish("http://localhost:8080/helloService",new HelloImpl());
	}
}
 

    在命令行键入“wsimport -p com.why.client -keep http://localhost:8080/helloService?wsdl”生成客户端代码,拷贝到工程相应文件夹里,这时,就可以调用这个服务了:

package com.why.client;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.GregorianCalendar;
import javax.activation.DataHandler;
import javax.activation.DataSource;
import javax.activation.FileDataSource;
import javax.xml.datatype.DatatypeConfigurationException;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.namespace.QName;

/**
 * 
 * @author why
 *
 */
public class SoapClient {
	public static void main(String[] args) throws ParseException, MalformedURLException {
		QName qName = new QName("http://service.why.com/","HelloService");
		HelloService helloService = new HelloService(new URL("http://127.0.0.1:8080/helloService?wsdl"),qName);
		Hello hello = (Hello) helloService.getPort(Hello.class);
		
		hello.printContext();
		
		System.out.println("---------------------------------------------------");
		
		Customer customer = new Customer();
		customer.setName("why");
		DataSource ds = hello.selectCustomerByName(customer).getImageData().getDataSource();
		String attachmentMimeType = ds.getContentType();
		System.out.println(attachmentMimeType);
		try {
			InputStream is = ds.getInputStream();
			OutputStream os = new FileOutputStream("c:\\why_temp.jpg");
			byte[] bytes = new byte[1024];
			int c;
			while ((c = is.read(bytes)) != -1) {
				os.write(bytes, 0, c);
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		System.out.println("########################################");
		
		Customer c1 = new Customer();
		c1.setId(1);
		c1.setName("why");
		GregorianCalendar calendar = (GregorianCalendar)GregorianCalendar.getInstance();
		calendar.setTime(new SimpleDateFormat("yyyy-MM-dd").parse("1985-10-07"));
		try {
			c1.setBirthday(DatatypeFactory.newInstance().newXMLGregorianCalendar(calendar));
		} catch (DatatypeConfigurationException e) {
			e.printStackTrace();
		}
		c1.setImageData(new DataHandler(new FileDataSource("c:\\c1.jpg")));
		
		Customer c2 = new Customer();
		c2.setId(2);
		c2.setName("abc");
		calendar.setTime(new SimpleDateFormat("yyyy-MM-dd").parse("1986-10-07"));
		try {
			c2.setBirthday(DatatypeFactory.newInstance().newXMLGregorianCalendar(calendar));
		} catch (DatatypeConfigurationException e) {
			e.printStackTrace();
		}
		c2.setImageData(new DataHandler(new FileDataSource("c:\\c2.jpg")));
		
		Customer c = hello.selectMaxAgeCustomer(c1,c2);
		System.out.println(c.getName());
		
	}
}
 

附件是我的工程,当然运行这个程序,需先在C盘建立几个文件c1.jpg、c2.jpg、origin.jpg和why.jpg。

11
0
分享到:
评论
7 楼 avi9111 2011-06-23  
MIME Type                  Java Type
image/gif or image/jpeg             java.awt.Image
text/plain                                    java.lang.String
text/xml or application/xml          javax.xml.transform.Source
*/* or application/octet-stream    javax.activation.DataHandler



不知道REST能这样用么
6 楼 wuhongyu 2011-04-15  
wcxxian 写道
希望楼主 public Hello getHelloServicePort(WebServiceFeature... features) {
        return super.getPort(new QName("http://service.why.com/", "HelloServicePort"), Hello.class, features);
    }
解释下附带项目里面的这个方法为什么出错?

附件是从我的工程直接导出的,在我机器上没报错啊,不知道你那里报什么错误了?
5 楼 wcxxian 2011-04-14  
希望楼主 public Hello getHelloServicePort(WebServiceFeature... features) {
        return super.getPort(new QName("http://service.why.com/", "HelloServicePort"), Hello.class, features);
    }
解释下附带项目里面的这个方法为什么出错?
4 楼 wuhongyu 2010-11-26  
zfanxu 写道
刚刚路径问题,我知道了!楼主的这一系列的文章写的也很好!对我帮助很大.就是有一个疑问:我想直接把图片或是其他格式的文件直接以附件MTOM的形式传输过去。
   eg:
   我想添加一个提供下载图片或是其他文件的方法
   public DataHandler download();
问题是:生成的客户端程序就变成了
   public byte[] download();
了!
如何让客户端的返回类型也是DataHandler呢?

PS:希望知道楼主的邮箱,好一起交流这方面的问题!


这个问题我也碰见了,有些地方没太搞清楚,所以就没写这样的例子,以下仅供参考,希望对zfanxu能有帮助:
当使用SOAPBinding.Style.DOCUMENT方式时,可以在接口中下载的方法前加入@XmlMimeType("*/*")或@XmlMimeType("application/octet-stream")注解,这样,在生成的客户端代码中返回类型也是DataHandler了。
在http传输过程中媒体内容的类型和JAVA编程对象的对应关系是:
MIME Type                  Java Type
image/gif or image/jpeg             java.awt.Image
text/plain                                    java.lang.String
text/xml or application/xml          javax.xml.transform.Source
*/* or application/octet-stream    javax.activation.DataHandler

但用RPC方式时,生成的一直都是byte类型,不知道什么原因,如果zfanxu或哪位朋友知道并解决了希望也告诉兄弟一声啊!
3 楼 zfanxu 2010-11-26  
刚刚路径问题,我知道了!楼主的这一系列的文章写的也很好!对我帮助很大.就是有一个疑问:我想直接把图片或是其他格式的文件直接以附件MTOM的形式传输过去。
   eg:
   我想添加一个提供下载图片或是其他文件的方法
   public DataHandler download();
问题是:生成的客户端程序就变成了
   public byte[] download();
了!
如何让客户端的返回类型也是DataHandler呢?

PS:希望知道楼主的邮箱,好一起交流这方面的问题!
2 楼 zfanxu 2010-11-26  
zfanxu 写道
“在命令行键入“wsimport -p com.why.client -keep http://localhost:8080/helloService?wsdl”生成客户端代码”
  

请问客户端的代码生成的路径在哪?
1 楼 zfanxu 2010-11-26  
“在命令行键入“wsimport -p com.why.client -keep http://localhost:8080/helloService?wsdl”生成客户端代码”
  

相关推荐

    JAVA6开发WebService (四)——SAAJ调用WebService

    在本篇主题“JAVA6开发WebService(四)——SAAJ调用WebService”中,我们将探讨如何使用Java API for XML Messaging (SAAJ)来与WebService进行交互。SAAJ是Java平台中用于处理SOAP消息的API,它提供了创建、解析和...

    WebService(WEB服务)--获取网络数据

    **WebService(Web服务)——获取网络数据** WebService是一种基于互联网的、平台独立的交互方式,它允许不同系统之间通过标准的协议(如SOAP、REST)进行数据交换。在本示例中,我们将深入探讨如何使用Java来实现...

    webservice客户端以及服务端

    在Java中,我们可以利用JDK自带的JAX-WS(Java API for XML Web Services)来创建Web服务。JAX-WS提供了一种声明式的方式来定义服务接口,并将其实现为SOAP(Simple Object Access Protocol)服务。以下是一个简单的...

    apache-cxf-3.1.0

    标签中的"CXF webservice"表明了CXF的主要用途——构建Web服务。CXF支持两种主要的Web服务标准:JAX-WS和JAX-RS。JAX-WS用于基于SOAP的Web服务,而JAX-RS则面向RESTful风格的服务。这两种技术的结合使CXF成为一个...

    weatherTest

    通过"weatherTest"项目,我们可以深入学习Web Service的核心概念,理解其工作流程,并掌握如何使用Java JAX-WS进行开发和测试。这个例子是一个宝贵的实践平台,对于初学者和有经验的开发者来说,都是巩固理论知识和...

    JDK6 webservice的应用(注意SOAPBinding.Style不同的差异)

    在实际开发中,使用JDK 6创建Web服务时,开发者会编写Java接口,然后使用JAX-WS工具(如wsimport或JAXB)自动生成服务器端实现和客户端存根代码。接口中的方法将映射到SOAP消息的操作,而XSD文件则用来验证输入和...

    CXF webservice Demo

    这些库文件通常包含了CXF的核心组件,以及对其他相关技术(如JAXB、JAX-WS等)的支持,使得开发者能够在Java环境中方便地构建Web服务。 而`myCXFTest`文件可能是一个包含服务器端和客户端代码的项目。服务器端代码...

    xfire+spring+webservice例子

    【标题】"xfire+spring+webservice例子"是一个典型的示例项目,它演示了如何在Java环境中结合XFire和Spring框架来创建和消费Web服务。这个项目旨在帮助开发者理解和实践基于Spring的Web服务实现,同时也展示了XFire...

    使用CXF发布和调用接口(星座运势接口)

    Apache CXF是一个流行的开源框架,它允许开发人员创建和使用Web服务,支持多种协议和标准,如SOAP、RESTful、JAX-RS和JAX-WS等。 首先,让我们理解什么是Apache CXF。CXF源于两个项目:XFire和 Celtix,这两个项目...

    apahe cxf 与spring 开发例子1

    Apache CXF 是一个开放源码的Web服务框架,它允许开发者以多种方式(如JAX-WS,JAX-RS等)创建和消费Web服务。CXF 提供了丰富的功能,包括SOAP、RESTful API、WS-* 标准支持、多种传输机制(HTTP、HTTPS、JMS等)...

    使用Jersey框架搭建Rest服务

    Jersey是JAX-RS(Java API for RESTful Web Services)的参考实现,简化了REST服务的开发。要开始使用Jersey,首先需要在项目中引入其依赖。如果你使用的是Maven,可以在pom.xml文件中添加以下依赖: ```xml ...

Global site tag (gtag.js) - Google Analytics