zoukankan      html  css  js  c++  java
  • 转:CXF学习笔记一:如何创建、发布和访问基于CXF的服务

    主要参考http://cxf.apache.org的相关内容:

    1.使用CXF创建服务的基本方法(使用CXF自带的jetty容器

       参考:http://cxf.apache.org/docs/a-simple-jax-ws-service.html

    分4步:

    ① 设置build环境

    ② 写服务

    ③ 发布服务

    ④ 访问服务

    1)设置build环境

    创建一个新项目,将apache-cxf-2.2.4.zip中lib目录中的下列文件添加到Build Path:

    commons-logging-1.1.1.jar

    geronimo-activation_1.1_spec-1.0.2.jar (or Sun's Activation jar)

    geronimo-annotation_1.0_spec-1.1.1.jar (JSR 250)

    geronimo-javamail_1.4_spec-1.6.jar (or Sun's JavaMail jar)

    geronimo-servlet_2.5_spec-1.2.jar (or Sun's Servlet jar)

    geronimo-ws-metadata_2.0_spec-1.1.2.jar (JSR 181)

    geronimo-jaxws_2.1_spec-1.0.jar (or Sun's jaxws-api-2.1.jar)

    geronimo-stax-api_1.0_spec-1.0.1.jar (or other stax-api jar)

    jaxb-api-2.1.jar

    jaxb-impl-2.1.12.jar

    jetty-6.1.21.jar

    jetty-util-6.1.21.jar

    neethi-2.0.4.jar

    saaj-api-1.3.jar

    saaj-impl-1.3.2.jar

    wsdl4j-1.6.2.jar

    wstx-asl-3.2.8.jar

    XmlSchema-1.4.5.jar

    xml-resolver-1.2.jar

    cxf-2.2.4.jar

    可选:添加Spring jars,为XML Configuration添加Spring支持。添加的jars如下:

    aopalliance-1.0.jar

    spring-core-2.5.5.jar

    spring-beans-2.5.5.jar

    spring-context-2.5.5.jar

    spring-web-2.5.5.jar

    2)写服务

    A)写接口

    @WebService

    public interface HelloWorld {

    String sayHi(String text);

        // JAX-WS/JAXB 不能直接支持高级用例,处理他们需要写特殊的XmlAdapter

        String sayHiToUser(User user);

        /* Map 传递

         * JAXB 不支持 Maps。它能很好的处理Lists,但Maps不能直接支持他们。

         * 他们也需要使用一个XmlAdapter来将maps映射进JAXB可以使用的beans

         */

        @XmlJavaTypeAdapter(IntegerUserMapAdapter.class)

        Map<Integer, User> getUsers();

    }

    注意:wsdl会重命名参数的名字,如果不希望这样,应该这样写:

    @WebService

    public interface HelloWorld {

        String sayHi(@WebParam(name="text") String text);

    }

    B)写实现:

    package demo.hw.server;

    import java.util.LinkedHashMap;

    import java.util.Map;

    import javax.jws.WebService;

    @WebService(endpointInterface = "demo.hw.server.HelloWorld",

                serviceName = "HelloWorld")    //告诉CXF用哪一个接口创建WSDL

    public class HelloWorldImpl implements HelloWorld {

        Map<Integer, User> users = new LinkedHashMap<Integer, User>();

        public String sayHi(String text) {

            System.out.println("sayHi called");

            return "Hello " + text;

        }

        public String sayHiToUser(User user) {

            System.out.println("sayHiToUser called");

            users.put(users.size() + 1, user);

            return "Hello "  + user.getName();

        }

        public Map<Integer, User> getUsers() {

            System.out.println("getUsers called");

            return users;

        }

    }

    3)发布服务(CXF自带Jetty服务器,所以无需Tomcat就可发布)

    A)使用jws的高层封装:

    System.out.println("Starting Server");

    HelloWorldImpl implementor = new HelloWorldImpl();

    String address = "http://localhost:9000/helloWorld";

    Endpoint.publish(address, implementor);

    B)使用下列代码比较精确地控制服务的行为:

    HelloWorldImpl implementor = new HelloWorldImpl();

    JaxWsServerFactoryBean svrFactory = new JaxWsServerFactoryBean();

    svrFactory.setServiceClass(HelloWorld.class);   //可省,但不建议,因为可能会有些小问题

    svrFactory.setAddress("http://localhost:9000/helloWorld");

    svrFactory.setServiceBean(implementor);

    svrFactory.getInInterceptors().add(new LoggingInInterceptor());

    svrFactory.getOutInterceptors().add(new LoggingOutInterceptor());

    svrFactory.create();

    自此,可以通过http://localhost:9000/helloWorld?wsdl来显示该服务的wsdl

    LoggingInInterceptor和LoggingOutInterceptor是日志拦截器,用于输入和输出时显示日志,下同。

    4)访问服务

    A)使用jws的高层封装:

    //第一个参数是接口实现类包名的反缀

    private static final QName SERVICE_NAME = new QName("http://server.hw.demo/", "HelloWorld");

    private static final QName PORT_NAME= new QName("http://server.hw.demo/", "HelloWorldPort");

    ……

    Service service = Service.create(SERVICE_NAME);

    // Endpoint Address

    String endpointAddress = "http://localhost:9000/helloWorld";

    // Add a port to the Service

    service.addPort(PORT_NAME, SOAPBinding.SOAP11HTTP_BINDING, endpointAddress);

    HelloWorld hw = service.getPort(HelloWorld.class);

    System.out.println(hw.sayHi("World"));

    B)或者使用下面代码更精确的控制服务:

    JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();

    factory.getInInterceptors().add(new LoggingInInterceptor());

    factory.getOutInterceptors().add(new LoggingOutInterceptor());

    factory.setServiceClass(HelloWorld.class);

    factory.setAddress("http://localhost:9000/helloWorld");

    HelloWorld client = (HelloWorld) factory.create();

    String reply = client.sayHi("HI");

    System.out.println("Server said: " + reply);

    System.exit(0);

    2.wsdl2java:从wsdl文档中生成java类,供client使用

    设置环境变量CXF_HOME=D:\Program Files\apache-cxf-2.2.4,PATH后加上“;%CXF_HOME%\bin”(可选),然后执行wsdl2java批处理程序,用法如下:
    wsdl2java –p 包名 –d 目录名 wsdl路径
    如:wsdl2java –p demo.service.client –d e:\src htt://localhost:8080/helloWorld?wsdl
    -p  指定其wsdl的命名空间,也就是要生成代码的包名
    -d  指定要产生代码所在目录
    -client 生成客户端测试web service的代码
    -server 生成服务器启动web  service的代码
    -impl 生成web service的实现代码
    -ant  生成build.xml文件
    -all 生成所有开始端点代码:types,service proxy,,service interface, server mainline, client mainline, implementation object, and an Ant build.xml file.
    详细用法见http://cwiki.apache.org/CXF20DOC/wsdl-to-java.html

    3.定义复杂类型(基本类型如int,String,无须额外定义),参考资料:http://cxf.apache.org/docs/defining-contract-first-webservices-with-wsdl-generation-from-java.html

    例如:

    package com.example.customerservice;

    @XmlAccessorType( XmlAccessType.FIELD )

    public class Customer {  //自定义类

        String name;

        String\[\] address;

        int numOrders;

        double revenue;

        BigDecimal test;

        Date birthDate;

        CustomerType type; //自定义枚举类型

    }

    public enum CustomerType {

        PRIVATE, BUSINESS

    }

    //定义Exception

    @WebFault(name="NoSuchCustomer")

    @XmlAccessorType( XmlAccessType.FIELD )

    public class NoSuchCustomerException extends RuntimeException {

    /**

     * We only define the fault details here. Additionally each fault has a message

     * that should not be defined separately

     */

    String customerName;

    }     //定义Exceptions的默认行为是在后面生成Java code时创建Exception_Exception,所以必须用@WebFault标记来为Bean取一个名字,以与Exception名字相区别

    @WebService    //标记本接口为一个服务

    public interface CustomerService {

    public Customer[] getCustomersByName(@WebParam(name="name") String name) throws NoSuchCustomerException;     //@WebParam标记wsdl中的参数名。如果省略,wsdl将使用arg0代替

    }

    // @WebService还可用来自定义接口名和服务名,分别对应:endpointInterface和serviceName,如:

    @WebService(endpointInterface = "com.example.customerservice", serviceName = "HelloWorld")

    生成的WSDL

    <xs:complexType name="customer">  //复杂类型

        <xs:sequence>

            <xs:element minOccurs="0" name="name" type="xs:string"/>

            <xs:element maxOccurs="unbounded" minOccurs="0" name="address" nillable="true" type="xs:string"/>

            <xs:element name="numOrders" type="xs:int"/>

            <xs:element name="revenue" type="xs:double"/>

            <xs:element minOccurs="0" name="test" type="xs:decimal"/>

            <xs:element minOccurs="0" name="birthDate" type="xs:dateTime"/>

            <xs:element minOccurs="0" name="type" type="tns:customerType"/>

        </xs:sequence>

    </xs:complexType>

    minOccurs="0"是可选项,这样可以随时加入新元素,保持兼容性。如果不想要这个选项,可以使用标记@XmlElement(required=true)

    maxOccurs="unbounded"是为了便于后面的xml重复该元素以形成数组。

    <xs:simpleType name="customerType">    //枚举类型

        <xs:restriction base="xs:string">

            <xs:enumeration value="PRIVATE"/>

            <xs:enumeration value="BUSINESS"/>

        </xs:restriction>

    </xs:simpleType>

    <xs:element name="NoSuchCustomer" type="tns:NoSuchCustomer"/> //异常类

        <xs:complexType name="NoSuchCustomer">

            <xs:sequence>

                <xs:element name="customerName" nillable="true" type="xs:string"/>

            </xs:sequence>

     </xs:complexType>

     <wsdl:message name="NoSuchCustomerException">

        <wsdl:part name="NoSuchCustomerException" element="tns:NoSuchCustomer">

        </wsdl:part>

     </wsdl:message>

    // 注意:Element和Message的名字是不同的,这是通过标记@Webfault标记来实现的。也可以让他们同名,但那样会话,生成的Exception的名字会比较丑:NoSuchCustomerException_Exception

  • 相关阅读:
    创建Variant数组
    ASP与存储过程(Stored Procedures)
    FileSystemObject对象成员概要
    Kotlin 朱涛9 委托 代理 懒加载 Delegate
    Kotlin 朱涛 思维4 空安全思维 平台类型 非空断言
    Kotlin 朱涛7 高阶函数 函数类型 Lambda SAM
    Kotlin 朱涛16 协程 生命周期 Job 结构化并发
    Proxy 代理模式 动态代理 cglib MD
    RxJava 设计理念 观察者模式 Observable lambdas MD
    动态图片 Movie androidgifdrawable GifView
  • 原文地址:https://www.cnblogs.com/phoebus0501/p/1970708.html
Copyright © 2011-2022 走看看