天天看點

JAVA6開發WebService (二)——JAX-WS例子

上一篇寫了個最簡單的小例子,隻是為了說明JAVA6開發Web Service很友善,這一篇稍微深入一點,寫個稍微有點代表性的小例子。

依然使用 JAX-WS(jdk自帶的實作)方式,這次要在服務中使用一個複雜類型Customer,并實作附件傳輸的功能,這裡使用MTOM的附件傳輸方式。MTOM(SOAP Message Transmission Optimization Mechanism)是SOAP 消息傳輸優化機制,MTOM可以在SOAP 消息中發送二進制資料。

先來看Customer類:

[java] view plain copy print ?

  1. package com.why.server;
  2. import java.util.Date;
  3. import javax.activation.DataHandler;
  4. import javax.xml.bind.annotation.XmlAccessType;
  5. import javax.xml.bind.annotation.XmlAccessorType;
  6. import javax.xml.bind.annotation.XmlMimeType;
  7. import javax.xml.bind.annotation.XmlRootElement;
  8. @XmlRootElement(name ="Customer")
  9. @XmlAccessorType(XmlAccessType.FIELD)
  10. public class Customer {
  11. private long id;
  12. private String name;
  13. private Date birthday;
  14. @XmlMimeType("application/octet-stream")
  15. private DataHandler imageData;
  16. //getter and setter
  17. ......
  18. }

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 ?

  1. package com.why.server;
  2. import javax.jws.WebParam;
  3. import javax.jws.WebService;
  4. import javax.xml.ws.soap.MTOM;
  5. @WebService(name="Hello")
  6. @SOAPBinding(style = SOAPBinding.Style.RPC)
  7. @MTOM
  8. public interface Hello {
  9. public void printContext();
  10. public Customer selectCustomerByName(@WebParam(name ="customer")Customer customer);
  11. public Customer selectMaxAgeCustomer(Customer c1, Customer c2);
  12. }

@MTOM注解用于開啟MTOM功能。

@WebService注解中的name屬性标注在接口類上,可以指定wsdl中接口名稱,也就是生成的用戶端代碼中接口類的名字。

@SOAPBinding(style = SOAPBinding.Style.RPC)指定SOAP消息樣式,有兩個枚舉值:SOAPBinding.Style.DOCUMENT(預設)和SOAPBinding.Style.RPC,可以對比這兩種方式生成的wsdl會有所不同,而且生成的用戶端代碼也會有所不同。

實作類:

