WebService—CXF—實現接口發布和客戶端調用


(一)接口發布的幾種方式

定義接口:

@WebService(targetNamespace="http://www.itfad.net/queryUser")  
public interface IQueryUser  
{  
    String query(@WebParam(name = "user") UserInfo user);  
}

實現類:

@WebService(endpointInterface="net.itfad.services.IQueryUser")  
public class QueryUserImpl implements IQueryUser  
{  
    public String query(UserInfo user)  
    {  
        if (user == null)  
            throw new IllegalArgumentException("參數user不能為null");  
        return "your name is " + user.getUserName();  
    }  
} 

 

一、使用jax-ws方式(Java EE原生代碼方式)

package server;   
import hb.QueryUserImpl;  
import hb.SessionSendMsg;   
import javax.xml.ws.Endpoint;  
public class DeployHelloWorldService {  
      
    public static void main(String[] args)  {  
        //發布第1個接口
        QueryUserImpl service = new QueryUserImpl();  
        String address = "http://localhost:9000/helloWorld";  
        Endpoint.publish(address, service);         
//發布第2個接口 SessionSendMsg sessionSendMsg
= new SessionSendMsg(); String address1 = "http://localhost:9000/session"; Endpoint.publish(address1, sessionSendMsg); } }

 

二、使用CXF方式

String url="http://localhost:8080/queryUser";  
JaxWsServerFactoryBean factoryBean=new JaxWsServerFactoryBean();  
factoryBean.setAddress(url);  
factoryBean.setServiceClass(IQueryUser.class);  
factoryBean.setServiceBean(new QueryUserImpl());  
factoryBean.create()

 

三、CXF Simple FrontEnd方式

該方式無需在類中指定相關協議,也就是說不需要在類中指定相關webservice注解,一個普通類就行。

ServerFactoryBean svrFactory = new ServerFactoryBean();  
//設置服務接口類  
svrFactory.setServiceClass(IQueryUser.class);  
svrFactory.setAddress("http://localhost:8080/queryUser");  
//設置服務實現接口類  
svrFactory.setServiceBean(QueryUserImpl);  
svrFactory.create(); 

 

 

(二)客戶端調用的幾種方式

一、WSDL2Java WSDL2Java generated Client

根據wsdl文件生成客戶端代碼,本地化調用。cxf框架有基於maven的生成客戶端代碼的插件,使用如下:

<plugins>  
         <plugin>  
                <artifactId>maven-compiler-plugin</artifactId>  
                <configuration>  
                    <source>1.5</source>  
                    <target>1.5</target>  
                </configuration>  
         </plugin>  
         <plugin>  
                <groupId>org.apache.cxf</groupId>  
                <artifactId>cxf-codegen-plugin</artifactId>  
                <version>${cxf.version}</version>  
                <executions>  
                    <execution>  
                        <id>generate-sources</id>  
                        <phase>generate-sources</phase>  
                        <configuration>  
                            <wsdlOptions>  
                                <wsdlOption>  
                                    <wsdl>src/main/resources/OrderProcess.wsdl</wsdl>  
                                </wsdlOption>  
                            </wsdlOptions>  
                        </configuration>  
                        <goals>  
                            <goal>wsdl2java</goal>  
                        </goals>  
                    </execution>  
                </executions>  
         </plugin>
</plugins>

 

二、JaxWsProxyFactoryBean

客戶端直接調用服務器端提供的服務接口,不需要生成客戶端代碼,類似RMI的機制。CXF通過運行時代理生成遠程服務的代理對象,在客戶端完成對webservice的訪問。所以客戶端也必須依賴服務器端的接口,限制是很大的,要求服務器端的webservice必須是java實現。似乎失去了webservice跨平台數據調用的意義。

 

    package demo.order.client;
    import demo.order.Order;  
    import demo.order.OrderProcess;  
    import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;      
    public class ClientProxyClient { 
      
        public static void main(String args[]) throws Exception {  
            JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();  
            factory.setServiceClass(OrderProcess.class);  
            factory.setAddress("http://localhost:8080/OrderProcess");  
            OrderProcess service = (OrderProcess)factory.create();  
      
            Order order = new Order();  
            order.setCustomerID("C001");  
            order.setItemID("I001");  
            order.setPrice(100.00);  
            order.setQty(20);       
            String result = service.processOrder(order);  
            System.out.println("The order ID is " + result);                
        }            
    }  

 

三、Dynamic Client 動態代理

CXF提供動態類的兩個工廠類。如果你的服務是在JAX-WS的規范來定義,你應該使用jaxwsdynamicclientfactory。如果你不想要或不需要JAX-WS語義,使用dynamicclientfactory。

 

