0%

SOAP之spring与cxf集成

初识SOAP

SOAP 是基于 XML 的简易协议,可使应用程序在 HTTP 之上进行信息交换。或者更简单地说:SOAP 是用于访问网络服务的协议。

  • SOAP 指简易对象访问协议
  • SOAP 是一种通信协议
  • SOAP 用于应用程序之间的通信
  • SOAP 是一种用于发送消息的格式
  • SOAP 被设计用来通过因特网进行通信
  • SOAP 独立于平台
  • SOAP 独立于语言
  • SOAP 基于 XML
  • SOAP 很简单并可扩展
  • SOAP 允许您绕过防火墙
  • SOAP 将被作为 W3C 标准来发展

构建demo

demoe结构

demo的项目结构大致如下

demo结构

关键依赖

既然是spring与cxf的集成,这里则需要添加cxf的依赖到我们的pom文件中(spring以及其他的依赖此处省略),cxf的依赖如下:

1
2
3
4
5
6
7
8
9
10
11
12
<dependencies>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http</artifactId>
<version>3.1.12</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxws</artifactId>
<version>3.1.12</version>
</dependency>
</dependencies>

server端

web.xml文件配置

由于是用cxf,所以需要在web.xml中使用CXFServlet,如下是相关配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
<display-name>Archetype Created Web Application</display-name>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring_soapserver_basic.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

<!-- 配置CXF的Servlet -->
<servlet>
<servlet-name>CXF</servlet-name>
<servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>CXF</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>

<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>

webservice接口定义及实现

这里我们可以自定义我们的服务在wsdl文件中暴露在外的请求参数,服务名,以及返回类型值等信息。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
package com.soapserver.service;

import com.soapserver.entity.Result;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;
import javax.xml.ws.BindingType;
import javax.xml.ws.soap.SOAPBinding;

@WebService(targetNamespace = "selfNamespace")
@BindingType(value = SOAPBinding.SOAP12HTTP_BINDING)
public interface HelloSoap {
@WebMethod(operationName = "HelloSoap")
@WebResult(name = "response")
Result helloSoap(@WebParam(name = "NAME") String name, @WebParam(name = "GREETING") String greeting);
}

package com.soapserver.service.impl;

import com.soapserver.entity.Result;
import com.soapserver.service.HelloSoap;
import org.springframework.stereotype.Service;

import javax.jws.WebService;

@Service("HelloSoapImpl")
@WebService(targetNamespace = "selfNamespace", serviceName = "HelloSoapService")
public class HelloSoapImpl implements HelloSoap {

@Override
public Result helloSoap(String name, String greeting) {
return new Result(0, greeting + "," + name);
}
}

spring配置

服务端的sping配置中需要配置我们要暴露的请求路径以及service。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?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.xsd
http://cxf.apache.org/jaxws
http://cxf.apache.org/schemas/jaxws.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">

<context:component-scan base-package="com.soapserver.service">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Service"/>
</context:component-scan>

<jaxws:server address="/helloSoap">
<jaxws:serviceBean>
<ref bean="HelloSoapImpl"/>
</jaxws:serviceBean>
</jaxws:server>
</beans>

WSDL

待简单的demo集成后,并且发布成功,我们就可以访问我们定义好的url: http://localhost:8080/server/hellosoap?wsdl 来查看我们的webservice的wsdl文件,通过分析该文件,可以很容的出服务端的服务相关信息,并因此来定义客户端的请求。本demo的wdsl信息如下:

wdsl样例

client端

webservice接口定义

客户端请求接口是需要分析服务端wsdl中暴露的信息来定义的。本demo的定义如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package com.soapclient.service;
import com.soapclient.entity.Result;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;
import javax.xml.ws.BindingType;
import javax.xml.ws.soap.SOAPBinding;

@WebService(targetNamespace = "selfNamespace")
@BindingType(value = SOAPBinding.SOAP12HTTP_BINDING)
public interface HelloSoap {
@WebMethod(operationName = "HelloSoap")
@WebResult(name = "response")
Result helloSoap(@WebParam(name = "NAME") String name, @WebParam(name = "GREETING") String greeting);
}

spring配置

客户端的spring配置中需要配置服务端的请求地址信息,配置如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?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:jaxws="http://cxf.apache.org/jaxws"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://cxf.apache.org/jaxws
http://cxf.apache.org/schemas/jaxws.xsd">

<jaxws:client id="request" address="http://localhost:8080/server/helloSoap"
serviceClass="com.soapclient.service.HelloSoap">
</jaxws:client>
</beans>

main函数

本demo是用main方式打jar包来发布客户端,当然,我们也可以将我们的客户端请求集成到springmvc中,通过war包的形式来发布。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package com.soapclient.main;

import com.soapclient.entity.Result;
import com.soapclient.service.HelloSoap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main {
private static final Logger LOGGER = LoggerFactory.getLogger(Main.class);

public static void main(String[] args) {

ApplicationContext context = new ClassPathXmlApplicationContext("classpath:spring_soapclient_basic.xml");
HelloSoap helloSoap = (HelloSoap) context.getBean("request", HelloSoap.class);
Result result = helloSoap.helloSoap("girl", "hello");
LOGGER.info("result: {} ; {}", result.getResult(), result.getDescription());
}
}