[java] view plain copy print ?

  1. package com.why.server;
  2. import java.io.File;
  3. import java.io.FileOutputStream;
  4. import java.io.IOException;
  5. import java.io.InputStream;
  6. import java.io.OutputStream;
  7. import java.text.ParseException;
  8. import java.text.SimpleDateFormat;
  9. import java.util.Date;
  10. import java.util.Set;
  11. import javax.activation.DataHandler;
  12. import javax.activation.FileDataSource;
  13. import javax.annotation.Resource;
  14. import javax.jws.WebService;
  15. import javax.xml.ws.WebServiceContext;
  16. import javax.xml.ws.handler.MessageContext;
  17. @WebService(serviceName="HelloService",portName="HelloServicePort",targetNamespace="http://service.why.com/",endpointInterstring">"com.why.server.Hello")
  18. public class HelloImplimplements Hello {
  19. @Resource
  20. private WebServiceContext context;
  21. @Override
  22. public void printContext(){
  23. MessageContext ctx = context.getMessageContext();
  24. Set<String> set = ctx.keySet();
  25. for (String key : set) {
  26. System.out.println("{" + key +"," + ctx.get(key) +"}");
  27. try {
  28. System.out.println("key.scope=" + ctx.getScope(key));
  29. } catch (Exception e) {
  30. System.out.println(key + " is not exits");
  31. }
  32. }
  33. }
  34. @Override
  35. public Customer selectCustomerByName(Customer customer) {
  36. if("why".equals(customer.getName())){
  37. customer.setId(1);
  38. try {
  39. customer.setBirthday(new SimpleDateFormat("yyyy-MM-dd").parse("1985-10-07"));
  40. } catch (ParseException e) {
  41. e.printStackTrace();
  42. }
  43. customer.setImageData(new DataHandler(new FileDataSource(new File("c:"+ File.separator + "why.jpg"))));
  44. }else{
  45. customer.setId(2);
  46. customer.setBirthday(new Date());
  47. customer.setImageData(new DataHandler(new FileDataSource(new File("c:"+ File.separator + "origin.jpg"))));
  48. }
  49. return customer;
  50. }
  51. @Override
  52. public Customer selectMaxAgeCustomer(Customer c1, Customer c2) {
  53. try {
  54. // 輸出接收到的附件
  55. System.out.println("c1.getImageData().getContentType()=" + c1.getImageData().getContentType());
  56. InputStream is = c2.getImageData().getInputStream();
  57. OutputStream os = new FileOutputStream("c:\\temp1.jpg");
  58. byte[] bytes = new byte[1024];
  59. int c;
  60. while ((c = is.read(bytes)) != -1) {
  61. os.write(bytes, 0, c);
  62. }
  63. os.close();
  64. System.out.println("c2.getImageData().getContentType()=" + c2.getImageData().getContentType());
  65. is = c2.getImageData().getInputStream();
  66. os = new FileOutputStream("c:\\temp2.jpg");
  67. bytes = new byte[1024];
  68. while ((c = is.read(bytes)) != -1) {
  69. os.write(bytes, 0, c);
  70. }
  71. os.close();
  72. } catch (IOException e) {
  73. e.printStackTrace();
  74. }
  75. if (c1.getBirthday().getTime() > c2.getBirthday().getTime()){
  76. return c2;
  77. }
  78. else{
  79. return c1;
  80. }
  81. }
  82. }

@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 ?

  1. package com.why.server;
  2. import javax.xml.ws.Endpoint;
  3. public class SoapServer {
  4. public staticvoid main(String[] args) {
  5. Endpoint.publish("http://localhost:8080/helloService",new HelloImpl());
  6. }
  7. }

在指令行鍵入“wsimport -p com.why.client -keep http://localhost:8080/helloService?wsdl”生成用戶端代碼,拷貝到工程相應檔案夾裡,這時,就可以調用這個服務了:

[java] view plain copy print ?

  1. package com.why.client;
  2. import java.io.FileOutputStream;
  3. import java.io.IOException;
  4. import java.io.InputStream;
  5. import java.io.OutputStream;
  6. import java.net.MalformedURLException;
  7. import java.net.URL;
  8. import java.text.ParseException;
  9. import java.text.SimpleDateFormat;
  10. import java.util.GregorianCalendar;
  11. import javax.activation.DataHandler;
  12. import javax.activation.DataSource;
  13. import javax.activation.FileDataSource;
  14. import javax.xml.datatype.DatatypeConfigurationException;
  15. import javax.xml.datatype.DatatypeFactory;
  16. import javax.xml.namespace.QName;
  17. public class SoapClient {
  18. public staticvoid main(String[] args) throws ParseException, MalformedURLException {
  19. QName qName = new QName("http://service.why.com/","HelloService");
  20. HelloService helloService = new HelloService(new URL("http://127.0.0.1:8080/helloService?wsdl"),qName);
  21. Hello hello = (Hello) helloService.getPort(Hello.class);
  22. hello.printContext();
  23. System.out.println("---------------------------------------------------");
  24. Customer customer = new Customer();
  25. customer.setName("why");
  26. DataSource ds = hello.selectCustomerByName(customer).getImageData().getDataSource();
  27. String attachmentMimeType = ds.getContentType();
  28. System.out.println(attachmentMimeType);
  29. try {
  30. InputStream is = ds.getInputStream();
  31. OutputStream os = new FileOutputStream("c:\\why_temp.jpg");
  32. byte[] bytes = new byte[1024];
  33. int c;
  34. while ((c = is.read(bytes)) != -1) {
  35. os.write(bytes, 0, c);
  36. }
  37. } catch (IOException e) {
  38. e.printStackTrace();
  39. }
  40. System.out.println("########################################");
  41. Customer c1 = new Customer();
  42. c1.setId(1);
  43. c1.setName("why");
  44. GregorianCalendar calendar = (GregorianCalendar)GregorianCalendar.getInstance();
  45. calendar.setTime(new SimpleDateFormat("yyyy-MM-dd").parse("1985-10-07"));
  46. try {
  47. c1.setBirthday(DatatypeFactory.newInstance().newXMLGregorianCalendar(calendar));
  48. } catch (DatatypeConfigurationException e) {
  49. e.printStackTrace();
  50. }
  51. c1.setImageData(new DataHandler(new FileDataSource("c:\\c1.jpg")));
  52. Customer c2 = new Customer();
  53. c2.setId(2);
  54. c2.setName("abc");
  55. calendar.setTime(new SimpleDateFormat("yyyy-MM-dd").parse("1986-10-07"));
  56. try {
  57. c2.setBirthday(DatatypeFactory.newInstance().newXMLGregorianCalendar(calendar));
  58. } catch (DatatypeConfigurationException e) {
  59. e.printStackTrace();
  60. }
  61. c2.setImageData(new DataHandler(new FileDataSource("c:\\c2.jpg")));
  62. Customer c = hello.selectMaxAgeCustomer(c1,c2);
  63. System.out.println(c.getName());
  64. }
  65. }

附件是我的工程,當然運作這個程式,需先在C槽建立幾個檔案c1.jpg、c2.jpg、origin.jpg和why.jpg。