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

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

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

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

先来看Customer类:


package  org.duke.jaxws.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;

    
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;
    }

    
public  DataHandler getImageData() {
        
return  imageData;
    }

    
public   void  setImageData(DataHandler imageData) {
        
this .imageData  =  imageData;
    }

}

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

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

接口类:


package  org.duke.jaxws.server;

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

@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  org.duke.jaxws.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;

@WebService(serviceName 
=   " Hello " , portName  =   " HelloPort " , targetNamespace  =   " http://server.jaxws.duke.org/ " , endpointInterface  =   " org.duke.jaxws.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  ( " duke " .equals(customer.getName())) {
            customer.setId(
1 );
            
try  {
                customer.setBirthday(
new  SimpleDateFormat( " yyyy-MM-dd " )
                        .parse(
" 1985-03-14 " ));
            } 
catch  (ParseException e) {
                e.printStackTrace();
            }
            customer.setImageData(
new  DataHandler( new  FileDataSource( new  File(
                    
" c: "   +  File.separator  +   " duke.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  org.duke.jaxws.server;

import  javax.xml.ws.Endpoint;

public   class  SoapServer {
    
public   static   void  main(String[] args) {
        Endpoint.publish(
" http://localhost:8080/Service/Hello " new  HelloImpl());
    }
}
在命令行键入“wsimport -s src -p org.duke.jaxws.client -keep http://localhost:8080/Service/Hello?wsdl”生成客户端代码,拷贝到工程相应文件夹里,这时,就可以调用这个服务了:

package  org.duke.jaxws.test;

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;

import  org.duke.jaxws.client.Customer;
import  org.duke.jaxws.client.Hello;
import  org.duke.jaxws.client.Hello_Service;

public   class  SoapClient {
    
public   static   void  main(String[] args)  throws  ParseException,
            MalformedURLException {
        QName qName 
=   new  QName( " http://server.jaxws.duke.org/ " " Hello " );
        Hello_Service helloService 
=   new  Hello_Service( new  URL(
                
" http://localhost:8080/Service/Hello?wsdl " ), qName);
        Hello hello 
=  (Hello) helloService.getPort(Hello. class );

        hello.printContext();

        System.out.println(
" ######################################## " );

        Customer customer 
=   new  Customer();
        customer.setName(
" duke " );
        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:\\Shawn\\duke-real_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(
" duke " );
        GregorianCalendar calendar 
=  (GregorianCalendar) GregorianCalendar
                .getInstance();
        calendar.setTime(
new  SimpleDateFormat( " yyyy-MM-dd " ).parse( " 1985-03-14 " ));
        
try  {
            c1.setBirthday(DatatypeFactory.newInstance()
                    .newXMLGregorianCalendar(calendar));
        } 
catch  (DatatypeConfigurationException e) {
            e.printStackTrace();
        }
        c1.setImageData(
new  DataHandler( new  FileDataSource(
                
" c:\\Shawn\\duke1.jpg " )));

        Customer c2 
=   new  Customer();
        c2.setId(
2 );
        c2.setName(
" abc " );
        calendar.setTime(
new  SimpleDateFormat( " yyyy-MM-dd " ).parse( " 1986-03-14 " ));
        
try  {
            c2.setBirthday(DatatypeFactory.newInstance()
                    .newXMLGregorianCalendar(calendar));
        } 
catch  (DatatypeConfigurationException e) {
            e.printStackTrace();
        }
        c2.setImageData(
new  DataHandler( new  FileDataSource(
                
" c:\\Shawn\\duke-real_temp.jpg " )));

        Customer c 
=  hello.selectMaxAgeCustomer(c1, c2);
        System.out.println(c.getName());

    }
}






你可能感兴趣的:(JAVA6开发WebService (二)——JAX-WS)