下文使用jaxws語義。只要指定服務器端wsdl文件的位置,然后指定要調用的方法和方法的參數即可,不關心服務端的實現方式,動態生成客戶端代碼。讓我們假設您有一個WSDL,它定義了一個"echo"操作(方法),它接受一個字符串的輸入並輸出一個字符串。你可以使用jaxwsdynamicclientfactory它這樣:

JaxWsDynamicClientFactory dcf = JaxWsDynamicClientFactory.newInstance();
Client client = dcf.createClient("echo.wsdl"); 
Object[] res = client.invoke("echo", "test echo");
System.out.println("Echo response: " + res[0]);

由於有許多的WSDL將有更復雜的類型。在這種情況下,jaxwsdynamicclientfactory更關心的是生成這些類型的java類。例如,我們可能有一個跟蹤組織中人員的人員服務。在樣品下面我們創建一個Person對象,動態地發送到服務器的addperson操作(方法):

JaxWsDynamicClientFactory dcf = JaxWsDynamicClientFactory.newInstance();
Client client = dcf.createClient("people.wsdl", classLoader); 
Object person = Thread.currentThread().getContextClassLoader().loadClass("com.acme.Person").newInstance(); 
Method m = person.getClass().getMethod("setName", String.class);
m.invoke(person, "Joe Schmoe"); 
client.invoke("addPerson", person);

You may be asking yourself the following question: "Where did the class name 'com.acme.Person' come from?"

One way to get the class names is to run wsdl2java and examine the results. The dynamic client factory uses the same code generator as that tool. 

 

四、JaxWsServerFactoryBean

 用JaxWsServerFactoryBean發布,需要獨立的jetty包。SUN針對Java的Web Service實現先后提出兩套API,一個是JaxRPC,另一個JaxWs。 JaxWsServiceFactoryBean繼承了ReflectionServiceFactoryBean, 並提供JaxWsAPI的支持。在該類中這里主要是支持JSR181,重載了很多父類的方法,有關createServiceFromWSDL的部分則可重用父類ReflectionServiceFactoryBean.

在CXF中有幾個很相似名詞 JaxWsServiceFactoryBean, JaxWsServerFactoryBean,很相似。Service創建客戶端的代理,生成factory對象,用於調用服務端的方法。Server創建服務端的對象 用於發布服務。Server 是對服務器端來說,Service是針對服務信息來說的。也就是一個Server必然要包含一個Servie信息。如果使用CXF內部API來創建服務的話,只需要通過設置JaxWsServerFactoryBean 就可以發布服務了。在JaxWsServerFactorBean的構造函數中會創建一個缺省JaxWsServiceFactoryBean. 當然在構建自己的Server的同時也可以設置自己的ServiceFactoryBean,(API目的在於CXF對Spring的支持?)你可以在Spring中定義裝配符合自己要求的服務,自然需要有讀取和設置的這或者那樣Bean的方法了。

 

五、Ajax(js+xml的方式調用)

Ajax請求URL即webservice服務地址,請求方式必須是POST。需要手動設置請求頭,構造請求體。必須要對SOAP文件非常的了解。一般使用ajax調用,應該是在已經獲知了以下信息以后才去調用:

a:獲知請求(request)的soap文本。

b:獲知響應(response)的soap文本。

 

請求文件和響應文本格式,一般會隨web服務的發布一同發布。我們可以通過WSExplorer獲取上面兩段文本。具體調用方法如下:

1:前端頁面請求: 

<body>
          <input type="text" id="msg" />
          <input type="button" onclick="sendAjaxWS();" value="通過ajax調用webservice服務"/>
</body>

 

 2:js里面封裝請求信息:

      <script>
               var xhr;
               function sendAjaxWS(){
                    xhr = new ActiveXObject("Microsoft.XMLHTTP");                 
                    //指定ws的請求地址
                    var wsUrl = "http://192.168.1.108:5678/hello";
                    //手動構造請求體
                var requestBody = '<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" ' 
+ 'xmlns:q0="http://service.itcast.cn/" xmlns:xsd="http://www.w3.org/2001/XMLSchema "'
+ ' xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">'
+ '<soapenv:Body><q0:sayHello><arg0>'
+ document.getElementById("msg").value+'</arg0> <arg1>10</arg1> </q0:sayHello></soapenv:Body></soapenv:Envelope>';        //打開連接 xhr.open("POST",wsUrl,true); //重新設置請求頭
xhr.setRequestHeader("content-type","text/xml;charset=utf8");
//設置回調函數 xhr.onreadystatechange = _back; //發送請求 xhr.send(requestBody); }

//定義回調函數 function _back(){ if(xhr.readyState == 4){ if(xhr.status == 200){ var ret = xhr.responseXML; //解析xml var eles = ret.getElementsByTagName("return")[0]; alert(eles.text); } } } </script>

 

 

 

 

 
        

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM