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

    FROM:http://blog.csdn.net/yuvmen/archive/2009/11/09/4790805.aspx

    主要参考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:complexTypeCOLOR: green">customer">  //复杂类型

        <xs:sequence>

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

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

            <xs:elementCOLOR: green">numOrders"COLOR: green">xs:int"/>

            <xs:elementCOLOR: green">revenue"COLOR: green">xs:double"/>

            <xs:element minOccurs="0"COLOR: green">test"COLOR: green">xs:decimal"/>

            <xs:element minOccurs="0"COLOR: green">birthDate"COLOR: green">xs:dateTime"/>

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

        </xs:sequence>

    </xs:complexType>

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

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

    <xs:simpleTypeCOLOR: green">customerType">    //枚举类型

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

            <xs:enumeration value="PRIVATE"/>

            <xs:enumeration value="BUSINESS"/>

        </xs:restriction>

    </xs:simpleType>

    <xs:elementCOLOR: green">NoSuchCustomer"COLOR: green">tns:NoSuchCustomer"/> //异常类

        <xs:complexTypeCOLOR: green">NoSuchCustomer">

            <xs:sequence>

                <xs:elementCOLOR: green">customerName" nillable="true"COLOR: green">xs:string"/>

            </xs:sequence>

     </xs:complexType>

     <wsdl:messageCOLOR: green">NoSuchCustomerException">

        <wsdl:partCOLOR: green">NoSuchCustomerException" element="tns:NoSuchCustomer">

        </wsdl:part>

     </wsdl:message>

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

  • 相关阅读:
    归并排序
    希尔排序
    字符串操作
    引用
    直接插入排序
    变量赋值
    C#中关于公共类的使用
    关于SQL中Between语句查询日期的问题
    用户控件 与 重写控件 的区别
    什么是命名空间,为什么要使用命名空间?
  • 原文地址:https://www.cnblogs.com/huqingyu/p/1692519.html
Copyright © 2011-2022 走看看