1. 程式人生 > >webservice(三) 使用JDK的EndPoint和cxf框架分別釋出webservice服務

webservice(三) 使用JDK的EndPoint和cxf框架分別釋出webservice服務

在JDK1.6中JAX-WS規範定義瞭如何釋出一個webService服務。
    JAX-WS是指Java Api for XML – WebService.
與web服務相關的是EndPoint類,此類為端點服務類,它提供一個publish方法用於將一個已經添加了@WebService註解物件繫結到一個地址的埠上。

使用jdk的EndPoint釋出web服務

1.在要釋出服務的類上新增@WebService註解。將要釋出服務的方法設定為public。

2.呼叫EndPoint.publish(,)釋出服務

其他注意事項:
1.給類新增上@WebService註解後,類中所有的非靜態方法都將會對外公佈。
2.不支援靜態方法,final方法。
3.如果希望某個方法(非static,非final)不對外公開,可以在方法上新增@WebMethod(exclude=true),阻止對外公開。
4.被添加了@WebService註解的類至少要有一個可以公開的方法,否則將會啟動失敗。

使用CXF框架釋出服務

釋出服務

兩種方式釋出服務:ServerFactoryBean 和JaxWsServerFactoryBean

JaxWsServerFactoryBean是ServerFactoryBean 的子類,也是功能擴充套件類。


1.ServerFactoryBean 方式

public class ServerFactoryBeanDemo {
	public String sayHi(String name){
		String s="hello "+name;
		return s;
	}
	
	public static void main(String[] args) {
		ServerFactoryBean sf=new ServerFactoryBean();
		//服務實現類
		sf.setServiceClass(ServerFactoryBeanDemo.class);
		//服務的釋出地址
		sf.setAddress("http://localhost:5678/hello");
		//服務的例項
        sf.setServiceBean(new ServerFactoryBeanDemo());
        //釋出服務
		sf.create();
		System.out.println("server ready……");
	}
}

ServerFactoryBean 方式

①不需要提供@WebService註解,依舊可以釋出

②不需要提供對外暴露的方法,依舊可以釋出(當然這也沒什麼意義)

2.JaxWsServerFactoryBean方式(建議使用)

@WebService
public class JaxWsServiceDemo {
	public String sayHi(String name) {
		String s = "hello " + name;
		return s;
	}

	public static void main(String[] args) {
		JaxWsServerFactoryBean sf = new JaxWsServerFactoryBean();
		// 服務實現類
		sf.setServiceClass(JaxWsServiceDemo.class);
		// 服務的釋出地址
		sf.setAddress("http://localhost:5678/hello");
		// 服務的例項
		sf.setServiceBean(new JaxWsServiceDemo());
		// 釋出服務
		sf.create();
		System.out.println("server ready……");
	}
}

JaxWsServerFactoryBean方式

①需要提供@WebService註解

  雖然不提供該註解也可以釋出成功,但是暴露的方法依舊無法顯示,所以通常也會提供註解來顯示暴露的方法。

  (可以通過檢視wsdl文件來驗證)


標準的做法
通常會提供一個服務介面,用以表明服務的型別。要加上@Webservice註解。這有點類似於Spring中的服務層的實現。

注意:不提供介面也行,但是在任何情況下都建議使用介面。

            如果使用spring的配置檔案釋出,則必須提供介面。

@WebService
public interface IHelloService {
	public String sayHi(String name);
}

然後提供一個實現類

public class HelloServiceImpl implements IHelloService{
	@Override
	public String sayHi(String name) {
		String s = "hello " + name;
		return s;
	}
	
	public static void main(String[] args) {
		JaxWsServerFactoryBean sf = new JaxWsServerFactoryBean();
		// 服務的型別
		sf.setServiceClass(IHelloService.class);//注意:介面型別
		// 服務的釋出地址
		sf.setAddress("http://localhost:5678/hello");
		// 服務的實現類例項
		sf.setServiceBean(new HelloServiceImpl());//注意:實現類例項
		// 釋出服務
		sf.create();
		System.out.println("server ready……");
	}
}

wsdl2java工具

cxf也提供了一個用於生成客戶端呼叫程式碼的工具wsdl2java.exe。它的功能同wsimport一樣。它是可以支援SOAP1.1 和SOAP1.2的協議的。

此工具位於cxf_home/bin目錄下。引數與wsimport有所不同。
它包含以下引數:
-d引數,指定程式碼生成的目錄。
-p引數,指定生成的新的包結構。

注意:由於wsdl2java是根據jdk1.7生成的原生代碼,所以,需要對生成的程式碼做一點點修改。

1、注意:由於使用的是apache-cxf-2.4.0版本,它是支援jdk1.7的。所以,對於生成的Service要進行稍微的修改。
   在jdk1.6中的javax.xml.ws.Service的構造方法接收二個引數為:(String url,QName qname);
   在jdk1.7中的javax.xml.ws.Service的構造方法中接收三個引數為:(String url,QName qname,features);


2、將生成的程式碼,拷貝到專案目錄,然後使用以前相同方法呼叫。
    注意:如果將@WebMethod設定了header=true引數,將會在呼叫時多傳遞一個引數。引數可以直接傳null值。
             對於這種情況,可以將header=true修改成header=false然後再重要獲取客戶端原始碼。


3、可能發現,使用cxf生成的客戶端程式碼與wsimport差不多,甚至是一樣,那為什麼還要使用cxf呢?
      原因:它較好的釋出方式、較容易的與其他伺服器整合、及與Spring的完美結合都不得不讓我們使用cxf。

對於上面標準實現中的程式碼執行該命令,會生成程式碼供客戶端使用。(用法類似於wsimport)


給服務新增訊息攔截器

作用:類似於使用TCP/IP Monitor,用來捕獲SOAP訊息的過程。

LoggingInInterceptor – 資訊輸入時的攔截器 –請求
LoggingOutInterceptor –資訊輸出時的攔截器 - 響應

server.getInInterceptors().add(new LoggingInInterceptor());
server.getOutInterceptors().add(new LoggingOutInterceptor());

public class Server {
	public static void main(String[] args) {
		JaxWsServerFactoryBean sf = new JaxWsServerFactoryBean();
		sf.setServiceClass(IHelloService.class);
		sf.setServiceBean(new HelloServiceImpl());
		sf.setAddress("http://localhost:5678/hello");

		// 加入請求的訊息攔截器
		sf.getInInterceptors().add(new LoggingInInterceptor());
		// 加入響應的訊息攔截器
		sf.getOutInterceptors().add(new LoggingOutInterceptor());
		sf.create();
		System.out.println("server ready……");
	}
}

可以在服務端控制檯檢視 攔截到的請求資訊和傳送給客戶端的響應資訊。