转载自http://wuhongyu.iteye.com/blog/807836
上一篇写了个最简单的小例子,只是为了说明JAVA6开发Web Service很方便,这一篇稍微深入一点,写个稍微有点代表性的小例子。
依然使用 JAX-WS(jdk自带的实现)方式,这次要在服务中使用一个复杂类型Customer,并实现附件传输的功能,这里使用MTOM的附件传输方式。MTOM(SOAP Message Transmission Optimization Mechanism)是SOAP 消息传输优化机制,MTOM可以在SOAP 消息中发送二进制数据。
先来看Customer类:
packagecom.why.server;importjava.util.Date;importjavax.activation.DataHandler;importjavax.xml.bind.annotation.XmlAccessType;importjavax.xml.bind.annotation.XmlAccessorType;importjavax.xml.bind.annotation.XmlMimeType;importjavax.xml.bind.annotation.XmlRootElement;
@XmlRootElement(name= "Customer")
@XmlAccessorType(XmlAccessType.FIELD)public classCustomer {private longid;privateString name;privateDate birthday;
@XmlMimeType("application/octet-stream")privateDataHandler imageData;//getter and setter
......
}
MTOM 方式中要传输的附件必须使用javax.activation.DataHandler 类,还要注意必须在类上使用@XmlAccessorType(FIELD)注解,标注JAXB 在进行JAVA 对象与XML 之间进行转换时只关注字段,而不关注属性(getXXX()方法),否则发布Web 服务时会报出现了两个imageData 属性的错误,原因未知,可能是BUG。
然后使用@XmlMimeType 注解标注这是一个附件类型的数据,这里我们标注imageData 是一个二进制文件,当然你也可以使用具体的MIME类型,譬如:image/jpg、image/gif 等,但要考虑到客户端是否支持。
接口类:
packagecom.why.server;importjavax.jws.WebParam;importjavax.jws.WebService;importjavax.xml.ws.soap.MTOM;@WebService(name="Hello")
@SOAPBinding(style=SOAPBinding.Style.RPC)
@MTOMpublic interfaceHello {public voidprintContext();public Customer selectCustomerByName(@WebParam(name = "customer")Customer customer);publicCustomer selectMaxAgeCustomer(Customer c1, Customer c2);
}
@MTOM注解用于开启MTOM功能。
@WebService注解中的name属性标注在接口类上,可以指定wsdl中接口名称,也就是生成的客户端代码中接口类的名字。
@SOAPBinding(style = SOAPBinding.Style.RPC)指定SOAP消息样式,有两个枚举值:SOAPBinding.Style.DOCUMENT(默认)和SOAPBinding.Style.RPC,可以对比这两种方式生成的wsdl会有所不同,而且生成的客户端代码也会有所不同。
实现类:
packagecom.why.server;importjava.io.File;importjava.io.FileOutputStream;importjava.io.IOException;importjava.io.InputStream;importjava.io.OutputStream;importjava.text.ParseException;importjava.text.SimpleDateFormat;importjava.util.Date;importjava.util.Set;importjavax.activation.DataHandler;importjavax.activation.FileDataSource;importjavax.annotation.Resource;importjavax.jws.WebService;importjavax.xml.ws.WebServiceContext;importjavax.xml.ws.handler.MessageContext;@WebService(serviceName="HelloService",portName="HelloServicePort",targetNamespace="http://service.why.com/",endpointInterface="com.why.server.Hello")public class HelloImpl implementsHello {
@ResourceprivateWebServiceContext context;
@Overridepublic voidprintContext(){
MessageContext ctx=context.getMessageContext();
Set 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");
}
}
}
@OverridepublicCustomer 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(newDate());
customer.setImageData(new DataHandler(new FileDataSource(new File("c:"+ File.separator + "origin.jpg"))));
}returncustomer;
}
@OverridepublicCustomer 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];intc;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()){returnc2;
}else{returnc1;
}
}
}
@WebService注解的serviceName属性指定wsdl中service节点的name属性值。portName属性指定wsdl中service节点下port节点name属性值。targetNamespace属性指定wsdl根节点definitions的targetNamespace属性值。endpointInterface属性指定要发布的WebService接口的全路径名,当实现类实现了多个接口时,需要通过此属性标注哪个类是WebService的服务端点接口(SEI)。
在这个类中,通过@Resource注解注入了一个WebServiceContext对象,这个对象即是WebService的上下文环境。
发布这个服务:
packagecom.why.server;importjavax.xml.ws.Endpoint;public classSoapServer {public static voidmain(String[] args) {
Endpoint.publish("http://localhost:8080/helloService",newHelloImpl());
}
}
在命令行键入“wsimport -p com.why.client -keep http://localhost:8080/helloService?wsdl”生成客户端代码,拷贝到工程相应文件夹里,这时,就可以调用这个服务了:
packagecom.why.client;importjava.io.FileOutputStream;importjava.io.IOException;importjava.io.InputStream;importjava.io.OutputStream;importjava.net.MalformedURLException;importjava.net.URL;importjava.text.ParseException;importjava.text.SimpleDateFormat;importjava.util.GregorianCalendar;importjavax.activation.DataHandler;importjavax.activation.DataSource;importjavax.activation.FileDataSource;importjavax.xml.datatype.DatatypeConfigurationException;importjavax.xml.datatype.DatatypeFactory;importjavax.xml.namespace.QName;
public classSoapClient {public static void main(String[] args) throwsParseException, 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= newCustomer();
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];intc;while ((c = is.read(bytes)) != -1) {
os.write(bytes,0, c);
}
}catch(IOException e) {
e.printStackTrace();
}
System.out.println("########################################");
Customer c1= newCustomer();
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= newCustomer();
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。