转:CXF学习笔记一:如何创建、发布和访问基于CXF的服务

摘要:
它可以很好地处理Lists,但Maps不能直接支持它们*它们还需要使用XmlAdapter将映射映射到JAXB可以使用的bean*/@XmlJavaTypeAdapterMapgetUsers();}注意:wsdl将重命名参数的名称。如果不需要这样做,则应按如下方式编写:@WebServicepublicinterfaceHelloWorld{StringsayHi;}B) 编写实现:packagedemo。硬件。服务器导入java.util。LinkedHashMap;导入java.util。地图importjavax.jws。WebService;@WebService//告诉CXF使用哪个接口创建WSDLpublicclassHelloWorldImplementsHelloWorld{Mapusers=newLinkedHashMap();publicStringsayHi{System.out.println;return“Hello”+text;}publicStringsayHiToUser{System.out.println;users.put;return“Hello”+user.getName();}publicMap<Integer,User>getUsers(){System.out.println;returnusers;}}3) 发布服务A)使用jws:System的高级封装。出来打印ln;HelloWorldImpimplementor=newHelloWorldImpl();字符串地址=“http://localhost:9000/helloWorld“;Endpoint.publish;B)使用以下代码精确控制服务行为:HelloWorldImplementer=newHelloWorldImpl();JaxWsServerFactoryBeansvrFactory=newJaxWnServerFactoryBean();svrFactory.setServiceClass;//它可以保存,但不建议使用,因为可能存在一些小问题svrFactories.setAddress;svrFactory.setServiceBean;svrFactory.getInInterceptors()添加svrFactory。获取OutInterceptor().add;svrFactory。create();此后,您可以使用http://localhost:9000/helloWorld?
主要参考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

免责声明:文章转载自《转:CXF学习笔记一:如何创建、发布和访问基于CXF的服务》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇存储过程 返回值 procedure return valuesiOS 如何在一个已经存在多个project的workspace中引入cocoapods管理第三方类库下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

JSP上传视频等大文件

前言:因自己负责的项目(jetty内嵌启动的SpringMvc)中需要实现文件上传,而自己对java文件上传这一块未接触过,且对 Http 协议较模糊,故这次采用渐进的方式来学习文件上传的原理与实践。该博客重在实践。 一. Http协议原理简介      HTTP是一个属于应用层的面向对象的协议,由于其简捷、快速的方式,适用于分布式超媒体信息系统。它于19...

C#调用WPS将文档转换成pdf进行预览

vs启动项目可以生成wps实例 本地iis部署的站点却不行 原因是vs是管理员权限,而iis没有权限 解决方法 启动IIS,应用程序池-“选定的应用程序池”-高级设置-进程模型-标识:设置为管理员账号administrator     代码 1.安装WPS 2016 专业版 2.方法一:在项目中引用etapi.dll,wpsapi.dll,wpp...

音频拼接的简单实现方法(python一种,java两种)

音频拼接,就是5s+5s=10s的这种拼接。 需要修改的地方都是有三处,在代码里标注好了。 一、Python实现: Python3 #!/usr/bin/env python # -*- coding:utf-8 -*- # ok,音频拼接 from pydub import AudioSegment # 先导入这个模块 # 加载需要合并的两个mp3音...

itext生成pdf(附带页眉,页脚,页码)

packagecn.picclife.mwx.salesupport.marketactivity.util; importjava.io.File; importjava.io.FileOutputStream; importjava.io.IOException; importjava.net.MalformedURLException; impo...

如何用Netty实现一个轻量级的HTTP代理服务器

为什么会想通过Netty构建一个HTTP代理服务器?这也是笔者发表这篇文章的目的所在。 其主要还是源于解决在日常开发测试过程中,一直困扰测试同学很久的一个问题,现在我就来具体阐述一下这个问题。 在日常开发测试过程中,为了确保上线项目的万无一失,集成测试通常有部署,测试环境和回归环境这两套环境。开发人员根据需求编写代码模块,自测通过之后,由测试的同学更新到测...

3.开始使用Spring Cloud实战微服务

                 开始使用Spring Cloud实战微服务 3.1. Spring Cloud实战前提               3.1.1. 需要的技术储备                   语言方面:可以使用Java、scala、Groovy...等等,推荐使用Java                   构建工具方面:Java...