在多系统中进行数据交互时,可以采用WEB SERVICE的形式来发布,这样可以解决不同语言之间的问题,而不像RMI那样,下面就记录下Spring和apache的cxf整合发布webservice服务,以及客户端的调用。
首先创建一个maven 项目,对应的pom.xml文件如下:
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.jacksoft</groupId> <artifactId>cxf-test</artifactId> <packaging>war</packaging> <version>0.0.1-SNAPSHOT</version> <name>cxf-test Maven Webapp</name> <url>http://maven.apache.org</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <spring.version>3.0.5.RELEASE</spring.version> <slf4j.version>1.6.4</slf4j.version> <cxf.version>2.4.1</cxf.version> </properties> <repositories> <repository> <id>maven2-repository.java.net</id> <name>Java.net Repository for Maven</name> <url>http://download.java.net/maven/2/</url> <layout>default</layout> </repository> </repositories> <dependencies> <!-- CXF Dependencies --> <dependency> <groupId>jta</groupId> <artifactId>jta</artifactId> <version>1.0.1b</version> </dependency> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-core</artifactId> <version>${cxf.version}</version> </dependency> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-frontend-simple</artifactId> <version>${cxf.version}</version> </dependency> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-frontend-jaxws</artifactId> <version>${cxf.version}</version> </dependency> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-databinding-aegis</artifactId> <version>${cxf.version}</version> </dependency> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-transports-local</artifactId> <version>${cxf.version}</version> </dependency> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-transports-http</artifactId> <version>${cxf.version}</version> </dependency> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-transports-http-jetty</artifactId> <version>${cxf.version}</version> </dependency> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-transports-jms</artifactId> <version>${cxf.version}</version> </dependency> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-management</artifactId> <version>${cxf.version}</version> </dependency> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-common-utilities</artifactId> <version>${cxf.version}</version> </dependency> <!-- End of CXF Dependencies --> <dependency> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-servlets</artifactId> <version>7.4.0.v20110414</version> <scope>provided</scope> <exclusions> <exclusion> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-client</artifactId> </exclusion> </exclusions> </dependency> <!-- Spring Dependencies ${spring.version} --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-beans</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-orm</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-expression</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> </dependency> <dependency> <groupId>org.apache.geronimo.specs</groupId> <artifactId>geronimo-annotation_1.0_spec</artifactId> <version>1.1.1</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>${slf4j.version}</version> <type>jar</type> <scope>compile</scope> </dependency> <dependency> <groupId>org.apache.axis</groupId> <artifactId>axis</artifactId> <version>1.4</version> </dependency> <dependency> <groupId>org.apache.axis</groupId> <artifactId>axis-jaxrpc</artifactId> <version>1.4</version> </dependency> <dependency> <groupId>commons-discovery</groupId> <artifactId>commons-discovery</artifactId> <version>0.5</version> </dependency> </dependencies> <build> <finalName>${project.artifactId}</finalName> <plugins> <plugin> <groupId>org.mortbay.jetty</groupId> <artifactId>jetty-maven-plugin</artifactId> <version>7.4.2.v20110526</version> <configuration> <scanIntervalSeconds>10</scanIntervalSeconds> <connectors> <connector implementation="org.eclipse.jetty.server.nio.SelectChannelConnector"> <port>8085</port> </connector> </connectors> <webAppConfig> <contextPath>/${project.artifactId}</contextPath> </webAppConfig> </configuration> </plugin> <plugin> <artifactId>maven-compiler-plugin</artifactId> <version>2.3.2</version> <configuration> <source>1.6</source> <target>1.6</target> </configuration> </plugin> </plugins> </build> </project>
这里我有其他的使用,所以jar包就多了,可以根据需要来删除部分,比如jetty。 我这里是采用jetty来启动服务。
接下来就是编写代码,首先定义一个接口,并且将该接口定义为webservice
HelloWorld:
package com.jacksoft.webservice;
import java.util.List;
import javax.jws.WebParam;
import javax.jws.WebService;
import com.jacksoft.entry.User;
@WebService
public interface HelloWorld {
public String sayHello(@WebParam(name="username")String userName);
public void sayHi();
public List<User> getList();
}
有3个方法,分别是有返回值,没有返回值的,下面是对于的User类:
User:
package com.jacksoft.entry;
public class User {
private String username;
private Integer age;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
一个简单的pojo类,接下来就是接口的一个具体实现类:
HelloWorldImpl:
package com.jacksoft.webservice;
import java.util.ArrayList;
import java.util.List;
import javax.jws.WebService;
import com.jacksoft.entry.User;
@WebService(endpointInterface="com.jacksoft.webservice.HelloWorld")
public class HelloWorldImpl implements HelloWorld {
public String sayHello(String userName) {
System.out.println("-------HelloWorldImpl.sayHello-----------------");
return "Hello," + userName;
}
public void sayHi() {
System.out.println("Hi...................");
}
/**
*
*/
public List<User> getList(){
List<User> list = new ArrayList<User>();
for(int i = 0;i< 10;i++){
User user = new User();
user.setUsername("Hello" + i);
user.setAge(i);
list.add(user);
}
return list;
}
}
endpointInterface 指定接口的全名,到这里,代码部分就基本上写完了,下面就是一些配置信息,
首先是web.xml文件,首先需要定义一个servlet:CXFServlet,让他来给我们列举出那些是webservice服务
然后就是spring容器的启动:
web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5"> <!-- Servlet Mapping for CXFServlet --> <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>/*</url-pattern> </servlet-mapping> <!-- Context parameters --> <context-param> <param-name>log4jConfigLocation</param-name> <param-value>classpath:log4j.properties</param-value> </context-param> <context-param> <param-name>log4jExposeWebAppRoot</param-name> <param-value>false</param-value> </context-param> <listener> <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class> </listener> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:applicationContext.xml</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> </web-app>
然后是applicationContext.xml文件,需要将上面写的webservice丢给spring来进行管理
<?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:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xmlns:jee="http://www.springframework.org/schema/jee" xmlns:lang="http://www.springframework.org/schema/lang" xmlns:p="http://www.springframework.org/schema/p" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:util="http://www.springframework.org/schema/util" 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://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee.xsd http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd"> <!-- Initiliaing Client Webservices --> <import resource="classpath:META-INF/cxf/cxf.xml" /> <import resource="classpath:META-INF/cxf/cxf-servlet.xml" /> <bean id="hello" class="com.jacksoft.webservice.HelloWorldImpl"/> <!-- JAX-WS Service Endpoint --> <jaxws:endpoint id="helloWorld" implementor="#hello" address="/helloWorld" /> </beans>
这里cxf.xml和cxf-servlet.xml是需要引入的,里面定义了一些必要的bean,具体的路径在
cxf-rt-core-2.4.1.jar包下面META-INF/cxf/cxf.xml
cxf-rt-transports-http-2.4.1.jar 包下面META-INF/cxf/cxf-servlet.xml
这样服务端就写完了,到目录下运行 mvn jetty:run 来启动服务器,启动完毕后,在浏览器输入:
http://localhost:8085/cxf-test/
可以看到如下内容:
点击链接之后,可以看到内容如下:
<wsdl:definitions xmlns:ns1="http://schemas.xmlsoap.org/soap/http" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://webservice.jacksoft.com/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="HelloWorldImplService" targetNamespace="http://webservice.jacksoft.com/"> <wsdl:types> <xs:schema xmlns:tns="http://webservice.jacksoft.com/" xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="unqualified" targetNamespace="http://webservice.jacksoft.com/" version="1.0"> <xs:element name="getList" type="tns:getList"/> <xs:element name="getListResponse" type="tns:getListResponse"/> <xs:element name="sayHello" type="tns:sayHello"/> <xs:element name="sayHelloResponse" type="tns:sayHelloResponse"/> <xs:element name="sayHi" type="tns:sayHi"/> <xs:element name="sayHiResponse" type="tns:sayHiResponse"/> <xs:complexType name="sayHi"> <xs:sequence/> </xs:complexType> <xs:complexType name="sayHiResponse"> <xs:sequence/> </xs:complexType> <xs:complexType name="getList"> <xs:sequence/> </xs:complexType> <xs:complexType name="getListResponse"> <xs:sequence> <xs:element maxOccurs="unbounded" minOccurs="0" name="return" type="tns:user"/> </xs:sequence> </xs:complexType> <xs:complexType name="user"> <xs:sequence> <xs:element minOccurs="0" name="age" type="xs:int"/> <xs:element minOccurs="0" name="username" type="xs:string"/> </xs:sequence> </xs:complexType> <xs:complexType name="sayHello"> <xs:sequence> <xs:element minOccurs="0" name="username" type="xs:string"/> </xs:sequence> </xs:complexType> <xs:complexType name="sayHelloResponse"> <xs:sequence> <xs:element minOccurs="0" name="return" type="xs:string"/> </xs:sequence> </xs:complexType> </xs:schema> </wsdl:types> <wsdl:message name="sayHi"> <wsdl:part element="tns:sayHi" name="parameters"></wsdl:part> </wsdl:message> <wsdl:message name="sayHelloResponse"> <wsdl:part element="tns:sayHelloResponse" name="parameters"></wsdl:part> </wsdl:message> <wsdl:message name="sayHello"> <wsdl:part element="tns:sayHello" name="parameters"></wsdl:part> </wsdl:message> <wsdl:message name="getListResponse"> <wsdl:part element="tns:getListResponse" name="parameters"></wsdl:part> </wsdl:message> <wsdl:message name="getList"> <wsdl:part element="tns:getList" name="parameters"></wsdl:part> </wsdl:message> <wsdl:message name="sayHiResponse"> <wsdl:part element="tns:sayHiResponse" name="parameters"></wsdl:part> </wsdl:message> <wsdl:portType name="HelloWorld"> <wsdl:operation name="sayHi"> <wsdl:input message="tns:sayHi" name="sayHi"></wsdl:input> <wsdl:output message="tns:sayHiResponse" name="sayHiResponse"></wsdl:output> </wsdl:operation> <wsdl:operation name="getList"> <wsdl:input message="tns:getList" name="getList"></wsdl:input> <wsdl:output message="tns:getListResponse" name="getListResponse"></wsdl:output> </wsdl:operation> <wsdl:operation name="sayHello"> <wsdl:input message="tns:sayHello" name="sayHello"></wsdl:input> <wsdl:output message="tns:sayHelloResponse" name="sayHelloResponse"></wsdl:output> </wsdl:operation> </wsdl:portType> <wsdl:binding name="HelloWorldImplServiceSoapBinding" type="tns:HelloWorld"> <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/> <wsdl:operation name="getList"> <soap:operation soapAction="" style="document"/> <wsdl:input name="getList"> <soap:body use="literal"/> </wsdl:input> <wsdl:output name="getListResponse"> <soap:body use="literal"/> </wsdl:output> </wsdl:operation> <wsdl:operation name="sayHi"> <soap:operation soapAction="" style="document"/> <wsdl:input name="sayHi"> <soap:body use="literal"/> </wsdl:input> <wsdl:output name="sayHiResponse"> <soap:body use="literal"/> </wsdl:output> </wsdl:operation> <wsdl:operation name="sayHello"> <soap:operation soapAction="" style="document"/> <wsdl:input name="sayHello"> <soap:body use="literal"/> </wsdl:input> <wsdl:output name="sayHelloResponse"> <soap:body use="literal"/> </wsdl:output> </wsdl:operation> </wsdl:binding> <wsdl:service name="HelloWorldImplService"> <wsdl:port binding="tns:HelloWorldImplServiceSoapBinding" name="HelloWorldImplPort"> <soap:address location="http://localhost:8085/cxf-test/helloWorld"/> </wsdl:port> </wsdl:service> </wsdl:definitions>
到此,说明服务器端就已经OK了。
接下来就是客户端的调用,这里会存在一个问题,如果两个都是我们自己写的,那么接口啥的,我们是清楚的,自己拿过来用就可以了,但是使用一些公共的webservice的话,接口我们是不清楚的,需要去解析生成的wsdl文件,这里apache的cxf自带了wsdl2java的工具,自己根据wsdl来生成我们的一些接口或者是pojo类,同样Aixs2.0也带了这个工具,使用方法都是一样的,生成代码。
那么我这里就直接使用工具来完成了,在命令行执行下面的命令:
wsdl2java http://localhost:8085/cxf-test/helloWorld?wsdl
这样就可以生成我们需要的代码,在eclisps里面再次创建一个maven项目,这里我就直接拷贝这个项目了,然后把刚刚生成的代码粘贴到src下面
编写一个java类来进行测试
WebServiceTest:
package com.jacksoft.webservice.test;
import java.util.List;
import org.apache.cxf.endpoint.Client;
import org.apache.cxf.jaxws.endpoint.dynamic.JaxWsDynamicClientFactory;
import org.junit.Test;
import com.jacksoft.webservice.User;
public class WebServiceTest {
@Test
public void testSayHi(){
try {
JaxWsDynamicClientFactory factory = JaxWsDynamicClientFactory.newInstance();
Client client = factory.createClient("http://localhost:8085/cxf-test/helloWorld?wsdl");
Object[] obj = client.invoke("sayHello", "Jack");
System.out.println(obj[0]);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 获取用户信息
*/
@Test
public void getUserList(){
try {
JaxWsDynamicClientFactory factory = JaxWsDynamicClientFactory.newInstance();
Client client = factory.createClient("http://localhost:8085/cxf-test/helloWorld?wsdl");
Object[] obj = client.invoke("getList");
List<User> list = (List<User>) obj[0];
for(User user: list){
System.out.println(user.getUsername() + " " + user.getAge());
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
这里没有写断言了,最后就是测试下,执行后能正常调用服务端的一些方法