CXF+Spring搭建webservice服务
Apache CXF 是一个开源的 Services 框架,CXF 帮助您利用 Frontend 编程 API 来构建和开发 Services ,像 JAX-WS 。这些 Services 可以支持多种协议,比如:SOAP、XML/HTTP、RESTful HTTP 或者 CORBA ,并且可以在多种传输协议上运行,比如:HTTP、JMS 或者 JBI,CXF 大大简化了 Services 的创建,同时它继承了 XFire 传统,一样可以天然地和 Spring 进行无缝集成。
先贴出maven项目的pom.xml,这里使用了spring,而且有坑,spring的版本选用太新会启动不了服务器,后改为3.X版本才好。
1 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 2 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> 3 <modelVersion>4.0.0</modelVersion> 4 <groupId>com.bigbang</groupId> 5 <artifactId>cxf</artifactId> 6 <packaging>war</packaging> 7 <version>0.0.1-SNAPSHOT</version> 8 <name>cxf Maven Webapp</name> 9 <url>http://maven.apache.org</url> 10 <properties> 11 <cxf.version>3.1.11</cxf.version> 12 <spring.version>3.1.0.RELEASE</spring.version> 13 </properties> 14 <dependencies> 15 <dependency> 16 <groupId>junit</groupId> 17 <artifactId>junit</artifactId> 18 <version>3.8.1</version> 19 <scope>test</scope> 20 </dependency> 21 <dependency> 22 <groupId>org.apache.cxf</groupId> 23 <artifactId>cxf-rt-frontend-jaxws</artifactId> 24 <version>${cxf.version}</version> 25 </dependency> 26 <dependency> 27 <groupId>org.apache.cxf</groupId> 28 <artifactId>cxf-rt-transports-http</artifactId> 29 <version>${cxf.version}</version> 30 </dependency> 31 <!-- Jetty is needed if you're are not using the CXFServlet --> 32 <dependency> 33 <groupId>org.apache.cxf</groupId> 34 <artifactId>cxf-rt-transports-http-jetty</artifactId> 35 <version>${cxf.version}</version> 36 </dependency> 37 <dependency> 38 <groupId>org.springframework</groupId> 39 <artifactId>spring-context</artifactId> 40 <version>${spring.version}</version> 41 </dependency> 42 <dependency> 43 <groupId>org.springframework</groupId> 44 <artifactId>spring-web</artifactId> 45 <version>${spring.version}</version> 46 </dependency> 47 <dependency> 48 <groupId>org.springframework</groupId> 49 <artifactId>spring-beans</artifactId> 50 <version>${spring.version}</version> 51 </dependency> 52 </dependencies> 53 <build> 54 <plugins> 55 <plugin> 56 <groupId>org.mortbay.jetty</groupId> 57 <artifactId>maven-jetty-plugin</artifactId> 58 <version>6.1.26</version> 59 <configuration> 60 <webAppConfig> 61 <contextPath>/</contextPath> 62 </webAppConfig> 63 </configuration> 64 </plugin> 65 66 <plugin> 67 <groupId>org.apache.maven.plugins</groupId> 68 <artifactId>maven-compiler-plugin</artifactId> 69 <configuration> 70 <source>1.8</source> 71 <target>1.8</target> 72 </configuration> 73 </plugin> 74 </plugins> 75 <finalName>cxf</finalName> 76 </build> 77 78 </project>
项目web.xml文件的配置如下:
1 <context-param> 2 <param-name>contextConfigLocation</param-name> 3 <param-value>classpath*:/application*.xml</param-value> 4 </context-param> 5 <servlet> 6 <servlet-name>CXFServlet</servlet-name> 7 <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class> 8 <load-on-startup>1</load-on-startup> 9 </servlet> 10 <servlet-mapping> 11 <servlet-name>CXFServlet</servlet-name> 12 <url-pattern>/service/*</url-pattern> 13 </servlet-mapping> 14 <listener> 15 <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> 16 </listener>
其中CXFServlet是要访问的webservice入口配置。
Spring文件的相关配置如下:
1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jaxws="http://cxf.apache.org/jaxws" 4 xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd 5 http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd"> 6 7 <import resource="classpath:META-INF/cxf/cxf.xml" /> 8 <import resource="classpath:META-INF/cxf/cxf-servlet.xml" /> 9 10 <bean id="loginService" class="com.bigbang.cxf.service.LoginServiceImpl"/> 11 <jaxws:endpoint implementor="#loginService" address="/login"/> 12 </beans>
需要引入jax-ws的命名空间。并且引入两个xml配置文件,这两个文件在cxf的包里面,可以不用关心。 此处配置了一个bean,该bean是实现webservice服务的实现类。里面是具体的业务逻辑。
jaxws:endpoint是配置webservice端地址的,implementor指向一个实现类,address是webservice的访问地址。结合web.xml里面的cxfServlet配置,访问webservice的地址应该为:http://IP:端口/项目名/service/login?wsdl
webservice的接口和实现类如下:
接口类:
1 package com.bigbang.cxf.service; 2 3 import javax.jws.WebParam; 4 import javax.jws.WebService; 5 6 /** 7 * @author pzj 8 * 9 */ 10 @WebService 11 public interface LoginService { 12 13 String login(@WebParam(name="name")String name,@WebParam(name="password")String password); 14 }
@webservice注解说明这是一个webservice类,@WebParam是指明webservice接口方法的参数名称。类似于springmvc的@requestParam注解。此处如果不指明参数名称,webservice的wsdl文件里将使用arg0,arg1...代替,在写客户端代码请求webservice的时候,将引起困扰,不易编写代码。
实现类为:
1 package com.bigbang.cxf.service; 2 3 import javax.jws.WebService; 4 5 /** 6 * @author pzj 2017年5月16日 下午4:58:43 7 * 8 */ 9 @WebService(endpointInterface="com.bigbang.cxf.service.LoginService") 10 public class LoginServiceImpl implements LoginService { 11 12 /* (non-Javadoc) 13 * @see com.bigbang.cxf.LoginService#login(java.lang.String, java.lang.String) 14 */ 15 @Override 16 public String login(String name, String password) { 17 return name+"登录成功!密码是:"+password; 18 } 19 20 }
和上面接口不同的是,此处需要指明终端接口类的地址(包名+类名)。
全部准备好之后,使用jetty启动,会显示如下启动信息:
五月 18, 2017 9:58:05 上午 org.apache.cxf.wsdl.service.factory.ReflectionServiceFactoryBean buildServiceFromClass 信息: Creating Service {http://service.cxf.bigbang.com/}LoginServiceImplService from class com.bigbang.cxf.service.LoginService 五月 18, 2017 9:58:06 上午 org.apache.cxf.endpoint.ServerImpl initDestination 信息: Setting the server's publish address to be /login 2017-05-18 09:58:06.173:INFO:oejs.AbstractConnector:Started SelectChannelConnector@0.0.0.0:8080
说明webservice发布成功了,访问http://localhost:8080/service/login?wsdl,会生成xml页面:
1 This XML file does not appear to have any style information associated with it. The document tree is shown below. 2 <wsdl:definitions xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:tns="http://service.cxf.bigbang.com/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:ns1="http://schemas.xmlsoap.org/soap/http" name="LoginServiceImplService" targetNamespace="http://service.cxf.bigbang.com/"> 3 <wsdl:types> 4 <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://service.cxf.bigbang.com/" elementFormDefault="unqualified" targetNamespace="http://service.cxf.bigbang.com/" version="1.0"> 5 <xs:element name="login" type="tns:login"/> 6 <xs:element name="loginResponse" type="tns:loginResponse"/> 7 <xs:complexType name="login"> 8 <xs:sequence> 9 <xs:element minOccurs="0" name="name" type="xs:string"/> 10 <xs:element minOccurs="0" name="password" type="xs:string"/> 11 </xs:sequence> 12 </xs:complexType> 13 <xs:complexType name="loginResponse"> 14 <xs:sequence> 15 <xs:element minOccurs="0" name="return" type="xs:string"/> 16 </xs:sequence> 17 </xs:complexType> 18 </xs:schema> 19 </wsdl:types> 20 <wsdl:message name="login"> 21 <wsdl:part element="tns:login" name="parameters"></wsdl:part> 22 </wsdl:message> 23 <wsdl:message name="loginResponse"> 24 <wsdl:part element="tns:loginResponse" name="parameters"></wsdl:part> 25 </wsdl:message> 26 <wsdl:portType name="LoginService"> 27 <wsdl:operation name="login"> 28 <wsdl:input message="tns:login" name="login"></wsdl:input> 29 <wsdl:output message="tns:loginResponse" name="loginResponse"></wsdl:output> 30 </wsdl:operation> 31 </wsdl:portType> 32 <wsdl:binding name="LoginServiceImplServiceSoapBinding" type="tns:LoginService"> 33 <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/> 34 <wsdl:operation name="login"> 35 <soap:operation soapAction="" style="document"/> 36 <wsdl:input name="login"> 37 <soap:body use="literal"/> 38 </wsdl:input> 39 <wsdl:output name="loginResponse"> 40 <soap:body use="literal"/> 41 </wsdl:output> 42 </wsdl:operation> 43 </wsdl:binding> 44 <wsdl:service name="LoginServiceImplService"> 45 <wsdl:port binding="tns:LoginServiceImplServiceSoapBinding" name="LoginServiceImplPort"> 46 <soap:address location="http://localhost:8080/service/login"/> 47 </wsdl:port> 48 </wsdl:service> 49 </wsdl:definitions>