在 Web 容器中使用 Spring + CXF 發佈 WS(一)

一 服務端的發佈

第一步:配置 Maven 依賴

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.chuyu.demo</groupId>
  <artifactId>ws-demo-server</artifactId>
  <packaging>war</packaging>
  <version>1.0-SNAPSHOT</version>
  <name>ws-demo-server Maven Webapp</name>
  <url>http://maven.apache.org</url>
<properties>
    <!-- spring 版本號 -->
    <spring.version>4.0.2.RELEASE</spring.version>
  </properties>
  <dependencies>
    <dependency>
      <groupId>org.apache.cxf</groupId>
      <artifactId>cxf</artifactId>
      <version>2.7.7</version>
      <type>pom</type>
    </dependency>
    <dependency>
      <groupId>org.apache.cxf</groupId>
      <artifactId>cxf-rt-frontend-jaxws</artifactId>
      <version>2.7.7</version>
    </dependency>
    <dependency>
      <groupId>org.apache.cxf</groupId>
      <artifactId>cxf-rt-transports-http</artifactId>
      <version>2.7.7</version>
    </dependency>
    <dependency>
      <groupId>org.apache.geronimo.specs</groupId>
      <artifactId>geronimo-javamail_1.4_spec</artifactId>
      <version>1.7.1</version>
    </dependency>
    <!--導入spring依賴的jar包-->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-core</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-web</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-oxm</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-tx</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-jdbc</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-aop</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context-support</artifactId>
      <version>${spring.version}</version>
    </dependency>

第二步:寫一個 WS 接口及其實現

接口部分:html

package com.chuyu.webservices;

import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebService;

@WebService
public interface Myservice {
    @WebMethod
    public  String sayHello(@WebParam(name = "name")String name);
    public  String  saygodby(String name);
}

實現部分:java

package com.chuyu.webservices;

import org.springframework.stereotype.Component;

import javax.jws.WebService;

@WebService(endpointInterface = "com.chuyu.webservices.Myservice")
@Component
public class MyServiceImpl implements Myservice {
    @Override
    public String sayHello(String name) {
        return "你好"+name;
    }

    @Override
    public String saygodby(String name) {
        return "再見"+name;
    }
}

須要在實現類上添加 Spring 的 org.springframework.stereotype.Component 註解,這樣才能被 Spring IOC 容器掃描到web

