百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术资源 > 正文

Spring整合CXF 发布webservice接口服务器和客户端,WSDL简单解析

moboyou 2025-03-29 15:05 15 浏览

在垮平台通讯中有很多的接口方式,这里做个简单的webservice接口。发布webservice接口的方式也多种多样,这里做个基于CXF的webservice接口。首先做点知识储备,javax.jws包中常用的注解,参考链接:
http://blog.csdn.net/w410589502/article/details/51742004

下面开始,这里Spring用的4.2的,CXF用的3.2的,JDK是1.8的,这里只要是1.6及以后的就没问题了,主要是要用javax.jws的包

服务端webservice接口

package com.lovo.webservice;

import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
import javax.jws.soap.SOAPBinding.Style;

/**
 * SOAP协议的webservice接口
 * @author WZH
 *服务器端,服务提供者
 */

/*
 * @WebService 标记为一个webservice接口
 * 1.targetNamespace:指定你想要的名称空间,默认认是使用接口实现类的包名的反缀,
 * 但是在实际测试中发现cxf+spring编写webservice的时候,targetNamespace要指向
 * 服务类的接口所在的包名而不是实现类的包名,否则,在客户端将不能识别可用的服务
 * 2.serviceName: 对外发布的服务名,指定 Web Service 的服务名称:wsdl:service。
 * 缺省值为 Java 类的简单名称 + Service。(字符串)
 * 3.portName:  wsdl:portName。缺省值为 WebService.name+Port。
 * 
 * @SOAPBinding 消息绑定, 这个标记怎么说,我这里测试的时候加不加都无所谓,但是有同仁说过
 * 不加这个有时候会出现客户端无法识别,有的人又报错,所以还是加上吧
 * Exception in thread "main" com.sun.xml.internal.ws.model.RuntimeModelerException: 
 * runtime modeler error: Wrapper class org.soap.service.jaxws.Add is not found. Have you run APT to generate them?
 */
@WebService(targetNamespace ="http://webservice.lovo.com/",serviceName="HelloService",portName="HellowServicePort")
@SOAPBinding(style=Style.RPC)
public interface IHelloService {
    
    /*
     * @WebResult 注释用于定制从返回值至 WSDL 部件或 XML 元素的映射。将此注释应用于客户机或服务器服务端点接口(SEI)上的方法,
     * 或者应用于 JavaBeans 端点的服务器端点实现类
     * 1.name:当返回值列示在 WSDL 文件中并且在连接上的消息中找到该返回值时,指定该返回值的名称。对于 RPC 绑定,这是用于表示返回值的
     * 2.targetNamespace:指定返回值的 XML 名称空间。仅当操作类型为 RPC 或者操作是文档类型并且参数类型为 BARE 时才使用此参数。(字符串)
     * 
     * @WebMethod 注释表示作为一项 Web Service 操作的方法,将此注释应用于客户机或服务器服务端点接口(SEI)上的方法,
     * 或者应用于 JavaBeans 端点的服务器端点实现类。
     * 1.operationName:指定与此方法相匹配的wsdl:operation 的名称。缺省值为 Java 方法的名称。(字符串)
     * 
     * @WebParam 注释用于定制从单个参数至 Web Service 消息部件和 XML 元素的映射
     * 1.name :参数的名称。如果操作是远程过程调用(RPC)类型并且未指定partName 属性,
     * 那么这是用于表示参数的 wsdl:part 属性的名称。如果操作是文档类型或者参数映射至某个头,那么 -name 是用于表示该参数的 XML 元素的局部名称。
     * 如果操作是文档类型、参数类型为 BARE 并且方式为 OUT 或 INOUT,那么必须指定此属性。(字符串)
     */
    
    @WebResult(name="helloRequest",targetNamespace="http://webservice.lovo.com/")
    @WebMethod(operationName="sayHello1")
    public String hello(@WebParam(name="msg")String message);
}

服务端接口实现类

package com.lovo.webservice.impl;

import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
import javax.jws.soap.SOAPBinding.Style;

import org.springframework.stereotype.Service;

import com.lovo.webservice.IHelloService;

/*
 * endpointInterface: 服务接口全路径, 指定做SEI(Service EndPoint Interface)服务端点接口,简单的说就写接口的全路径
 */
@WebService(endpointInterface="com.lovo.webservice.IHelloService")
@SOAPBinding(style=Style.RPC)
public class HelloServiceImpl implements IHelloService {

