JAVA6開(kāi)發(fā)WebService (二)——JAX-WS例子博客分類(lèi):
java 學(xué)習筆記WebServiceJavaOSCC#上一篇寫(xiě)了個(gè)最簡(jiǎn)單的小例子,只是為了說(shuō)明JAVA6開(kāi)發(fā)Web Service很方便,這一篇稍微深入一點(diǎn),寫(xiě)個(gè)稍微有點(diǎn)代表性的小例子。
依然使用 JAX-WS(jdk自帶的實(shí)現)方式,這次要在服務(wù)中使用一個(gè)復雜類(lèi)型Customer,并實(shí)現附件傳輸的功能,這里使用MTOM的附件傳輸方式。MTOM(SOAP Message Transmission Optimization Mechanism)是SOAP 消息傳輸優(yōu)化機制,MTOM可以在SOAP 消息中發(fā)送二進(jìn)制數據。
先來(lái)看Customer類(lèi):
Java代碼
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 類(lèi),還要注意必須在類(lèi)上使用@XmlAccessorType(FIELD)注解,標注JAXB 在進(jìn)行JAVA 對象與XML 之間進(jìn)行轉換時(shí)只關(guān)注字段,而不關(guān)注屬性(getXXX()方法),否則發(fā)布Web 服務(wù)時(shí)會(huì )報出現了兩個(gè)imageData 屬性的錯誤,原因未知,可能是BUG。
然后使用@XmlMimeType 注解標注這是一個(gè)附件類(lèi)型的數據,這里我們標注imageData 是一個(gè)二進(jìn)制文件,當然你也可以使用具體的MIME類(lèi)型,譬如:image/jpg、image/gif 等,但要考慮到客戶(hù)端是否支持。
接口類(lèi):
Java代碼
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注解用于開(kāi)啟MTOM功能。
@WebService注解中的name屬性標注在接口類(lèi)上,可以指定wsdl中接口名稱(chēng),也就是生成的客戶(hù)端代碼中接口類(lèi)的名字。
@SOAPBinding(style = SOAPBinding.Style.RPC)指定SOAP消息樣式,有兩個(gè)枚舉值:SOAPBinding.Style.DOCUMENT(默認)和SOAPBinding.Style.RPC,可以對比這兩種方式生成的wsdl會(huì )有所不同,而且生成的客戶(hù)端代碼也會(huì )有所不同。
實(shí)現類(lèi):
Java代碼
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節點(diǎn)的name屬性值。portName屬性指定wsdl中service節點(diǎn)下port節點(diǎn)name屬性值。targetNamespace屬性指定wsdl根節點(diǎn)definitions的targetNamespace屬性值。endpointInterface屬性指定要發(fā)布的WebService接口的全路徑名,當實(shí)現類(lèi)實(shí)現了多個(gè)接口時(shí),需要通過(guò)此屬性標注哪個(gè)類(lèi)是WebService的服務(wù)端點(diǎn)接口(SEI)。
在這個(gè)類(lèi)中,通過(guò)@Resource注解注入了一個(gè)WebServiceContext對象,這個(gè)對象即是WebService的上下文環(huán)境。
發(fā)布這個(gè)服務(wù):
Java代碼
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”生成客戶(hù)端代碼,拷貝到工程相應文件夾里,這時(shí),就可以調用這個(gè)服務(wù)了:
Java代碼
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());
}
}
附件是我的工程,當然運行這個(gè)程序,需先在C盤(pán)建立幾個(gè)文件c1.jpg、c2.jpg、origin.jpg和why.jpg。