Spring5.x+CXF3.x+Tomcat构建SOAP服务

JDK自带类库支持发布SOAP服务,开发比较简单,但是不方便管理和扩展.CXF对ws和rs类的WebService有良好的支持,并且可以无缝与Sping集成,使得开发过程非常简单,且便于扩展。

一、使用JDK原生的类库开发SOAP服务

1、创建java项目(不需要是Web项目,用main方法启动)

2、创建接口类

百度搜到最多的就是sayHello,这里的注解可以不用加,形参里面的注解能够修改WSDL文件中参数的名字

package test;
import javax.jws.WebService;
import javax.jws.WebParam;
@WebService
public interface ICxfTest {
    public String say(@WebParam(name="hello")String str);
    public String powerOfTwo(int n);

}

3、创建实现类

这里实现了接口中的2个方法,say()返回一段写死的字符串加上客户端传输的字符串。powerOfTwo()返回2的幂,能够计算一个较大的值,比如2的1000次方,通过模拟手算乘法的进位,以字符串返回结果来实现。

package test;
import javax.jws.WebParam;
import javax.jws.WebService;
@WebService
public class CxfTest implements ICxfTest{
    public String say(@WebParam(name="hello")String str)
    {
        return "原生jdk实现CXF" +str;
    }
    
    public String powerOfTwo(int n)
    {
        String result = powerOfNumber(2,n);        
        return result;
        
    }
    public static String powerOfNumber(int baseNumber, int n)
    {
        if(baseNumber>9||baseNumber<0) return null;
        String result = "";
        int a[];
        a = new int[n];
        int i,j;
        for(i=0;i<n;i++)
        {
            a[i]=0;
        }
        a[0]=1;
        for(i=0;i<n;i++)
        {
            for(j=0;j<n;j++)
            {
                a[j]*=baseNumber;
            }
            for(j=0;j<n;j++)
            {
                if(a[j]>9)
                {
                    a[j+1]+=a[j]/10;
                    a[j]=a[j]%10;
                }
            }
        }
        int k = n-1;
        for(;k>=0;k--)
        {
            if(a[k]!=0)break;
        }
        for(i=k;i>=0;i--)
        {
            result +=a[i];
        }
        return result;
    }

}

4、创建发布类

这里使用了JDK自带的EndPoint类发布服务,没有借助任何第三方框架,通过main方法来启动,一旦启动,可以持续访问。这一步完成后将服务的发布地址copy到浏览器或SoapUI就可以看到WSDL文件了,通过SoapUI传递入参还可以收到返回。但是这里把服务地址写死了,只能这个地址,本人尝试过在访问时用ipconfig得到的IP替换localhost,结果是拒绝连接,如果想发布给其他人使用,可以将localhost换成IP,这样在局域网内其他人就可以访问了,端口不一定非要是8080,只要是没有被占用的端口都可以,至此,服务端已经开发完毕了。

package test;
import javax.xml.ws.Endpoint;

public class PublishServiceTest {
    public static void main(String[] args)
    {
        System.out.println("服务开始启动");
        ICxfTest cxfTest = new CxfTest();
        String address = "http://localhost:8080/test";
        //使用Endpoint类提供的publish方法发布WebService,发布时要保证使用的端口号没有被其他应用程序占用
        Endpoint.publish(address, cxfTest);
        System.out.println("服务已启动");
    }

}

5、创建客户端

创建客户端就更简单了,可以通过CMD的命令生成,如

//通过wsdl按指定名称输出package:
wsimport -s ./ -p com.skd.client.wsimport http://localhost:8080/test?wsdl

会在指定地方生成一些类,如下是我输入命令后生成的一些文件,那时候求2的次方函数名字还是叫squareOfTwo()

如下是我创建的客户端Java项目,只导入了生成的部分java文件,并把CxfTest.java中的一点内容删掉了,即注释部分,因为我没有引入那个类,不删除会报错,这个参考了https://blog.csdn.net/lovecarpenter/article/details/53946108第4节的做法,较为简单。

如下是调用的类,这里的访问地址最好与你的发布地址一致,启动main方法后即可获得你传参对应的返回。

package wsimportTest;
import java.net.URL;
import java.net.MalformedURLException;
import javax.xml.ws.Service;
import javax.xml.namespace.QName;