    @Override
    public String hello(String message) {
        
        return "你好" + message;
    }

}

前面的两段代码只是简单的java加上一些注解,下面把代码整合入Spring的web工程
web.xml 配置
需在web.xml中配置CXF

 
  
    cxf
    org.apache.cxf.transport.servlet.CXFServlet
    1
  
  
  
    cxf
    /webservice/*
  

完整的xml文件:



  Spring
  
    
    webAppRootKey
    Spring.root
  



  
    contextConfigLocation
    /WEB-INF/classes/applicationContext.xml
  
    
 
    log4jConfigLocation
    /WEB-INF/log4j.xml
  
  
  
  
    log4jRefreshInterval
    60000
    
    
       
    org.springframework.web.util.Log4jConfigListener


    org.springframework.web.context.ContextLoaderListener
  


  
    index.jsp  
  



  
    characterEncodingFilter  
    org.springframework.web.filter.CharacterEncodingFilter  
      
        encoding  
        UTF-8  
      
      
        forceEncoding  
        true  
      
  
  
    characterEncodingFilter  
    /*  




 
  
    cxf
    org.apache.cxf.transport.servlet.CXFServlet
    1
  
  
  
    cxf
    /webservice/*
  
  
  

    Spring
    org.springframework.web.servlet.DispatcherServlet
  
  
    Spring
    /
   
  

配置cxf的配置文件,这个也可以直接配置在Spring的配置文件中,看项目风格吧




    
    <import resource="classpath:META-INF/cxf/cxf.xml" />
    

    
     
        
            
        
     
    

在application.xml中引入cxf.xml


<import resource="classpath:META-INF/cxf/cxf.xml"/>
<import resource="classpath:/cxf-beans.xml"/>

完整的application.xml




    
    
    
    


    
    
        
        
        
        
        
        
        
        
        
        
        
    

    
    
        
        
        
    

    
    
        
        
    

    
    
        
    


    

    
    
        
            
            
            
            

            
            
            

            
            
            
            

            
            
            


        
    

    
        
        
    



    
    

    
    <import resource="classpath:META-INF/cxf/cxf.xml"/>
    <import resource="classpath:/cxf-beans.xml"/>

下面来测试下发布是否成功,我这里是tomcat 工程名是Spring,拦截的是webservice,所以访问的地址是:
http://localhost:8080/Spring/webservice?wsdl

出现界面

右键连接地址可以下载wsdl

这样就发布了一个简单的webservice接口,下面在发布一个接口以便wsdl的时候做对比,然后再发布一个rest风格的接口

package com.lovo.webservice;

import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
import javax.jws.soap.SOAPBinding.Style;

/**
 * SOAP协议的webservice接口
 * @author WZH
 *服务器端,服务提供者
 */

/*
 * @WebService 标记为一个webservice接口
 * 1.targetNamespace:指定你想要的名称空间,默认认是使用接口实现类的包名的反缀,
 * 但是在实际测试中发现cxf+spring编写webservice的时候,targetNamespace要指向
 * 服务类的接口所在的包名而不是实现类的包名,否则,在客户端将不能识别可用的服务
 * 2.serviceName: 对外发布的服务名,指定 Web Service 的服务名称:wsdl:service。
 * 缺省值为 Java 类的简单名称 + Service。(字符串)
 * 3.portName:  wsdl:portName。缺省值为 WebService.name+Port。
 * 
 * @SOAPBinding 消息绑定, 这个标记怎么说,我这里测试的时候加不加都无所谓,但是有同仁说过
 * 不加这个有时候会出现客户端无法识别,有的人又报错,所以还是加上吧
 * Exception in thread "main" com.sun.xml.internal.ws.model.RuntimeModelerException: 
 * runtime modeler error: Wrapper class org.soap.service.jaxws.Add is not found. Have you run APT to generate them?
 */
@WebService(targetNamespace ="http://webservice.lovo.com/",serviceName="HelloService",portName="HellowServicePort")
@SOAPBinding(style=Style.RPC)
public interface IHelloService {
    