第三步:配置 web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">

    <!-- 加載Spring容器 -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:spring.xml</param-value>
    </context-param>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <!-- CXF的Servlet -->
    <servlet>
        <servlet-name>cxf</servlet-name>
        <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <!-- 本系統的WebService路徑必須以/webservice/開頭 -->
    <servlet-mapping>
        <servlet-name>cxf</servlet-name>
        <url-pattern>/webservice/*</url-pattern>
    </servlet-mapping>

<display-name>Archetype Created Web Application</display-name>
</web-app>

全部帶有 /webservice/ 前綴的請求,將會交給被 CXFServlet 進行處理,也就是處理 WS 請求了。目前主要使用了 Spring IOC 的特性,利用了 ContextLoaderListener 加載 Spring 配置文件,即這裏定義的 spring.xml 文件。spring

第四步:配置 Spring

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans

http://www.springframework.org/schema/beans/spring-beans-4.0.xsd


http://www.springframework.org/schema/context


http://www.springframework.org/schema/context/spring-context-4.0.xsd">

    <context:component-scan base-package="com.chuyu.webservices"/>

    <import resource="cxf-servlet.xml"/>

</beans>

以上配置作了兩件事情:apache

  1. 定義 IOC 容器掃描路徑,即這裏定義的 demo.ws,在這個包下面(包括全部子包)凡是帶有 Component 的類都會掃描到 Spring IOC 容器中。
  2. 引入 spring-cxf.xml 文件,用於編寫 CXF 相關配置。將配置文件分離,是一種很好的開發方式。

第五步:配置 CXF

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:jaxws="http://cxf.apache.org/jaxws"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
        http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd">
    <!--1.  cxf-servlet.xml中import導入的文件不用本身建立,這是在依賴包中的。 -->
    <import resource="classpath:META-INF/cxf/cxf.xml"/>
    <import resource="classpath:META-INF/cxf/cxf-servlet.xml"/>
    <!-- springIOC 注入 -->
    <!--  <bean id="myServiceImpl" class="com.chuyu.webservices.MyServiceImpl" /> -->
  <!--  2. webservice發佈配置中implementor能夠直接寫入實現類,如:

    <jaxws:endpoint id="testService" implementor="test.service.impl.MyServiceImpl" address="/testService"/>
    -->

    <jaxws:endpoint id="testService" implementor="#myServiceImpl" address="/testService"/>
    <!--3.address參數是重點,這是webservice發佈後其wsdl的相對路徑,其絕對路徑爲應用訪問路徑/cxf攔截路徑/address?wsdl-->

</beans>

 這裏的 implementor 屬性值是 #MyServiceImpl,這是 CXF 特有的簡寫方式,並不是是 Spring 的規範,意思是經過 Spring 的 Bean ID 獲取 Bean 實例。瀏覽器

address參數是重點,這是webservice發佈後其wsdl的相對路徑,其絕對路徑爲: 應用訪問路徑/cxf攔截路徑/address?wsdlmvc

第六步:啓動 Tomcat

將應用部署到 Tomcat 中,在瀏覽器中輸入如下地址可進入 CXF 控制檯:http://localhost:8080/webservice/testService?wsdlapp

二 客戶端的調用

方案一:靜態代理客戶端

package demo.ws.soap_cxf;
 
import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;
 
public class JaxWsClient {
 
    public static void main(String[] args) {
        JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
        factory.setAddress("http://localhost:8080/ws/soap/hello");
        factory.setServiceClass(HelloService.class);
 
        HelloService helloService = factory.create(HelloService.class);
        String result = helloService.say("world");
        System.out.println(result);
    }
}

這種方案須要自行經過 WSDL 打客戶端 jar 包,經過靜態代理的方式來調用 WS。這種作法最爲原始frontend

方案二:動態代理客戶端

package demo.ws.soap_cxf;
 
import org.apache.cxf.endpoint.Client;
import org.apache.cxf.jaxws.endpoint.dynamic.JaxWsDynamicClientFactory;
 
public class JaxWsDynamicClient {
 
    public static void main(String[] args) {
        JaxWsDynamicClientFactory factory = JaxWsDynamicClientFactory.newInstance();
        Client client = factory.createClient("http://localhost:8080/ws/soap/hello?wsdl");
 
        try {
            Object[] results = client.invoke("say", "world");
            System.out.println(results[0]);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

這種方案無需經過 WSDL 打客戶端 jar 包,底層實際上經過 JDK 的動態代理特性完成的,CXF 實際上作了一個簡單的封裝。與 JDK 動態客戶端不同的是,此時無需使用 HelloService 接口.maven

方案三:通用動態代理客戶端

package demo.ws.soap_cxf;
 
import org.apache.cxf.endpoint.Client;
import org.apache.cxf.endpoint.dynamic.DynamicClientFactory;
 
public class DynamicClient {
 
    public static void main(String[] args) {
        DynamicClientFactory factory = DynamicClientFactory.newInstance();
        Client client = factory.createClient("http://localhost:8080/ws/soap/hello?wsdl");
 
        try {
            Object[] results = client.invoke("say", "world");
            System.out.println(results[0]);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

方案四:基於 Spring 的客戶端

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:jaxws="http://cxf.apache.org/jaxws"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
 
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
 
 
http://cxf.apache.org/jaxws
 
 
http://cxf.apache.org/schemas/jaxws.xsd">
 
    <jaxws:client id="helloService"
                  serviceClass="demo.ws.soap_spring_cxf.HelloService"
                  address="http://localhost:8080/ws/soap/hello"/>
 
</beans>

serviceClass中指定的類是自行經過 WSDL 打客戶端 jar 包.

helloService做爲Bean被spring容器管理,在程序中調用自動注入便可.

 

至此,spring 整合 cxf的基本應用基本上結束.

參考文獻:http://www.importnew.com/24816.html

相關文章
相關標籤/搜索