上一篇寫了個最簡單的小例子,隻是為了說明JAVA6開發Web Service很友善,這一篇稍微深入一點,寫個稍微有點代表性的小例子。
依然使用 JAX-WS(jdk自帶的實作)方式,這次要在服務中使用一個複雜類型Customer,并實作附件傳輸的功能,這裡使用MTOM的附件傳輸方式。MTOM(SOAP Message Transmission Optimization Mechanism)是SOAP 消息傳輸優化機制,MTOM可以在SOAP 消息中發送二進制資料。
先來看Customer類:
[java] view plain copy print ?
- 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 等,但要考慮到用戶端是否支援。
接口類:
[java] view plain copy print ?
- package com.why.server;
- import javax.jws.WebParam;
- import javax.jws.WebService;
- 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會有所不同,而且生成的用戶端代碼也會有所不同。
實作類:
[java] view plain copy print ?
- 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;
- @WebService(serviceName="HelloService",portName="HelloServicePort",targetNamespace="http://service.why.com/",endpointInterstring">"com.why.server.Hello")
- public class HelloImplimplements 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的上下文環境。
釋出這個服務:
[java] view plain copy print ?
- package com.why.server;
- import javax.xml.ws.Endpoint;
- public class SoapServer {
- public staticvoid main(String[] args) {
- Endpoint.publish("http://localhost:8080/helloService",new HelloImpl());
- }
- }
在指令行鍵入“wsimport -p com.why.client -keep http://localhost:8080/helloService?wsdl”生成用戶端代碼,拷貝到工程相應檔案夾裡,這時,就可以調用這個服務了:
[java] view plain copy print ?
- 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;
- public class SoapClient {
- public staticvoid 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。