    /*
     * @WebResult 注释用于定制从返回值至 WSDL 部件或 XML 元素的映射。将此注释应用于客户机或服务器服务端点接口(SEI)上的方法,
     * 或者应用于 JavaBeans 端点的服务器端点实现类
     * 1.name:当返回值列示在 WSDL 文件中并且在连接上的消息中找到该返回值时,指定该返回值的名称。对于 RPC 绑定,这是用于表示返回值的
     * 2.targetNamespace:指定返回值的 XML 名称空间。仅当操作类型为 RPC 或者操作是文档类型并且参数类型为 BARE 时才使用此参数。(字符串)
     * 
     * @WebMethod 注释表示作为一项 Web Service 操作的方法,将此注释应用于客户机或服务器服务端点接口(SEI)上的方法,
     * 或者应用于 JavaBeans 端点的服务器端点实现类。
     * 1.operationName:指定与此方法相匹配的wsdl:operation 的名称。缺省值为 Java 方法的名称。(字符串)
     * 
     * @WebParam 注释用于定制从单个参数至 Web Service 消息部件和 XML 元素的映射
     * 1.name :参数的名称。如果操作是远程过程调用(RPC)类型并且未指定partName 属性,
     * 那么这是用于表示参数的 wsdl:part 属性的名称。如果操作是文档类型或者参数映射至某个头,那么 -name 是用于表示该参数的 XML 元素的局部名称。
     * 如果操作是文档类型、参数类型为 BARE 并且方式为 OUT 或 INOUT,那么必须指定此属性。(字符串)
     */
    
    @WebResult(name="helloRequest",targetNamespace="http://webservice.lovo.com/")
    @WebMethod(operationName="sayHello1")
    public String hello(@WebParam(name="msg")String message);
    
    @WebResult(name="loginRequest",targetNamespace="http://webservice.lovo.com/")
    @WebMethod(operationName="login")
    public String login(@WebParam(name="userName")String userName,@WebParam(name="password")String password);
}

这里需要特别注意,targetNamespace中路径结尾需写反斜杠/不然会出现问题

package com.lovo.webservice.impl;

import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
import javax.jws.soap.SOAPBinding.Style;

import org.springframework.stereotype.Service;

import com.lovo.webservice.IHelloService;

/*
 * endpointInterface: 服务接口全路径, 指定做SEI(Service EndPoint Interface)服务端点接口,简单的说就写接口的全路径
 */
@WebService(endpointInterface="com.lovo.webservice.IHelloService")
@SOAPBinding(style=Style.RPC)
public class HelloServiceImpl implements IHelloService {

    @Override
    public String hello(String message) {
        
        return "你好" + message;
    }

    @Override
    public String login(String userName, String password) {
        String req = null;
        //这里做个假的登录验证
        if("小明".equals(userName)&&"123456".equals(password))
        {
            req = "登录成功";
        }else
        {
            req = "登录失败";
        }
        return req;
    }

}

这个时候再访问wsdl的网址就看见有两个方法了

下载wsdl



  
    
    
  
  
    
    
  
  
    
    
  
  
    
    
    
    
  
  
    
      
    
      
    
    
    
      
    
      
    
    
  
  
    
    
      
      
        
      
      
        
      
    
    
      
      
        
      
      
        
      
    
  
  
    
      
    
  

阅读wsdl的方法详细的阅读方式方式可以看这篇文章:
http://blog.csdn.net/liuchunming033/article/details/41210151

拿到一个wsdl,个人一般是先看最后,也就是wsdl:service部分。wsdl:service:存放接口名和接口地址


  
    
    
       
      
    
  

然后再看binding部分,也就是wsdl:binding
wsdl:binding:每个端口定义消息格式和协议细节


  
    
    
    
    
      
      
        
        
      
      
        
      
    
    
      
      
        
      
      
        
      
    
  

再看portType部分,wsdl:portType
wsdl:portType:描述webservice可被执行的操作,以及相关的消息,通过binding指向portType

  
  
    
    
      
      
    
      
    
    
    
      
    
      
    
    
  

在看message,wsdl:message
wsdl:message:定义一个操作(方法)的数据参数(可有多个参数)

  
  
    
    
  
  
    
    
  
  
    
    
  
  
  
    
    
    
    
    
  

最后还是需要看看开始部分



这么一个简单的xml就解析完了
完整的xml文档




  
  
    
    
  
  
    
    
  
  
    
    
  
  
  
    
    
    
    
    
  
  
  
    
    
      
      
    
      
    
    
    
      
    
      
    
    
  
  
  
    
    
    
    
      
      
        
        
      
      
        
      
    
    
      
      
        
      
      
        
      
    
  
  
  
    
    
       
      
    
  

wsdl阅读完成了,需要的参数都明白了,下面就可以做个简单的客户端进行调用,webService客户端调用的方法有很多,我们这里简单的做几个。
一:Service编程方式
特点:可以自定义关键元素,方便以后维护,是一种标准的开发方式
首先写一个客户端调用对象