public class Test {
    public static void main(String[] args) throws MalformedURLException
    {
        String wsUrl = "http://127.0.0.1:8080/test?wsdl";
        //QName的第一个参数是服务的命名空间,第二个参数是服务的名称
        Service service = Service.create(new URL(wsUrl), new QName("http://test/","CxfTestService"));
        //QName的第一个参数是服务的命名空间,第二个参数是得到接口的Port
        CxfTest port = service.getPort(new QName("http://test/","CxfTestPort"),CxfTest.class);
        String ret = port.say("CXF 客户端测试");
        String result = port.squareOfTwo(1000);
        System.out.println(ret);
        System.out.println(result);
    }

除了使用wsimport命令生成客户端外,还可以通过Eclipse的创建客户端项目生成,也可以使用SoapUI来生成,当然,可以直接使用HttpURLConnection构造SOAP消息来调用。

二、使用Spring5.0.0+CXF3.2.5构建SOAP服务

我下载的时候Spring已经更新到5.0.7(http://repo.springsource.org/libs-release-local/org/springframework/spring/),CXF更新到3.2.5(http://cxf.apache.org/download.html)。在学习搭建的时候在百度上还没有找到Spring5.x的内容,主要集中在使用maven引入jar包,但即便是根据各种帖子的引入包来搭建,我仍然遇到了很多很多的问题。如下是我引入的jar包,在实践中发现缺一不可,而不是很多帖子的spring2个包,CXF2个包。比如commons-logging是使用spring必须引入的包,具体的缺包提示可参考:https://blog.csdn.net/w1014074794/article/details/47862163,非常全。这些包最好放在lib目录下,本人尝试过在lib目录下分别创建2个文件夹,放入各自的包并手动引入,遇到很多问题。

1、创建Web项目,引入Spring和CXF的包,并在web.xml配置spring的监听和CXF的Servlet,如下:

<listener>
  <description>SpringListener</description>
  <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>
  <context-param>
  <param-name>contextConfigLocation</param-name>
  <param-value>/WEB-INF/spring.xml</param-value>
  </context-param>
  <servlet>
  <servlet-name>CXFServlet</servlet-name>
  <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
  </servlet>
  <servlet-mapping>
  <servlet-name>CXFServlet</servlet-name>
  <url-pattern>/ws/*</url-pattern>
  </servlet-mapping>

2、创建接口

package com.weijie.service.api;
import javax.jws.WebService;

@WebService
public interface IExcelExport {
    String invokeTask(String appID);
    String searchTaskStatus(String guid,String appID);
    public String powerOfTwo(int n);
    public String say(String str);

}

3、实现接口

package com.weijie.service.impl;
import com.weijie.service.api.IExcelExport;
import com.weijie.util.Sequence;
import javax.jws.WebService;

@WebService(serviceName = "IExcelExport",
endpointInterface = "com.weijie.service.api.IExcelExport")
public class ExcelExport implements IExcelExport {
    public String invokeTask(String appID)
    {
        //String guid = null;
        return Sequence.generateSequence();
    }
    public String searchTaskStatus(String guid,String appID)
    {
        String status = "";
        return status;
    }
    public String powerOfTwo(int n)
    {
        return powerOfNumber(2,n);
    }
    public static String powerOfNumber(int baseNumber, int n)
    {
        if(baseNumber>9||baseNumber<0) return null;
        String result = "";
        int a[];
        a = new int[n];
        int i,j;
        for(i=0;i<n;i++)
        {
            a[i]=0;
        }
        a[0]=1;
        for(i=0;i<n;i++)
        {
            for(j=0;j<n;j++)
            {
                a[j]*=baseNumber;
            }
            for(j=0;j<n;j++)
            {
                if(a[j]>9)
                {
                    a[j+1]+=a[j]/10;
                    a[j]=a[j]%10;
                }
            }
        }
        int k = n-1;
        for(;k>=0;k--)
        {
            if(a[k]!=0)break;
        }
        for(i=k;i>=0;i--)
        {
            result +=a[i];
        }
        return result;
    }
    public String say(String str)
    {
        return "你好,这里是我第一个用CXF框架构建的SOAP服务,欢迎使用!" +str;
    }

}

4、Spring的配置文件

这里的jaxws:endpoint标签即是发布服务,配置了bean,并指出了实现类和发布地址(此处并没有指定IP和端口,使用了Tomcat部署,默认8080端口)

<?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"
       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://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context-4.0.xsd
       http://cxf.apache.org/jaxws
       http://cxf.apache.org/schemas/jaxws.xsd">
    
    <!--  <bean id="IExcelExportBean" class="com.weijie.service.impl.ExcelExport"></bean>
    -->
    <jaxws:endpoint id="IExcelExport" implementor="com.weijie.service.impl.ExcelExport" address="/IExcelExport">
    </jaxws:endpoint>
</beans>

这里的<jaxws:endpoint……>方式相当于前面使用原生JDK的方式发布SOAP服务,相当于:

Endpoint.publish("http://localhost:8080/IExcelExport", new ExcelExport());

还可以使用<jaxws:server serviceClass="com.weijie.service.impl.ExcelExport" address="/IExcelExport">,相当于:

JaxWsServerFactoryBean factory = new JaxWsServerFactoryBean();

这是cxf-rt-frontend-jaxws包下的类,通过继承依赖一些CXF其它的包,事实上,不依赖Spring,CXF也能构建SOAP服务,只是不方便修改和扩展。

在百度搜到的很多帖子都有在spring的配置文件里配置引入CXF的配置文件,有少数贴说这个已经不用了,经实践,已经不需要了,至此,通过Spring+CXF+Tomcat构建SOAP服务已经完成,可通过SoapUI测试

访问地址格式:http://IP:port/项目名/CXF拦截器拦截的地址/服务发布地址?wsdl

最近想深入学习一下Spring,于是又回来倒腾了,但是发现一个奇怪的现象,用浏览器访问?wsdl是OK的,但是用SoapUI访问却报错了,我清晰的记得之前用SoapUI都调过方法的,并取得了返回值的,无奈继续百度排查

经百度说是缺少了两个jar包  stax2-api-3.1.x.jar 和 woodstox-core-asl-4.2.x.jar,添加包后恢复

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值