SpringBoot 整合 webservice 示例
现在有一些老项目是使用webservice提供远程接口服务的,工作中遇到了,在这里使用Apache CXF 特意做一个示例,供参考!
1.webservice技术特点?
- webservice接口调用可以跨语言(不管程序是用什么语言开发的,webservice接口都可以相互调用)
- 也是基于http协议
- 可以使用xml进行数据传递(使用jaxws协议),也可以使用json进行数据传递(使用jaxrs协议),本示例演示xml进行数据传递
2.构建webservice服务端
1、新建一个SringBoot工程,引入依赖,注意:这里不用引入web依赖,springboot 整合 webservice 依赖中包含web依赖
<!--springboot 整合 webservice 依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web-services</artifactId>
</dependency>
<!--cxf 核心依赖-->
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http</artifactId>
<version>3.4.3</version>
</dependency>
<!--jaxws 协议的 cxf webservice依赖 -->
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxws</artifactId>
<version>3.4.4</version>
</dependency>
2、新建一个接口服务
@WebService(targetNamespace = "http://service.winson.com", name = "HelloService")//与接口中的命名空间一致,一般是接口的包名倒(要与实现类定义的值相同,否则利用动态代理创建客户端,无法调用接口方法)
public interface HelloService {
@WebMethod
String hello(@WebParam(name = "name") String name);
}
3、接口实现类。注:目标命名空间必须与接口一致
@Service
@WebService(serviceName = "HelloService",// 与接口中指定的name一致
targetNamespace = "http://service.winson.com",// 与接口中的命名空间一致,一般是接口的包名倒
endpointInterface = "com.winson.service.HelloService")// 接口地址
public class HelloServiceImpl implements HelloService {
@Override
public String hello(String name) {
return name + ",welcome to china!";
}
}
4、新建一个配置类,注册服务,暴露服务调用地址
@Configuration
public class WebServiceConfig {
@Autowired
private HelloService helloService;
/**
* 注入servlet bean name不能dispatcherServlet 否则会覆盖dispatcherServlet
*
* @return
*/
@Bean
public ServletRegistrationBean cxfServlet() {
return new ServletRegistrationBean(new CXFServlet(), "/ws/*");//第二个参数:设置CXFServlet注册地址
}
@Bean(name = Bus.DEFAULT_BUS_ID)
public SpringBus springBus() {
return new SpringBus();
}
/**
* 注册WebService接口到webservice服务
*
* @return
*/
@Bean(name = "helloServiceEndpoint")
public Endpoint sweptPayEndpoint() {
EndpointImpl endpoint = new EndpointImpl(springBus(), helloService);
endpoint.publish("/webservice");//设置接口注册地址
return endpoint;
}
}
5、访问接口服务
WSDL:webservice 描述语言,如何解读不赘述,查看规则是从下到上分析来看
地址:http://localhost:8080/ws/webservice?wsdl
地址格式: (http://ip+端口/cxfServlet注册地址/具体服务接口地址+ ?wsdl)
报文示例:
<wsdl:definitions xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:tns="http://service.winson.com" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:ns1="http://schemas.xmlsoap.org/soap/http" name="HelloService" targetNamespace="http://service.winson.com">
<wsdl:types>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://service.winson.com" elementFormDefault="unqualified" targetNamespace="http://service.winson.com" version="1.0">
<xs:element name="hello" type="tns:hello"/>
<xs:element name="helloResponse" type="tns:helloResponse"/>
<xs:complexType name="hello">
<xs:sequence>
<xs:element minOccurs="0" name="name" type="xs:string"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="helloResponse">
<xs:sequence>
<xs:element minOccurs="0" name="return" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
</wsdl:types>
<wsdl:message name="hello">
<wsdl:part element="tns:hello" name="parameters"> </wsdl:part>
</wsdl:message>
<wsdl:message name="helloResponse">
<wsdl:part element="tns:helloResponse" name="parameters"> </wsdl:part>
</wsdl:message>
<wsdl:portType name="HelloService">
<wsdl:operation name="hello">
<wsdl:input message="tns:hello" name="hello"> </wsdl:input>
<wsdl:output message="tns:helloResponse" name="helloResponse"> </wsdl:output>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="HelloServiceSoapBinding" type="tns:HelloService">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="hello">
<soap:operation soapAction="" style="document"/>
<wsdl:input name="hello">
<soap:body use="literal"/>
</wsdl:input>
<wsdl:output name="helloResponse">
<soap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="HelloService">
<wsdl:port binding="tns:HelloServiceSoapBinding" name="HelloServiceImplPort">
<soap:address location="http://localhost:8080/ws/webservice"/>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
3.构建webservice客户端
1、构建一个 SpringBoot 工程,引入依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web-services</artifactId>
</dependency>
<!--webservice 依赖-->
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxws</artifactId>
<version>3.4.4</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http</artifactId>
<version>3.4.4</version>
</dependency>
<!--测试依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
</dependencies>
有两种方式测试:
-
方式1:代理类工厂的方式,需要拿到对方的接口
@Test public void testWebserviceServer() { try { // 接口地址 String address = "http://localhost:8080/ws/webservice?wsdl"; // 代理工厂 JaxWsProxyFactoryBean jaxWsProxyFactoryBean = new JaxWsProxyFactoryBean(); // 设置代理地址 jaxWsProxyFactoryBean.setAddress(address); // 设置接口类型 jaxWsProxyFactoryBean.setServiceClass(HelloService.class); // 创建一个代理接口实现 HelloService helloService = (HelloService) jaxWsProxyFactoryBean.create(); // 调用代理接口的方法调用并返回结果 String res = helloService.hello("winson"); System.out.println("返回结果:" + res); } catch (Exception e) { e.printStackTrace(); } }
-
方式2:动态调用方式,优点:动态客户端调用,利用反射不需要引入服务端Service类
@Test public void test02() { //创建动态客户端 JaxWsDynamicClientFactory dcf = JaxWsDynamicClientFactory.newInstance(); try { Client client = dcf.createClient("http://localhost:8080/ws/webservice?wsdl"); // 需要密码的情况需要加上用户名和密码 // client.getOutInterceptors().add(new ClientLoginInterceptor(USER_NAME, PASS_WORD)); Object[] objects = new Object[0]; // invoke("方法名",参数1,参数2,参数3....); objects = client.invoke("hello", "elnimo"); System.out.println("返回数据:" + objects[0]); } catch (java.lang.Exception e) { e.printStackTrace(); } }
4.启动测试用例,返回结果
返回数据:elnimo,welcome to china!
Disconnected from the target VM, address: '127.0.0.1:51792', transport: 'socket'
Process finished with exit code 0
以上几步就是利用SpringBoot + webservice(jaxws) 实现webservice示例,代码中的注释很重要,请仔细参考,否则启动程序会报错。