package com.lovo.client;

import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
import javax.jws.soap.SOAPBinding.Style;

/**
 * 客户端调用者,根据wsdl初始化接口对象
 * @author WZH
 *
 *targetNamespace 对应wsdl抬头 targetNamespace,serviceName和portName分别对应wsdl结尾的wsdl:service name="HelloService"
 *和wsdl:port binding="tns:HelloServiceSoapBinding" name="HellowServicePort">
 *因为wsdl文档中有指定SOAP类型,所以需书写类型 
 */
@WebService(targetNamespace="http://webservice.lovo.com/",serviceName="HelloService",portName="HellowServicePort")
@SOAPBinding(style=Style.RPC)
public interface HellowService {
    /**
     * 方法名对应wsdl wsdl:operation name="login"
     * @param username 参数名对应 wsdl:part name="userName" type="xsd:string"
     * @param password
     * @return
     * 
     * 方法名映射 
     *  地址映射
     * 参数映射: 
     */
    @WebResult(name="login",targetNamespace="http://webservice.lovo.com/")
    @WebMethod(operationName = "login")
    public String login(@WebParam(name = "userName")String username , @WebParam(name = "password")String password);
    
    @WebResult(name="helloRequest",targetNamespace="http://webservice.lovo.com/")
    @WebMethod(operationName="sayHello1")
    public String hello(@WebParam(name="msg")String msg);
    
}

这里需要特别注意,targetNamespace中路径结尾需写反斜杠/不然会出现问题

准备工作做好了,可以做个客户端的调用了

package com.lovo.client;

import java.net.URL;

import javax.xml.namespace.QName;
import javax.xml.ws.Service;
import javax.xml.ws.soap.SOAPBinding;

public class wsClient {
    
    /**
     * XML 类 第一个参数表示地址,第二个参数表示端口名
     * 这里第一个参数是wsdl 表头targetNamespace
     * 第二个参数是service name
     */
    private static final QName SERVICE_NAME =  new QName("http://webservice.lovo.com/", "HelloService");
    private static final QName PORT_NAME = new QName("http://webservice.lovo.com/", "HellowServicePort");
    
    //编程方式一 begin -----------------------
    public static void testSayHello()
    {
        try {
            //创建Serivce业务类
            Service service = Service.create(SERVICE_NAME);
            //连接地址  
            String endPointAddress = "http://localhost:8080/Spring/webservice/HelloService";
            //配置业务访问参数 portName, bindingId, endpointAddress,
            //这里因为是SOPA11的所有配置11,SOAP现在有11和12两种 可通过xmlns:ns1="http://schemas.xmlsoap.org/soap/http" 判断
            service.addPort(PORT_NAME, SOAPBinding.SOAP11HTTP_BINDING, endPointAddress);
            
            //把本地客户端的接口与网络上的WSDL连接起来
            HellowService hs = service.getPort(HellowService.class);
            System.out.println(hs.hello("小明"));
        } catch (Exception e) {
            e.printStackTrace();
        }
        
    }
    
    //end-------------------------------------
    
    
    //编程方式二 begin  不知道为什么 Service.create报错,可能是jar原因-----------------------
    public static void testSayHello2()
    {
        try 
        {
            //创建WSDL的URL,注意不是服务地址  
            URL url = new URL("http://localhost:8080/Spring/webservice?wsdl");
            //创建服务名,代码有写成了静态常量,这里直接引用
            
            //创建服务视图
            javax.xml.ws.Service service = Service.create(url, SERVICE_NAME);
            //获取服务实例
            HellowService hs = service.getPort(new QName("http://webservice.lovo.com/", "HellowServicePort"), HellowService.class);
            System.out.println(hs.hello("小明"));
            
        } catch (Exception e) 
        {
            e.printStackTrace();
        }
    }
    
    
    //end-------------------------------------
    
    public static void main(String[] args) {
        //testSayHello();
        testSayHello2();
    }

}

剩下的等有空的再完善

相关推荐

Excel技巧:SHEETSNA函数一键提取所有工作表名称批量生产目录

