在 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

相关文章
相关标签/搜索