首先介绍一下此函数:SHEETSNAME函数用于获取工作表的名称,有三个可选参数。语法:=SHEETSNAME([参照区域],[结果方向],[工作表范围])(参照区域,可选。给出参照,只返回参照单元格...

Excel HOUR函数:“小时”提取器_excel+hour函数提取器怎么用

一、函数概述HOUR函数是Excel中用于提取时间值小时部分的日期时间函数,返回0(12:00AM)到23(11:00PM)之间的整数。该函数在时间数据分析、考勤统计、日程安排等场景中应用广泛。语...

Filter+Search信息管理不再难|多条件|模糊查找|Excel函数应用

原创版权所有介绍一个信息管理系统,要求可以实现:多条件、模糊查找,手动输入的内容能去空格。先看效果,如下图动画演示这样的一个效果要怎样实现呢?本文所用函数有Filter和Search。先用filter...

FILTER函数介绍及经典用法12:FILTER+切片器的应用

EXCEL函数技巧:FILTER经典用法12。FILTER+切片器制作筛选按钮。FILTER的函数的经典用法12是用FILTER的函数和切片器制作一个筛选按钮。像左边的原始数据,右边想要制作一...

office办公应用网站推荐_office办公软件大全

以下是针对Office办公应用(Word/Excel/PPT等)的免费学习网站推荐,涵盖官方教程、综合平台及垂直领域资源,适合不同学习需求:一、官方权威资源1.微软Office官方培训...

WPS/Excel职场办公最常用的60个函数大全(含卡片),效率翻倍!

办公最常用的60个函数大全:从入门到精通,效率翻倍!在职场中,WPS/Excel几乎是每个人都离不开的工具,而函数则是其灵魂。掌握常用的函数,不仅能大幅提升工作效率,还能让你在数据处理、报表分析、自动...

收藏|查找神器Xlookup全集|一篇就够|Excel函数|图解教程

原创版权所有全程图解,方便阅读,内容比较多,请先收藏!Xlookup是Vlookup的升级函数,解决了Vlookup的所有缺点,可以完全取代Vlookup,学完本文后你将可以应对所有的查找难题,内容...

批量查询快递总耗时?用Excel这个公式,自动计算揽收到签收天数

批量查询快递总耗时?用Excel这个公式,自动计算揽收到签收天数在电商运营、物流对账等工作中,经常需要统计快递“揽收到签收”的耗时——比如判断某快递公司是否符合“3天内送达”的服务承...

Excel函数公式教程(490个实例详解)

Excel函数公式教程(490个实例详解)管理层的财务人员为什么那么厉害?就是因为他们精通excel技能!财务人员在日常工作中,经常会用到Excel财务函数公式,比如财务报表分析、工资核算、库存管理等...

Excel(WPS表格)Tocol函数应用技巧案例解读,建议收藏备用!

工作中,经常需要从多个单元格区域中提取唯一值,如体育赛事报名信息中提取唯一的参赛者信息等,此时如果复制粘贴然后去重,效率就会很低。如果能合理利用Tocol函数,将会极大地提高工作效率。一、功能及语法结...

Excel中的SCAN函数公式,把计算过程理清,你就会了

Excel新版本里面,除了出现非常好用的xlookup,Filter公式之外,还更新一批自定义函数,可以像写代码一样写公式其中SCAN函数公式,也非常强大,它是一个循环函数,今天来了解这个函数公式的计...

Excel(WPS表格)中多列去重就用Tocol+Unique组合函数,简单高效

在数据的分析和处理中,“去重”一直是绕不开的话题,如果单列去重,可以使用Unique函数完成,如果多列去重,如下图:从数据信息中可以看到,每位参赛者参加了多项运动,如果想知道去重后的参赛者有多少人,该...

Excel(WPS表格)函数Groupby,聚合统计,快速提高效率!

在前期的内容中,我们讲了很多的统计函数,如Sum系列、Average系列、Count系列、Rank系列等等……但如果用一个函数实现类似数据透视表的功能,就必须用Groupby函数,按指定字段进行聚合汇...

Excel新版本,IFS函数公式,太强大了!

我们举一个工作实例,现在需要计算业务员的奖励数据,右边是公司的奖励标准:在新版本的函数公式出来之前,我们需要使用IF函数公式来解决1、IF函数公式IF函数公式由三个参数组成,IF(判断条件,对的时候返...

Excel不用函数公式数据透视表,1秒完成多列项目汇总统计

如何将这里的多组数据进行汇总统计?每组数据当中一列是不同菜品,另一列就是该菜品的销售数量。如何进行汇总统计得到所有的菜品销售数量的求和、技术、平均、最大、最小值等数据?不用函数公式和数据透视表,一秒就...